mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-03-07 06:09:42 +00:00
Compare commits
168 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
779228857e | ||
|
|
8d0b696d33 | ||
|
|
b7940e0002 | ||
|
|
b3fd8bd0ae | ||
|
|
bffeb237de | ||
|
|
23e3602ea1 | ||
|
|
34cfd205f6 | ||
|
|
df3da8be7a | ||
|
|
940243f45e | ||
|
|
75d6599143 | ||
|
|
929a27a5ac | ||
|
|
82ddee2104 | ||
|
|
a141678119 | ||
|
|
96d109af81 | ||
|
|
a309eb9f3c | ||
|
|
d034dab265 | ||
|
|
883a035e5c | ||
|
|
08603091c5 | ||
|
|
a2e84e5a1e | ||
|
|
9439621849 | ||
|
|
15ded89618 | ||
|
|
b84f74c167 | ||
|
|
a97300f8be | ||
|
|
9e12cff317 | ||
|
|
ecdf1f4ddc | ||
|
|
2fa7a48163 | ||
|
|
8adf76dcc9 | ||
|
|
15899c10b2 | ||
|
|
05ff05ea4b | ||
|
|
bd62df48c2 | ||
|
|
2366cbc833 | ||
|
|
25fb609544 | ||
|
|
af793395f0 | ||
|
|
8f41776858 | ||
|
|
139b13b8d1 | ||
|
|
4c611a5be1 | ||
|
|
5e7a21e177 | ||
|
|
5f7dda5ba8 | ||
|
|
2dfa1ca0f2 | ||
|
|
358cdcf4c4 | ||
|
|
c8f4ace5c4 | ||
|
|
5cac6ca8bb | ||
|
|
fccad71df1 | ||
|
|
97ae2674dc | ||
|
|
7c70affd7f | ||
|
|
52ff568d86 | ||
|
|
b917aeaa0b | ||
|
|
8de443ec4c | ||
|
|
7d9893c614 | ||
|
|
3540712517 | ||
|
|
a8b1a86bd7 | ||
|
|
1babd3a5a2 | ||
|
|
50399e5194 | ||
|
|
b734acf1b1 | ||
|
|
33aa8e2471 | ||
|
|
2c58fe736b | ||
|
|
6fe1de5d86 | ||
|
|
064460b95f | ||
|
|
2c3b19a539 | ||
|
|
dc30a4c1ae | ||
|
|
86e9901bf2 | ||
|
|
6519e0835a | ||
|
|
a52344fc01 | ||
|
|
b67424643d | ||
|
|
575a4c01c9 | ||
|
|
f0d4ee6618 | ||
|
|
8753186a0d | ||
|
|
ff8fb8000d | ||
|
|
9dd38b99d6 | ||
|
|
dfe08c1ec9 | ||
|
|
062d8d0f4f | ||
|
|
c0d1e2c07a | ||
|
|
e70feceafe | ||
|
|
71ac0286b1 | ||
|
|
022f4d2c11 | ||
|
|
a83a839cff | ||
|
|
b259ee89aa | ||
|
|
65cf14bfce | ||
|
|
d9476fb5ca | ||
|
|
9882365ab4 | ||
|
|
2d758ce963 | ||
|
|
1dd003d26a | ||
|
|
0df5b77595 | ||
|
|
e190a005db | ||
|
|
45596a0342 | ||
|
|
405429a300 | ||
|
|
d009a29426 | ||
|
|
f1fb42460a | ||
|
|
5e110e9f7b | ||
|
|
77a409935d | ||
|
|
863baeb68b | ||
|
|
11142690a0 | ||
|
|
02e8c5faca | ||
|
|
c41081d35c | ||
|
|
db4c26a400 | ||
|
|
331a23fc20 | ||
|
|
db5a40d743 | ||
|
|
e4ab51329d | ||
|
|
86782aeb1b | ||
|
|
49a44fc92e | ||
|
|
cd39a52c25 | ||
|
|
634101ceb5 | ||
|
|
55555c8787 | ||
|
|
d36d825ac1 | ||
|
|
9bb01cd67c | ||
|
|
29b91075d2 | ||
|
|
6d46fc9f9f | ||
|
|
a2c41c9e36 | ||
|
|
ee700ac861 | ||
|
|
9884a4336f | ||
|
|
5b83d4bef8 | ||
|
|
d320a89590 | ||
|
|
f7e4afc282 | ||
|
|
88e87d589b | ||
|
|
d8c6dede7e | ||
|
|
5cc84133e3 | ||
|
|
f7728aa1f6 | ||
|
|
2b61f9a731 | ||
|
|
f407022fe6 | ||
|
|
41b9f19b01 | ||
|
|
09c6faf923 | ||
|
|
26d0177c01 | ||
|
|
f7415c8a8f | ||
|
|
4cf79088f9 | ||
|
|
50cd321818 | ||
|
|
83bbe6a9d9 | ||
|
|
0a33c18e36 | ||
|
|
6cf158ac63 | ||
|
|
f96bfa6afa | ||
|
|
2b64cf9126 | ||
|
|
a8dcfc44f5 | ||
|
|
0ff9c9da27 | ||
|
|
07e7c2d852 | ||
|
|
10e4b5b2a3 | ||
|
|
998653ea9d | ||
|
|
1a38e925bf | ||
|
|
c8f51380e6 | ||
|
|
2406d57d51 | ||
|
|
cb1e47eb71 | ||
|
|
c0a650f28b | ||
|
|
460cf6fd20 | ||
|
|
5bedfc1c84 | ||
|
|
5001592fb4 | ||
|
|
f6495e59c5 | ||
|
|
66bf431481 | ||
|
|
d9685e991e | ||
|
|
e0790700cd | ||
|
|
910a9600bd | ||
|
|
fc52b2b940 | ||
|
|
b99f828583 | ||
|
|
f38891cace | ||
|
|
8c5111e11a | ||
|
|
5575b981c8 | ||
|
|
0b36732911 | ||
|
|
52f3081a40 | ||
|
|
00c71dc26a | ||
|
|
5218c8584f | ||
|
|
6054bd6621 | ||
|
|
55af4ed385 | ||
|
|
64aee9c8ae | ||
|
|
5233e72205 | ||
|
|
db5b45222a | ||
|
|
fc4787da4e | ||
|
|
4ffbb46cf9 | ||
|
|
c3c2550f17 | ||
|
|
41e8ab5383 | ||
|
|
a802940616 | ||
|
|
dec848f072 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -8,7 +8,7 @@ netDb
|
||||
/i2pd
|
||||
/libi2pd.a
|
||||
/libi2pdclient.a
|
||||
i2pd.exe
|
||||
*.exe
|
||||
|
||||
|
||||
# Autotools
|
||||
|
||||
44
ChangeLog
44
ChangeLog
@@ -1,6 +1,46 @@
|
||||
# for this file format description,
|
||||
# see https://github.com/olivierlacan/keep-a-changelog
|
||||
|
||||
## [2.22.0] - 2018-11-09
|
||||
### Added
|
||||
- Multiple tunnel config files from tunnels.d folder
|
||||
### Changed
|
||||
- Fetch own RouterInfo upon SessionRequest for NTCP2
|
||||
- Faster XOR between AES blocks for non AVX capable CPUs
|
||||
### Fixed
|
||||
- Fixed NTCP2 termination send
|
||||
|
||||
## [2.21.1] - 2018-10-22
|
||||
### Changed
|
||||
- cost=13 for unpublished NTCP2 address
|
||||
### Fixed
|
||||
- Handle I2NP messages longer than 32K
|
||||
|
||||
## [2.21.0] - 2018-10-04
|
||||
### Added
|
||||
- EdDSA, x25519 and SipHash from openssl 1.1.1
|
||||
- NTCP2 ipv6 incoming connections
|
||||
- Show total number of destination's outgoing tags in the web console
|
||||
### Changed
|
||||
- Android build with openssl 1.1.1/boost 1.64
|
||||
- Bandwidth classes 'P' and 'X' don't add 'O' anymore
|
||||
### Fixed
|
||||
- Update own RouterInfo if no SSU
|
||||
- Recognize 'P' and 'X' routers as high bandwidth without 'O'
|
||||
- NTCP address doesn't disappear if NTCP2 enabled
|
||||
- Android with api 26+
|
||||
|
||||
## [2.20.0] - 2018-08-23
|
||||
### Added
|
||||
- Full implementation of NTCP2
|
||||
- Assets for android
|
||||
### Changed
|
||||
- armeabi-v7a and x86 in one apk for android
|
||||
- NTCP2 is enabled by default
|
||||
- Show lease's expiration time in readable format in the web console
|
||||
### Fixed
|
||||
- Correct names for transports in the web console
|
||||
|
||||
## [2.19.0] - 2018-06-26
|
||||
### Added
|
||||
- ECIES support for RouterInfo
|
||||
@@ -68,7 +108,7 @@
|
||||
- NTCP soft and hard descriptors limits
|
||||
- Support full timestamps in logs
|
||||
### Changed
|
||||
- Faster implmentation of GOST R 34.11 hash
|
||||
- Faster implementation of GOST R 34.11 hash
|
||||
- Reject routers with RSA signtures
|
||||
- Reload config and shudown from Windows GUI
|
||||
- Update tunnels address(destination) without restart
|
||||
@@ -168,7 +208,7 @@
|
||||
- Initial iOS support
|
||||
|
||||
### Changed
|
||||
- Reduced file descriptiors usage
|
||||
- Reduced file descriptors usage
|
||||
- Strict reseed checks enabled by default
|
||||
|
||||
## Fixed
|
||||
|
||||
10
Makefile
10
Makefile
@@ -18,6 +18,14 @@ USE_AVX := yes
|
||||
USE_STATIC := no
|
||||
USE_MESHNET := no
|
||||
USE_UPNP := no
|
||||
DEBUG := yes
|
||||
|
||||
ifeq ($(DEBUG),yes)
|
||||
CXX_DEBUG = -g
|
||||
else
|
||||
CXX_DEBUG = -Os
|
||||
LD_DEBUG = -s
|
||||
endif
|
||||
|
||||
ifeq ($(WEBSOCKETS),1)
|
||||
NEEDED_CXXFLAGS += -DWITH_EVENTS
|
||||
@@ -122,6 +130,8 @@ doxygen:
|
||||
.PHONY: deps
|
||||
.PHONY: doxygen
|
||||
.PHONY: dist
|
||||
.PHONY: last-dist
|
||||
.PHONY: api
|
||||
.PHONY: api_client
|
||||
.PHONY: mk_obj_dir
|
||||
.PHONY: install
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
CXX = clang++
|
||||
CXXFLAGS ?= -g -Wall -Wextra -Wno-unused-parameter -pedantic -Wno-misleading-indentation
|
||||
CXXFLAGS ?= ${CXX_DEBUG} -Wall -Wextra -Wno-unused-parameter -pedantic -Wno-misleading-indentation
|
||||
## NOTE: NEEDED_CXXFLAGS is here so that custom CXXFLAGS can be specified at build time
|
||||
## **without** overwriting the CXXFLAGS which we need in order to build.
|
||||
## For example, when adding 'hardening flags' to the build
|
||||
@@ -8,5 +8,5 @@ CXXFLAGS ?= -g -Wall -Wextra -Wno-unused-parameter -pedantic -Wno-misleading-ind
|
||||
## custom FLAGS to work at build-time.
|
||||
NEEDED_CXXFLAGS = -std=c++11 -D_GLIBCXX_USE_NANOSLEEP=1
|
||||
INCFLAGS = -I/usr/include/ -I/usr/local/include/
|
||||
LDFLAGS = -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
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
# root directory holding homebrew
|
||||
BREWROOT = /usr/local
|
||||
BOOSTROOT = ${BREWROOT}/opt/boost
|
||||
SSLROOT = ${BREWROOT}/opt/libressl
|
||||
SSLROOT = ${BREWROOT}/opt/openssl@1.1
|
||||
UPNPROOT = ${BREWROOT}/opt/miniupnpc
|
||||
CXXFLAGS = -g -Wall -std=c++11 -DMAC_OSX -Wno-overloaded-virtual
|
||||
CXXFLAGS = ${CXX_DEBUG} -Wall -std=c++11 -DMAC_OSX -Wno-overloaded-virtual
|
||||
INCFLAGS = -I${SSLROOT}/include -I${BOOSTROOT}/include
|
||||
LDFLAGS = ${LD_DEBUG}
|
||||
|
||||
ifndef TRAVIS
|
||||
CXX = clang++
|
||||
@@ -13,7 +14,7 @@ endif
|
||||
ifeq ($(USE_STATIC),yes)
|
||||
LDLIBS = -lz ${SSLROOT}/lib/libcrypto.a ${SSLROOT}/lib/libssl.a ${BOOSTROOT}/lib/libboost_system.a ${BOOSTROOT}/lib/libboost_date_time.a ${BOOSTROOT}/lib/libboost_filesystem.a ${BOOSTROOT}/lib/libboost_program_options.a -lpthread
|
||||
else
|
||||
LDFLAGS = -L${SSLROOT}/lib -L${BOOSTROOT}/lib
|
||||
LDFLAGS += -L${SSLROOT}/lib -L${BOOSTROOT}/lib
|
||||
LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
|
||||
endif
|
||||
|
||||
@@ -34,15 +35,20 @@ endif
|
||||
# Seems like all recent Mac's have AES-NI, after firmware upgrade 2.2
|
||||
# Found no good way to detect it from command line. TODO: Might be some osx sysinfo magic
|
||||
ifeq ($(USE_AESNI),yes)
|
||||
CXXFLAGS += -maes -DAESNI
|
||||
CXXFLAGS += -maes
|
||||
endif
|
||||
ifeq ($(USE_AVX),1)
|
||||
CXXFLAGS += -mavx
|
||||
endif
|
||||
|
||||
|
||||
# Disabled, since it will be the default make rule. I think its better
|
||||
# to define the default rule in Makefile and not Makefile.<ostype> - torkel
|
||||
#install: all
|
||||
# test -d ${PREFIX} || mkdir -p ${PREFIX}/
|
||||
# cp -r i2p ${PREFIX}/
|
||||
install: all
|
||||
install -d ${PREFIX}/bin ${PREFIX}/etc/i2pd ${PREFIX}/share/doc/i2pd ${PREFIX}/share/i2pd ${PREFIX}/share/man/man1 ${PREFIX}/var/lib/i2pd
|
||||
install -m 755 ${I2PD} ${PREFIX}/bin/
|
||||
install -m 644 contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/etc/i2pd
|
||||
@cp -R contrib/certificates ${PREFIX}/share/i2pd/
|
||||
install -m 644 ChangeLog LICENSE README.md contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/share/doc/i2pd
|
||||
@gzip debian/i2pd.1 && install debian/i2pd.1.gz ${PREFIX}/share/man/man1
|
||||
@ln -sf ${PREFIX}/share/i2pd/certificates ${PREFIX}/var/lib/i2pd/
|
||||
@ln -sf ${PREFIX}/etc/i2pd/i2pd.conf ${PREFIX}/var/lib/i2pd/i2pd.conf
|
||||
@ln -sf ${PREFIX}/etc/i2pd/subscriptions.txt ${PREFIX}/var/lib/i2pd/subscriptions.txt
|
||||
@ln -sf ${PREFIX}/etc/i2pd/tunnels.conf ${PREFIX}/var/lib/i2pd/tunnels.conf
|
||||
@@ -1,13 +1,13 @@
|
||||
# set defaults instead redefine
|
||||
CXXFLAGS ?= -g -Wall -Wextra -Wno-unused-parameter -pedantic -Wno-misleading-indentation
|
||||
INCFLAGS ?=
|
||||
CXXFLAGS ?= ${CXX_DEBUG} -Wall -Wextra -Wno-unused-parameter -pedantic -Wno-misleading-indentation
|
||||
LDFLAGS ?= ${LD_DEBUG}
|
||||
|
||||
## NOTE: The NEEDED_CXXFLAGS are here so that custom CXXFLAGS can be specified at build time
|
||||
## **without** overwriting the CXXFLAGS which we need in order to build.
|
||||
## For example, when adding 'hardening flags' to the build
|
||||
## (e.g. -fstack-protector-strong -Wformat -Werror=format-security), we do not want to remove
|
||||
## -std=c++11. If you want to remove this variable please do so in a way that allows setting
|
||||
## custom FLAGS to work at build-time.
|
||||
## custom FDLAGS to work at build-time.
|
||||
|
||||
# detect proper flag for c++11 support by compilers
|
||||
CXXVER := $(shell $(CXX) -dumpversion)
|
||||
@@ -21,8 +21,10 @@ else ifeq ($(shell expr match ${CXXVER} "4\.6"),3) # = 4.6
|
||||
NEEDED_CXXFLAGS += -std=c++0x
|
||||
else ifeq ($(shell expr match ${CXXVER} "[5-7]\.[0-9]"),3) # gcc >= 5.0
|
||||
NEEDED_CXXFLAGS += -std=c++11
|
||||
LDLIBS = -latomic
|
||||
else ifeq ($(shell expr match ${CXXVER} "[7-8]"),1) # gcc 7 ubuntu or gcc 8 arch
|
||||
NEEDED_CXXFLAGS += -std=c++11
|
||||
LDLIBS = -latomic
|
||||
else # not supported
|
||||
$(error Compiler too old)
|
||||
endif
|
||||
@@ -34,7 +36,7 @@ ifeq ($(USE_STATIC),yes)
|
||||
# Using 'getaddrinfo' in statically linked applications requires at runtime
|
||||
# the shared libraries from the glibc version used for linking
|
||||
LIBDIR := /usr/lib
|
||||
LDLIBS = $(LIBDIR)/libboost_system.a
|
||||
LDLIBS += $(LIBDIR)/libboost_system.a
|
||||
LDLIBS += $(LIBDIR)/libboost_date_time.a
|
||||
LDLIBS += $(LIBDIR)/libboost_filesystem.a
|
||||
LDLIBS += $(LIBDIR)/libboost_program_options.a
|
||||
@@ -44,7 +46,7 @@ ifeq ($(USE_STATIC),yes)
|
||||
LDLIBS += -lpthread -static-libstdc++ -static-libgcc -lrt -ldl
|
||||
USE_AESNI := no
|
||||
else
|
||||
LDLIBS = -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
|
||||
LDLIBS += -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
|
||||
endif
|
||||
|
||||
# UPNP Support (miniupnpc 1.5 and higher)
|
||||
@@ -64,7 +66,7 @@ ifneq ($(shell $(GREP) -c aes /proc/cpuinfo),0)
|
||||
ifeq ($(machine), aarch64)
|
||||
CXXFLAGS += -DARM64AES
|
||||
else
|
||||
CPU_FLAGS += -maes -DAESNI
|
||||
CPU_FLAGS += -maes
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
USE_WIN32_APP=yes
|
||||
CXX = g++
|
||||
WINDRES = windres
|
||||
CXXFLAGS = -Os -D_MT -DWIN32 -D_WINDOWS -DWIN32_LEAN_AND_MEAN
|
||||
CXXFLAGS := ${CXX_DEBUG} -D_MT -DWIN32 -D_WINDOWS -DWIN32_LEAN_AND_MEAN
|
||||
NEEDED_CXXFLAGS = -std=c++11
|
||||
BOOST_SUFFIX = -mt
|
||||
INCFLAGS = -Idaemon -I.
|
||||
LDFLAGS = -s -Wl,-rpath,/usr/local/lib -Wl,-Bstatic -static-libgcc -static-libstdc++
|
||||
LDFLAGS := ${LD_DEBUG} -Wl,-Bstatic -static-libgcc -static-libstdc++
|
||||
|
||||
# UPNP Support
|
||||
ifeq ($(USE_UPNP),yes)
|
||||
@@ -37,7 +37,7 @@ endif
|
||||
|
||||
# don't change following line to ifeq ($(USE_AESNI),yes) !!!
|
||||
ifeq ($(USE_AESNI),1)
|
||||
CPU_FLAGS += -maes -DAESNI
|
||||
CPU_FLAGS += -maes
|
||||
else
|
||||
CPU_FLAGS += -msse
|
||||
endif
|
||||
|
||||
13
Makefile.osx
13
Makefile.osx
@@ -1,8 +1,7 @@
|
||||
CXX = clang++
|
||||
CXXFLAGS = -Os -Wall -std=c++11 -DMAC_OSX
|
||||
#CXXFLAGS = -g -O2 -Wall -std=c++11
|
||||
CXXFLAGS := ${CXX_DEBUG} -Wall -std=c++11 -DMAC_OSX
|
||||
INCFLAGS = -I/usr/local/include
|
||||
LDFLAGS = -Wl,-rpath,/usr/local/lib -L/usr/local/lib
|
||||
LDFLAGS := -Wl,-rpath,/usr/local/lib -L/usr/local/lib
|
||||
|
||||
ifeq ($(USE_STATIC),yes)
|
||||
LDLIBS = -lz /usr/local/lib/libcrypto.a /usr/local/lib/libssl.a /usr/local/lib/libboost_system.a /usr/local/lib/libboost_date_time.a /usr/local/lib/libboost_filesystem.a /usr/local/lib/libboost_program_options.a -lpthread
|
||||
@@ -21,7 +20,7 @@ ifeq ($(USE_UPNP),yes)
|
||||
endif
|
||||
|
||||
ifeq ($(USE_AESNI),1)
|
||||
CXXFLAGS += -maes -DAESNI
|
||||
CXXFLAGS += -maes
|
||||
else
|
||||
CXXFLAGS += -msse
|
||||
endif
|
||||
@@ -29,9 +28,3 @@ endif
|
||||
ifeq ($(USE_AVX),1)
|
||||
CXXFLAGS += -mavx
|
||||
endif
|
||||
|
||||
# Disabled, since it will be the default make rule. I think its better
|
||||
# to define the default rule in Makefile and not Makefile.<ostype> - torkel
|
||||
#install: all
|
||||
# test -d ${PREFIX} || mkdir -p ${PREFIX}/
|
||||
# cp -r i2p ${PREFIX}/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#define I2Pd_AppName "i2pd"
|
||||
#define I2Pd_ver "2.19.0"
|
||||
#define I2Pd_ver "2.22.0"
|
||||
#define I2Pd_Publisher "PurpleI2P"
|
||||
|
||||
[Setup]
|
||||
@@ -32,6 +32,7 @@ Source: ..\contrib\i2pd.conf; DestDir: {userappdata}\i2pd; Flags: onlyifdoesntex
|
||||
Source: ..\contrib\subscriptions.txt; DestDir: {userappdata}\i2pd; Flags: onlyifdoesntexist
|
||||
Source: ..\contrib\tunnels.conf; DestDir: {userappdata}\i2pd; Flags: onlyifdoesntexist
|
||||
Source: ..\contrib\certificates\*; DestDir: {userappdata}\i2pd\certificates; Flags: onlyifdoesntexist recursesubdirs createallsubdirs
|
||||
Source: ..\contrib\tunnels.d\*; DestDir: {userappdata}\i2pd\tunnels.d; Flags: onlyifdoesntexist recursesubdirs createallsubdirs
|
||||
|
||||
[Icons]
|
||||
Name: {group}\I2Pd; Filename: {app}\i2pd.exe
|
||||
|
||||
9
android/.gitignore
vendored
9
android/.gitignore
vendored
@@ -1,12 +1,15 @@
|
||||
gen
|
||||
tests
|
||||
bin
|
||||
libs
|
||||
log*
|
||||
obj
|
||||
.gradle
|
||||
.idea
|
||||
.externalNativeBuild
|
||||
ant.properties
|
||||
local.properties
|
||||
build.sh
|
||||
bin
|
||||
log*
|
||||
.gradle
|
||||
android.iml
|
||||
build
|
||||
gradle
|
||||
|
||||
@@ -3,17 +3,18 @@
|
||||
package="org.purplei2p.i2pd"
|
||||
android:installLocation="auto"
|
||||
android:versionCode="1"
|
||||
android:versionName="2.19.0">
|
||||
android:versionName="2.22.0">
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="14"
|
||||
android:targetSdkVersion="25" />
|
||||
android:targetSdkVersion="28" />
|
||||
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" /> <!-- normal perm, per https://developer.android.com/guide/topics/permissions/normal-permissions.html -->
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- normal perm -->
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <!-- required in API 26+ -->
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@drawable/icon"
|
||||
|
||||
1
android/assets/certificates
Symbolic link
1
android/assets/certificates
Symbolic link
@@ -0,0 +1 @@
|
||||
../../contrib/certificates
|
||||
82
android/assets/i2pd.conf
Normal file
82
android/assets/i2pd.conf
Normal file
@@ -0,0 +1,82 @@
|
||||
## Configuration file for a typical i2pd user
|
||||
## See https://i2pd.readthedocs.io/en/latest/user-guide/configuration/
|
||||
## for more options you can use in this file.
|
||||
|
||||
#logfile = /sdcard/i2pd/i2pd.log
|
||||
loglevel = none
|
||||
#tunnelsdir = /sdcard/i2pd/tunnels.d
|
||||
|
||||
# host = 1.2.3.4
|
||||
# port = 4567
|
||||
|
||||
ipv4 = true
|
||||
ipv6 = false
|
||||
|
||||
# ntcp = true
|
||||
# ntcpproxy = http://127.0.0.1:8118
|
||||
# ssu = true
|
||||
|
||||
bandwidth = L
|
||||
# share = 100
|
||||
|
||||
# notransit = true
|
||||
# floodfill = true
|
||||
|
||||
[ntcp2]
|
||||
enabled = true
|
||||
|
||||
[http]
|
||||
enabled = true
|
||||
address = 127.0.0.1
|
||||
port = 7070
|
||||
# auth = true
|
||||
# user = i2pd
|
||||
# pass = changeme
|
||||
|
||||
[httpproxy]
|
||||
enabled = true
|
||||
address = 127.0.0.1
|
||||
port = 4444
|
||||
# keys = http-proxy-keys.dat
|
||||
# addresshelper = true
|
||||
# outproxy = http://false.i2p
|
||||
## httpproxy section also accepts I2CP parameters, like "inbound.length" etc.
|
||||
|
||||
[socksproxy]
|
||||
enabled = true
|
||||
address = 127.0.0.1
|
||||
port = 4447
|
||||
# keys = socks-proxy-keys.dat
|
||||
# outproxy.enabled = false
|
||||
# outproxy = 127.0.0.1
|
||||
# outproxyport = 9050
|
||||
## socksproxy section also accepts I2CP parameters, like "inbound.length" etc.
|
||||
|
||||
[sam]
|
||||
enabled = false
|
||||
# address = 127.0.0.1
|
||||
# port = 7656
|
||||
|
||||
[precomputation]
|
||||
elgamal = true
|
||||
|
||||
[upnp]
|
||||
enabled = true
|
||||
# name = I2Pd
|
||||
|
||||
[reseed]
|
||||
verify = true
|
||||
## Path to local reseed data file (.su3) for manual reseeding
|
||||
# file = /path/to/i2pseeds.su3
|
||||
## or HTTPS URL to reseed from
|
||||
# file = https://legit-website.com/i2pseeds.su3
|
||||
## Path to local ZIP file or HTTPS URL to reseed from
|
||||
# zipfile = /path/to/netDb.zip
|
||||
## If you run i2pd behind a proxy server, set proxy server for reseeding here
|
||||
## Should be http://address:port or socks://address:port
|
||||
# proxy = http://127.0.0.1:8118
|
||||
## Minimum number of known routers, below which i2pd triggers reseeding. 25 by default
|
||||
# threshold = 25
|
||||
|
||||
[limits]
|
||||
transittunnels = 50
|
||||
3
android/assets/subscriptions.txt
Normal file
3
android/assets/subscriptions.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
http://inr.i2p/export/alive-hosts.txt
|
||||
http://stats.i2p/cgi-bin/newhosts.txt
|
||||
http://i2p-projekt.i2p/hosts.txt
|
||||
33
android/assets/tunnels.conf
Normal file
33
android/assets/tunnels.conf
Normal file
@@ -0,0 +1,33 @@
|
||||
[IRC-IRC2P]
|
||||
#type = client
|
||||
#address = 127.0.0.1
|
||||
#port = 6668
|
||||
#destination = irc.postman.i2p
|
||||
#destinationport = 6667
|
||||
#keys = irc-keys.dat
|
||||
|
||||
#[IRC-ILITA]
|
||||
#type = client
|
||||
#address = 127.0.0.1
|
||||
#port = 6669
|
||||
#destination = irc.ilita.i2p
|
||||
#destinationport = 6667
|
||||
#keys = irc-keys.dat
|
||||
|
||||
#[SMTP]
|
||||
#type = client
|
||||
#address = 127.0.0.1
|
||||
#port = 7659
|
||||
#destination = smtp.postman.i2p
|
||||
#destinationport = 25
|
||||
#keys = smtp-keys.dat
|
||||
|
||||
#[POP3]
|
||||
#type = client
|
||||
#address = 127.0.0.1
|
||||
#port = 7660
|
||||
#destination = pop.postman.i2p
|
||||
#destinationport = 110
|
||||
#keys = pop3-keys.dat
|
||||
|
||||
# see more examples at https://i2pd.readthedocs.io/en/latest/user-guide/tunnels/
|
||||
1
android/assets/tunnels.d
Symbolic link
1
android/assets/tunnels.d
Symbolic link
@@ -0,0 +1 @@
|
||||
../../contrib/tunnels.d
|
||||
@@ -17,18 +17,27 @@ repositories {
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile 'com.android.support:support-compat:28.0.0'
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 25
|
||||
buildToolsVersion "25.0.3"
|
||||
compileSdkVersion 28
|
||||
buildToolsVersion "28.0.1"
|
||||
defaultConfig {
|
||||
applicationId "org.purplei2p.i2pd"
|
||||
targetSdkVersion 25
|
||||
targetSdkVersion 28
|
||||
minSdkVersion 14
|
||||
versionCode 1
|
||||
versionName "2.19.0"
|
||||
versionName "2.22.0"
|
||||
ndk {
|
||||
abiFilters 'armeabi-v7a'
|
||||
//abiFilters 'x86'
|
||||
abiFilters 'x86'
|
||||
}
|
||||
externalNativeBuild {
|
||||
ndkBuild {
|
||||
arguments "-j4"
|
||||
}
|
||||
}
|
||||
}
|
||||
sourceSets {
|
||||
@@ -37,6 +46,7 @@ android {
|
||||
java.srcDirs = ['src']
|
||||
res.srcDirs = ['res']
|
||||
jniLibs.srcDirs = ['libs']
|
||||
assets.srcDirs = ['assets']
|
||||
}
|
||||
}
|
||||
signingConfigs {
|
||||
|
||||
1
android/gradle.properties
Normal file
1
android/gradle.properties
Normal file
@@ -0,0 +1 @@
|
||||
org.gradle.parallel=true
|
||||
@@ -25,49 +25,49 @@ include $(BUILD_SHARED_LIBRARY)
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := boost_system
|
||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_62_0/$(TARGET_ARCH_ABI)/lib/libboost_system.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_62_0/include
|
||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_system.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := boost_date_time
|
||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_62_0/$(TARGET_ARCH_ABI)/lib/libboost_date_time.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_62_0/include
|
||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_date_time.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := boost_filesystem
|
||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_62_0/$(TARGET_ARCH_ABI)/lib/libboost_filesystem.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_62_0/include
|
||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_filesystem.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := boost_program_options
|
||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_62_0/$(TARGET_ARCH_ABI)/lib/libboost_program_options.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_62_0/include
|
||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_program_options.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := crypto
|
||||
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.0e/$(TARGET_ARCH_ABI)/lib/libcrypto.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.0e/include
|
||||
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1/$(TARGET_ARCH_ABI)/lib/libcrypto.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1/include
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := ssl
|
||||
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.0e/$(TARGET_ARCH_ABI)/lib/libssl.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.0e/include
|
||||
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1/$(TARGET_ARCH_ABI)/lib/libssl.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1/include
|
||||
LOCAL_STATIC_LIBRARIES := crypto
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := miniupnpc
|
||||
LOCAL_SRC_FILES := $(MINIUPNP_PATH)/miniupnp-2.0/$(TARGET_ARCH_ABI)/lib/libminiupnpc.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(MINIUPNP_PATH)/miniupnp-2.0/include
|
||||
LOCAL_SRC_FILES := $(MINIUPNP_PATH)/miniupnpc-2.1/$(TARGET_ARCH_ABI)/lib/libminiupnpc.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(MINIUPNP_PATH)/miniupnpc-2.1/include
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#APP_ABI := all
|
||||
#APP_ABI := armeabi-v7a x86
|
||||
APP_ABI := armeabi-v7a x86
|
||||
#APP_ABI := x86
|
||||
#APP_ABI := x86_64
|
||||
APP_ABI := armeabi-v7a
|
||||
#APP_ABI := armeabi-v7a
|
||||
#can be android-3 but will fail for x86 since arch-x86 is not present at ndkroot/platforms/android-3/ . libz is taken from there.
|
||||
APP_PLATFORM := android-14
|
||||
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
#include "DaemonAndroid.h"
|
||||
#include "Daemon.h"
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <exception>
|
||||
#include <boost/exception/diagnostic_information.hpp>
|
||||
#include <boost/exception_ptr.hpp>
|
||||
#include <exception>
|
||||
//#include "mainwindow.h"
|
||||
#include "FS.h"
|
||||
#include "DaemonAndroid.h"
|
||||
#include "Daemon.h"
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
@@ -80,6 +83,17 @@ namespace android
|
||||
//mutex=new QMutex(QMutex::Recursive);
|
||||
//setRunningCallback(0);
|
||||
//m_IsRunning=false;
|
||||
|
||||
// make sure assets are ready before proceed
|
||||
i2p::fs::DetectDataDir("", false);
|
||||
int numAttempts = 0;
|
||||
do
|
||||
{
|
||||
if (i2p::fs::Exists (i2p::fs::DataDirPath("assets.ready"))) break; // assets ready
|
||||
numAttempts++;
|
||||
std::this_thread::sleep_for (std::chrono::seconds(1)); // otherwise wait for 1 more second
|
||||
}
|
||||
while (numAttempts <= 10); // 10 seconds max
|
||||
return Daemon.init(argc,argv);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,4 +11,4 @@
|
||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||
|
||||
# Project target.
|
||||
target=android-25
|
||||
target=android-28
|
||||
|
||||
1
android/settings.gradle
Normal file
1
android/settings.gradle
Normal file
@@ -0,0 +1 @@
|
||||
rootProject.name = "i2pd"
|
||||
@@ -1,12 +1,17 @@
|
||||
package org.purplei2p.i2pd;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.support.annotation.RequiresApi;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
@@ -104,22 +109,41 @@ public class ForegroundService extends Service {
|
||||
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
|
||||
new Intent(this, I2PDActivity.class), 0);
|
||||
|
||||
// If earlier version channel ID is not used
|
||||
// https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#NotificationCompat.Builder(android.content.Context)
|
||||
String channelId = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) ? createNotificationChannel() : "";
|
||||
|
||||
// Set the info for the views that show in the notification panel.
|
||||
Notification notification = new Notification.Builder(this)
|
||||
.setSmallIcon(R.drawable.itoopie_notification_icon) // the status icon
|
||||
.setTicker(text) // the status text
|
||||
.setWhen(System.currentTimeMillis()) // the time stamp
|
||||
.setContentTitle(getText(R.string.app_name)) // the label of the entry
|
||||
.setContentText(text) // the contents of the entry
|
||||
.setContentIntent(contentIntent) // The intent to send when the entry is clicked
|
||||
Notification notification = new NotificationCompat.Builder(this, channelId)
|
||||
.setOngoing(true)
|
||||
.setSmallIcon(R.drawable.itoopie_notification_icon) // the status icon
|
||||
.setPriority(Notification.PRIORITY_DEFAULT)
|
||||
.setCategory(Notification.CATEGORY_SERVICE)
|
||||
.setTicker(text) // the status text
|
||||
.setWhen(System.currentTimeMillis()) // the time stamp
|
||||
.setContentTitle(getText(R.string.app_name)) // the label of the entry
|
||||
.setContentText(text) // the contents of the entry
|
||||
.setContentIntent(contentIntent) // The intent to send when the entry is clicked
|
||||
.build();
|
||||
|
||||
// Send the notification.
|
||||
//mNM.notify(NOTIFICATION, notification);
|
||||
startForeground(NOTIFICATION, notification);
|
||||
shown=true;
|
||||
shown = true;
|
||||
}
|
||||
|
||||
private static final DaemonSingleton daemon = DaemonSingleton.getInstance();
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
private synchronized String createNotificationChannel() {
|
||||
String channelId = getString(R.string.app_name);
|
||||
CharSequence channelName = "I2Pd service";
|
||||
NotificationChannel chan = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_LOW);
|
||||
//chan.setLightColor(Color.PURPLE);
|
||||
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
|
||||
NotificationManager service = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
service.createNotificationChannel(chan);
|
||||
return channelId;
|
||||
}
|
||||
|
||||
private static final DaemonSingleton daemon = DaemonSingleton.getInstance();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
package org.purplei2p.i2pd;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Timer;
|
||||
@@ -10,7 +18,9 @@ import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.content.res.AssetManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
@@ -18,25 +28,31 @@ import android.view.MenuItem;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class I2PDActivity extends Activity {
|
||||
private static final String TAG = "i2pdActvt";
|
||||
public static final int GRACEFUL_DELAY_MILLIS = 10 * 60 * 1000;
|
||||
// For future package update checking
|
||||
import org.purplei2p.i2pd.BuildConfig;
|
||||
|
||||
private TextView textView;
|
||||
public class I2PDActivity extends Activity {
|
||||
private static final String TAG = "i2pdActvt";
|
||||
public static final int GRACEFUL_DELAY_MILLIS = 10 * 60 * 1000;
|
||||
|
||||
private TextView textView;
|
||||
private boolean assetsCopied;
|
||||
private String i2pdpath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/i2pd/";
|
||||
|
||||
private static final DaemonSingleton daemon = DaemonSingleton.getInstance();
|
||||
|
||||
private final DaemonSingleton.StateUpdateListener daemonStateUpdatedListener =
|
||||
new DaemonSingleton.StateUpdateListener() {
|
||||
|
||||
new DaemonSingleton.StateUpdateListener() {
|
||||
@Override
|
||||
public void daemonStateUpdate() {
|
||||
public void daemonStateUpdate()
|
||||
{
|
||||
processAssets();
|
||||
runOnUiThread(new Runnable(){
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if(textView==null)return;
|
||||
if(textView==null) return;
|
||||
Throwable tr = daemon.getLastThrowable();
|
||||
if(tr!=null) {
|
||||
textView.setText(throwableToString(tr));
|
||||
@@ -44,10 +60,10 @@ public class I2PDActivity extends Activity {
|
||||
}
|
||||
DaemonSingleton.State state = daemon.getState();
|
||||
textView.setText(
|
||||
String.valueOf(state)+
|
||||
(DaemonSingleton.State.startFailed.equals(state)?": "+daemon.getDaemonStartResult():"")+
|
||||
(DaemonSingleton.State.gracefulShutdownInProgress.equals(state)?": "+formatGraceTimeRemaining()+" "+getText(R.string.remaining):"")
|
||||
);
|
||||
String.valueOf(state)+
|
||||
(DaemonSingleton.State.startFailed.equals(state)?": "+daemon.getDaemonStartResult():"")+
|
||||
(DaemonSingleton.State.gracefulShutdownInProgress.equals(state)?": "+formatGraceTimeRemaining()+" "+getText(R.string.remaining):"")
|
||||
);
|
||||
} catch (Throwable tr) {
|
||||
Log.e(TAG,"error ignored",tr);
|
||||
}
|
||||
@@ -55,121 +71,120 @@ public class I2PDActivity extends Activity {
|
||||
});
|
||||
}
|
||||
};
|
||||
private static volatile long graceStartedMillis;
|
||||
private static final Object graceStartedMillis_LOCK=new Object();
|
||||
private static volatile long graceStartedMillis;
|
||||
private static final Object graceStartedMillis_LOCK=new Object();
|
||||
|
||||
private static String formatGraceTimeRemaining() {
|
||||
long remainingSeconds;
|
||||
synchronized (graceStartedMillis_LOCK){
|
||||
remainingSeconds=Math.round(Math.max(0,graceStartedMillis+GRACEFUL_DELAY_MILLIS-System.currentTimeMillis())/1000.0D);
|
||||
}
|
||||
long remainingMinutes=(long)Math.floor(remainingSeconds/60.0D);
|
||||
long remSec=remainingSeconds-remainingMinutes*60;
|
||||
return remainingMinutes+":"+(remSec/10)+remSec%10;
|
||||
}
|
||||
private static String formatGraceTimeRemaining() {
|
||||
long remainingSeconds;
|
||||
synchronized (graceStartedMillis_LOCK){
|
||||
remainingSeconds=Math.round(Math.max(0,graceStartedMillis+GRACEFUL_DELAY_MILLIS-System.currentTimeMillis())/1000.0D);
|
||||
}
|
||||
long remainingMinutes=(long)Math.floor(remainingSeconds/60.0D);
|
||||
long remSec=remainingSeconds-remainingMinutes*60;
|
||||
return remainingMinutes+":"+(remSec/10)+remSec%10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
textView = new TextView(this);
|
||||
setContentView(textView);
|
||||
daemon.addStateChangeListener(daemonStateUpdatedListener);
|
||||
daemonStateUpdatedListener.daemonStateUpdate();
|
||||
textView = new TextView(this);
|
||||
setContentView(textView);
|
||||
daemon.addStateChangeListener(daemonStateUpdatedListener);
|
||||
daemonStateUpdatedListener.daemonStateUpdate();
|
||||
|
||||
//set the app be foreground
|
||||
doBindService();
|
||||
// set the app be foreground
|
||||
doBindService();
|
||||
|
||||
final Timer gracefulQuitTimer = getGracefulQuitTimer();
|
||||
if(gracefulQuitTimer!=null){
|
||||
long gracefulStopAtMillis;
|
||||
synchronized (graceStartedMillis_LOCK) {
|
||||
gracefulStopAtMillis = graceStartedMillis + GRACEFUL_DELAY_MILLIS;
|
||||
}
|
||||
rescheduleGraceStop(gracefulQuitTimer, gracefulStopAtMillis);
|
||||
}
|
||||
}
|
||||
final Timer gracefulQuitTimer = getGracefulQuitTimer();
|
||||
if(gracefulQuitTimer!=null){
|
||||
long gracefulStopAtMillis;
|
||||
synchronized (graceStartedMillis_LOCK) {
|
||||
gracefulStopAtMillis = graceStartedMillis + GRACEFUL_DELAY_MILLIS;
|
||||
}
|
||||
rescheduleGraceStop(gracefulQuitTimer, gracefulStopAtMillis);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
textView = null;
|
||||
daemon.removeStateChangeListener(daemonStateUpdatedListener);
|
||||
//cancelGracefulStop();
|
||||
textView = null;
|
||||
daemon.removeStateChangeListener(daemonStateUpdatedListener);
|
||||
//cancelGracefulStop();
|
||||
try{
|
||||
doUnbindService();
|
||||
}catch(Throwable tr){
|
||||
doUnbindService();
|
||||
}catch(Throwable tr){
|
||||
Log.e(TAG, "", tr);
|
||||
}
|
||||
}
|
||||
|
||||
private static void cancelGracefulStop() {
|
||||
Timer gracefulQuitTimer = getGracefulQuitTimer();
|
||||
if(gracefulQuitTimer!=null) {
|
||||
gracefulQuitTimer.cancel();
|
||||
setGracefulQuitTimer(null);
|
||||
}
|
||||
}
|
||||
|
||||
private CharSequence throwableToString(Throwable tr) {
|
||||
StringWriter sw = new StringWriter(8192);
|
||||
PrintWriter pw = new PrintWriter(sw);
|
||||
tr.printStackTrace(pw);
|
||||
pw.close();
|
||||
return sw.toString();
|
||||
private static void cancelGracefulStop() {
|
||||
Timer gracefulQuitTimer = getGracefulQuitTimer();
|
||||
if(gracefulQuitTimer!=null) {
|
||||
gracefulQuitTimer.cancel();
|
||||
setGracefulQuitTimer(null);
|
||||
}
|
||||
}
|
||||
|
||||
// private LocalService mBoundService;
|
||||
private CharSequence throwableToString(Throwable tr) {
|
||||
StringWriter sw = new StringWriter(8192);
|
||||
PrintWriter pw = new PrintWriter(sw);
|
||||
tr.printStackTrace(pw);
|
||||
pw.close();
|
||||
return sw.toString();
|
||||
}
|
||||
|
||||
private ServiceConnection mConnection = new ServiceConnection() {
|
||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||
// This is called when the connection with the service has been
|
||||
// established, giving us the service object we can use to
|
||||
// interact with the service. Because we have bound to a explicit
|
||||
// service that we know is running in our own process, we can
|
||||
// cast its IBinder to a concrete class and directly access it.
|
||||
// mBoundService = ((LocalService.LocalBinder)service).getService();
|
||||
// private LocalService mBoundService;
|
||||
|
||||
// Tell the user about this for our demo.
|
||||
// Toast.makeText(Binding.this, R.string.local_service_connected,
|
||||
// Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
private ServiceConnection mConnection = new ServiceConnection() {
|
||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||
// This is called when the connection with the service has been
|
||||
// established, giving us the service object we can use to
|
||||
// interact with the service. Because we have bound to a explicit
|
||||
// service that we know is running in our own process, we can
|
||||
// cast its IBinder to a concrete class and directly access it.
|
||||
// mBoundService = ((LocalService.LocalBinder)service).getService();
|
||||
|
||||
public void onServiceDisconnected(ComponentName className) {
|
||||
// This is called when the connection with the service has been
|
||||
// unexpectedly disconnected -- that is, its process crashed.
|
||||
// Because it is running in our same process, we should never
|
||||
// see this happen.
|
||||
// mBoundService = null;
|
||||
// Toast.makeText(Binding.this, R.string.local_service_disconnected,
|
||||
// Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
};
|
||||
// Tell the user about this for our demo.
|
||||
// Toast.makeText(Binding.this, R.string.local_service_connected,
|
||||
// Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
public void onServiceDisconnected(ComponentName className) {
|
||||
// This is called when the connection with the service has been
|
||||
// unexpectedly disconnected -- that is, its process crashed.
|
||||
// Because it is running in our same process, we should never
|
||||
// see this happen.
|
||||
// mBoundService = null;
|
||||
// Toast.makeText(Binding.this, R.string.local_service_disconnected,
|
||||
// Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
};
|
||||
|
||||
private static volatile boolean mIsBound;
|
||||
private static volatile boolean mIsBound;
|
||||
|
||||
private void doBindService() {
|
||||
synchronized (I2PDActivity.class) {
|
||||
if (mIsBound) return;
|
||||
// Establish a connection with the service. We use an explicit
|
||||
// class name because we want a specific service implementation that
|
||||
// we know will be running in our own process (and thus won't be
|
||||
// supporting component replacement by other applications).
|
||||
bindService(new Intent(this, ForegroundService.class), mConnection, Context.BIND_AUTO_CREATE);
|
||||
mIsBound = true;
|
||||
}
|
||||
}
|
||||
private void doBindService() {
|
||||
synchronized (I2PDActivity.class) {
|
||||
if (mIsBound) return;
|
||||
// Establish a connection with the service. We use an explicit
|
||||
// class name because we want a specific service implementation that
|
||||
// we know will be running in our own process (and thus won't be
|
||||
// supporting component replacement by other applications).
|
||||
bindService(new Intent(this, ForegroundService.class), mConnection, Context.BIND_AUTO_CREATE);
|
||||
mIsBound = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void doUnbindService() {
|
||||
synchronized (I2PDActivity.class) {
|
||||
if (mIsBound) {
|
||||
// Detach our existing connection.
|
||||
unbindService(mConnection);
|
||||
mIsBound = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
private void doUnbindService() {
|
||||
synchronized (I2PDActivity.class) {
|
||||
if (mIsBound) {
|
||||
// Detach our existing connection.
|
||||
unbindService(mConnection);
|
||||
mIsBound = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
@@ -186,100 +201,219 @@ public class I2PDActivity extends Activity {
|
||||
int id = item.getItemId();
|
||||
|
||||
switch(id){
|
||||
case R.id.action_stop:
|
||||
i2pdStop();
|
||||
return true;
|
||||
case R.id.action_graceful_stop:
|
||||
i2pdGracefulStop();
|
||||
return true;
|
||||
}
|
||||
case R.id.action_stop:
|
||||
i2pdStop();
|
||||
return true;
|
||||
case R.id.action_graceful_stop:
|
||||
i2pdGracefulStop();
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void i2pdStop() {
|
||||
cancelGracefulStop();
|
||||
new Thread(new Runnable(){
|
||||
cancelGracefulStop();
|
||||
new Thread(new Runnable(){
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Log.d(TAG, "stopping");
|
||||
try{
|
||||
daemon.stopDaemon();
|
||||
}catch (Throwable tr) {
|
||||
Log.e(TAG, "", tr);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
Log.d(TAG, "stopping");
|
||||
try{
|
||||
daemon.stopDaemon();
|
||||
}catch (Throwable tr) {
|
||||
Log.e(TAG, "", tr);
|
||||
}
|
||||
}
|
||||
|
||||
},"stop").start();
|
||||
}
|
||||
},"stop").start();
|
||||
}
|
||||
|
||||
private static volatile Timer gracefulQuitTimer;
|
||||
private static volatile Timer gracefulQuitTimer;
|
||||
|
||||
private void i2pdGracefulStop() {
|
||||
if(daemon.getState()==DaemonSingleton.State.stopped){
|
||||
Toast.makeText(this, R.string.already_stopped,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
if(getGracefulQuitTimer()!=null){
|
||||
Toast.makeText(this, R.string.graceful_stop_is_already_in_progress,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
Toast.makeText(this, R.string.graceful_stop_is_in_progress,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
new Thread(new Runnable(){
|
||||
private void i2pdGracefulStop() {
|
||||
if(daemon.getState()==DaemonSingleton.State.stopped){
|
||||
Toast.makeText(this, R.string.already_stopped,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
if(getGracefulQuitTimer()!=null){
|
||||
Toast.makeText(this, R.string.graceful_stop_is_already_in_progress,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
Toast.makeText(this, R.string.graceful_stop_is_in_progress,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
new Thread(new Runnable(){
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try{
|
||||
Log.d(TAG, "grac stopping");
|
||||
if(daemon.isStartedOkay()) {
|
||||
daemon.stopAcceptingTunnels();
|
||||
long gracefulStopAtMillis;
|
||||
synchronized (graceStartedMillis_LOCK) {
|
||||
graceStartedMillis = System.currentTimeMillis();
|
||||
gracefulStopAtMillis = graceStartedMillis + GRACEFUL_DELAY_MILLIS;
|
||||
}
|
||||
rescheduleGraceStop(null,gracefulStopAtMillis);
|
||||
}else{
|
||||
i2pdStop();
|
||||
}
|
||||
} catch(Throwable tr) {
|
||||
if(daemon.isStartedOkay()) {
|
||||
daemon.stopAcceptingTunnels();
|
||||
long gracefulStopAtMillis;
|
||||
synchronized (graceStartedMillis_LOCK) {
|
||||
graceStartedMillis = System.currentTimeMillis();
|
||||
gracefulStopAtMillis = graceStartedMillis + GRACEFUL_DELAY_MILLIS;
|
||||
}
|
||||
rescheduleGraceStop(null,gracefulStopAtMillis);
|
||||
}else{
|
||||
i2pdStop();
|
||||
}
|
||||
} catch(Throwable tr) {
|
||||
Log.e(TAG,"",tr);
|
||||
}
|
||||
}
|
||||
|
||||
},"gracInit").start();
|
||||
}
|
||||
},"gracInit").start();
|
||||
}
|
||||
|
||||
private void rescheduleGraceStop(Timer gracefulQuitTimerOld, long gracefulStopAtMillis) {
|
||||
if(gracefulQuitTimerOld!=null)gracefulQuitTimerOld.cancel();
|
||||
final Timer gracefulQuitTimer = new Timer(true);
|
||||
setGracefulQuitTimer(gracefulQuitTimer);
|
||||
gracefulQuitTimer.schedule(new TimerTask(){
|
||||
private void rescheduleGraceStop(Timer gracefulQuitTimerOld, long gracefulStopAtMillis) {
|
||||
if(gracefulQuitTimerOld!=null)gracefulQuitTimerOld.cancel();
|
||||
final Timer gracefulQuitTimer = new Timer(true);
|
||||
setGracefulQuitTimer(gracefulQuitTimer);
|
||||
gracefulQuitTimer.schedule(new TimerTask(){
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
i2pdStop();
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
i2pdStop();
|
||||
}
|
||||
|
||||
}, Math.max(0,gracefulStopAtMillis-System.currentTimeMillis()));
|
||||
final TimerTask tickerTask = new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
daemonStateUpdatedListener.daemonStateUpdate();
|
||||
}
|
||||
};
|
||||
gracefulQuitTimer.scheduleAtFixedRate(tickerTask,0/*start delay*/,1000/*millis period*/);
|
||||
}
|
||||
}, Math.max(0,gracefulStopAtMillis-System.currentTimeMillis()));
|
||||
final TimerTask tickerTask = new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
daemonStateUpdatedListener.daemonStateUpdate();
|
||||
}
|
||||
};
|
||||
gracefulQuitTimer.scheduleAtFixedRate(tickerTask,0/*start delay*/,1000/*millis period*/);
|
||||
}
|
||||
|
||||
private static Timer getGracefulQuitTimer() {
|
||||
return gracefulQuitTimer;
|
||||
private static Timer getGracefulQuitTimer() {
|
||||
return gracefulQuitTimer;
|
||||
}
|
||||
|
||||
private static void setGracefulQuitTimer(Timer gracefulQuitTimer) {
|
||||
I2PDActivity.gracefulQuitTimer = gracefulQuitTimer;
|
||||
I2PDActivity.gracefulQuitTimer = gracefulQuitTimer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the asset at the specified path to this app's data directory. If the
|
||||
* asset is a directory, its contents are also copied.
|
||||
*
|
||||
* @param path
|
||||
* Path to asset, relative to app's assets directory.
|
||||
*/
|
||||
private void copyAsset(String path) {
|
||||
AssetManager manager = getAssets();
|
||||
|
||||
// If we have a directory, we make it and recurse. If a file, we copy its
|
||||
// contents.
|
||||
try {
|
||||
String[] contents = manager.list(path);
|
||||
|
||||
// The documentation suggests that list throws an IOException, but doesn't
|
||||
// say under what conditions. It'd be nice if it did so when the path was
|
||||
// to a file. That doesn't appear to be the case. If the returned array is
|
||||
// null or has 0 length, we assume the path is to a file. This means empty
|
||||
// directories will get turned into files.
|
||||
if (contents == null || contents.length == 0)
|
||||
throw new IOException();
|
||||
|
||||
// Make the directory.
|
||||
File dir = new File(i2pdpath, path);
|
||||
dir.mkdirs();
|
||||
|
||||
// Recurse on the contents.
|
||||
for (String entry : contents) {
|
||||
copyAsset(path + "/" + entry);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
copyFileAsset(path);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the asset file specified by path to app's data directory. Assumes
|
||||
* parent directories have already been created.
|
||||
*
|
||||
* @param path
|
||||
* Path to asset, relative to app's assets directory.
|
||||
*/
|
||||
private void copyFileAsset(String path) {
|
||||
File file = new File(i2pdpath, path);
|
||||
if(!file.exists()) try {
|
||||
InputStream in = getAssets().open(path);
|
||||
OutputStream out = new FileOutputStream(file);
|
||||
byte[] buffer = new byte[1024];
|
||||
int read = in.read(buffer);
|
||||
while (read != -1) {
|
||||
out.write(buffer, 0, read);
|
||||
read = in.read(buffer);
|
||||
}
|
||||
out.close();
|
||||
in.close();
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteRecursive(File fileOrDirectory) {
|
||||
if (fileOrDirectory.isDirectory()) {
|
||||
for (File child : fileOrDirectory.listFiles()) {
|
||||
deleteRecursive(child);
|
||||
}
|
||||
}
|
||||
fileOrDirectory.delete();
|
||||
}
|
||||
|
||||
private void processAssets() {
|
||||
if (!assetsCopied) try {
|
||||
assetsCopied = true; // prevent from running on every state update
|
||||
|
||||
File holderfile = new File(i2pdpath, "assets.ready");
|
||||
String versionName = BuildConfig.VERSION_NAME; // here will be app version, like 2.XX.XX
|
||||
StringBuilder text = new StringBuilder();
|
||||
|
||||
if (holderfile.exists()) try { // if holder file exists, read assets version string
|
||||
BufferedReader br = new BufferedReader(new FileReader(holderfile));
|
||||
String line;
|
||||
|
||||
while ((line = br.readLine()) != null) {
|
||||
text.append(line);
|
||||
}
|
||||
br.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
Log.e(TAG, "", e);
|
||||
}
|
||||
|
||||
// if version differs from current app version or null, try to delete certificates folder
|
||||
if (!text.toString().contains(versionName)) try {
|
||||
holderfile.delete();
|
||||
File certpath = new File(i2pdpath, "certificates");
|
||||
deleteRecursive(certpath);
|
||||
}
|
||||
catch (Throwable tr) {
|
||||
Log.e(TAG, "", tr);
|
||||
}
|
||||
|
||||
// copy assets. If processed file exists, it won't be overwrited
|
||||
copyAsset("certificates");
|
||||
copyAsset("i2pd.conf");
|
||||
copyAsset("subscriptions.txt");
|
||||
copyAsset("tunnels.conf");
|
||||
|
||||
// update holder file about successful copying
|
||||
FileWriter writer = new FileWriter(holderfile);
|
||||
writer.append(versionName);
|
||||
writer.flush();
|
||||
writer.close();
|
||||
}
|
||||
catch (Throwable tr)
|
||||
{
|
||||
Log.e(TAG,"copy assets",tr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
18
android_binary_only/.gitignore
vendored
Normal file
18
android_binary_only/.gitignore
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
gen
|
||||
tests
|
||||
bin
|
||||
libs
|
||||
log*
|
||||
obj
|
||||
.gradle
|
||||
.idea
|
||||
.externalNativeBuild
|
||||
ant.properties
|
||||
local.properties
|
||||
build.sh
|
||||
android.iml
|
||||
build
|
||||
gradle
|
||||
gradlew
|
||||
gradlew.bat
|
||||
|
||||
@@ -26,49 +26,49 @@ include $(BUILD_EXECUTABLE)
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := boost_system
|
||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_62_0/$(TARGET_ARCH_ABI)/lib/libboost_system.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_62_0/include
|
||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_system.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := boost_date_time
|
||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_62_0/$(TARGET_ARCH_ABI)/lib/libboost_date_time.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_62_0/include
|
||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_date_time.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := boost_filesystem
|
||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_62_0/$(TARGET_ARCH_ABI)/lib/libboost_filesystem.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_62_0/include
|
||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_filesystem.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := boost_program_options
|
||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_62_0/$(TARGET_ARCH_ABI)/lib/libboost_program_options.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_62_0/include
|
||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_64_0/$(TARGET_ARCH_ABI)/lib/libboost_program_options.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_64_0/include
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := crypto
|
||||
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.0e/$(TARGET_ARCH_ABI)/lib/libcrypto.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.0e/include
|
||||
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1/$(TARGET_ARCH_ABI)/lib/libcrypto.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1/include
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := ssl
|
||||
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.0e/$(TARGET_ARCH_ABI)/lib/libssl.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.0e/include
|
||||
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1/$(TARGET_ARCH_ABI)/lib/libssl.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1/include
|
||||
LOCAL_STATIC_LIBRARIES := crypto
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := miniupnpc
|
||||
LOCAL_SRC_FILES := $(MINIUPNP_PATH)/miniupnp-2.0/$(TARGET_ARCH_ABI)/lib/libminiupnpc.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(MINIUPNP_PATH)/miniupnp-2.0/include
|
||||
LOCAL_SRC_FILES := $(MINIUPNP_PATH)/miniupnpc-2.1/$(TARGET_ARCH_ABI)/lib/libminiupnpc.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(MINIUPNP_PATH)/miniupnpc-2.1/include
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
version: 2.19.{build}
|
||||
version: 2.22.0.{build}
|
||||
pull_requests:
|
||||
do_not_increment_build_number: true
|
||||
branches:
|
||||
@@ -18,9 +18,9 @@ environment:
|
||||
|
||||
install:
|
||||
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Rns gcc-fortran gcc"
|
||||
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu "
|
||||
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu --force"
|
||||
|
||||
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu"
|
||||
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu --force"
|
||||
|
||||
- if "%MSYSTEM%" == "MINGW64" (
|
||||
c:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-x86_64-boost mingw-w64-x86_64-miniupnpc"
|
||||
|
||||
@@ -190,7 +190,7 @@ if (CXX11_SUPPORTED)
|
||||
elseif (CXX0X_SUPPORTED) # gcc 4.6
|
||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x" )
|
||||
elseif (NOT MSVC)
|
||||
message(SEND_ERROR "C++11 standart not seems to be supported by compiler. Too old version?")
|
||||
message(SEND_ERROR "C++11 standard not seems to be supported by compiler. Too old version?")
|
||||
endif ()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
@@ -202,9 +202,11 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
endif ()
|
||||
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
# more tweaks
|
||||
if (NOT (MSVC OR MSYS OR APPLE))
|
||||
if (LINUX)
|
||||
set (CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -stdlib=libstdc++" ) # required for <atomic>
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "stdc++") # required to link with -stdlib=libstdc++
|
||||
endif()
|
||||
if (NOT (MSVC OR MSYS OR APPLE))
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-const-variable -Wno-overloaded-virtual -Wno-c99-extensions" )
|
||||
endif()
|
||||
endif ()
|
||||
@@ -234,7 +236,6 @@ endif ()
|
||||
|
||||
if (WITH_AESNI)
|
||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes" )
|
||||
add_definitions ( -DAESNI )
|
||||
endif()
|
||||
|
||||
if (WITH_AVX)
|
||||
@@ -339,7 +340,7 @@ target_link_libraries(libi2pdclient libi2pd)
|
||||
|
||||
find_package ( Boost COMPONENTS system filesystem program_options date_time REQUIRED )
|
||||
if(NOT DEFINED Boost_INCLUDE_DIRS)
|
||||
message(SEND_ERROR "Boost is not found, or your boost version was bellow 1.46. Please download Boost!")
|
||||
message(SEND_ERROR "Boost is not found, or your boost version was below 1.46. Please download Boost!")
|
||||
endif()
|
||||
|
||||
find_package ( OpenSSL REQUIRED )
|
||||
|
||||
@@ -21,6 +21,8 @@ set MSYSTEM=MINGW32
|
||||
|
||||
set "xSH=%WD%bash -lc"
|
||||
|
||||
set "FILELIST=i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates contrib/tunnels.d"
|
||||
|
||||
REM detecting number of processors and subtract 1.
|
||||
set /a threads=%NUMBER_OF_PROCESSORS%-1
|
||||
|
||||
@@ -62,12 +64,12 @@ exit /b 0
|
||||
%xSH% "make clean" >> nul
|
||||
echo Building i2pd %tag% for win%bitness%:
|
||||
echo Build AVX+AESNI...
|
||||
%xSH% "make USE_UPNP=yes USE_AVX=1 USE_AESNI=1 -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw_avx_aesni.zip i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates && make clean" > build/build_win%bitness%_avx_aesni.log 2>&1
|
||||
%xSH% "make DEBUG=no USE_UPNP=yes USE_AVX=1 USE_AESNI=1 -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw_avx_aesni.zip %FILELIST% && make clean" > build/build_win%bitness%_avx_aesni_%tag%.log 2>&1
|
||||
echo Build AVX...
|
||||
%xSH% "make USE_UPNP=yes USE_AVX=1 -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw_avx.zip i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates && make clean" > build/build_win%bitness%_avx.log 2>&1
|
||||
%xSH% "make DEBUG=no USE_UPNP=yes USE_AVX=1 -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw_avx.zip %FILELIST% && make clean" > build/build_win%bitness%_avx_%tag%.log 2>&1
|
||||
echo Build AESNI...
|
||||
%xSH% "make USE_UPNP=yes USE_AESNI=1 -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw_aesni.zip i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates && make clean" > build/build_win%bitness%_aesni.log 2>&1
|
||||
%xSH% "make DEBUG=no USE_UPNP=yes USE_AESNI=1 -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw_aesni.zip %FILELIST% && make clean" > build/build_win%bitness%_aesni_%tag%.log 2>&1
|
||||
echo Build without extensions...
|
||||
%xSH% "make USE_UPNP=yes -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw.zip i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates && make clean" > build/build_win%bitness%.log 2>&1
|
||||
%xSH% "make DEBUG=no USE_UPNP=yes -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw.zip %FILELIST% && make clean" > build/build_win%bitness%_%tag%.log 2>&1
|
||||
|
||||
:EOF
|
||||
@@ -2,7 +2,7 @@ FROM alpine:latest
|
||||
LABEL authors "Mikal Villa <mikal@sigterm.no>, Darknet Villain <supervillain@riseup.net>"
|
||||
|
||||
# Expose git branch, tag and URL variables as arguments
|
||||
ARG GIT_BRANCH="master"
|
||||
ARG GIT_BRANCH="openssl"
|
||||
ENV GIT_BRANCH=${GIT_BRANCH}
|
||||
ARG GIT_TAG=""
|
||||
ENV GIT_TAG=${GIT_TAG}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
## Configuration file for a typical i2pd user
|
||||
## See https://i2pd.readthedocs.org/en/latest/configuration.html
|
||||
## See https://i2pd.readthedocs.io/en/latest/user-guide/configuration/
|
||||
## for more options you can use in this file.
|
||||
|
||||
## Lines that begin with "## " try to explain what's going on. Lines
|
||||
@@ -10,6 +10,11 @@
|
||||
## Default: ~/.i2pd/tunnels.conf or /var/lib/i2pd/tunnels.conf
|
||||
# tunconf = /var/lib/i2pd/tunnels.conf
|
||||
|
||||
## Tunnels config files path
|
||||
## Use that path to store separated tunnels in different config files.
|
||||
## Default: ~/.i2pd/tunnels.d or /var/lib/i2pd/tunnels.d
|
||||
# tunnelsdir = /var/lib/i2pd/tunnels.conf.d
|
||||
|
||||
## Where to write pidfile (don't write by default)
|
||||
# pidfile = /var/run/i2pd.pid
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ RuntimeDirectoryMode=0700
|
||||
LogsDirectory=i2pd
|
||||
LogsDirectoryMode=0700
|
||||
Type=forking
|
||||
ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service
|
||||
ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --tunnelsdir=/etc/i2pd/tunnels.conf.d --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
PIDFile=/var/run/i2pd/i2pd.pid
|
||||
### Uncomment, if auto restart needed
|
||||
@@ -23,8 +23,10 @@ KillSignal=SIGQUIT
|
||||
#KillSignal=SIGINT
|
||||
#TimeoutStopSec=10m
|
||||
|
||||
# If you have problems with hanging i2pd, you can try enable this
|
||||
# If you have problems with hanging i2pd, you can try increase this
|
||||
LimitNOFILE=4096
|
||||
# To enable write of coredump uncomment this
|
||||
#LimitCORE=infinity
|
||||
PrivateDevices=yes
|
||||
|
||||
[Install]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
%define git_hash %(git rev-parse HEAD | cut -c -7)
|
||||
|
||||
Name: i2pd-git
|
||||
Version: 2.19.0
|
||||
Version: 2.22.0
|
||||
Release: git%{git_hash}%{?dist}
|
||||
Summary: I2P router written in C++
|
||||
Conflicts: i2pd
|
||||
@@ -60,11 +60,14 @@ install -D -m 755 i2pd %{buildroot}%{_sbindir}/i2pd
|
||||
install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf
|
||||
install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/tunnels.conf %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf
|
||||
install -d -m 755 %{buildroot}%{_datadir}/i2pd
|
||||
install -d -m 755 %{buildroot}%{_datadir}/i2pd/tunnels.conf.d
|
||||
%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/certificates/ %{buildroot}%{_datadir}/i2pd/certificates
|
||||
%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/tunnels.d/ %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf.d
|
||||
install -D -m 644 %{_builddir}/%{name}-%{version}/contrib/rpm/i2pd.service %{buildroot}%{_unitdir}/i2pd.service
|
||||
install -d -m 700 %{buildroot}%{_sharedstatedir}/i2pd
|
||||
install -d -m 700 %{buildroot}%{_localstatedir}/log/i2pd
|
||||
ln -s %{_datadir}/%{name}/certificates %{buildroot}%{_sharedstatedir}/i2pd/certificates
|
||||
ln -s %{_datadir}/i2pd/tunnels.conf.d %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf.d
|
||||
|
||||
|
||||
%pre
|
||||
@@ -91,6 +94,7 @@ getent passwd i2pd >/dev/null || \
|
||||
%{_sbindir}/i2pd
|
||||
%{_datadir}/i2pd/certificates
|
||||
%config(noreplace) %{_sysconfdir}/i2pd/*
|
||||
%config(noreplace) %{_sysconfdir}/i2pd/tunnels.conf.d/*
|
||||
/%{_unitdir}/i2pd.service
|
||||
%dir %attr(0700,i2pd,i2pd) %{_localstatedir}/log/i2pd
|
||||
%dir %attr(0700,i2pd,i2pd) %{_sharedstatedir}/i2pd
|
||||
@@ -98,5 +102,8 @@ getent passwd i2pd >/dev/null || \
|
||||
|
||||
|
||||
%changelog
|
||||
* Fri Nov 09 2018 r4sas <r4sas@i2pmail.org> - 2.22.0
|
||||
- add support of tunnelsdir option
|
||||
|
||||
* Thu Feb 01 2018 r4sas <r4sas@i2pmail.org> - 2.18.0
|
||||
- Initial i2pd-git based on i2pd 2.18.0-1 spec
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Name: i2pd
|
||||
Version: 2.19.0
|
||||
Version: 2.22.0
|
||||
Release: 1%{?dist}
|
||||
Summary: I2P router written in C++
|
||||
Conflicts: i2pd-git
|
||||
@@ -58,11 +58,14 @@ install -D -m 755 i2pd %{buildroot}%{_sbindir}/i2pd
|
||||
install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf
|
||||
install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/tunnels.conf %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf
|
||||
install -d -m 755 %{buildroot}%{_datadir}/i2pd
|
||||
install -d -m 755 %{buildroot}%{_datadir}/i2pd/tunnels.conf.d
|
||||
%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/certificates/ %{buildroot}%{_datadir}/i2pd/certificates
|
||||
%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/tunnels.d/ %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf.d
|
||||
install -D -m 644 %{_builddir}/%{name}-%{version}/contrib/rpm/i2pd.service %{buildroot}%{_unitdir}/i2pd.service
|
||||
install -d -m 700 %{buildroot}%{_sharedstatedir}/i2pd
|
||||
install -d -m 700 %{buildroot}%{_localstatedir}/log/i2pd
|
||||
ln -s %{_datadir}/%{name}/certificates %{buildroot}%{_sharedstatedir}/i2pd/certificates
|
||||
ln -s %{_datadir}/i2pd/tunnels.conf.d %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf.d
|
||||
|
||||
|
||||
%pre
|
||||
@@ -89,6 +92,7 @@ getent passwd i2pd >/dev/null || \
|
||||
%{_sbindir}/i2pd
|
||||
%{_datadir}/i2pd/certificates
|
||||
%config(noreplace) %{_sysconfdir}/i2pd/*
|
||||
%config(noreplace) %{_sysconfdir}/i2pd/tunnels.conf.d/*
|
||||
/%{_unitdir}/i2pd.service
|
||||
%dir %attr(0700,i2pd,i2pd) %{_localstatedir}/log/i2pd
|
||||
%dir %attr(0700,i2pd,i2pd) %{_sharedstatedir}/i2pd
|
||||
@@ -96,6 +100,19 @@ getent passwd i2pd >/dev/null || \
|
||||
|
||||
|
||||
%changelog
|
||||
* Fri Nov 09 2018 r4sas <r4sas@i2pmail.org> - 2.22.0
|
||||
- update to 2.22.0
|
||||
- add support of tunnelsdir option
|
||||
|
||||
* Thu Oct 22 2018 orignal <i2porignal@yandex.ru> - 2.21.1
|
||||
- update to 2.21.1
|
||||
|
||||
* Thu Oct 4 2018 orignal <i2porignal@yandex.ru> - 2.21.0
|
||||
- update to 2.21.0
|
||||
|
||||
* Thu Aug 23 2018 orignal <i2porignal@yandex.ru> - 2.20.0
|
||||
- update to 2.20.0
|
||||
|
||||
* Tue Jun 26 2018 orignal <i2porignal@yandex.ru> - 2.19.0
|
||||
- update to 2.19.0
|
||||
|
||||
|
||||
7
contrib/tunnels.d/IRC-Ilita.conf
Normal file
7
contrib/tunnels.d/IRC-Ilita.conf
Normal file
@@ -0,0 +1,7 @@
|
||||
#[IRC-ILITA]
|
||||
#type = client
|
||||
#address = 127.0.0.1
|
||||
#port = 6669
|
||||
#destination = irc.ilita.i2p
|
||||
#destinationport = 6667
|
||||
#keys = irc-keys.dat
|
||||
7
contrib/tunnels.d/IRC-Irc2P.conf
Normal file
7
contrib/tunnels.d/IRC-Irc2P.conf
Normal file
@@ -0,0 +1,7 @@
|
||||
#[IRC-IRC2P]
|
||||
#type = client
|
||||
#address = 127.0.0.1
|
||||
#port = 6668
|
||||
#destination = irc.postman.i2p
|
||||
#destinationport = 6667
|
||||
#keys = irc-keys.dat
|
||||
1
contrib/tunnels.d/README
Normal file
1
contrib/tunnels.d/README
Normal file
@@ -0,0 +1 @@
|
||||
In that directory you can store separated config files for every tunnel.
|
||||
@@ -152,6 +152,19 @@ namespace i2p
|
||||
i2p::context.SetSupportsV6 (ipv6);
|
||||
i2p::context.SetSupportsV4 (ipv4);
|
||||
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||
if (ntcp2)
|
||||
{
|
||||
bool published; i2p::config::GetOption("ntcp2.published", published);
|
||||
if (published)
|
||||
{
|
||||
uint16_t port; i2p::config::GetOption("ntcp2.port", port);
|
||||
i2p::context.PublishNTCP2Address (port, true); // publish
|
||||
}
|
||||
else
|
||||
i2p::context.PublishNTCP2Address (port, false); // unpublish
|
||||
}
|
||||
|
||||
bool transit; i2p::config::GetOption("notransit", transit);
|
||||
i2p::context.SetAcceptsTunnels (!transit);
|
||||
uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels);
|
||||
@@ -276,9 +289,10 @@ namespace i2p
|
||||
if(!ntcp) LogPrint(eLogInfo, "Daemon: ntcp disabled");
|
||||
|
||||
i2p::transport::transports.Start(ntcp, ssu);
|
||||
if (i2p::transport::transports.IsBoundNTCP() || i2p::transport::transports.IsBoundSSU()) {
|
||||
if (i2p::transport::transports.IsBoundNTCP() || i2p::transport::transports.IsBoundSSU() || i2p::transport::transports.IsBoundNTCP2())
|
||||
LogPrint(eLogInfo, "Daemon: Transports started");
|
||||
} else {
|
||||
else
|
||||
{
|
||||
LogPrint(eLogError, "Daemon: failed to start Transports");
|
||||
/** shut down netdb right away */
|
||||
i2p::transport::transports.Stop();
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include "Base.h"
|
||||
#include "FS.h"
|
||||
@@ -91,6 +92,8 @@ namespace http {
|
||||
const char HTTP_PARAM_SAM_SESSION_ID[] = "id";
|
||||
const char HTTP_PARAM_ADDRESS[] = "address";
|
||||
|
||||
static std::string ConvertTime (uint64_t time);
|
||||
|
||||
static void ShowUptime (std::stringstream& s, int seconds)
|
||||
{
|
||||
int num;
|
||||
@@ -259,17 +262,26 @@ namespace http {
|
||||
s << "<b>Our external address:</b>" << "<br>\r\n" ;
|
||||
for (const auto& address : i2p::context.GetRouterInfo().GetAddresses())
|
||||
{
|
||||
if (address->IsNTCP2 () && !address->IsPublishedNTCP2 ())
|
||||
{
|
||||
s << "NTCP2";
|
||||
if (address->host.is_v6 ()) s << "v6";
|
||||
s << " supported <br>\r\n";
|
||||
continue;
|
||||
}
|
||||
switch (address->transportStyle)
|
||||
{
|
||||
case i2p::data::RouterInfo::eTransportNTCP:
|
||||
if (address->host.is_v6 ())
|
||||
s << "NTCP6 ";
|
||||
else
|
||||
s << "NTCP ";
|
||||
break;
|
||||
{
|
||||
s << "NTCP";
|
||||
if (address->IsPublishedNTCP2 ()) s << "2";
|
||||
if (address->host.is_v6 ()) s << "v6";
|
||||
s << " ";
|
||||
break;
|
||||
}
|
||||
case i2p::data::RouterInfo::eTransportSSU:
|
||||
if (address->host.is_v6 ())
|
||||
s << "SSU6 ";
|
||||
s << "SSUv6 ";
|
||||
else
|
||||
s << "SSU ";
|
||||
break;
|
||||
@@ -369,10 +381,12 @@ namespace http {
|
||||
s << "<br>\r\n";
|
||||
s << "<b>Tags</b><br>Incoming: <i>" << dest->GetNumIncomingTags () << "</i><br>";
|
||||
if (!dest->GetSessions ().empty ()) {
|
||||
s << "<div class='slide'><label for='slide-tags'>Outgoing:</label>\r\n<input type='checkbox' id='slide-tags'/>\r\n<p class='content'>\r\n";
|
||||
for (const auto& it: dest->GetSessions ())
|
||||
s << i2p::client::context.GetAddressBook ().ToAddress(it.first) << " " << it.second->GetNumOutgoingTags () << "<br>\r\n";
|
||||
s << "</p>\r\n</div>\r\n";
|
||||
std::stringstream tmp_s; uint32_t out_tags = 0;
|
||||
for (const auto& it: dest->GetSessions ()) {
|
||||
tmp_s << i2p::client::context.GetAddressBook ().ToAddress(it.first) << " " << it.second->GetNumOutgoingTags () << "<br>\r\n";
|
||||
out_tags = out_tags + it.second->GetNumOutgoingTags ();
|
||||
}
|
||||
s << "<div class='slide'><label for='slide-tags'>Outgoing: <i>" << out_tags << "</i></label>\r\n<input type='checkbox' id='slide-tags'/>\r\n<p class='content'>\r\n" << tmp_s.str () << "</p>\r\n</div>\r\n";
|
||||
} else
|
||||
s << "Outgoing: <i>0</i><br>\r\n";
|
||||
s << "<br>\r\n";
|
||||
@@ -454,14 +468,14 @@ namespace http {
|
||||
s << "<div class='invalid'>!! Invalid !! </div>\r\n";
|
||||
s << "<div class='slide'><label for='slide" << counter << "'>" << dest.ToBase32() << "</label>\r\n";
|
||||
s << "<input type='checkbox' id='slide" << (counter++) << "'/>\r\n<p class='content'>\r\n";
|
||||
s << "<b>Expires:</b> " << ls.GetExpirationTime() << "<br>\r\n";
|
||||
s << "<b>Expires:</b> " << ConvertTime(ls.GetExpirationTime()) << "<br>\r\n";
|
||||
auto leases = ls.GetNonExpiredLeases();
|
||||
s << "<b>Non Expired Leases: " << leases.size() << "</b><br>\r\n";
|
||||
for ( auto & l : leases )
|
||||
{
|
||||
s << "<b>Gateway:</b> " << l->tunnelGateway.ToBase64() << "<br>\r\n";
|
||||
s << "<b>TunnelID:</b> " << l->tunnelID << "<br>\r\n";
|
||||
s << "<b>EndDate:</b> " << l->endDate << "<br>\r\n";
|
||||
s << "<b>EndDate:</b> " << ConvertTime(l->endDate) << "<br>\r\n";
|
||||
}
|
||||
s << "</p>\r\n</div>\r\n</div>\r\n";
|
||||
}
|
||||
@@ -540,6 +554,46 @@ namespace http {
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Sessions>
|
||||
static void ShowNTCPTransports (std::stringstream& s, const Sessions& sessions, const std::string name)
|
||||
{
|
||||
std::stringstream tmp_s, tmp_s6; uint16_t cnt = 0, cnt6 = 0;
|
||||
for (const auto& it: sessions )
|
||||
{
|
||||
if (it.second && it.second->IsEstablished () && !it.second->GetSocket ().remote_endpoint ().address ().is_v6 ())
|
||||
{
|
||||
// incoming connection doesn't have remote RI
|
||||
if (it.second->IsOutgoing ()) tmp_s << " ⇒ ";
|
||||
tmp_s << i2p::data::GetIdentHashAbbreviation (it.second->GetRemoteIdentity ()->GetIdentHash ()) << ": "
|
||||
<< it.second->GetSocket ().remote_endpoint().address ().to_string ();
|
||||
if (!it.second->IsOutgoing ()) tmp_s << " ⇒ ";
|
||||
tmp_s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
|
||||
tmp_s << "<br>\r\n" << std::endl;
|
||||
cnt++;
|
||||
}
|
||||
if (it.second && it.second->IsEstablished () && it.second->GetSocket ().remote_endpoint ().address ().is_v6 ())
|
||||
{
|
||||
if (it.second->IsOutgoing ()) tmp_s6 << " ⇒ ";
|
||||
tmp_s6 << i2p::data::GetIdentHashAbbreviation (it.second->GetRemoteIdentity ()->GetIdentHash ()) << ": "
|
||||
<< "[" << it.second->GetSocket ().remote_endpoint().address ().to_string () << "]";
|
||||
if (!it.second->IsOutgoing ()) tmp_s6 << " ⇒ ";
|
||||
tmp_s6 << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
|
||||
tmp_s6 << "<br>\r\n" << std::endl;
|
||||
cnt6++;
|
||||
}
|
||||
}
|
||||
if (!tmp_s.str ().empty ())
|
||||
{
|
||||
s << "<div class='slide'><label for='slide_" << boost::algorithm::to_lower_copy(name) << "'><b>" << name << "</b> ( " << cnt << " )</label>\r\n<input type='checkbox' id='slide_" << boost::algorithm::to_lower_copy(name) << "'/>\r\n<p class='content'>";
|
||||
s << tmp_s.str () << "</p>\r\n</div>\r\n";
|
||||
}
|
||||
if (!tmp_s6.str ().empty ())
|
||||
{
|
||||
s << "<div class='slide'><label for='slide_" << boost::algorithm::to_lower_copy(name) << "v6'><b>" << name << "v6</b> ( " << cnt6 << " )</label>\r\n<input type='checkbox' id='slide_" << boost::algorithm::to_lower_copy(name) << "v6'/>\r\n<p class='content'>";
|
||||
s << tmp_s6.str () << "</p>\r\n</div>\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
void ShowTransports (std::stringstream& s)
|
||||
{
|
||||
s << "<b>Transports:</b><br>\r\n<br>\r\n";
|
||||
@@ -548,43 +602,14 @@ namespace http {
|
||||
{
|
||||
auto sessions = ntcpServer->GetNTCPSessions ();
|
||||
if (!sessions.empty ())
|
||||
{
|
||||
std::stringstream tmp_s, tmp_s6; uint16_t cnt = 0, cnt6 = 0;
|
||||
for (const auto& it: sessions )
|
||||
{
|
||||
if (it.second && it.second->IsEstablished () && !it.second->GetSocket ().remote_endpoint ().address ().is_v6 ())
|
||||
{
|
||||
// incoming connection doesn't have remote RI
|
||||
if (it.second->IsOutgoing ()) tmp_s << " ⇒ ";
|
||||
tmp_s << i2p::data::GetIdentHashAbbreviation (it.second->GetRemoteIdentity ()->GetIdentHash ()) << ": "
|
||||
<< it.second->GetSocket ().remote_endpoint().address ().to_string ();
|
||||
if (!it.second->IsOutgoing ()) tmp_s << " ⇒ ";
|
||||
tmp_s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
|
||||
tmp_s << "<br>\r\n" << std::endl;
|
||||
cnt++;
|
||||
}
|
||||
if (it.second && it.second->IsEstablished () && it.second->GetSocket ().remote_endpoint ().address ().is_v6 ())
|
||||
{
|
||||
if (it.second->IsOutgoing ()) tmp_s6 << " ⇒ ";
|
||||
tmp_s6 << i2p::data::GetIdentHashAbbreviation (it.second->GetRemoteIdentity ()->GetIdentHash ()) << ": "
|
||||
<< "[" << it.second->GetSocket ().remote_endpoint().address ().to_string () << "]";
|
||||
if (!it.second->IsOutgoing ()) tmp_s6 << " ⇒ ";
|
||||
tmp_s6 << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
|
||||
tmp_s6 << "<br>\r\n" << std::endl;
|
||||
cnt6++;
|
||||
}
|
||||
}
|
||||
if (!tmp_s.str ().empty ())
|
||||
{
|
||||
s << "<div class='slide'><label for='slide_ntcp'><b>NTCP</b> ( " << cnt << " )</label>\r\n<input type='checkbox' id='slide_ntcp'/>\r\n<p class='content'>";
|
||||
s << tmp_s.str () << "</p>\r\n</div>\r\n";
|
||||
}
|
||||
if (!tmp_s6.str ().empty ())
|
||||
{
|
||||
s << "<div class='slide'><label for='slide_ntcp6'><b>NTCP6</b> ( " << cnt6 << " )</label>\r\n<input type='checkbox' id='slide_ntcp6'/>\r\n<p class='content'>";
|
||||
s << tmp_s6.str () << "</p>\r\n</div>\r\n";
|
||||
}
|
||||
}
|
||||
ShowNTCPTransports (s, sessions, "NTCP");
|
||||
}
|
||||
auto ntcp2Server = i2p::transport::transports.GetNTCP2Server ();
|
||||
if (ntcp2Server)
|
||||
{
|
||||
auto sessions = ntcp2Server->GetNTCP2Sessions ();
|
||||
if (!sessions.empty ())
|
||||
ShowNTCPTransports (s, sessions, "NTCP2");
|
||||
}
|
||||
auto ssuServer = i2p::transport::transports.GetSSUServer ();
|
||||
if (ssuServer)
|
||||
@@ -609,7 +634,7 @@ namespace http {
|
||||
auto sessions6 = ssuServer->GetSessionsV6 ();
|
||||
if (!sessions6.empty ())
|
||||
{
|
||||
s << "<div class='slide'><label for='slide_ssu6'><b>SSU6</b> ( " << (int) sessions6.size() << " )</label>\r\n<input type='checkbox' id='slide_ssu6'/>\r\n<p class='content'>";
|
||||
s << "<div class='slide'><label for='slide_ssuv6'><b>SSUv6</b> ( " << (int) sessions6.size() << " )</label>\r\n<input type='checkbox' id='slide_ssuv6'/>\r\n<p class='content'>";
|
||||
for (const auto& it: sessions6)
|
||||
{
|
||||
auto endpoint = it.second->GetRemoteEndpoint ();
|
||||
@@ -744,6 +769,16 @@ namespace http {
|
||||
}
|
||||
}
|
||||
|
||||
std::string ConvertTime (uint64_t time)
|
||||
{
|
||||
ldiv_t divTime = ldiv(time,1000);
|
||||
time_t t = divTime.quot;
|
||||
struct tm *tm = localtime(&t);
|
||||
char date[128];
|
||||
snprintf(date, sizeof(date), "%02d/%02d/%d %02d:%02d:%02d.%03ld", tm->tm_mday, tm->tm_mon + 1, tm->tm_year + 1900, tm->tm_hour, tm->tm_min, tm->tm_sec, divTime.rem);
|
||||
return date;
|
||||
}
|
||||
|
||||
HTTPConnection::HTTPConnection (std::string hostname, std::shared_ptr<boost::asio::ip::tcp::socket> socket):
|
||||
m_Socket (socket), m_Timer (socket->get_io_service ()), m_BufferLen (0),
|
||||
expected_host(hostname)
|
||||
@@ -862,7 +897,7 @@ namespace http {
|
||||
{
|
||||
/* deny request as it's from a non whitelisted hostname */
|
||||
res.code = 403;
|
||||
content = "host missmatch";
|
||||
content = "host mismatch";
|
||||
SendReply(res, content);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -131,8 +131,8 @@ namespace transport
|
||||
const auto& a = context.GetRouterInfo().GetAddresses();
|
||||
for (const auto& address : a)
|
||||
{
|
||||
if (!address->host.is_v6 ())
|
||||
TryPortMapping (address);
|
||||
if (!address->host.is_v6 () && address->port)
|
||||
TryPortMapping (address);
|
||||
}
|
||||
m_Timer.expires_from_now (boost::posix_time::minutes(20)); // every 20 minutes
|
||||
m_Timer.async_wait ([this](const boost::system::error_code& ecode)
|
||||
@@ -148,7 +148,7 @@ namespace transport
|
||||
const auto& a = context.GetRouterInfo().GetAddresses();
|
||||
for (const auto& address : a)
|
||||
{
|
||||
if (!address->host.is_v6 ())
|
||||
if (!address->host.is_v6 () && address->port)
|
||||
CloseMapping (address);
|
||||
}
|
||||
}
|
||||
|
||||
4
debian/.gitignore
vendored
4
debian/.gitignore
vendored
@@ -1,9 +1,9 @@
|
||||
debhelper-build-stamp
|
||||
files
|
||||
i2pd-dbg.substvars
|
||||
i2pd-dbg/
|
||||
i2pd.postinst.debhelper
|
||||
i2pd.postrm.debhelper
|
||||
i2pd.prerm.debhelper
|
||||
i2pd.substvars
|
||||
i2pd/
|
||||
|
||||
i2pd-dbg/
|
||||
|
||||
27
debian/changelog
vendored
27
debian/changelog
vendored
@@ -1,3 +1,30 @@
|
||||
i2pd (2.22.0-1) unstable; urgency=medium
|
||||
|
||||
* updated to version 2.22.0/0.9.37
|
||||
* update manpage (1)
|
||||
* update links, install files to support tunnelsdir option
|
||||
* renamed and updated patch (#1210)
|
||||
|
||||
-- r4sas <r4sas@i2pmail.org> Fri, 09 Nov 2018 02:00:00 +0000
|
||||
|
||||
i2pd (2.21.1-1) unstable; urgency=medium
|
||||
|
||||
* updated to version 2.21.1
|
||||
|
||||
-- orignal <orignal@i2pmail.org> Thu, 22 Oct 2018 16:00:00 +0000
|
||||
|
||||
i2pd (2.21.0-1) unstable; urgency=medium
|
||||
|
||||
* updated to version 2.21.0/0.9.37
|
||||
|
||||
-- orignal <orignal@i2pmail.org> Thu, 4 Oct 2018 16:00:00 +0000
|
||||
|
||||
i2pd (2.20.0-1) unstable; urgency=medium
|
||||
|
||||
* updated to version 2.20.0/0.9.36
|
||||
|
||||
-- orignal <orignal@i2pmail.org> Thu, 23 Aug 2018 16:00:00 +0000
|
||||
|
||||
i2pd (2.19.0-1) unstable; urgency=medium
|
||||
|
||||
* updated to version 2.19.0/0.9.35
|
||||
|
||||
2
debian/control
vendored
2
debian/control
vendored
@@ -1,7 +1,7 @@
|
||||
Source: i2pd
|
||||
Section: net
|
||||
Priority: optional
|
||||
Maintainer: R4SAS <r4sas@i2pmail.org>
|
||||
Maintainer: r4sas <r4sas@i2pmail.org>
|
||||
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: 3.9.6
|
||||
Homepage: http://i2pd.website/
|
||||
|
||||
5
debian/i2pd.1
vendored
5
debian/i2pd.1
vendored
@@ -45,6 +45,9 @@ Log messages with full CLF-formatted date and time (\fIdisabled\fR by default)
|
||||
\fB\-\-datadir=\fR
|
||||
Path to storage of i2pd data (RI, keys, peer profiles, ...)
|
||||
.TP
|
||||
\fB\-\-tunnelsdir=\fR
|
||||
Path to tunnels configuration files (default: \fI~/.i2pd/tunnels.d\fR or \fI/var/lib/i2pd/tunnels.d\fR)
|
||||
.TP
|
||||
\fB\-\-host=\fR
|
||||
The external IP address
|
||||
.TP
|
||||
@@ -96,7 +99,7 @@ Router will use system folders like \fI/var/lib/i2pd\fR (\fIdisabled\fR by defau
|
||||
\fB\-\-family=\fR
|
||||
Name of a family, router belongs to.
|
||||
.PP
|
||||
Switchs, which enabled by default (like \fB\-\-ssu\fR, \fB\-\-ntcp\fR, etc.), can be disabled in config file.
|
||||
Switches, which enabled by default (like \fB\-\-ssu\fR, \fB\-\-ntcp\fR, etc.), can be disabled in config file.
|
||||
.RE
|
||||
See service-specific parameters in example config file \fI/usr/share/doc/i2pd/i2pd.conf.gz\fR
|
||||
.SH "FILES"
|
||||
|
||||
1
debian/i2pd.dirs
vendored
1
debian/i2pd.dirs
vendored
@@ -1,2 +1,3 @@
|
||||
etc/i2pd
|
||||
etc/i2pd/tunnels.conf.d
|
||||
var/lib/i2pd
|
||||
|
||||
3
debian/i2pd.init
vendored
3
debian/i2pd.init
vendored
@@ -18,6 +18,7 @@ DAEMON_OPTS="" # Arguments to run the daemon with
|
||||
PIDFILE=/var/run/$NAME/$NAME.pid
|
||||
I2PCONF=/etc/$NAME/i2pd.conf
|
||||
TUNCONF=/etc/$NAME/tunnels.conf
|
||||
TUNDIR=/etc/$NAME/tunnels.conf.d
|
||||
LOGFILE=/var/log/$NAME/$NAME.log
|
||||
USER="i2pd"
|
||||
|
||||
@@ -53,7 +54,7 @@ do_start()
|
||||
|| return 1
|
||||
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --chuid "$USER" -- \
|
||||
--service --daemon --log=file --logfile=$LOGFILE --conf=$I2PCONF --tunconf=$TUNCONF \
|
||||
--pidfile=$PIDFILE $DAEMON_OPTS > /dev/null 2>&1 \
|
||||
--tunnelsdir=$TUNDIR --pidfile=$PIDFILE $DAEMON_OPTS > /dev/null 2>&1 \
|
||||
|| return 2
|
||||
return $?
|
||||
}
|
||||
|
||||
1
debian/i2pd.install
vendored
1
debian/i2pd.install
vendored
@@ -3,4 +3,5 @@ contrib/i2pd.conf etc/i2pd/
|
||||
contrib/tunnels.conf etc/i2pd/
|
||||
contrib/subscriptions.txt etc/i2pd/
|
||||
contrib/certificates/ usr/share/i2pd/
|
||||
contrib/tunnels.d/ etc/i2pd/tunnels.conf.d
|
||||
contrib/apparmor/usr.sbin.i2pd etc/apparmor.d
|
||||
|
||||
1
debian/i2pd.links
vendored
1
debian/i2pd.links
vendored
@@ -1,4 +1,5 @@
|
||||
etc/i2pd/i2pd.conf var/lib/i2pd/i2pd.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.conf.d
|
||||
usr/share/i2pd/certificates var/lib/i2pd/certificates
|
||||
|
||||
3
debian/i2pd.openrc
vendored
3
debian/i2pd.openrc
vendored
@@ -4,10 +4,11 @@ pidfile="/var/run/i2pd/i2pd.pid"
|
||||
logfile="/var/log/i2pd/i2pd.log"
|
||||
mainconf="/etc/i2pd/i2pd.conf"
|
||||
tunconf="/etc/i2pd/tunnels.conf"
|
||||
tundir="/etc/i2pd/tunnels.conf.d"
|
||||
|
||||
name="i2pd"
|
||||
command="/usr/sbin/i2pd"
|
||||
command_args="--service --daemon --log=file --logfile=$logfile --conf=$mainconf --tunconf=$tunconf --pidfile=$pidfile"
|
||||
command_args="--service --daemon --log=file --logfile=$logfile --conf=$mainconf --tunconf=$tunconf --tunnelsdir=$tundir --pidfile=$pidfile"
|
||||
description="i2p router written in C++"
|
||||
required_dirs="/var/lib/i2pd"
|
||||
required_files="$mainconf"
|
||||
|
||||
2
debian/patches/01-tune-build-opts.patch
vendored
2
debian/patches/01-tune-build-opts.patch
vendored
@@ -13,5 +13,5 @@ index bdadfe0..2f71eec 100644
|
||||
USE_STATIC := no
|
||||
USE_MESHNET := no
|
||||
USE_UPNP := no
|
||||
DEBUG := yes
|
||||
|
||||
ifeq ($(WEBSOCKETS),1)
|
||||
|
||||
25
debian/patches/02-fix-1210.patch
vendored
Normal file
25
debian/patches/02-fix-1210.patch
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
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: 2018-08-25
|
||||
|
||||
--- a/contrib/i2pd.service
|
||||
+++ b/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=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
1
debian/patches/series
vendored
1
debian/patches/series
vendored
@@ -1 +1,2 @@
|
||||
01-tune-build-opts.patch
|
||||
02-fix-1210.patch
|
||||
|
||||
2
debian/rules
vendored
2
debian/rules
vendored
@@ -17,6 +17,6 @@ DEB_BUILD_MAINT_OPTIONS=hardening=+bindnow
|
||||
override_dh_strip:
|
||||
dh_strip --dbg-package=i2pd-dbg
|
||||
|
||||
## uncoment this if you have "missing info" problem when building package
|
||||
## uncomment this if you have "missing info" problem when building package
|
||||
#override_dh_shlibdeps:
|
||||
# dh_shlibdeps --dpkg-shlibdeps-params=--ignore-missing-info
|
||||
|
||||
@@ -1094,7 +1094,7 @@ HTML_STYLESHEET =
|
||||
# cascading style sheets that are included after the standard style sheets
|
||||
# created by doxygen. Using this option one can overrule certain style aspects.
|
||||
# This is preferred over using HTML_STYLESHEET since it does not replace the
|
||||
# standard style sheet and is therefor more robust against future updates.
|
||||
# standard style sheet and is therefore more robust against future updates.
|
||||
# Doxygen will copy the style sheet files to the output directory.
|
||||
# Note: The order of the extra stylesheet files is of importance (e.g. the last
|
||||
# stylesheet in the list overrules the setting of the previous ones in the
|
||||
@@ -1637,7 +1637,7 @@ EXTRA_PACKAGES =
|
||||
# Note: Only use a user-defined header if you know what you are doing! The
|
||||
# following commands have a special meaning inside the header: $title,
|
||||
# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
|
||||
# $projectbrief, $projectlogo. Doxygen will replace $title with the empy string,
|
||||
# $projectbrief, $projectlogo. Doxygen will replace $title with the empty string,
|
||||
# for the replacement values of the other commands the user is referred to
|
||||
# HTML_HEADER.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
@@ -21,23 +21,35 @@ namespace cpu
|
||||
|
||||
void Detect()
|
||||
{
|
||||
#if defined(__AES__) || defined(__AVX__)
|
||||
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
int info[4];
|
||||
__cpuid(0, info[0], info[1], info[2], info[3]);
|
||||
if (info[0] >= 0x00000001) {
|
||||
__cpuid(0x00000001, info[0], info[1], info[2], info[3]);
|
||||
#ifdef __AES__
|
||||
aesni = info[2] & bit_AES; // AESNI
|
||||
#endif // __AES__
|
||||
#ifdef __AVX__
|
||||
avx = info[2] & bit_AVX; // AVX
|
||||
#endif // __AVX__
|
||||
}
|
||||
#endif
|
||||
#endif // defined(__x86_64__) || defined(__i386__)
|
||||
|
||||
#ifdef __AES__
|
||||
if(aesni)
|
||||
{
|
||||
LogPrint(eLogInfo, "AESNI enabled");
|
||||
}
|
||||
#endif // __AES__
|
||||
#ifdef __AVX__
|
||||
if(avx)
|
||||
{
|
||||
LogPrint(eLogInfo, "AVX enabled");
|
||||
}
|
||||
#endif // __AVX__
|
||||
#endif // defined(__AES__) || defined(__AVX__)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,8 +32,10 @@ namespace config {
|
||||
options_description general("General options");
|
||||
general.add_options()
|
||||
("help", "Show this message")
|
||||
("version", "Show i2pd version")
|
||||
("conf", value<std::string>()->default_value(""), "Path to main i2pd config file (default: try ~/.i2pd/i2pd.conf or /var/lib/i2pd/i2pd.conf)")
|
||||
("tunconf", value<std::string>()->default_value(""), "Path to config with tunnels list and options (default: try ~/.i2pd/tunnels.conf or /var/lib/i2pd/tunnels.conf)")
|
||||
("tunnelsdir", value<std::string>()->default_value(""), "Path to extra tunnels' configs folder (default: ~/.i2pd/tunnels.d or /var/lib/i2pd/tunnels.d")
|
||||
("pidfile", value<std::string>()->default_value(""), "Path to pidfile (default: ~/i2pd/i2pd.pid or /var/lib/i2pd/i2pd.pid)")
|
||||
("log", value<std::string>()->default_value(""), "Logs destination: stdout, file, syslog (stdout if not set)")
|
||||
("logfile", value<std::string>()->default_value(""), "Path to logfile (stdout if not set, autodetect if daemon)")
|
||||
@@ -59,7 +61,6 @@ namespace config {
|
||||
("ntcp", value<bool>()->default_value(true), "Enable NTCP transport (default: enabled)")
|
||||
("ssu", value<bool>()->default_value(true), "Enable SSU transport (default: enabled)")
|
||||
("ntcpproxy", value<std::string>()->default_value(""), "Proxy URL for NTCP transport")
|
||||
("ntcp2", value<bool>()->default_value(false), "Enable NTCP2 (experimental, default: disabled)")
|
||||
#ifdef _WIN32
|
||||
("svcctl", value<std::string>()->default_value(""), "Windows service management ('install' or 'remove')")
|
||||
("insomnia", bool_switch()->default_value(false), "Prevent system from sleeping (default: disabled)")
|
||||
@@ -232,6 +233,13 @@ namespace config {
|
||||
("exploratory.outbound.quantity", value<int>()->default_value(3), "Exploratory outbound tunnels quantity")
|
||||
;
|
||||
|
||||
options_description ntcp2("NTCP2 Options");
|
||||
ntcp2.add_options()
|
||||
("ntcp2.enabled", value<bool>()->default_value(true), "Enable NTCP2 (default: enabled)")
|
||||
("ntcp2.published", value<bool>()->default_value(false), "Publish NTCP2 (default: disabled)")
|
||||
("ntcp2.port", value<uint16_t>()->default_value(0), "Port to listen for incoming NTCP2 connections (default: auto)")
|
||||
;
|
||||
|
||||
m_OptionsDesc
|
||||
.add(general)
|
||||
.add(limits)
|
||||
@@ -249,6 +257,7 @@ namespace config {
|
||||
.add(trust)
|
||||
.add(websocket)
|
||||
.add(exploratory)
|
||||
.add(ntcp2)
|
||||
;
|
||||
}
|
||||
|
||||
@@ -276,6 +285,23 @@ namespace config {
|
||||
std::cout << m_OptionsDesc;
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
else if (m_Options.count("version"))
|
||||
{
|
||||
std::cout << "i2pd version " << I2PD_VERSION << " (" << I2P_VERSION << ")" << std::endl;
|
||||
std::cout << "Boost version "
|
||||
<< BOOST_VERSION / 100000 << "." // maj. version
|
||||
<< BOOST_VERSION / 100 % 1000 << "." // min. version
|
||||
<< BOOST_VERSION % 100 // patch version
|
||||
<< std::endl;
|
||||
#if defined(OPENSSL_VERSION_TEXT)
|
||||
std::cout << OPENSSL_VERSION_TEXT << std::endl;
|
||||
#endif
|
||||
#if defined(LIBRESSL_VERSION_TEXT)
|
||||
std::cout << LIBRESSL_VERSION_TEXT << std::endl;
|
||||
#endif
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
void ParseConfig(const std::string& path)
|
||||
|
||||
@@ -12,9 +12,8 @@
|
||||
#if LEGACY_OPENSSL
|
||||
#include "ChaCha20.h"
|
||||
#include "Poly1305.h"
|
||||
#else
|
||||
#include <openssl/evp.h>
|
||||
#endif
|
||||
#include "Ed25519.h"
|
||||
#include "I2PEndian.h"
|
||||
#include "Log.h"
|
||||
|
||||
@@ -278,6 +277,80 @@ namespace crypto
|
||||
BN_free (pk);
|
||||
}
|
||||
|
||||
// x25519
|
||||
X25519Keys::X25519Keys ()
|
||||
{
|
||||
#if OPENSSL_X25519
|
||||
m_Ctx = EVP_PKEY_CTX_new_id (NID_X25519, NULL);
|
||||
#else
|
||||
m_Ctx = BN_CTX_new ();
|
||||
#endif
|
||||
}
|
||||
|
||||
X25519Keys::X25519Keys (const uint8_t * priv, const uint8_t * pub)
|
||||
{
|
||||
#if OPENSSL_X25519
|
||||
m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_X25519, NULL, priv, 32);
|
||||
m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL);
|
||||
memcpy (m_PublicKey, pub, 32); // TODO: verify against m_Pkey
|
||||
#else
|
||||
memcpy (m_PrivateKey, priv, 32);
|
||||
memcpy (m_PublicKey, pub, 32);
|
||||
m_Ctx = BN_CTX_new ();
|
||||
#endif
|
||||
}
|
||||
|
||||
X25519Keys::~X25519Keys ()
|
||||
{
|
||||
#if OPENSSL_X25519
|
||||
EVP_PKEY_CTX_free (m_Ctx);
|
||||
if (m_Pkey)
|
||||
EVP_PKEY_free (m_Pkey);
|
||||
#else
|
||||
BN_CTX_free (m_Ctx);
|
||||
#endif
|
||||
}
|
||||
|
||||
void X25519Keys::GenerateKeys ()
|
||||
{
|
||||
#if OPENSSL_X25519
|
||||
m_Pkey = nullptr;
|
||||
EVP_PKEY_keygen_init (m_Ctx);
|
||||
EVP_PKEY_keygen (m_Ctx, &m_Pkey);
|
||||
EVP_PKEY_CTX_free (m_Ctx);
|
||||
m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL); // TODO: do we really need to re-create m_Ctx?
|
||||
size_t len = 32;
|
||||
EVP_PKEY_get_raw_public_key (m_Pkey, m_PublicKey, &len);
|
||||
#else
|
||||
RAND_bytes (m_PrivateKey, 32);
|
||||
GetEd25519 ()->ScalarMulB (m_PrivateKey, m_PublicKey, m_Ctx);
|
||||
#endif
|
||||
}
|
||||
|
||||
void X25519Keys::Agree (const uint8_t * pub, uint8_t * shared)
|
||||
{
|
||||
#if OPENSSL_X25519
|
||||
EVP_PKEY_derive_init (m_Ctx);
|
||||
auto pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_X25519, NULL, pub, 32);
|
||||
EVP_PKEY_derive_set_peer (m_Ctx, pkey);
|
||||
size_t len = 32;
|
||||
EVP_PKEY_derive (m_Ctx, shared, &len);
|
||||
EVP_PKEY_free (pkey);
|
||||
#else
|
||||
GetEd25519 ()->ScalarMul (pub, m_PrivateKey, shared, m_Ctx);
|
||||
#endif
|
||||
}
|
||||
|
||||
void X25519Keys::GetPrivateKey (uint8_t * priv) const
|
||||
{
|
||||
#if OPENSSL_X25519
|
||||
size_t len = 32;
|
||||
EVP_PKEY_get_raw_private_key (m_Pkey, priv, &len);
|
||||
#else
|
||||
memcpy (priv, m_PrivateKey, 32);
|
||||
#endif
|
||||
}
|
||||
|
||||
// ElGamal
|
||||
void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding)
|
||||
{
|
||||
@@ -522,9 +595,9 @@ namespace crypto
|
||||
{
|
||||
uint64_t buf[256];
|
||||
uint64_t hash[12]; // 96 bytes
|
||||
#ifdef __AVX__
|
||||
if(i2p::cpu::avx)
|
||||
{
|
||||
#ifdef AVX
|
||||
__asm__
|
||||
(
|
||||
"vmovups %[key], %%ymm0 \n"
|
||||
@@ -543,30 +616,9 @@ namespace crypto
|
||||
[buf]"r"(buf), [hash]"r"(hash)
|
||||
: "memory", "%xmm0" // TODO: change to %ymm0 later
|
||||
);
|
||||
#else
|
||||
// ikeypad
|
||||
buf[0] = key.GetLL ()[0] ^ IPAD;
|
||||
buf[1] = key.GetLL ()[1] ^ IPAD;
|
||||
buf[2] = key.GetLL ()[2] ^ IPAD;
|
||||
buf[3] = key.GetLL ()[3] ^ IPAD;
|
||||
buf[4] = IPAD;
|
||||
buf[5] = IPAD;
|
||||
buf[6] = IPAD;
|
||||
buf[7] = IPAD;
|
||||
// okeypad
|
||||
hash[0] = key.GetLL ()[0] ^ OPAD;
|
||||
hash[1] = key.GetLL ()[1] ^ OPAD;
|
||||
hash[2] = key.GetLL ()[2] ^ OPAD;
|
||||
hash[3] = key.GetLL ()[3] ^ OPAD;
|
||||
hash[4] = OPAD;
|
||||
hash[5] = OPAD;
|
||||
hash[6] = OPAD;
|
||||
hash[7] = OPAD;
|
||||
// fill last 16 bytes with zeros (first hash size assumed 32 bytes in I2P)
|
||||
memset (hash + 10, 0, 16);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// ikeypad
|
||||
buf[0] = key.GetLL ()[0] ^ IPAD;
|
||||
@@ -600,7 +652,7 @@ namespace crypto
|
||||
}
|
||||
|
||||
// AES
|
||||
#ifdef AESNI
|
||||
#ifdef __AES__
|
||||
#ifdef ARM64AES
|
||||
void init_aesenc(void){
|
||||
// TODO: Implementation
|
||||
@@ -632,7 +684,7 @@ namespace crypto
|
||||
"movaps %%xmm3, "#round1"(%[sched]) \n"
|
||||
#endif
|
||||
|
||||
#ifdef AESNI
|
||||
#ifdef __AES__
|
||||
void ECBCryptoAESNI::ExpandKey (const AESKey& key)
|
||||
{
|
||||
__asm__
|
||||
@@ -673,7 +725,7 @@ namespace crypto
|
||||
#endif
|
||||
|
||||
|
||||
#if AESNI
|
||||
#ifdef __AES__
|
||||
#define EncryptAES256(sched) \
|
||||
"pxor (%["#sched"]), %%xmm0 \n" \
|
||||
"aesenc 16(%["#sched"]), %%xmm0 \n" \
|
||||
@@ -694,9 +746,9 @@ namespace crypto
|
||||
|
||||
void ECBEncryption::Encrypt (const ChipherBlock * in, ChipherBlock * out)
|
||||
{
|
||||
#ifdef __AES__
|
||||
if(i2p::cpu::aesni)
|
||||
{
|
||||
#ifdef AESNI
|
||||
__asm__
|
||||
(
|
||||
"movups (%[in]), %%xmm0 \n"
|
||||
@@ -704,17 +756,15 @@ namespace crypto
|
||||
"movups %%xmm0, (%[out]) \n"
|
||||
: : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out) : "%xmm0", "memory"
|
||||
);
|
||||
#else
|
||||
AES_encrypt (in->buf, out->buf, &m_Key);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
AES_encrypt (in->buf, out->buf, &m_Key);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef AESNI
|
||||
#ifdef __AES__
|
||||
#define DecryptAES256(sched) \
|
||||
"pxor 224(%["#sched"]), %%xmm0 \n" \
|
||||
"aesdec 208(%["#sched"]), %%xmm0 \n" \
|
||||
@@ -735,9 +785,9 @@ namespace crypto
|
||||
|
||||
void ECBDecryption::Decrypt (const ChipherBlock * in, ChipherBlock * out)
|
||||
{
|
||||
#ifdef __AES__
|
||||
if(i2p::cpu::aesni)
|
||||
{
|
||||
#ifdef AESNI
|
||||
__asm__
|
||||
(
|
||||
"movups (%[in]), %%xmm0 \n"
|
||||
@@ -745,17 +795,15 @@ namespace crypto
|
||||
"movups %%xmm0, (%[out]) \n"
|
||||
: : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out) : "%xmm0", "memory"
|
||||
);
|
||||
#else
|
||||
AES_decrypt (in->buf, out->buf, &m_Key);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
AES_decrypt (in->buf, out->buf, &m_Key);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef AESNI
|
||||
#ifdef __AES__
|
||||
#define CallAESIMC(offset) \
|
||||
"movaps "#offset"(%[shed]), %%xmm0 \n" \
|
||||
"aesimc %%xmm0, %%xmm0 \n" \
|
||||
@@ -764,15 +812,13 @@ namespace crypto
|
||||
|
||||
void ECBEncryption::SetKey (const AESKey& key)
|
||||
{
|
||||
#ifdef __AES__
|
||||
if(i2p::cpu::aesni)
|
||||
{
|
||||
#ifdef AESNI
|
||||
ExpandKey (key);
|
||||
#else
|
||||
AES_set_encrypt_key (key, 256, &m_Key);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
AES_set_encrypt_key (key, 256, &m_Key);
|
||||
}
|
||||
@@ -780,9 +826,9 @@ namespace crypto
|
||||
|
||||
void ECBDecryption::SetKey (const AESKey& key)
|
||||
{
|
||||
#ifdef __AES__
|
||||
if(i2p::cpu::aesni)
|
||||
{
|
||||
#ifdef AESNI
|
||||
ExpandKey (key); // expand encryption key first
|
||||
// then invert it using aesimc
|
||||
__asm__
|
||||
@@ -802,11 +848,9 @@ namespace crypto
|
||||
CallAESIMC(208)
|
||||
: : [shed]"r"(GetKeySchedule ()) : "%xmm0", "memory"
|
||||
);
|
||||
#else
|
||||
AES_set_decrypt_key (key, 256, &m_Key);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
AES_set_decrypt_key (key, 256, &m_Key);
|
||||
}
|
||||
@@ -815,9 +859,9 @@ namespace crypto
|
||||
|
||||
void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
|
||||
{
|
||||
#ifdef __AES__
|
||||
if(i2p::cpu::aesni)
|
||||
{
|
||||
#ifdef AESNI
|
||||
__asm__
|
||||
(
|
||||
"movups (%[iv]), %%xmm1 \n"
|
||||
@@ -837,16 +881,9 @@ namespace crypto
|
||||
[in]"r"(in), [out]"r"(out), [num]"r"(numBlocks)
|
||||
: "%xmm0", "%xmm1", "cc", "memory"
|
||||
);
|
||||
#else
|
||||
for (int i = 0; i < numBlocks; i++)
|
||||
{
|
||||
*m_LastBlock.GetChipherBlock () ^= in[i];
|
||||
m_ECBEncryption.Encrypt (m_LastBlock.GetChipherBlock (), m_LastBlock.GetChipherBlock ());
|
||||
out[i] = *m_LastBlock.GetChipherBlock ();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
for (int i = 0; i < numBlocks; i++)
|
||||
{
|
||||
@@ -867,9 +904,9 @@ namespace crypto
|
||||
|
||||
void CBCEncryption::Encrypt (const uint8_t * in, uint8_t * out)
|
||||
{
|
||||
#ifdef __AES__
|
||||
if(i2p::cpu::aesni)
|
||||
{
|
||||
#ifdef AESNI
|
||||
__asm__
|
||||
(
|
||||
"movups (%[iv]), %%xmm1 \n"
|
||||
@@ -883,19 +920,17 @@ namespace crypto
|
||||
[in]"r"(in), [out]"r"(out)
|
||||
: "%xmm0", "%xmm1", "memory"
|
||||
);
|
||||
#else
|
||||
Encrypt (1, (const ChipherBlock *)in, (ChipherBlock *)out);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif
|
||||
Encrypt (1, (const ChipherBlock *)in, (ChipherBlock *)out);
|
||||
}
|
||||
|
||||
void CBCDecryption::Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
|
||||
{
|
||||
#ifdef __AES__
|
||||
if(i2p::cpu::aesni)
|
||||
{
|
||||
#ifdef AESNI
|
||||
__asm__
|
||||
(
|
||||
"movups (%[iv]), %%xmm1 \n"
|
||||
@@ -916,17 +951,9 @@ namespace crypto
|
||||
[in]"r"(in), [out]"r"(out), [num]"r"(numBlocks)
|
||||
: "%xmm0", "%xmm1", "%xmm2", "cc", "memory"
|
||||
);
|
||||
#else
|
||||
for (int i = 0; i < numBlocks; i++)
|
||||
{
|
||||
ChipherBlock tmp = in[i];
|
||||
m_ECBDecryption.Decrypt (in + i, out + i);
|
||||
out[i] ^= *m_IV.GetChipherBlock ();
|
||||
*m_IV.GetChipherBlock () = tmp;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
for (int i = 0; i < numBlocks; i++)
|
||||
{
|
||||
@@ -947,9 +974,9 @@ namespace crypto
|
||||
|
||||
void CBCDecryption::Decrypt (const uint8_t * in, uint8_t * out)
|
||||
{
|
||||
#ifdef __AES__
|
||||
if(i2p::cpu::aesni)
|
||||
{
|
||||
#ifdef AESNI
|
||||
__asm__
|
||||
(
|
||||
"movups (%[iv]), %%xmm1 \n"
|
||||
@@ -963,19 +990,17 @@ namespace crypto
|
||||
[in]"r"(in), [out]"r"(out)
|
||||
: "%xmm0", "%xmm1", "memory"
|
||||
);
|
||||
#else
|
||||
Decrypt (1, (const ChipherBlock *)in, (ChipherBlock *)out);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif
|
||||
Decrypt (1, (const ChipherBlock *)in, (ChipherBlock *)out);
|
||||
}
|
||||
|
||||
void TunnelEncryption::Encrypt (const uint8_t * in, uint8_t * out)
|
||||
{
|
||||
#ifdef __AES__
|
||||
if(i2p::cpu::aesni)
|
||||
{
|
||||
#ifdef AESNI
|
||||
__asm__
|
||||
(
|
||||
// encrypt IV
|
||||
@@ -1001,14 +1026,9 @@ namespace crypto
|
||||
[in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes
|
||||
: "%xmm0", "%xmm1", "cc", "memory"
|
||||
);
|
||||
#else
|
||||
m_IVEncryption.Encrypt ((const ChipherBlock *)in, (ChipherBlock *)out); // iv
|
||||
m_LayerEncryption.SetIV (out);
|
||||
m_LayerEncryption.Encrypt (in + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, out + 16); // data
|
||||
m_IVEncryption.Encrypt ((ChipherBlock *)out, (ChipherBlock *)out); // double iv
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
m_IVEncryption.Encrypt ((const ChipherBlock *)in, (ChipherBlock *)out); // iv
|
||||
m_LayerEncryption.SetIV (out);
|
||||
@@ -1019,9 +1039,9 @@ namespace crypto
|
||||
|
||||
void TunnelDecryption::Decrypt (const uint8_t * in, uint8_t * out)
|
||||
{
|
||||
#ifdef __AES__
|
||||
if(i2p::cpu::aesni)
|
||||
{
|
||||
#ifdef AESNI
|
||||
__asm__
|
||||
(
|
||||
// decrypt IV
|
||||
@@ -1048,14 +1068,9 @@ namespace crypto
|
||||
[in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes
|
||||
: "%xmm0", "%xmm1", "%xmm2", "cc", "memory"
|
||||
);
|
||||
#else
|
||||
m_IVDecryption.Decrypt ((const ChipherBlock *)in, (ChipherBlock *)out); // iv
|
||||
m_LayerDecryption.SetIV (out);
|
||||
m_LayerDecryption.Decrypt (in + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, out + 16); // data
|
||||
m_IVDecryption.Decrypt ((ChipherBlock *)out, (ChipherBlock *)out); // double iv
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
m_IVDecryption.Decrypt ((const ChipherBlock *)in, (ChipherBlock *)out); // iv
|
||||
m_LayerDecryption.SetIV (out);
|
||||
@@ -1076,9 +1091,6 @@ namespace crypto
|
||||
uint8_t polyKey[64];
|
||||
memset(polyKey, 0, sizeof(polyKey));
|
||||
chacha20 (polyKey, 64, nonce, key, 0);
|
||||
// encrypt data
|
||||
memcpy (buf, msg, msgLen);
|
||||
chacha20 (buf, msgLen, nonce, key, 1);
|
||||
|
||||
// create Poly1305 message
|
||||
if (!ad) adLen = 0;
|
||||
@@ -1096,7 +1108,21 @@ namespace crypto
|
||||
memcpy (polyMsg.data () + offset, padding, rem); offset += rem;
|
||||
}
|
||||
}
|
||||
memcpy (polyMsg.data () + offset, encrypt ? buf : msg, msgLen); offset += msgLen; // encrypted data
|
||||
// encrypt/decrypt data and add to hash
|
||||
if (buf != msg)
|
||||
memcpy (buf, msg, msgLen);
|
||||
if (encrypt)
|
||||
{
|
||||
chacha20 (buf, msgLen, nonce, key, 1); // encrypt
|
||||
memcpy (polyMsg.data () + offset, buf, msgLen); // after encryption
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (polyMsg.data () + offset, buf, msgLen); // before decryption
|
||||
chacha20 (buf, msgLen, nonce, key, 1); // decrypt
|
||||
}
|
||||
offset += msgLen; // encrypted data
|
||||
|
||||
auto rem = msgLen & 0x0F; // %16
|
||||
if (rem)
|
||||
{
|
||||
@@ -1139,7 +1165,8 @@ namespace crypto
|
||||
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 16, (uint8_t *)(msg + msgLen));
|
||||
EVP_DecryptInit_ex(ctx, NULL, NULL, key, nonce);
|
||||
EVP_DecryptUpdate(ctx, NULL, &outlen, ad, adLen);
|
||||
ret = EVP_DecryptUpdate(ctx, buf, &outlen, msg, msgLen) > 0;
|
||||
EVP_DecryptUpdate(ctx, buf, &outlen, msg, msgLen);
|
||||
ret = EVP_DecryptFinal_ex(ctx, buf + outlen, &outlen) > 0;
|
||||
}
|
||||
|
||||
EVP_CIPHER_CTX_free (ctx);
|
||||
|
||||
@@ -13,11 +13,24 @@
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/engine.h>
|
||||
#include <openssl/opensslv.h>
|
||||
|
||||
#include "Base.h"
|
||||
#include "Tag.h"
|
||||
#include "CPU.h"
|
||||
|
||||
// recognize openssl version and features
|
||||
#if ((OPENSSL_VERSION_NUMBER < 0x010100000) || defined(LIBRESSL_VERSION_NUMBER)) // 1.0.2 and below or LibreSSL
|
||||
# define LEGACY_OPENSSL 1
|
||||
#else
|
||||
# define LEGACY_OPENSSL 0
|
||||
# if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1
|
||||
# define OPENSSL_EDDSA 1
|
||||
# define OPENSSL_X25519 1
|
||||
# define OPENSSL_SIPHASH 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
namespace crypto
|
||||
@@ -48,6 +61,32 @@ namespace crypto
|
||||
uint8_t m_PublicKey[256];
|
||||
};
|
||||
|
||||
// x25519
|
||||
class X25519Keys
|
||||
{
|
||||
public:
|
||||
|
||||
X25519Keys ();
|
||||
X25519Keys (const uint8_t * priv, const uint8_t * pub); // for RouterContext
|
||||
~X25519Keys ();
|
||||
|
||||
void GenerateKeys ();
|
||||
const uint8_t * GetPublicKey () const { return m_PublicKey; };
|
||||
void GetPrivateKey (uint8_t * priv) const;
|
||||
void Agree (const uint8_t * pub, uint8_t * shared);
|
||||
|
||||
private:
|
||||
|
||||
uint8_t m_PublicKey[32];
|
||||
#if OPENSSL_X25519
|
||||
EVP_PKEY_CTX * m_Ctx;
|
||||
EVP_PKEY * m_Pkey;
|
||||
#else
|
||||
BN_CTX * m_Ctx;
|
||||
uint8_t m_PrivateKey[32];
|
||||
#endif
|
||||
};
|
||||
|
||||
// ElGamal
|
||||
void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding = false);
|
||||
bool ElGamalDecrypt (const uint8_t * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding = false);
|
||||
@@ -69,9 +108,9 @@ namespace crypto
|
||||
|
||||
void operator^=(const ChipherBlock& other) // XOR
|
||||
{
|
||||
#ifdef __AVX__
|
||||
if (i2p::cpu::avx)
|
||||
{
|
||||
#ifdef AVX
|
||||
__asm__
|
||||
(
|
||||
"vmovups (%[buf]), %%xmm0 \n"
|
||||
@@ -82,16 +121,21 @@ namespace crypto
|
||||
: [buf]"r"(buf), [other]"r"(other.buf)
|
||||
: "%xmm0", "%xmm1", "memory"
|
||||
);
|
||||
#else
|
||||
for (int i = 0; i < 16; i++)
|
||||
buf[i] ^= other.buf[i];
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// TODO: implement it better
|
||||
for (int i = 0; i < 16; i++)
|
||||
buf[i] ^= other.buf[i];
|
||||
if (!(((size_t)buf | (size_t)other.buf) & 0x03)) // multiple of 4 ?
|
||||
{
|
||||
// we are good to cast to uint32_t *
|
||||
for (int i = 0; i < 4; i++)
|
||||
((uint32_t *)buf)[i] ^= ((uint32_t *)other.buf)[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 16; i++)
|
||||
buf[i] ^= other.buf[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -123,7 +167,7 @@ namespace crypto
|
||||
};
|
||||
|
||||
|
||||
#ifdef AESNI
|
||||
#ifdef __AES__
|
||||
#ifdef ARM64AES
|
||||
void init_aesenc(void) __attribute__((constructor));
|
||||
#endif
|
||||
@@ -143,7 +187,7 @@ namespace crypto
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef AESNI
|
||||
#ifdef __AES__
|
||||
class ECBEncryption: public ECBCryptoAESNI
|
||||
#else
|
||||
class ECBEncryption
|
||||
@@ -159,7 +203,7 @@ namespace crypto
|
||||
AES_KEY m_Key;
|
||||
};
|
||||
|
||||
#ifdef AESNI
|
||||
#ifdef __AES__
|
||||
class ECBDecryption: public ECBCryptoAESNI
|
||||
#else
|
||||
class ECBDecryption
|
||||
@@ -263,9 +307,7 @@ namespace crypto
|
||||
}
|
||||
}
|
||||
|
||||
// take care about openssl version
|
||||
#include <openssl/opensslv.h>
|
||||
#define LEGACY_OPENSSL ((OPENSSL_VERSION_NUMBER < 0x010100000) || defined(LIBRESSL_VERSION_NUMBER)) // 1.0.2 and below or LibreSSL
|
||||
// take care about openssl below 1.1.0
|
||||
#if LEGACY_OPENSSL
|
||||
// define getters and setters introduced in 1.1.0
|
||||
inline int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace client
|
||||
{
|
||||
it = params->find (I2CP_PARAM_OUTBOUND_NICKNAME);
|
||||
if (it != params->end ()) m_Nickname = it->second;
|
||||
// otherwise we set deafult nickname in Start when we know local address
|
||||
// otherwise we set default nickname in Start when we know local address
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace i2p
|
||||
|
||||
std::shared_ptr<I2NPMessage> NewI2NPMessage (size_t len)
|
||||
{
|
||||
return (len < I2NP_MAX_SHORT_MESSAGE_SIZE/2) ? NewI2NPShortMessage () : NewI2NPMessage ();
|
||||
return (len < I2NP_MAX_SHORT_MESSAGE_SIZE - I2NP_HEADER_SIZE - 2) ? NewI2NPShortMessage () : NewI2NPMessage ();
|
||||
}
|
||||
|
||||
void I2NPMessage::FillI2NPMessageHeader (I2NPMessageType msgType, uint32_t replyMsgID)
|
||||
|
||||
@@ -26,6 +26,9 @@ namespace i2p
|
||||
const size_t I2NP_SHORT_HEADER_EXPIRATION_OFFSET = I2NP_SHORT_HEADER_TYPEID_OFFSET + 1;
|
||||
const size_t I2NP_SHORT_HEADER_SIZE = I2NP_SHORT_HEADER_EXPIRATION_OFFSET + 4;
|
||||
|
||||
// I2NP NTCP2 header
|
||||
const size_t I2NP_NTCP2_HEADER_SIZE = I2NP_HEADER_EXPIRATION_OFFSET + 4;
|
||||
|
||||
// Tunnel Gateway header
|
||||
const size_t TUNNEL_GATEWAY_HEADER_TUNNELID_OFFSET = 0;
|
||||
const size_t TUNNEL_GATEWAY_HEADER_LENGTH_OFFSET = TUNNEL_GATEWAY_HEADER_TUNNELID_OFFSET + 4;
|
||||
@@ -103,7 +106,7 @@ namespace tunnel
|
||||
class TunnelPool;
|
||||
}
|
||||
|
||||
const size_t I2NP_MAX_MESSAGE_SIZE = 32768;
|
||||
const size_t I2NP_MAX_MESSAGE_SIZE = 62708;
|
||||
const size_t I2NP_MAX_SHORT_MESSAGE_SIZE = 4096;
|
||||
const unsigned int I2NP_MESSAGE_EXPIRATION_TIMEOUT = 8000; // in milliseconds (as initial RTT)
|
||||
const unsigned int I2NP_MESSAGE_CLOCK_SKEW = 60*1000; // 1 minute in milliseconds
|
||||
@@ -194,6 +197,24 @@ namespace tunnel
|
||||
len = offset + I2NP_SHORT_HEADER_SIZE + bufbe16toh (header + I2NP_HEADER_SIZE_OFFSET);
|
||||
return bufbe32toh (header + I2NP_HEADER_MSGID_OFFSET);
|
||||
}
|
||||
// for NTCP2 only
|
||||
uint8_t * GetNTCP2Header () { return GetPayload () - I2NP_NTCP2_HEADER_SIZE; };
|
||||
size_t GetNTCP2Length () const { return GetPayloadLength () + I2NP_NTCP2_HEADER_SIZE; };
|
||||
void FromNTCP2 ()
|
||||
{
|
||||
const uint8_t * ntcp2 = GetNTCP2Header ();
|
||||
memcpy (GetHeader () + I2NP_HEADER_TYPEID_OFFSET, ntcp2 + I2NP_HEADER_TYPEID_OFFSET, 5); // typeid + msgid
|
||||
SetExpiration (bufbe32toh (ntcp2 + I2NP_HEADER_EXPIRATION_OFFSET)*1000LL);
|
||||
SetSize (len - offset - I2NP_HEADER_SIZE);
|
||||
SetChks (0);
|
||||
}
|
||||
|
||||
void ToNTCP2 ()
|
||||
{
|
||||
uint8_t * ntcp2 = GetNTCP2Header ();
|
||||
htobe32buf (ntcp2 + I2NP_HEADER_EXPIRATION_OFFSET, bufbe64toh (GetHeader () + I2NP_HEADER_EXPIRATION_OFFSET)/1000LL);
|
||||
memcpy (ntcp2 + I2NP_HEADER_TYPEID_OFFSET, GetHeader () + I2NP_HEADER_TYPEID_OFFSET, 5); // typeid + msgid
|
||||
}
|
||||
|
||||
void FillI2NPMessageHeader (I2NPMessageType msgType, uint32_t replyMsgID = 0);
|
||||
void RenewI2NPMessageHeader ();
|
||||
|
||||
@@ -72,29 +72,10 @@ namespace data
|
||||
break;
|
||||
}
|
||||
case SIGNING_KEY_TYPE_RSA_SHA256_2048:
|
||||
{
|
||||
memcpy (m_StandardIdentity.signingKey, signingKey, 128);
|
||||
excessLen = i2p::crypto::RSASHA2562048_KEY_LENGTH - 128; // 128 = 256 - 128
|
||||
excessBuf = new uint8_t[excessLen];
|
||||
memcpy (excessBuf, signingKey + 128, excessLen);
|
||||
break;
|
||||
}
|
||||
case SIGNING_KEY_TYPE_RSA_SHA384_3072:
|
||||
{
|
||||
memcpy (m_StandardIdentity.signingKey, signingKey, 128);
|
||||
excessLen = i2p::crypto::RSASHA3843072_KEY_LENGTH - 128; // 256 = 384 - 128
|
||||
excessBuf = new uint8_t[excessLen];
|
||||
memcpy (excessBuf, signingKey + 128, excessLen);
|
||||
break;
|
||||
}
|
||||
case SIGNING_KEY_TYPE_RSA_SHA512_4096:
|
||||
{
|
||||
memcpy (m_StandardIdentity.signingKey, signingKey, 128);
|
||||
excessLen = i2p::crypto::RSASHA5124096_KEY_LENGTH - 128; // 384 = 512 - 128
|
||||
excessBuf = new uint8_t[excessLen];
|
||||
memcpy (excessBuf, signingKey + 128, excessLen);
|
||||
break;
|
||||
}
|
||||
LogPrint (eLogError, "Identity: RSA signing key type ", (int)type, " is not supported");
|
||||
break;
|
||||
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
|
||||
{
|
||||
size_t padding = 128 - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; // 96 = 128 - 32
|
||||
@@ -368,32 +349,10 @@ namespace data
|
||||
break;
|
||||
}
|
||||
case SIGNING_KEY_TYPE_RSA_SHA256_2048:
|
||||
{
|
||||
uint8_t signingKey[i2p::crypto::RSASHA2562048_KEY_LENGTH];
|
||||
memcpy (signingKey, m_StandardIdentity.signingKey, 128);
|
||||
size_t excessLen = i2p::crypto::RSASHA2562048_KEY_LENGTH - 128; // 128 = 256- 128
|
||||
memcpy (signingKey + 128, m_ExtendedBuffer + 4, excessLen); // right after signing and crypto key types
|
||||
UpdateVerifier (new i2p::crypto:: RSASHA2562048Verifier (signingKey));
|
||||
break;
|
||||
}
|
||||
case SIGNING_KEY_TYPE_RSA_SHA384_3072:
|
||||
{
|
||||
uint8_t signingKey[i2p::crypto::RSASHA3843072_KEY_LENGTH];
|
||||
memcpy (signingKey, m_StandardIdentity.signingKey, 128);
|
||||
size_t excessLen = i2p::crypto::RSASHA3843072_KEY_LENGTH - 128; // 256 = 384- 128
|
||||
memcpy (signingKey + 128, m_ExtendedBuffer + 4, excessLen); // right after signing and crypto key types
|
||||
UpdateVerifier (new i2p::crypto:: RSASHA3843072Verifier (signingKey));
|
||||
break;
|
||||
}
|
||||
case SIGNING_KEY_TYPE_RSA_SHA512_4096:
|
||||
{
|
||||
uint8_t signingKey[i2p::crypto::RSASHA5124096_KEY_LENGTH];
|
||||
memcpy (signingKey, m_StandardIdentity.signingKey, 128);
|
||||
size_t excessLen = i2p::crypto::RSASHA5124096_KEY_LENGTH - 128; // 384 = 512- 128
|
||||
memcpy (signingKey + 128, m_ExtendedBuffer + 4, excessLen); // right after signing and crypto key types
|
||||
UpdateVerifier (new i2p::crypto:: RSASHA5124096Verifier (signingKey));
|
||||
break;
|
||||
}
|
||||
LogPrint (eLogError, "Identity: RSA signing key type ", (int)keyType, " is not supported");
|
||||
break;
|
||||
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
|
||||
{
|
||||
size_t padding = 128 - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; // 96 = 128 - 32
|
||||
@@ -564,13 +523,9 @@ namespace data
|
||||
m_Signer.reset (new i2p::crypto::ECDSAP521Signer (m_SigningPrivateKey));
|
||||
break;
|
||||
case SIGNING_KEY_TYPE_RSA_SHA256_2048:
|
||||
m_Signer.reset (new i2p::crypto::RSASHA2562048Signer (m_SigningPrivateKey));
|
||||
break;
|
||||
case SIGNING_KEY_TYPE_RSA_SHA384_3072:
|
||||
m_Signer.reset (new i2p::crypto::RSASHA3843072Signer (m_SigningPrivateKey));
|
||||
break;
|
||||
case SIGNING_KEY_TYPE_RSA_SHA512_4096:
|
||||
m_Signer.reset (new i2p::crypto::RSASHA5124096Signer (m_SigningPrivateKey));
|
||||
LogPrint (eLogError, "Identity: RSA signing key type ", (int)m_Public->GetSigningKeyType (), " is not supported");
|
||||
break;
|
||||
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
|
||||
m_Signer.reset (new i2p::crypto::EDDSA25519Signer (m_SigningPrivateKey, m_Public->GetStandardIdentity ().certificate - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH));
|
||||
@@ -642,7 +597,7 @@ namespace data
|
||||
case SIGNING_KEY_TYPE_RSA_SHA256_2048:
|
||||
case SIGNING_KEY_TYPE_RSA_SHA384_3072:
|
||||
case SIGNING_KEY_TYPE_RSA_SHA512_4096:
|
||||
LogPrint (eLogWarning, "Identity: RSA signature type is not supported. Create EdDSA");
|
||||
LogPrint (eLogWarning, "Identity: RSA signature type is not supported. Creating EdDSA");
|
||||
// no break here
|
||||
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
|
||||
i2p::crypto::CreateEDDSA25519RandomKeys (keys.m_SigningPrivateKey, signingPublicKey);
|
||||
@@ -719,24 +674,29 @@ namespace data
|
||||
XORMetric operator^(const IdentHash& key1, const IdentHash& key2)
|
||||
{
|
||||
XORMetric m;
|
||||
#if defined(__AVX__) // for AVX
|
||||
__asm__
|
||||
(
|
||||
"vmovups %1, %%ymm0 \n"
|
||||
"vmovups %2, %%ymm1 \n"
|
||||
"vxorps %%ymm0, %%ymm1, %%ymm1 \n"
|
||||
"vmovups %%ymm1, %0 \n"
|
||||
: "=m"(*m.metric)
|
||||
: "m"(*key1), "m"(*key2)
|
||||
: "memory", "%xmm0", "%xmm1" // should be replaced by %ymm0/1 once supported by compiler
|
||||
);
|
||||
#else
|
||||
const uint64_t * hash1 = key1.GetLL (), * hash2 = key2.GetLL ();
|
||||
m.metric_ll[0] = hash1[0] ^ hash2[0];
|
||||
m.metric_ll[1] = hash1[1] ^ hash2[1];
|
||||
m.metric_ll[2] = hash1[2] ^ hash2[2];
|
||||
m.metric_ll[3] = hash1[3] ^ hash2[3];
|
||||
#ifdef __AVX__
|
||||
if(i2p::cpu::avx)
|
||||
{
|
||||
__asm__
|
||||
(
|
||||
"vmovups %1, %%ymm0 \n"
|
||||
"vmovups %2, %%ymm1 \n"
|
||||
"vxorps %%ymm0, %%ymm1, %%ymm1 \n"
|
||||
"vmovups %%ymm1, %0 \n"
|
||||
: "=m"(*m.metric)
|
||||
: "m"(*key1), "m"(*key2)
|
||||
: "memory", "%xmm0", "%xmm1" // should be replaced by %ymm0/1 once supported by compiler
|
||||
);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
const uint64_t * hash1 = key1.GetLL (), * hash2 = key2.GetLL ();
|
||||
m.metric_ll[0] = hash1[0] ^ hash2[0];
|
||||
m.metric_ll[1] = hash1[1] ^ hash2[1];
|
||||
m.metric_ll[2] = hash1[2] ^ hash2[2];
|
||||
m.metric_ll[3] = hash1[3] ^ hash2[3];
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
1264
libi2pd/NTCP2.cpp
1264
libi2pd/NTCP2.cpp
File diff suppressed because it is too large
Load Diff
182
libi2pd/NTCP2.h
182
libi2pd/NTCP2.h
@@ -1,10 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2018, 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
|
||||
*
|
||||
* Kovri go write your own code
|
||||
*
|
||||
*/
|
||||
#ifndef NTCP2_H__
|
||||
#define NTCP2_H__
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <array>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <boost/asio.hpp>
|
||||
#include "Crypto.h"
|
||||
#include "util.h"
|
||||
#include "RouterInfo.h"
|
||||
#include "TransportSession.h"
|
||||
|
||||
@@ -12,6 +29,99 @@ namespace i2p
|
||||
{
|
||||
namespace transport
|
||||
{
|
||||
|
||||
const size_t NTCP2_UNENCRYPTED_FRAME_MAX_SIZE = 65519;
|
||||
const int NTCP2_MAX_PADDING_RATIO = 6; // in %
|
||||
|
||||
const int NTCP2_CONNECT_TIMEOUT = 5; // 5 seconds
|
||||
const int NTCP2_ESTABLISH_TIMEOUT = 10; // 10 seconds
|
||||
const int NTCP2_TERMINATION_TIMEOUT = 120; // 2 minutes
|
||||
const int NTCP2_TERMINATION_CHECK_TIMEOUT = 30; // 30 seconds
|
||||
|
||||
const int NTCP2_CLOCK_SKEW = 60; // in seconds
|
||||
const int NTCP2_MAX_OUTGOING_QUEUE_SIZE = 500; // how many messages we can queue up
|
||||
|
||||
enum NTCP2BlockType
|
||||
{
|
||||
eNTCP2BlkDateTime = 0,
|
||||
eNTCP2BlkOptions, // 1
|
||||
eNTCP2BlkRouterInfo, // 2
|
||||
eNTCP2BlkI2NPMessage, // 3
|
||||
eNTCP2BlkTermination, // 4
|
||||
eNTCP2BlkPadding = 254
|
||||
};
|
||||
|
||||
enum NTCP2TerminationReason
|
||||
{
|
||||
eNTCP2NormalClose = 0,
|
||||
eNTCP2TerminationReceived, // 1
|
||||
eNTCP2IdleTimeout, // 2
|
||||
eNTCP2RouterShutdown, // 3
|
||||
eNTCP2DataPhaseAEADFailure, // 4
|
||||
eNTCP2IncompatibleOptions, // 5
|
||||
eNTCP2IncompatibleSignatureType, // 6
|
||||
eNTCP2ClockSkew, // 7
|
||||
eNTCP2PaddingViolation, // 8
|
||||
eNTCP2AEADFramingError, // 9
|
||||
eNTCP2PayloadFormatError, // 10
|
||||
eNTCP2Message1Error, // 11
|
||||
eNTCP2Message2Error, // 12
|
||||
eNTCP2Message3Error, // 13
|
||||
eNTCP2IntraFrameReadTimeout, // 14
|
||||
eNTCP2RouterInfoSignatureVerificationFail, // 15
|
||||
eNTCP2IncorrectSParameter, // 16
|
||||
eNTCP2Banned, // 17
|
||||
};
|
||||
|
||||
|
||||
typedef std::array<uint8_t, NTCP2_UNENCRYPTED_FRAME_MAX_SIZE> NTCP2FrameBuffer;
|
||||
struct NTCP2Establisher
|
||||
{
|
||||
NTCP2Establisher ();
|
||||
~NTCP2Establisher ();
|
||||
|
||||
const uint8_t * GetPub () const { return m_EphemeralKeys.GetPublicKey (); };
|
||||
const uint8_t * GetRemotePub () const { return m_RemoteEphemeralPublicKey; }; // Y for Alice and X for Bob
|
||||
uint8_t * GetRemotePub () { return m_RemoteEphemeralPublicKey; }; // to set
|
||||
|
||||
const uint8_t * GetK () const { return m_K; };
|
||||
const uint8_t * GetCK () const { return m_CK; };
|
||||
const uint8_t * GetH () const { return m_H; };
|
||||
|
||||
void KDF1Alice ();
|
||||
void KDF1Bob ();
|
||||
void KDF2Alice ();
|
||||
void KDF2Bob ();
|
||||
void KDF3Alice (); // for SessionConfirmed part 2
|
||||
void KDF3Bob ();
|
||||
|
||||
void MixKey (const uint8_t * inputKeyMaterial);
|
||||
void MixHash (const uint8_t * buf, size_t len);
|
||||
void KeyDerivationFunction1 (const uint8_t * pub, i2p::crypto::X25519Keys& priv, const uint8_t * rs, const uint8_t * epub); // for SessionRequest, (pub, priv) for DH
|
||||
void KeyDerivationFunction2 (const uint8_t * sessionRequest, size_t sessionRequestLen, const uint8_t * epub); // for SessionCreate
|
||||
void CreateEphemeralKey ();
|
||||
|
||||
void CreateSessionRequestMessage ();
|
||||
void CreateSessionCreatedMessage ();
|
||||
void CreateSessionConfirmedMessagePart1 (const uint8_t * nonce);
|
||||
void CreateSessionConfirmedMessagePart2 (const uint8_t * nonce);
|
||||
|
||||
bool ProcessSessionRequestMessage (uint16_t& paddingLen);
|
||||
bool ProcessSessionCreatedMessage (uint16_t& paddingLen);
|
||||
bool ProcessSessionConfirmedMessagePart1 (const uint8_t * nonce);
|
||||
bool ProcessSessionConfirmedMessagePart2 (const uint8_t * nonce, uint8_t * m3p2Buf);
|
||||
|
||||
i2p::crypto::X25519Keys m_EphemeralKeys;
|
||||
uint8_t m_RemoteEphemeralPublicKey[32]; // x25519
|
||||
uint8_t m_RemoteStaticKey[32], m_IV[16], m_H[32] /*h*/, m_CK[33] /*ck*/, m_K[32] /*k*/;
|
||||
i2p::data::IdentHash m_RemoteIdentHash;
|
||||
uint16_t m3p2Len;
|
||||
|
||||
uint8_t * m_SessionRequestBuffer, * m_SessionCreatedBuffer, * m_SessionConfirmedBuffer;
|
||||
size_t m_SessionRequestBufferLen, m_SessionCreatedBufferLen;
|
||||
|
||||
};
|
||||
|
||||
class NTCP2Server;
|
||||
class NTCP2Session: public TransportSession, public std::enable_shared_from_this<NTCP2Session>
|
||||
{
|
||||
@@ -20,25 +130,29 @@ namespace transport
|
||||
NTCP2Session (NTCP2Server& server, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter = nullptr);
|
||||
~NTCP2Session ();
|
||||
void Terminate ();
|
||||
void TerminateByTimeout ();
|
||||
void Done ();
|
||||
|
||||
boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; };
|
||||
|
||||
bool IsEstablished () const { return m_IsEstablished; };
|
||||
bool IsTerminated () const { return m_IsTerminated; };
|
||||
|
||||
void ClientLogin (); // Alice
|
||||
void ServerLogin (); // Bob
|
||||
void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs) {}; // TODO
|
||||
|
||||
void SendLocalRouterInfo (); // after handshake
|
||||
void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs);
|
||||
|
||||
private:
|
||||
|
||||
void MixKey (const uint8_t * inputKeyMaterial, uint8_t * derived);
|
||||
void Established ();
|
||||
|
||||
void CreateNonce (uint64_t seqn, uint8_t * nonce);
|
||||
void KeyDerivationFunction1 (const uint8_t * rs, const uint8_t * priv, const uint8_t * pub, uint8_t * derived); // for SessionRequest
|
||||
void KeyDerivationFunction2 (const uint8_t * priv, const uint8_t * pub, const uint8_t * sessionRequest, size_t sessionRequestLen, uint8_t * derived); // for SessionCreate
|
||||
void KeyDerivationFunction3 (const uint8_t * staticPrivKey, uint8_t * derived); // for SessionConfirmed part 2
|
||||
void KeyDerivationFunctionDataPhase ();
|
||||
void SetSipKeys (const uint8_t * sendSipKey, const uint8_t * receiveSipKey);
|
||||
|
||||
// establish
|
||||
void CreateEphemeralKey (uint8_t * pub);
|
||||
void SendSessionRequest ();
|
||||
void SendSessionCreated ();
|
||||
void SendSessionConfirmed ();
|
||||
@@ -50,6 +164,7 @@ namespace transport
|
||||
void HandleSessionCreatedReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||
void HandleSessionCreatedPaddingReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||
void HandleSessionConfirmedSent (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||
void HandleSessionConfirmedReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||
|
||||
// data
|
||||
void ReceiveLength ();
|
||||
@@ -60,6 +175,11 @@ namespace transport
|
||||
|
||||
void SendNextFrame (const uint8_t * payload, size_t len);
|
||||
void HandleNextFrameSent (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||
void SendQueue ();
|
||||
void SendRouterInfo ();
|
||||
void SendTermination (NTCP2TerminationReason reason);
|
||||
void SendTerminationAndTerminate (NTCP2TerminationReason reason);
|
||||
void PostI2NPMessages (std::vector<std::shared_ptr<I2NPMessage> > msgs);
|
||||
|
||||
private:
|
||||
|
||||
@@ -67,16 +187,29 @@ namespace transport
|
||||
boost::asio::ip::tcp::socket m_Socket;
|
||||
bool m_IsEstablished, m_IsTerminated;
|
||||
|
||||
uint8_t m_EphemeralPrivateKey[32]; // x25519
|
||||
uint8_t m_RemoteStaticKey[32], m_IV[16], m_H[32] /*h*/, m_CK[33] /*ck*/, m_K[32] /* derived after SessionCreated */, m_Y[32] /* or X for Bob */;
|
||||
uint8_t * m_SessionRequestBuffer, * m_SessionCreatedBuffer, * m_SessionConfirmedBuffer;
|
||||
size_t m_SessionRequestBufferLen, m_SessionCreatedBufferLen;
|
||||
std::unique_ptr<NTCP2Establisher> m_Establisher;
|
||||
// data phase
|
||||
uint8_t m_Kab[33], m_Kba[32], m_Sipkeysab[33], m_Sipkeysba[32];
|
||||
const uint8_t * m_SendKey, * m_ReceiveKey;
|
||||
#if OPENSSL_SIPHASH
|
||||
EVP_PKEY * m_SendSipKey, * m_ReceiveSipKey;
|
||||
EVP_MD_CTX * m_SendMDCtx, * m_ReceiveMDCtx;
|
||||
#else
|
||||
const uint8_t * m_SendSipKey, * m_ReceiveSipKey;
|
||||
#endif
|
||||
uint16_t m_NextReceivedLen;
|
||||
uint8_t * m_NextReceivedBuffer, * m_NextSendBuffer;
|
||||
uint8_t m_ReceiveIV[8], m_SendIV[8];
|
||||
union
|
||||
{
|
||||
uint8_t buf[8];
|
||||
uint16_t key;
|
||||
} m_ReceiveIV, m_SendIV;
|
||||
uint64_t m_ReceiveSequenceNumber, m_SendSequenceNumber;
|
||||
|
||||
i2p::I2NPMessagesHandler m_Handler;
|
||||
|
||||
bool m_IsSending;
|
||||
std::list<std::shared_ptr<I2NPMessage> > m_SendQueue;
|
||||
};
|
||||
|
||||
class NTCP2Server
|
||||
@@ -89,14 +222,28 @@ namespace transport
|
||||
void Start ();
|
||||
void Stop ();
|
||||
|
||||
bool AddNTCP2Session (std::shared_ptr<NTCP2Session> session);
|
||||
void RemoveNTCP2Session (std::shared_ptr<NTCP2Session> session);
|
||||
std::shared_ptr<NTCP2Session> FindNTCP2Session (const i2p::data::IdentHash& ident);
|
||||
|
||||
boost::asio::io_service& GetService () { return m_Service; };
|
||||
|
||||
void Connect(const boost::asio::ip::address & address, uint16_t port, std::shared_ptr<NTCP2Session> conn);
|
||||
|
||||
NTCP2FrameBuffer * NewNTCP2FrameBuffer () { return m_NTCP2FrameBuffersPool.Acquire(); }
|
||||
void DeleteNTCP2FrameBuffer (NTCP2FrameBuffer * buf) { return m_NTCP2FrameBuffersPool.Release(buf); }
|
||||
|
||||
private:
|
||||
|
||||
void Run ();
|
||||
void HandleConnect (const boost::system::error_code& ecode, std::shared_ptr<NTCP2Session> conn);
|
||||
void HandleAccept (std::shared_ptr<NTCP2Session> conn, const boost::system::error_code& error);
|
||||
void HandleAcceptV6 (std::shared_ptr<NTCP2Session> conn, const boost::system::error_code& error);
|
||||
|
||||
void HandleConnect (const boost::system::error_code& ecode, std::shared_ptr<NTCP2Session> conn, std::shared_ptr<boost::asio::deadline_timer> timer);
|
||||
|
||||
// timer
|
||||
void ScheduleTermination ();
|
||||
void HandleTerminationTimer (const boost::system::error_code& ecode);
|
||||
|
||||
private:
|
||||
|
||||
@@ -104,6 +251,17 @@ namespace transport
|
||||
std::thread * m_Thread;
|
||||
boost::asio::io_service m_Service;
|
||||
boost::asio::io_service::work m_Work;
|
||||
boost::asio::deadline_timer m_TerminationTimer;
|
||||
std::unique_ptr<boost::asio::ip::tcp::acceptor> m_NTCP2Acceptor, m_NTCP2V6Acceptor;
|
||||
std::map<i2p::data::IdentHash, std::shared_ptr<NTCP2Session> > m_NTCP2Sessions;
|
||||
std::list<std::shared_ptr<NTCP2Session> > m_PendingIncomingSessions;
|
||||
|
||||
i2p::util::MemoryPool<NTCP2FrameBuffer> m_NTCP2FrameBuffersPool;
|
||||
|
||||
public:
|
||||
|
||||
// for HTTP/I2PControl
|
||||
const decltype(m_NTCP2Sessions)& GetNTCP2Sessions () const { return m_NTCP2Sessions; };
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,7 +402,7 @@ namespace transport
|
||||
uint32_t tsA1 = be32toh (tsA);
|
||||
if (tsA1 < ts - NTCP_CLOCK_SKEW || tsA1 > ts + NTCP_CLOCK_SKEW)
|
||||
{
|
||||
LogPrint (eLogError, "NTCP: Phase3 time difference ", ts - tsA1, " exceeds clock skew");
|
||||
LogPrint (eLogError, "NTCP: Phase3 time difference ", (int)(ts - tsA1), " exceeds clock skew");
|
||||
Terminate ();
|
||||
return;
|
||||
}
|
||||
@@ -485,7 +485,7 @@ namespace transport
|
||||
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
||||
if (tsB < ts - NTCP_CLOCK_SKEW || tsB > ts + NTCP_CLOCK_SKEW)
|
||||
{
|
||||
LogPrint (eLogError, "NTCP: Phase4 time difference ", ts - tsB, " exceeds clock skew");
|
||||
LogPrint (eLogError, "NTCP: Phase4 time difference ", (int)(ts - tsB), " exceeds clock skew");
|
||||
Terminate ();
|
||||
return;
|
||||
}
|
||||
@@ -819,7 +819,7 @@ namespace transport
|
||||
for (const auto& address: addresses)
|
||||
{
|
||||
if (!address) continue;
|
||||
if (address->transportStyle == i2p::data::RouterInfo::eTransportNTCP)
|
||||
if (address->transportStyle == i2p::data::RouterInfo::eTransportNTCP && !address->IsNTCP2 ())
|
||||
{
|
||||
if (address->host.is_v4())
|
||||
{
|
||||
|
||||
@@ -130,18 +130,17 @@ namespace data
|
||||
lastDestinationCleanup = ts;
|
||||
}
|
||||
|
||||
if (ts - lastPublish >= NETDB_PUBLISH_INTERVAL && !m_HiddenMode) // publish
|
||||
if (ts - lastPublish >= NETDB_PUBLISH_INTERVAL) // update timestamp and publish
|
||||
{
|
||||
Publish ();
|
||||
i2p::context.UpdateTimestamp (ts);
|
||||
if (!m_HiddenMode) Publish ();
|
||||
lastPublish = ts;
|
||||
}
|
||||
if (ts - lastExploratory >= 30) // exploratory every 30 seconds
|
||||
{
|
||||
auto numRouters = m_RouterInfos.size ();
|
||||
if (numRouters == 0)
|
||||
{
|
||||
throw std::runtime_error("No known routers, reseed seems to be totally failed");
|
||||
}
|
||||
if (!numRouters)
|
||||
throw std::runtime_error("No known routers, reseed seems to be totally failed");
|
||||
else // we have peers now
|
||||
m_FloodfillBootstrap = nullptr;
|
||||
if (numRouters < 2500 || ts - lastExploratory >= 90)
|
||||
@@ -734,7 +733,7 @@ namespace data
|
||||
m_Requests.RequestComplete (ident, nullptr);
|
||||
}
|
||||
else
|
||||
// no more requests for detination possible. delete it
|
||||
// no more requests for destination possible. delete it
|
||||
m_Requests.RequestComplete (ident, nullptr);
|
||||
}
|
||||
else if(!m_FloodfillBootstrap)
|
||||
|
||||
@@ -133,9 +133,14 @@ namespace crypto
|
||||
|
||||
struct Poly1305
|
||||
{
|
||||
|
||||
#if (__GNUC__ == 4) && (__GNUC_MINOR__ < 8) // older than gcc 4.8
|
||||
Poly1305(const uint8_t * key) : m_Leftover(0), m_Final(0)
|
||||
{
|
||||
memset (&m_H, 0, sizeof (m_H));
|
||||
#else
|
||||
Poly1305(const uint8_t * key) : m_Leftover(0), m_H{0}, m_Final(0)
|
||||
{
|
||||
#endif
|
||||
m_R.PutKey(key);
|
||||
m_Pad.Put(key + 16);
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ namespace data
|
||||
BN_CTX * bnctx = BN_CTX_new ();
|
||||
BIGNUM * s = BN_new (), * n = BN_new ();
|
||||
BN_bin2bn (signature, signatureLength, s);
|
||||
BN_bin2bn (it->second, i2p::crypto::RSASHA5124096_KEY_LENGTH, n);
|
||||
BN_bin2bn (it->second, 512, n); // RSA 4096 assumed
|
||||
BN_mod_exp (s, s, i2p::crypto::GetRSAE (), n, bnctx); // s = s^e mod n
|
||||
uint8_t * enSigBuf = new uint8_t[signatureLength];
|
||||
i2p::crypto::bn2buf (s, enSigBuf, signatureLength);
|
||||
@@ -300,7 +300,7 @@ namespace data
|
||||
s.read (localFileName, fileNameLength);
|
||||
localFileName[fileNameLength] = 0;
|
||||
s.seekg (extraFieldLength, std::ios::cur);
|
||||
// take care about data desriptor if presented
|
||||
// take care about data descriptor if presented
|
||||
if (bitFlag & ZIP_BIT_FLAG_DATA_DESCRIPTOR)
|
||||
{
|
||||
size_t pos = s.tellg ();
|
||||
|
||||
@@ -50,7 +50,9 @@ namespace i2p
|
||||
port = rand () % (30777 - 9111) + 9111; // I2P network ports range
|
||||
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
|
||||
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2", ntcp2);
|
||||
bool ssu; i2p::config::GetOption("ssu", ssu);
|
||||
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||
bool nat; i2p::config::GetOption("nat", nat);
|
||||
std::string ifname; i2p::config::GetOption("ifname", ifname);
|
||||
std::string ifname4; i2p::config::GetOption("ifname4", ifname4);
|
||||
@@ -67,8 +69,10 @@ namespace i2p
|
||||
if(ifname4.size())
|
||||
host = i2p::util::net::GetInterfaceAddress(ifname4, false).to_string();
|
||||
|
||||
routerInfo.AddSSUAddress (host.c_str(), port, routerInfo.GetIdentHash ());
|
||||
routerInfo.AddNTCPAddress (host.c_str(), port);
|
||||
if (ssu)
|
||||
routerInfo.AddSSUAddress (host.c_str(), port, routerInfo.GetIdentHash ());
|
||||
if (ntcp)
|
||||
routerInfo.AddNTCPAddress (host.c_str(), port);
|
||||
}
|
||||
if (ipv6)
|
||||
{
|
||||
@@ -81,8 +85,10 @@ namespace i2p
|
||||
if(ifname6.size())
|
||||
host = i2p::util::net::GetInterfaceAddress(ifname6, true).to_string();
|
||||
|
||||
routerInfo.AddSSUAddress (host.c_str(), port, routerInfo.GetIdentHash ());
|
||||
routerInfo.AddNTCPAddress (host.c_str(), port);
|
||||
if (ssu)
|
||||
routerInfo.AddSSUAddress (host.c_str(), port, routerInfo.GetIdentHash ());
|
||||
if (ntcp)
|
||||
routerInfo.AddNTCPAddress (host.c_str(), port);
|
||||
}
|
||||
|
||||
routerInfo.SetCaps (i2p::data::RouterInfo::eReachable |
|
||||
@@ -93,11 +99,12 @@ namespace i2p
|
||||
m_RouterInfo.SetRouterIdentity (GetIdentity ());
|
||||
m_RouterInfo.Update (routerInfo.GetBuffer (), routerInfo.GetBufferLen ());
|
||||
|
||||
if (ntcp2)
|
||||
if (ntcp2) // we don't store iv in the address if non published so we must update it from keys
|
||||
{
|
||||
NewNTCP2Keys ();
|
||||
m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv);
|
||||
if (!m_NTCP2Keys) NewNTCP2Keys ();
|
||||
UpdateNTCP2Address (true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void RouterContext::UpdateRouterInfo ()
|
||||
@@ -109,12 +116,12 @@ namespace i2p
|
||||
|
||||
void RouterContext::NewNTCP2Keys ()
|
||||
{
|
||||
m_StaticKeys.reset (new i2p::crypto::X25519Keys ());
|
||||
m_StaticKeys->GenerateKeys ();
|
||||
m_NTCP2Keys.reset (new NTCP2PrivateKeys ());
|
||||
RAND_bytes (m_NTCP2Keys->staticPrivateKey, 32);
|
||||
m_StaticKeys->GetPrivateKey (m_NTCP2Keys->staticPrivateKey);
|
||||
memcpy (m_NTCP2Keys->staticPublicKey, m_StaticKeys->GetPublicKey (), 32);
|
||||
RAND_bytes (m_NTCP2Keys->iv, 16);
|
||||
BN_CTX * ctx = BN_CTX_new ();
|
||||
i2p::crypto::GetEd25519 ()->ScalarMulB (m_NTCP2Keys->staticPrivateKey, m_NTCP2Keys->staticPublicKey, ctx);
|
||||
BN_CTX_free (ctx);
|
||||
// save
|
||||
std::ofstream fk (i2p::fs::DataDirPath (NTCP2_KEYS), std::ofstream::binary | std::ofstream::out);
|
||||
fk.write ((char *)m_NTCP2Keys.get (), sizeof (NTCP2PrivateKeys));
|
||||
@@ -145,7 +152,7 @@ namespace i2p
|
||||
bool updated = false;
|
||||
for (auto& address : m_RouterInfo.GetAddresses ())
|
||||
{
|
||||
if (address->port != port)
|
||||
if (!address->IsNTCP2 () && address->port != port)
|
||||
{
|
||||
address->port = port;
|
||||
updated = true;
|
||||
@@ -155,6 +162,53 @@ namespace i2p
|
||||
UpdateRouterInfo ();
|
||||
}
|
||||
|
||||
void RouterContext::PublishNTCP2Address (int port, bool publish)
|
||||
{
|
||||
if (!m_NTCP2Keys) return;
|
||||
if (!port)
|
||||
port = rand () % (30777 - 9111) + 9111; // I2P network ports range
|
||||
bool updated = false;
|
||||
for (auto& address : m_RouterInfo.GetAddresses ())
|
||||
{
|
||||
if (address->IsNTCP2 () && (address->port != port || address->ntcp2->isPublished != publish))
|
||||
{
|
||||
address->port = port;
|
||||
address->cost = publish ? 3 : 14;
|
||||
address->ntcp2->isPublished = publish;
|
||||
address->ntcp2->iv = m_NTCP2Keys->iv;
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
if (updated)
|
||||
UpdateRouterInfo ();
|
||||
}
|
||||
|
||||
void RouterContext::UpdateNTCP2Address (bool enable)
|
||||
{
|
||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
||||
bool found = false, updated = false;
|
||||
for (auto it = addresses.begin (); it != addresses.end (); ++it)
|
||||
{
|
||||
if ((*it)->IsNTCP2 ())
|
||||
{
|
||||
found = true;
|
||||
if (!enable)
|
||||
{
|
||||
addresses.erase (it);
|
||||
updated= true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (enable && !found)
|
||||
{
|
||||
m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv);
|
||||
updated = true;
|
||||
}
|
||||
if (updated)
|
||||
UpdateRouterInfo ();
|
||||
}
|
||||
|
||||
void RouterContext::UpdateAddress (const boost::asio::ip::address& host)
|
||||
{
|
||||
bool updated = false;
|
||||
@@ -291,7 +345,7 @@ namespace i2p
|
||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
||||
for (auto it = addresses.begin (); it != addresses.end (); ++it)
|
||||
{
|
||||
if ((*it)->transportStyle == i2p::data::RouterInfo::eTransportNTCP &&
|
||||
if ((*it)->transportStyle == i2p::data::RouterInfo::eTransportNTCP && !(*it)->IsNTCP2 () &&
|
||||
(*it)->host.is_v4 ())
|
||||
{
|
||||
addresses.erase (it);
|
||||
@@ -318,16 +372,19 @@ namespace i2p
|
||||
caps |= i2p::data::RouterInfo::eFloodfill;
|
||||
m_RouterInfo.SetCaps (caps);
|
||||
|
||||
// insert NTCP back
|
||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
||||
for (const auto& addr : addresses)
|
||||
{
|
||||
if (addr->transportStyle == i2p::data::RouterInfo::eTransportSSU &&
|
||||
addr->host.is_v4 ())
|
||||
// insert NTCP back
|
||||
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
|
||||
if (ntcp) {
|
||||
for (const auto& addr : addresses)
|
||||
{
|
||||
// insert NTCP address with host/port from SSU
|
||||
m_RouterInfo.AddNTCPAddress (addr->host.to_string ().c_str (), addr->port);
|
||||
break;
|
||||
if (addr->transportStyle == i2p::data::RouterInfo::eTransportSSU &&
|
||||
addr->host.is_v4 ())
|
||||
{
|
||||
// insert NTCP address with host/port from SSU
|
||||
m_RouterInfo.AddNTCPAddress (addr->host.to_string ().c_str (), addr->port);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// delete previous introducers
|
||||
@@ -397,6 +454,39 @@ namespace i2p
|
||||
UpdateRouterInfo ();
|
||||
}
|
||||
|
||||
void RouterContext::UpdateNTCP2V6Address (const boost::asio::ip::address& host)
|
||||
{
|
||||
bool updated = false, found = false;
|
||||
int port = 0;
|
||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
||||
for (auto& addr: addresses)
|
||||
{
|
||||
if (addr->IsPublishedNTCP2 ())
|
||||
{
|
||||
if (addr->host.is_v6 ())
|
||||
{
|
||||
if (addr->host != host)
|
||||
{
|
||||
addr->host = host;
|
||||
updated = true;
|
||||
}
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
port = addr->port; // NTCP2 v4
|
||||
}
|
||||
}
|
||||
|
||||
if (!found && port) // we have found NTCP2 v4 but not v6
|
||||
{
|
||||
m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, host, port);
|
||||
updated = true;
|
||||
}
|
||||
if (updated)
|
||||
UpdateRouterInfo ();
|
||||
}
|
||||
|
||||
void RouterContext::UpdateStats ()
|
||||
{
|
||||
if (m_IsFloodfill)
|
||||
@@ -408,6 +498,12 @@ namespace i2p
|
||||
}
|
||||
}
|
||||
|
||||
void RouterContext::UpdateTimestamp (uint64_t ts)
|
||||
{
|
||||
if (ts > m_LastUpdateTime + ROUTER_INFO_UPDATE_INTERVAL)
|
||||
UpdateRouterInfo ();
|
||||
}
|
||||
|
||||
bool RouterContext::Load ()
|
||||
{
|
||||
std::ifstream fk (i2p::fs::DataDirPath (ROUTER_KEYS), std::ifstream::in | std::ifstream::binary);
|
||||
@@ -429,7 +525,21 @@ namespace i2p
|
||||
m_Keys.FromBuffer (buf, len);
|
||||
delete[] buf;
|
||||
}
|
||||
|
||||
// read NTCP2 keys if available
|
||||
std::ifstream n2k (i2p::fs::DataDirPath (NTCP2_KEYS), std::ifstream::in | std::ifstream::binary);
|
||||
if (n2k)
|
||||
{
|
||||
n2k.seekg (0, std::ios::end);
|
||||
len = n2k.tellg();
|
||||
n2k.seekg (0, std::ios::beg);
|
||||
if (len == sizeof (NTCP2PrivateKeys))
|
||||
{
|
||||
m_NTCP2Keys.reset (new NTCP2PrivateKeys ());
|
||||
n2k.read ((char *)m_NTCP2Keys.get (), sizeof (NTCP2PrivateKeys));
|
||||
}
|
||||
n2k.close ();
|
||||
}
|
||||
// read RouterInfo
|
||||
m_RouterInfo.SetRouterIdentity (GetIdentity ());
|
||||
i2p::data::RouterInfo routerInfo(i2p::fs::DataDirPath (ROUTER_INFO));
|
||||
if (!routerInfo.IsUnreachable ()) // router.info looks good
|
||||
@@ -452,28 +562,14 @@ namespace i2p
|
||||
SetReachable (); // we assume reachable until we discover firewall through peer tests
|
||||
|
||||
// read NTCP2
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2", ntcp2);
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||
if (ntcp2)
|
||||
{
|
||||
std::ifstream n2k (i2p::fs::DataDirPath (NTCP2_KEYS), std::ifstream::in | std::ifstream::binary);
|
||||
if (n2k)
|
||||
{
|
||||
n2k.seekg (0, std::ios::end);
|
||||
len = fk.tellg();
|
||||
n2k.seekg (0, std::ios::beg);
|
||||
if (len == sizeof (NTCP2PrivateKeys))
|
||||
{
|
||||
m_NTCP2Keys.reset (new NTCP2PrivateKeys ());
|
||||
n2k.read ((char *)m_NTCP2Keys.get (), sizeof (NTCP2PrivateKeys));
|
||||
}
|
||||
n2k.close ();
|
||||
}
|
||||
if (!m_NTCP2Keys)
|
||||
{
|
||||
NewNTCP2Keys ();
|
||||
m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv);
|
||||
}
|
||||
if (!m_NTCP2Keys) NewNTCP2Keys ();
|
||||
UpdateNTCP2Address (true); // enable NTCP2
|
||||
}
|
||||
else
|
||||
UpdateNTCP2Address (false); // disable NTCP2
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -531,4 +627,18 @@ namespace i2p
|
||||
{
|
||||
return m_Decryptor ? m_Decryptor->Decrypt (encrypted, data, ctx, false) : false;
|
||||
}
|
||||
|
||||
i2p::crypto::X25519Keys& RouterContext::GetStaticKeys ()
|
||||
{
|
||||
if (!m_StaticKeys)
|
||||
{
|
||||
if (!m_NTCP2Keys) NewNTCP2Keys ();
|
||||
auto x = new i2p::crypto::X25519Keys (m_NTCP2Keys->staticPrivateKey, m_NTCP2Keys->staticPublicKey);
|
||||
if (!m_StaticKeys)
|
||||
m_StaticKeys.reset (x);
|
||||
else
|
||||
delete x;
|
||||
}
|
||||
return *m_StaticKeys;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ namespace i2p
|
||||
const uint8_t * GetNTCP2StaticPublicKey () const { return m_NTCP2Keys ? m_NTCP2Keys->staticPublicKey : nullptr; };
|
||||
const uint8_t * GetNTCP2StaticPrivateKey () const { return m_NTCP2Keys ? m_NTCP2Keys->staticPrivateKey : nullptr; };
|
||||
const uint8_t * GetNTCP2IV () const { return m_NTCP2Keys ? m_NTCP2Keys->iv : nullptr; };
|
||||
i2p::crypto::X25519Keys& GetStaticKeys ();
|
||||
|
||||
uint32_t GetUptime () const;
|
||||
uint32_t GetStartupTime () const { return m_StartupTime; };
|
||||
@@ -78,6 +79,8 @@ namespace i2p
|
||||
|
||||
void UpdatePort (int port); // called from Daemon
|
||||
void UpdateAddress (const boost::asio::ip::address& host); // called from SSU or Daemon
|
||||
void PublishNTCP2Address (int port, bool publish = true);
|
||||
void UpdateNTCP2Address (bool enable);
|
||||
bool AddIntroducer (const i2p::data::RouterInfo::Introducer& introducer);
|
||||
void RemoveIntroducer (const boost::asio::ip::udp::endpoint& e);
|
||||
bool IsUnreachable () const;
|
||||
@@ -98,7 +101,9 @@ namespace i2p
|
||||
void SetSupportsV4 (bool supportsV4);
|
||||
|
||||
void UpdateNTCPV6Address (const boost::asio::ip::address& host); // called from NTCP session
|
||||
void UpdateNTCP2V6Address (const boost::asio::ip::address& host); // called from NTCP2 session
|
||||
void UpdateStats ();
|
||||
void UpdateTimestamp (uint64_t ts); // in seconds, called from NetDb before publishing
|
||||
void CleanupDestination (); // garlic destination
|
||||
|
||||
// implements LocalDestination
|
||||
@@ -130,7 +135,7 @@ namespace i2p
|
||||
i2p::data::RouterInfo m_RouterInfo;
|
||||
i2p::data::PrivateKeys m_Keys;
|
||||
std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> m_Decryptor;
|
||||
uint64_t m_LastUpdateTime;
|
||||
uint64_t m_LastUpdateTime; // in seconds
|
||||
bool m_AcceptsTunnels, m_IsFloodfill;
|
||||
uint64_t m_StartupTime; // in seconds since epoch
|
||||
uint64_t m_BandwidthLimit; // allowed bandwidth
|
||||
@@ -140,6 +145,7 @@ namespace i2p
|
||||
int m_NetID;
|
||||
std::mutex m_GarlicMutex;
|
||||
std::unique_ptr<NTCP2PrivateKeys> m_NTCP2Keys;
|
||||
std::unique_ptr<i2p::crypto::X25519Keys> m_StaticKeys;
|
||||
};
|
||||
|
||||
extern RouterContext context;
|
||||
|
||||
@@ -176,13 +176,13 @@ namespace data
|
||||
auto address = std::make_shared<Address>();
|
||||
s.read ((char *)&address->cost, sizeof (address->cost));
|
||||
s.read ((char *)&address->date, sizeof (address->date));
|
||||
bool isNtcp2 = false;
|
||||
bool isNTCP2Only = false;
|
||||
char transportStyle[6];
|
||||
auto transportStyleLen = ReadString (transportStyle, 6, s) - 1;
|
||||
if (!strncmp (transportStyle, "NTCP", 4)) // NTCP or NTCP2
|
||||
{
|
||||
address->transportStyle = eTransportNTCP;
|
||||
if (transportStyleLen > 4 || transportStyle[4] == '2') isNtcp2= true;
|
||||
if (transportStyleLen > 4 && transportStyle[4] == '2') isNTCP2Only= true;
|
||||
}
|
||||
else if (!strcmp (transportStyle, "SSU"))
|
||||
{
|
||||
@@ -259,6 +259,7 @@ namespace data
|
||||
if (!address->ntcp2) address->ntcp2.reset (new NTCP2Ext ());
|
||||
supportedTransports |= (address->host.is_v4 ()) ? eNTCP2V4 : eNTCP2V6;
|
||||
Base64ToByteStream (value, strlen (value), address->ntcp2->iv, 16);
|
||||
address->ntcp2->isPublished = true; // presence if "i" means "published"
|
||||
}
|
||||
else if (key[0] == 'i')
|
||||
{
|
||||
@@ -292,7 +293,8 @@ namespace data
|
||||
if (!s) return;
|
||||
}
|
||||
if (introducers) supportedTransports |= eSSUV4; // in case if host is not presented
|
||||
if (supportedTransports && !isNtcp2) // we ignore NTCP2 addresses for now. TODO:
|
||||
if (isNTCP2Only && address->ntcp2) address->ntcp2->isNTCP2Only = true;
|
||||
if (supportedTransports)
|
||||
{
|
||||
addresses->push_back(address);
|
||||
m_SupportedTransports |= supportedTransports;
|
||||
@@ -373,7 +375,7 @@ namespace data
|
||||
break;
|
||||
case CAPS_FLAG_EXTRA_BANDWIDTH1:
|
||||
case CAPS_FLAG_EXTRA_BANDWIDTH2:
|
||||
m_Caps |= Caps::eExtraBandwidth;
|
||||
m_Caps |= Caps::eExtraBandwidth | Caps::eHighBandwidth;
|
||||
break;
|
||||
case CAPS_FLAG_HIDDEN:
|
||||
m_Caps |= Caps::eHidden;
|
||||
@@ -404,16 +406,14 @@ namespace data
|
||||
if (m_Caps & eExtraBandwidth) caps += (m_Caps & eHighBandwidth) ?
|
||||
CAPS_FLAG_EXTRA_BANDWIDTH2 : // 'X'
|
||||
CAPS_FLAG_EXTRA_BANDWIDTH1; // 'P'
|
||||
caps += CAPS_FLAG_HIGH_BANDWIDTH3; // 'O'
|
||||
else
|
||||
caps += CAPS_FLAG_HIGH_BANDWIDTH3; // 'O'
|
||||
caps += CAPS_FLAG_FLOODFILL; // floodfill
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_Caps & eExtraBandwidth)
|
||||
{
|
||||
caps += (m_Caps & eHighBandwidth) ? CAPS_FLAG_EXTRA_BANDWIDTH2 /* 'X' */ : CAPS_FLAG_EXTRA_BANDWIDTH1; /*'P' */
|
||||
caps += CAPS_FLAG_HIGH_BANDWIDTH3; // 'O'
|
||||
}
|
||||
else
|
||||
caps += (m_Caps & eHighBandwidth) ? CAPS_FLAG_HIGH_BANDWIDTH3 /* 'O' */: CAPS_FLAG_LOW_BANDWIDTH2 /* 'L' */; // bandwidth
|
||||
}
|
||||
@@ -455,7 +455,7 @@ namespace data
|
||||
else
|
||||
WriteString ("", s);
|
||||
|
||||
if (!address.IsNTCP2 ()) // we don't publish NTCP2 address fow now. TODO: implement
|
||||
if (!address.IsNTCP2 () || address.IsPublishedNTCP2 ())
|
||||
{
|
||||
WriteString ("host", properties);
|
||||
properties << '=';
|
||||
@@ -537,7 +537,14 @@ namespace data
|
||||
}
|
||||
}
|
||||
|
||||
if (!address.IsNTCP2 ()) // we don't publish NTCP2 address fow now. TODO: implement
|
||||
if (address.IsPublishedNTCP2 ())
|
||||
{
|
||||
// publish i for NTCP2
|
||||
WriteString ("i", properties); properties << '=';
|
||||
WriteString (address.ntcp2->iv.ToBase64 (), properties); properties << ';';
|
||||
}
|
||||
|
||||
if (!address.IsNTCP2 () || address.IsPublishedNTCP2 ())
|
||||
{
|
||||
WriteString ("port", properties);
|
||||
properties << '=';
|
||||
@@ -551,7 +558,6 @@ namespace data
|
||||
WriteString (address.ntcp2->staticKey.ToBase64 (), properties); properties << ';';
|
||||
WriteString ("v", properties); properties << '=';
|
||||
WriteString ("2", properties); properties << ';';
|
||||
// TODO: publish "i"
|
||||
}
|
||||
|
||||
uint16_t size = htobe16 (properties.str ().size ());
|
||||
@@ -660,12 +666,12 @@ namespace data
|
||||
addr->host = boost::asio::ip::address::from_string (host);
|
||||
addr->port = port;
|
||||
addr->transportStyle = eTransportNTCP;
|
||||
addr->cost = 2;
|
||||
addr->cost = 6;
|
||||
addr->date = 0;
|
||||
for (const auto& it: *m_Addresses) // don't insert same address twice
|
||||
if (*it == *addr) return;
|
||||
m_SupportedTransports |= addr->host.is_v6 () ? eNTCPV6 : eNTCPV4;
|
||||
m_Addresses->push_back(std::move(addr));
|
||||
m_Addresses->push_front(std::move(addr)); // always make NTCP first
|
||||
}
|
||||
|
||||
void RouterInfo::AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu)
|
||||
@@ -688,16 +694,17 @@ namespace data
|
||||
m_Caps |= eSSUIntroducer;
|
||||
}
|
||||
|
||||
void RouterInfo::AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv)
|
||||
void RouterInfo::AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv, const boost::asio::ip::address& host, int port)
|
||||
{
|
||||
for (const auto& it: *m_Addresses) // don't insert one more NTCP2
|
||||
if (it->ntcp2) return;
|
||||
auto addr = std::make_shared<Address>();
|
||||
addr->port = 0;
|
||||
addr->host = host;
|
||||
addr->port = port;
|
||||
addr->transportStyle = eTransportNTCP;
|
||||
addr->cost = 14;
|
||||
addr->cost = port ? 3 : 14; // override from RouterContext::PublishNTCP2Address
|
||||
addr->date = 0;
|
||||
addr->ntcp2.reset (new NTCP2Ext ());
|
||||
addr->ntcp2->isNTCP2Only = true; // NTCP2 only address
|
||||
if (port) addr->ntcp2->isPublished = true;
|
||||
memcpy (addr->ntcp2->staticKey, staticKey, 32);
|
||||
memcpy (addr->ntcp2->iv, iv, 16);
|
||||
m_Addresses->push_back(std::move(addr));
|
||||
@@ -853,37 +860,55 @@ namespace data
|
||||
|
||||
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetNTCPAddress (bool v4only) const
|
||||
{
|
||||
return GetAddress (eTransportNTCP, v4only);
|
||||
return GetAddress (
|
||||
[v4only](std::shared_ptr<const RouterInfo::Address> address)->bool
|
||||
{
|
||||
return (address->transportStyle == eTransportNTCP) && !address->IsNTCP2Only () && (!v4only || address->host.is_v4 ());
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSUAddress (bool v4only) const
|
||||
{
|
||||
return GetAddress (eTransportSSU, v4only);
|
||||
return GetAddress (
|
||||
[v4only](std::shared_ptr<const RouterInfo::Address> address)->bool
|
||||
{
|
||||
return (address->transportStyle == eTransportSSU) && (!v4only || address->host.is_v4 ());
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSUV6Address () const
|
||||
{
|
||||
return GetAddress (eTransportSSU, false, true);
|
||||
return GetAddress (
|
||||
[](std::shared_ptr<const RouterInfo::Address> address)->bool
|
||||
{
|
||||
return (address->transportStyle == eTransportSSU) && address->host.is_v6 ();
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetAddress (TransportStyle s, bool v4only, bool v6only) const
|
||||
template<typename Filter>
|
||||
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetAddress (Filter filter) const
|
||||
{
|
||||
// TODO: make it more gereric using comparator
|
||||
#if (BOOST_VERSION >= 105300)
|
||||
auto addresses = boost::atomic_load (&m_Addresses);
|
||||
#else
|
||||
auto addresses = m_Addresses;
|
||||
#endif
|
||||
for (const auto& address : *addresses)
|
||||
{
|
||||
if (address->transportStyle == s)
|
||||
{
|
||||
if ((!v4only || address->host.is_v4 ()) && (!v6only || address->host.is_v6 ()))
|
||||
return address;
|
||||
}
|
||||
}
|
||||
if (filter (address)) return address;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetNTCP2Address (bool publishedOnly, bool v4only) const
|
||||
{
|
||||
return GetAddress (
|
||||
[publishedOnly, v4only](std::shared_ptr<const RouterInfo::Address> address)->bool
|
||||
{
|
||||
return address->IsNTCP2 () && (!publishedOnly || address->IsPublishedNTCP2 ()) && (!v4only || address->host.is_v4 ());
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<RouterProfile> RouterInfo::GetProfile () const
|
||||
{
|
||||
if (!m_Profile)
|
||||
|
||||
@@ -94,6 +94,8 @@ namespace data
|
||||
{
|
||||
Tag<32> staticKey;
|
||||
Tag<16> iv;
|
||||
bool isPublished = false;
|
||||
bool isNTCP2Only = false;
|
||||
};
|
||||
|
||||
struct Address
|
||||
@@ -115,7 +117,8 @@ namespace data
|
||||
|
||||
bool operator==(const Address& other) const
|
||||
{
|
||||
return transportStyle == other.transportStyle && host == other.host && port == other.port;
|
||||
return transportStyle == other.transportStyle && IsNTCP2 () == other.IsNTCP2 () &&
|
||||
host == other.host && port == other.port;
|
||||
}
|
||||
|
||||
bool operator!=(const Address& other) const
|
||||
@@ -124,6 +127,8 @@ namespace data
|
||||
}
|
||||
|
||||
bool IsNTCP2 () const { return (bool)ntcp2; };
|
||||
bool IsPublishedNTCP2 () const { return IsNTCP2 () && ntcp2->isPublished; };
|
||||
bool IsNTCP2Only () const { return ntcp2 && ntcp2->isNTCP2Only; };
|
||||
};
|
||||
typedef std::list<std::shared_ptr<Address> > Addresses;
|
||||
|
||||
@@ -140,12 +145,13 @@ namespace data
|
||||
uint64_t GetTimestamp () const { return m_Timestamp; };
|
||||
Addresses& GetAddresses () { return *m_Addresses; }; // should be called for local RI only, otherwise must return shared_ptr
|
||||
std::shared_ptr<const Address> GetNTCPAddress (bool v4only = true) const;
|
||||
std::shared_ptr<const Address> GetNTCP2Address (bool publishedOnly, bool v4only = true) const;
|
||||
std::shared_ptr<const Address> GetSSUAddress (bool v4only = true) const;
|
||||
std::shared_ptr<const Address> GetSSUV6Address () const;
|
||||
|
||||
void AddNTCPAddress (const char * host, int port);
|
||||
void AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu = 0);
|
||||
void AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv);
|
||||
void AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv, const boost::asio::ip::address& host = boost::asio::ip::address(), int port = 0);
|
||||
bool AddIntroducer (const Introducer& introducer);
|
||||
bool RemoveIntroducer (const boost::asio::ip::udp::endpoint& e);
|
||||
void SetProperty (const std::string& key, const std::string& value); // called from RouterContext only
|
||||
@@ -213,7 +219,8 @@ namespace data
|
||||
size_t ReadString (char* str, size_t len, std::istream& s) const;
|
||||
void WriteString (const std::string& str, std::ostream& s) const;
|
||||
void ExtractCaps (const char * value);
|
||||
std::shared_ptr<const Address> GetAddress (TransportStyle s, bool v4only, bool v6only = false) const;
|
||||
template<typename Filter>
|
||||
std::shared_ptr<const Address> GetAddress (Filter filter) const;
|
||||
void UpdateCapsProperty ();
|
||||
|
||||
private:
|
||||
|
||||
@@ -320,7 +320,7 @@ namespace transport
|
||||
uint8_t * msgBuf = msg->GetSSUHeader ();
|
||||
|
||||
uint32_t fragmentNum = 0;
|
||||
while (len > 0)
|
||||
while (len > 0 && fragmentNum <= 127)
|
||||
{
|
||||
Fragment * fragment = new Fragment;
|
||||
fragment->fragmentNum = fragmentNum;
|
||||
@@ -332,7 +332,7 @@ namespace transport
|
||||
payload++;
|
||||
htobe32buf (payload, msgID);
|
||||
payload += 4;
|
||||
bool isLast = (len <= payloadSize);
|
||||
bool isLast = (len <= payloadSize) || fragmentNum == 127; // 127 fragments max
|
||||
size_t size = isLast ? len : payloadSize;
|
||||
uint32_t fragmentInfo = (fragmentNum << 17);
|
||||
if (isLast)
|
||||
|
||||
@@ -929,7 +929,13 @@ namespace transport
|
||||
if (m_State == eSessionStateEstablished)
|
||||
{
|
||||
for (const auto& it: msgs)
|
||||
if (it) m_Data.Send (it);
|
||||
if (it)
|
||||
{
|
||||
if (it->GetLength () <= SSU_MAX_I2NP_MESSAGE_SIZE)
|
||||
m_Data.Send (it);
|
||||
else
|
||||
LogPrint (eLogError, "SSU: I2NP message of size ", it->GetLength (), " can't be sent. Dropped");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ namespace transport
|
||||
const int SSU_CONNECT_TIMEOUT = 5; // 5 seconds
|
||||
const int SSU_TERMINATION_TIMEOUT = 330; // 5.5 minutes
|
||||
const int SSU_CLOCK_SKEW = 60; // in seconds
|
||||
const size_t SSU_MAX_I2NP_MESSAGE_SIZE = 32768;
|
||||
|
||||
// payload types (4 bits)
|
||||
const uint8_t PAYLOAD_TYPE_SESSION_REQUEST = 0;
|
||||
|
||||
@@ -6,6 +6,26 @@ namespace i2p
|
||||
{
|
||||
namespace crypto
|
||||
{
|
||||
#if OPENSSL_EDDSA
|
||||
EDDSA25519Verifier::EDDSA25519Verifier (const uint8_t * signingKey)
|
||||
{
|
||||
m_Pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_ED25519, NULL, signingKey, 32);
|
||||
m_MDCtx = EVP_MD_CTX_create ();
|
||||
EVP_DigestVerifyInit (m_MDCtx, NULL, NULL, NULL, m_Pkey);
|
||||
}
|
||||
|
||||
EDDSA25519Verifier::~EDDSA25519Verifier ()
|
||||
{
|
||||
EVP_MD_CTX_destroy (m_MDCtx);
|
||||
EVP_PKEY_free (m_Pkey);
|
||||
}
|
||||
|
||||
bool EDDSA25519Verifier::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const
|
||||
{
|
||||
return EVP_DigestVerify (m_MDCtx, signature, 64, buf, len);
|
||||
}
|
||||
|
||||
#else
|
||||
EDDSA25519Verifier::EDDSA25519Verifier (const uint8_t * signingKey)
|
||||
{
|
||||
memcpy (m_PublicKeyEncoded, signingKey, EDDSA25519_PUBLIC_KEY_LENGTH);
|
||||
@@ -14,6 +34,10 @@ namespace crypto
|
||||
BN_CTX_free (ctx);
|
||||
}
|
||||
|
||||
EDDSA25519Verifier::~EDDSA25519Verifier ()
|
||||
{
|
||||
}
|
||||
|
||||
bool EDDSA25519Verifier::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const
|
||||
{
|
||||
uint8_t digest[64];
|
||||
@@ -26,8 +50,9 @@ namespace crypto
|
||||
|
||||
return GetEd25519 ()->Verify (m_PublicKey, digest, signature);
|
||||
}
|
||||
#endif
|
||||
|
||||
EDDSA25519Signer::EDDSA25519Signer (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey)
|
||||
EDDSA25519SignerCompat::EDDSA25519SignerCompat (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey)
|
||||
{
|
||||
// expand key
|
||||
Ed25519::ExpandPrivateKey (signingPrivateKey, m_ExpandedPrivateKey);
|
||||
@@ -47,10 +72,58 @@ namespace crypto
|
||||
BN_CTX_free (ctx);
|
||||
}
|
||||
|
||||
void EDDSA25519Signer::Sign (const uint8_t * buf, int len, uint8_t * signature) const
|
||||
EDDSA25519SignerCompat::~EDDSA25519SignerCompat ()
|
||||
{
|
||||
}
|
||||
|
||||
void EDDSA25519SignerCompat::Sign (const uint8_t * buf, int len, uint8_t * signature) const
|
||||
{
|
||||
GetEd25519 ()->Sign (m_ExpandedPrivateKey, m_PublicKeyEncoded, buf, len, signature);
|
||||
}
|
||||
|
||||
#if OPENSSL_EDDSA
|
||||
EDDSA25519Signer::EDDSA25519Signer (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey):
|
||||
m_Fallback (nullptr)
|
||||
{
|
||||
m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_ED25519, NULL, signingPrivateKey, 32);
|
||||
uint8_t publicKey[EDDSA25519_PUBLIC_KEY_LENGTH];
|
||||
size_t len = EDDSA25519_PUBLIC_KEY_LENGTH;
|
||||
EVP_PKEY_get_raw_public_key (m_Pkey, publicKey, &len);
|
||||
if (memcmp (publicKey, signingPublicKey, EDDSA25519_PUBLIC_KEY_LENGTH))
|
||||
{
|
||||
LogPrint (eLogWarning, "EdDSA public key mismatch. Fallback");
|
||||
EVP_PKEY_free (m_Pkey);
|
||||
m_Fallback = new EDDSA25519SignerCompat (signingPrivateKey, signingPublicKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_MDCtx = EVP_MD_CTX_create ();
|
||||
EVP_DigestSignInit (m_MDCtx, NULL, NULL, NULL, m_Pkey);
|
||||
}
|
||||
}
|
||||
|
||||
EDDSA25519Signer::~EDDSA25519Signer ()
|
||||
{
|
||||
if (m_Fallback) delete m_Fallback;
|
||||
else
|
||||
{
|
||||
EVP_MD_CTX_destroy (m_MDCtx);
|
||||
EVP_PKEY_free (m_Pkey);
|
||||
}
|
||||
}
|
||||
|
||||
void EDDSA25519Signer::Sign (const uint8_t * buf, int len, uint8_t * signature) const
|
||||
{
|
||||
if (m_Fallback) return m_Fallback->Sign (buf, len, signature);
|
||||
else
|
||||
{
|
||||
size_t l = 64;
|
||||
uint8_t sig[64]; // temporary buffer for signature. openssl issue #7232
|
||||
EVP_DigestSign (m_MDCtx, sig, &l, buf, len);
|
||||
memcpy (signature, sig, 64);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/ecdsa.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/evp.h>
|
||||
#include "Crypto.h"
|
||||
#include "Ed25519.h"
|
||||
@@ -149,6 +148,7 @@ namespace crypto
|
||||
enum { hashLen = 64 };
|
||||
};
|
||||
|
||||
// EcDSA
|
||||
template<typename Hash, int curve, size_t keyLen>
|
||||
class ECDSAVerifier: public Verifier
|
||||
{
|
||||
@@ -269,97 +269,6 @@ namespace crypto
|
||||
CreateECDSARandomKeys (NID_secp521r1, ECDSAP521_KEY_LENGTH, signingPrivateKey, signingPublicKey);
|
||||
}
|
||||
|
||||
// RSA
|
||||
template<typename Hash, int type, size_t keyLen>
|
||||
class RSAVerifier: public Verifier
|
||||
{
|
||||
public:
|
||||
|
||||
RSAVerifier (const uint8_t * signingKey)
|
||||
{
|
||||
m_PublicKey = RSA_new ();
|
||||
RSA_set0_key (m_PublicKey, BN_bin2bn (signingKey, keyLen, NULL) /* n */ , BN_dup (GetRSAE ()) /* d */, NULL);
|
||||
}
|
||||
|
||||
~RSAVerifier ()
|
||||
{
|
||||
RSA_free (m_PublicKey);
|
||||
}
|
||||
|
||||
bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const
|
||||
{
|
||||
uint8_t digest[Hash::hashLen];
|
||||
Hash::CalculateHash (buf, len, digest);
|
||||
return RSA_verify (type, digest, Hash::hashLen, signature, GetSignatureLen (), m_PublicKey);
|
||||
}
|
||||
size_t GetPublicKeyLen () const { return keyLen; }
|
||||
size_t GetSignatureLen () const { return keyLen; }
|
||||
size_t GetPrivateKeyLen () const { return GetSignatureLen ()*2; };
|
||||
|
||||
private:
|
||||
|
||||
RSA * m_PublicKey;
|
||||
};
|
||||
|
||||
|
||||
template<typename Hash, int type, size_t keyLen>
|
||||
class RSASigner: public Signer
|
||||
{
|
||||
public:
|
||||
|
||||
RSASigner (const uint8_t * signingPrivateKey)
|
||||
{
|
||||
m_PrivateKey = RSA_new ();
|
||||
RSA_set0_key (m_PrivateKey, BN_bin2bn (signingPrivateKey, keyLen, NULL), /* n */
|
||||
BN_dup (GetRSAE ()) /* e */, BN_bin2bn (signingPrivateKey + keyLen, keyLen, NULL) /* d */);
|
||||
}
|
||||
|
||||
~RSASigner ()
|
||||
{
|
||||
RSA_free (m_PrivateKey);
|
||||
}
|
||||
|
||||
void Sign (const uint8_t * buf, int len, uint8_t * signature) const
|
||||
{
|
||||
uint8_t digest[Hash::hashLen];
|
||||
Hash::CalculateHash (buf, len, digest);
|
||||
unsigned int signatureLen = keyLen;
|
||||
RSA_sign (type, digest, Hash::hashLen, signature, &signatureLen, m_PrivateKey);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
RSA * m_PrivateKey;
|
||||
};
|
||||
|
||||
inline void CreateRSARandomKeys (size_t publicKeyLen, uint8_t * signingPrivateKey, uint8_t * signingPublicKey)
|
||||
{
|
||||
RSA * rsa = RSA_new ();
|
||||
BIGNUM * e = BN_dup (GetRSAE ()); // make it non-const
|
||||
RSA_generate_key_ex (rsa, publicKeyLen*8, e, NULL);
|
||||
const BIGNUM * n, * d, * e1;
|
||||
RSA_get0_key (rsa, &n, &e1, &d);
|
||||
bn2buf (n, signingPrivateKey, publicKeyLen);
|
||||
bn2buf (d, signingPrivateKey + publicKeyLen, publicKeyLen);
|
||||
bn2buf (n, signingPublicKey, publicKeyLen);
|
||||
BN_free (e); // this e is not assigned to rsa->e
|
||||
RSA_free (rsa);
|
||||
}
|
||||
|
||||
// RSA_SHA256_2048
|
||||
const size_t RSASHA2562048_KEY_LENGTH = 256;
|
||||
typedef RSAVerifier<SHA256Hash, NID_sha256, RSASHA2562048_KEY_LENGTH> RSASHA2562048Verifier;
|
||||
typedef RSASigner<SHA256Hash, NID_sha256, RSASHA2562048_KEY_LENGTH> RSASHA2562048Signer;
|
||||
|
||||
// RSA_SHA384_3072
|
||||
const size_t RSASHA3843072_KEY_LENGTH = 384;
|
||||
typedef RSAVerifier<SHA384Hash, NID_sha384, RSASHA3843072_KEY_LENGTH> RSASHA3843072Verifier;
|
||||
typedef RSASigner<SHA384Hash, NID_sha384, RSASHA3843072_KEY_LENGTH> RSASHA3843072Signer;
|
||||
|
||||
// RSA_SHA512_4096
|
||||
const size_t RSASHA5124096_KEY_LENGTH = 512;
|
||||
typedef RSAVerifier<SHA512Hash, NID_sha512, RSASHA5124096_KEY_LENGTH> RSASHA5124096Verifier;
|
||||
typedef RSASigner<SHA512Hash, NID_sha512, RSASHA5124096_KEY_LENGTH> RSASHA5124096Signer;
|
||||
|
||||
// EdDSA
|
||||
class EDDSA25519Verifier: public Verifier
|
||||
@@ -367,6 +276,8 @@ namespace crypto
|
||||
public:
|
||||
|
||||
EDDSA25519Verifier (const uint8_t * signingKey);
|
||||
~EDDSA25519Verifier ();
|
||||
|
||||
bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const;
|
||||
|
||||
size_t GetPublicKeyLen () const { return EDDSA25519_PUBLIC_KEY_LENGTH; };
|
||||
@@ -374,18 +285,25 @@ namespace crypto
|
||||
|
||||
private:
|
||||
|
||||
#if OPENSSL_EDDSA
|
||||
EVP_PKEY * m_Pkey;
|
||||
EVP_MD_CTX * m_MDCtx;
|
||||
#else
|
||||
EDDSAPoint m_PublicKey;
|
||||
uint8_t m_PublicKeyEncoded[EDDSA25519_PUBLIC_KEY_LENGTH];
|
||||
#endif
|
||||
};
|
||||
|
||||
class EDDSA25519Signer: public Signer
|
||||
class EDDSA25519SignerCompat: public Signer
|
||||
{
|
||||
public:
|
||||
|
||||
EDDSA25519Signer (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey = nullptr);
|
||||
EDDSA25519SignerCompat (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey = nullptr);
|
||||
// we pass signingPublicKey to check if it matches private key
|
||||
~EDDSA25519SignerCompat ();
|
||||
|
||||
void Sign (const uint8_t * buf, int len, uint8_t * signature) const;
|
||||
const uint8_t * GetPublicKey () const { return m_PublicKeyEncoded; };
|
||||
const uint8_t * GetPublicKey () const { return m_PublicKeyEncoded; }; // for keys creation
|
||||
|
||||
private:
|
||||
|
||||
@@ -393,11 +311,46 @@ namespace crypto
|
||||
uint8_t m_PublicKeyEncoded[EDDSA25519_PUBLIC_KEY_LENGTH];
|
||||
};
|
||||
|
||||
#if OPENSSL_EDDSA
|
||||
class EDDSA25519Signer: public Signer
|
||||
{
|
||||
public:
|
||||
|
||||
EDDSA25519Signer (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey = nullptr);
|
||||
// we pass signingPublicKey to check if it matches private key
|
||||
~EDDSA25519Signer ();
|
||||
|
||||
void Sign (const uint8_t * buf, int len, uint8_t * signature) const;
|
||||
|
||||
private:
|
||||
EVP_PKEY * m_Pkey;
|
||||
EVP_MD_CTX * m_MDCtx;
|
||||
EDDSA25519SignerCompat * m_Fallback;
|
||||
};
|
||||
#else
|
||||
|
||||
typedef EDDSA25519SignerCompat EDDSA25519Signer;
|
||||
|
||||
#endif
|
||||
|
||||
inline void CreateEDDSA25519RandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey)
|
||||
{
|
||||
#if OPENSSL_EDDSA
|
||||
EVP_PKEY *pkey = NULL;
|
||||
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id (EVP_PKEY_ED25519, NULL);
|
||||
EVP_PKEY_keygen_init (pctx);
|
||||
EVP_PKEY_keygen (pctx, &pkey);
|
||||
EVP_PKEY_CTX_free (pctx);
|
||||
size_t len = EDDSA25519_PUBLIC_KEY_LENGTH;
|
||||
EVP_PKEY_get_raw_public_key (pkey, signingPublicKey, &len);
|
||||
len = EDDSA25519_PRIVATE_KEY_LENGTH;
|
||||
EVP_PKEY_get_raw_private_key (pkey, signingPrivateKey, &len);
|
||||
EVP_PKEY_free (pkey);
|
||||
#else
|
||||
RAND_bytes (signingPrivateKey, EDDSA25519_PRIVATE_KEY_LENGTH);
|
||||
EDDSA25519Signer signer (signingPrivateKey);
|
||||
memcpy (signingPublicKey, signer.GetPublicKey (), EDDSA25519_PUBLIC_KEY_LENGTH);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -79,6 +79,7 @@ namespace transport
|
||||
bool IsTerminationTimeoutExpired (uint64_t ts) const
|
||||
{ return ts >= m_LastActivityTimestamp + GetTerminationTimeout (); };
|
||||
|
||||
virtual void SendLocalRouterInfo () { SendI2NPMessages ({ CreateDatabaseStoreMsg () }); };
|
||||
virtual void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -117,7 +117,8 @@ namespace transport
|
||||
Transports::Transports ():
|
||||
m_IsOnline (true), m_IsRunning (false), m_IsNAT (true), m_Thread (nullptr), m_Service (nullptr),
|
||||
m_Work (nullptr), m_PeerCleanupTimer (nullptr), m_PeerTestTimer (nullptr),
|
||||
m_NTCPServer (nullptr), m_SSUServer (nullptr), m_DHKeysPairSupplier (5), // 5 pre-generated keys
|
||||
m_NTCPServer (nullptr), m_SSUServer (nullptr), m_NTCP2Server (nullptr),
|
||||
m_DHKeysPairSupplier (5), // 5 pre-generated keys
|
||||
m_TotalSentBytes(0), m_TotalReceivedBytes(0), m_TotalTransitTransmittedBytes (0),
|
||||
m_InBandwidth (0), m_OutBandwidth (0), m_TransitBandwidth(0),
|
||||
m_LastInBandwidthUpdateBytes (0), m_LastOutBandwidthUpdateBytes (0),
|
||||
@@ -191,6 +192,13 @@ namespace transport
|
||||
LogPrint(eLogError, "Transports: invalid NTCP proxy url ", ntcpproxy);
|
||||
return;
|
||||
}
|
||||
// create NTCP2. TODO: move to acceptor
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||
if (ntcp2)
|
||||
{
|
||||
m_NTCP2Server = new NTCP2Server ();
|
||||
m_NTCP2Server->Start ();
|
||||
}
|
||||
|
||||
// create acceptors
|
||||
auto& addresses = context.GetRouterInfo ().GetAddresses ();
|
||||
@@ -262,6 +270,13 @@ namespace transport
|
||||
m_NTCPServer = nullptr;
|
||||
}
|
||||
|
||||
if (m_NTCP2Server)
|
||||
{
|
||||
m_NTCP2Server->Stop ();
|
||||
delete m_NTCP2Server;
|
||||
m_NTCP2Server = nullptr;
|
||||
}
|
||||
|
||||
m_DHKeysPairSupplier.Stop ();
|
||||
m_IsRunning = false;
|
||||
if (m_Service) m_Service->stop ();
|
||||
@@ -386,7 +401,22 @@ namespace transport
|
||||
{
|
||||
if (peer.router) // we have RI already
|
||||
{
|
||||
if (!peer.numAttempts) // NTCP
|
||||
if (!peer.numAttempts) // NTCP2
|
||||
{
|
||||
peer.numAttempts++;
|
||||
if (m_NTCP2Server) // we support NTCP2
|
||||
{
|
||||
// NTCP2 have priority over NTCP
|
||||
auto address = peer.router->GetNTCP2Address (true, !context.SupportsV6 ()); // published only
|
||||
if (address)
|
||||
{
|
||||
auto s = std::make_shared<NTCP2Session> (*m_NTCP2Server, peer.router);
|
||||
m_NTCP2Server->Connect (address->host, address->port, s);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (peer.numAttempts == 1) // NTCP1
|
||||
{
|
||||
peer.numAttempts++;
|
||||
auto address = peer.router->GetNTCPAddress (!context.SupportsV6 ());
|
||||
@@ -446,7 +476,7 @@ namespace transport
|
||||
else
|
||||
LogPrint (eLogDebug, "Transports: NTCP address is not present for ", i2p::data::GetIdentHashAbbreviation (ident), ", trying SSU");
|
||||
}
|
||||
if (peer.numAttempts == 1)// SSU
|
||||
if (peer.numAttempts == 2)// SSU
|
||||
{
|
||||
peer.numAttempts++;
|
||||
if (m_SSUServer && peer.router->IsSSU (!context.SupportsV6 ()))
|
||||
@@ -709,7 +739,7 @@ namespace transport
|
||||
sendDatabaseStore = false; // we have it in the list already
|
||||
}
|
||||
if (sendDatabaseStore)
|
||||
session->SendI2NPMessages ({ CreateDatabaseStoreMsg () });
|
||||
session->SendLocalRouterInfo ();
|
||||
else
|
||||
session->SetTerminationTimeout (10); // most likely it's publishing, no follow-up messages expected, set timeout to 10 seconds
|
||||
it->second.sessions.push_back (session);
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "TransportSession.h"
|
||||
#include "NTCPSession.h"
|
||||
#include "SSU.h"
|
||||
#include "NTCP2.h"
|
||||
#include "RouterInfo.h"
|
||||
#include "I2NPProtocol.h"
|
||||
#include "Identity.h"
|
||||
@@ -80,6 +81,7 @@ namespace transport
|
||||
|
||||
bool IsBoundNTCP() const { return m_NTCPServer != nullptr; }
|
||||
bool IsBoundSSU() const { return m_SSUServer != nullptr; }
|
||||
bool IsBoundNTCP2() const { return m_NTCP2Server != nullptr; }
|
||||
|
||||
bool IsOnline() const { return m_IsOnline; };
|
||||
void SetOnline (bool online) { m_IsOnline = online; };
|
||||
@@ -154,6 +156,7 @@ namespace transport
|
||||
|
||||
NTCPServer * m_NTCPServer;
|
||||
SSUServer * m_SSUServer;
|
||||
NTCP2Server * m_NTCP2Server;
|
||||
mutable std::mutex m_PeersMutex;
|
||||
std::map<i2p::data::IdentHash, Peer> m_Peers;
|
||||
|
||||
@@ -179,6 +182,7 @@ namespace transport
|
||||
// for HTTP only
|
||||
const NTCPServer * GetNTCPServer () const { return m_NTCPServer; };
|
||||
const SSUServer * GetSSUServer () const { return m_SSUServer; };
|
||||
const NTCP2Server * GetNTCP2Server () const { return m_NTCP2Server; };
|
||||
const decltype(m_Peers)& GetPeers () const { return m_Peers; };
|
||||
};
|
||||
|
||||
|
||||
@@ -511,7 +511,7 @@ namespace tunnel
|
||||
HandleI2NPMessage (msg->GetBuffer (), msg->GetLength ());
|
||||
break;
|
||||
default:
|
||||
LogPrint (eLogWarning, "Tunnel: unexpected messsage type ", (int) typeID);
|
||||
LogPrint (eLogWarning, "Tunnel: unexpected message type ", (int) typeID);
|
||||
}
|
||||
|
||||
msg = m_Queue.Get ();
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#define MAKE_VERSION(a,b,c) STRINGIZE(a) "." STRINGIZE(b) "." STRINGIZE(c)
|
||||
|
||||
#define I2PD_VERSION_MAJOR 2
|
||||
#define I2PD_VERSION_MINOR 19
|
||||
#define I2PD_VERSION_MINOR 22
|
||||
#define I2PD_VERSION_MICRO 0
|
||||
#define I2PD_VERSION_PATCH 0
|
||||
#define I2PD_VERSION MAKE_VERSION(I2PD_VERSION_MAJOR, I2PD_VERSION_MINOR, I2PD_VERSION_MICRO)
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
#define I2P_VERSION_MAJOR 0
|
||||
#define I2P_VERSION_MINOR 9
|
||||
#define I2P_VERSION_MICRO 35
|
||||
#define I2P_VERSION_MICRO 37
|
||||
#define I2P_VERSION_PATCH 0
|
||||
#define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO)
|
||||
|
||||
|
||||
@@ -377,7 +377,7 @@ namespace client
|
||||
}
|
||||
numAddresses++;
|
||||
auto it = m_Addresses.find (name);
|
||||
if (it != m_Addresses.end ()) // aleady exists ?
|
||||
if (it != m_Addresses.end ()) // already exists ?
|
||||
{
|
||||
if (it->second != ident->GetIdentHash ()) // address changed?
|
||||
{
|
||||
@@ -741,7 +741,7 @@ namespace client
|
||||
std::string response;
|
||||
uint8_t recv_buf[4096];
|
||||
bool end = false;
|
||||
int numAttempts = 5;
|
||||
int numAttempts = 0;
|
||||
while (!end)
|
||||
{
|
||||
stream->AsyncReceive (boost::asio::buffer (recv_buf, 4096),
|
||||
@@ -755,7 +755,8 @@ namespace client
|
||||
},
|
||||
SUBSCRIPTION_REQUEST_TIMEOUT);
|
||||
std::unique_lock<std::mutex> l(newDataReceivedMutex);
|
||||
if (newDataReceived.wait_for (l, std::chrono::seconds (SUBSCRIPTION_REQUEST_TIMEOUT)) == std::cv_status::timeout)
|
||||
// wait 1 more second
|
||||
if (newDataReceived.wait_for (l, std::chrono::seconds (SUBSCRIPTION_REQUEST_TIMEOUT + 1)) == std::cv_status::timeout)
|
||||
{
|
||||
LogPrint (eLogError, "Addressbook: subscriptions request timeout expired");
|
||||
numAttempts++;
|
||||
|
||||
@@ -410,18 +410,44 @@ namespace client
|
||||
|
||||
void ClientContext::ReadTunnels ()
|
||||
{
|
||||
boost::property_tree::ptree pt;
|
||||
int numClientTunnels = 0, numServerTunnels = 0;
|
||||
std::string tunConf; i2p::config::GetOption("tunconf", tunConf);
|
||||
if (tunConf == "") {
|
||||
if (tunConf.empty ())
|
||||
{
|
||||
// TODO: cleanup this in 2.8.0
|
||||
tunConf = i2p::fs::DataDirPath ("tunnels.cfg");
|
||||
if (i2p::fs::Exists(tunConf)) {
|
||||
LogPrint(eLogWarning, "FS: please rename tunnels.cfg -> tunnels.conf here: ", tunConf);
|
||||
} else {
|
||||
if (i2p::fs::Exists(tunConf))
|
||||
LogPrint(eLogWarning, "Clients: please rename tunnels.cfg -> tunnels.conf here: ", tunConf);
|
||||
else
|
||||
tunConf = i2p::fs::DataDirPath ("tunnels.conf");
|
||||
}
|
||||
LogPrint(eLogDebug, "Clients: tunnels config file: ", tunConf);
|
||||
ReadTunnels (tunConf, numClientTunnels, numServerTunnels);
|
||||
|
||||
std::string tunDir; i2p::config::GetOption("tunnelsdir", tunDir);
|
||||
if (tunDir.empty ())
|
||||
tunDir = i2p::fs::DataDirPath ("tunnels.d");
|
||||
if (i2p::fs::Exists (tunDir))
|
||||
{
|
||||
std::vector<std::string> files;
|
||||
if (i2p::fs::ReadDir (tunDir, files))
|
||||
{
|
||||
for (auto& it: files)
|
||||
{
|
||||
LogPrint(eLogDebug, "Clients: tunnels extra config file: ", it);
|
||||
ReadTunnels (it, numClientTunnels, numServerTunnels);
|
||||
}
|
||||
}
|
||||
}
|
||||
LogPrint(eLogDebug, "FS: tunnels config file: ", tunConf);
|
||||
|
||||
LogPrint (eLogInfo, "Clients: ", numClientTunnels, " I2P client tunnels created");
|
||||
LogPrint (eLogInfo, "Clients: ", numServerTunnels, " I2P server tunnels created");
|
||||
}
|
||||
|
||||
|
||||
void ClientContext::ReadTunnels (const std::string& tunConf, int& numClientTunnels, int& numServerTunnels)
|
||||
{
|
||||
boost::property_tree::ptree pt;
|
||||
try
|
||||
{
|
||||
boost::property_tree::read_ini (tunConf, pt);
|
||||
@@ -432,7 +458,6 @@ namespace client
|
||||
return;
|
||||
}
|
||||
|
||||
int numClientTunnels = 0, numServerTunnels = 0;
|
||||
for (auto& section: pt)
|
||||
{
|
||||
std::string name = section.first;
|
||||
@@ -500,7 +525,8 @@ namespace client
|
||||
if (type == I2P_TUNNELS_SECTION_TYPE_SOCKS)
|
||||
{
|
||||
// socks proxy
|
||||
auto tun = std::make_shared<i2p::proxy::SOCKSProxy>(name, address, port, false, "", destinationPort, localDestination);
|
||||
std::string outproxy = section.second.get("outproxy", "");
|
||||
auto tun = std::make_shared<i2p::proxy::SOCKSProxy>(name, address, port, !outproxy.empty(), outproxy, destinationPort, localDestination);
|
||||
clientTunnel = tun;
|
||||
clientEndpoint = tun->GetLocalEndpoint ();
|
||||
}
|
||||
@@ -671,8 +697,6 @@ namespace client
|
||||
LogPrint (eLogError, "Clients: Can't read tunnel ", name, " params: ", ex.what ());
|
||||
}
|
||||
}
|
||||
LogPrint (eLogInfo, "Clients: ", numClientTunnels, " I2P client tunnels created");
|
||||
LogPrint (eLogInfo, "Clients: ", numServerTunnels, " I2P server tunnels created");
|
||||
}
|
||||
|
||||
void ClientContext::ReadHttpProxy ()
|
||||
|
||||
@@ -87,6 +87,7 @@ namespace client
|
||||
private:
|
||||
|
||||
void ReadTunnels ();
|
||||
void ReadTunnels (const std::string& tunConf, int& numClientTunnels, int& numServerTunnels);
|
||||
void ReadHttpProxy ();
|
||||
void ReadSocksProxy ();
|
||||
template<typename Section, typename Type>
|
||||
|
||||
@@ -387,7 +387,7 @@ namespace proxy {
|
||||
LogPrint(eLogDebug, "HTTPProxy: ", m_ClientRequestURL.host);
|
||||
m_ClientRequestURL.schema = "";
|
||||
m_ClientRequestURL.host = "";
|
||||
std::string origURI = m_ClientRequest.uri; // TODO: what do we need to chage uri for?
|
||||
std::string origURI = m_ClientRequest.uri; // TODO: what do we need to change uri for?
|
||||
m_ClientRequest.uri = m_ClientRequestURL.to_string();
|
||||
|
||||
m_ClientRequest.write(m_ClientRequestBuffer);
|
||||
|
||||
@@ -250,7 +250,7 @@ namespace client
|
||||
if (handler)
|
||||
(this->*handler)(m_Payload, m_PayloadLen);
|
||||
else
|
||||
LogPrint (eLogError, "I2CP: Unknown I2CP messsage ", (int)m_Header[I2CP_HEADER_TYPE_OFFSET]);
|
||||
LogPrint (eLogError, "I2CP: Unknown I2CP message ", (int)m_Header[I2CP_HEADER_TYPE_OFFSET]);
|
||||
}
|
||||
|
||||
void I2CPSession::Terminate ()
|
||||
@@ -398,7 +398,7 @@ namespace client
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogError, "I2CP: create session signature verification falied");
|
||||
LogPrint (eLogError, "I2CP: create session signature verification failed");
|
||||
SendSessionStatusMessage (3); // invalid
|
||||
}
|
||||
}
|
||||
@@ -455,16 +455,16 @@ namespace client
|
||||
LogPrint(eLogError, "I2CP: invalid reconfigure message signature");
|
||||
}
|
||||
else
|
||||
LogPrint(eLogError, "I2CP: mapping size missmatch");
|
||||
LogPrint(eLogError, "I2CP: mapping size mismatch");
|
||||
}
|
||||
else
|
||||
LogPrint(eLogError, "I2CP: destination missmatch");
|
||||
LogPrint(eLogError, "I2CP: destination mismatch");
|
||||
}
|
||||
else
|
||||
LogPrint(eLogError, "I2CP: malfromed destination");
|
||||
}
|
||||
else
|
||||
LogPrint(eLogError, "I2CP: session missmatch");
|
||||
LogPrint(eLogError, "I2CP: session mismatch");
|
||||
}
|
||||
else
|
||||
LogPrint(eLogError, "I2CP: short message");
|
||||
|
||||
@@ -1027,11 +1027,29 @@ namespace client
|
||||
{
|
||||
auto it = params->find (SAM_PARAM_SIGNATURE_TYPE);
|
||||
if (it != params->end ())
|
||||
{
|
||||
// TODO: extract string values
|
||||
signatureType = std::stoi(it->second);
|
||||
try
|
||||
{
|
||||
signatureType = std::stoi(it->second);
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
LogPrint (eLogWarning, "SAM: ", SAM_PARAM_SIGNATURE_TYPE, "error: ", ex.what ());
|
||||
}
|
||||
}
|
||||
it = params->find (SAM_PARAM_CRYPTO_TYPE);
|
||||
if (it != params->end ())
|
||||
cryptoType = std::stoi(it->second);
|
||||
{
|
||||
try
|
||||
{
|
||||
cryptoType = std::stoi(it->second);
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
LogPrint (eLogWarning, "SAM: ", SAM_PARAM_CRYPTO_TYPE, "error: ", ex.what ());
|
||||
}
|
||||
}
|
||||
}
|
||||
localDestination = i2p::client::context.CreateNewLocalDestination (true, signatureType, cryptoType, params);
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace client
|
||||
const char SAM_NAMING_REPLY[] = "NAMING REPLY RESULT=OK NAME=ME VALUE=%s\n";
|
||||
const char SAM_DATAGRAM_RECEIVED[] = "DATAGRAM RECEIVED DESTINATION=%s SIZE=%lu\n";
|
||||
const char SAM_NAMING_REPLY_INVALID_KEY[] = "NAMING REPLY RESULT=INVALID_KEY NAME=%s\n";
|
||||
const char SAM_NAMING_REPLY_KEY_NOT_FOUND[] = "NAMING REPLY RESULT=INVALID_KEY_NOT_FOUND NAME=%s\n";
|
||||
const char SAM_NAMING_REPLY_KEY_NOT_FOUND[] = "NAMING REPLY RESULT=KEY_NOT_FOUND NAME=%s\n";
|
||||
const char SAM_PARAM_MIN[] = "MIN";
|
||||
const char SAM_PARAM_MAX[] = "MAX";
|
||||
const char SAM_PARAM_STYLE[] = "STYLE";
|
||||
|
||||
@@ -84,8 +84,8 @@ namespace proxy
|
||||
SOCKS5_HOST_UNREACH = 4, // Host unreachable
|
||||
SOCKS5_CONN_REFUSED = 5, // Connection refused by the peer
|
||||
SOCKS5_TTL_EXPIRED = 6, // TTL Expired
|
||||
SOCKS5_CMD_UNSUP = 7, // Command unsuported
|
||||
SOCKS5_ADDR_UNSUP = 8, // Address type unsuported
|
||||
SOCKS5_CMD_UNSUP = 7, // Command unsupported
|
||||
SOCKS5_ADDR_UNSUP = 8, // Address type unsupported
|
||||
SOCKS4_OK = 90, // No error for SOCKS4
|
||||
SOCKS4_FAIL = 91, // Failed establishing connecting or not allowed
|
||||
SOCKS4_IDENTD_MISSING = 92, // Couldn't connect to the identd server
|
||||
|
||||
@@ -31,16 +31,15 @@ void ClientTunnelConfig::saveToStringStream(std::stringstream& out) {
|
||||
out << "address=" << address << "\n"
|
||||
<< "port=" << port << "\n"
|
||||
<< "destination=" << dest << "\n"
|
||||
<< "keys=" << keys << "\n"
|
||||
<< "destinationport=" << destinationPort << "\n"
|
||||
<< "signaturetype=" << sigType << "\n";
|
||||
if(!keys.empty()) out << "keys=" << keys << "\n";
|
||||
}
|
||||
|
||||
|
||||
void ServerTunnelConfig::saveToStringStream(std::stringstream& out) {
|
||||
out << "host=" << host << "\n"
|
||||
<< "port=" << port << "\n"
|
||||
<< "keys=" << keys << "\n"
|
||||
<< "signaturetype=" << sigType << "\n"
|
||||
<< "inport=" << inPort << "\n"
|
||||
<< "accesslist=" << accessList << "\n"
|
||||
@@ -49,5 +48,6 @@ void ServerTunnelConfig::saveToStringStream(std::stringstream& out) {
|
||||
<< "address=" << address << "\n"
|
||||
<< "hostoverride=" << hostOverride << "\n"
|
||||
<< "webircpassword=" << webircpass << "\n";
|
||||
if(!keys.empty()) out << "keys=" << keys << "\n";
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0"?>
|
||||
<manifest package="org.purplei2p.i2pd" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="2.19.0" android:versionCode="2" android:installLocation="auto">
|
||||
<manifest package="org.purplei2p.i2pd" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="2.22.0" android:versionCode="1" android:installLocation="auto">
|
||||
<uses-sdk android:minSdkVersion="11" android:targetSdkVersion="23"/>
|
||||
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
|
||||
<!-- <application android:hardwareAccelerated="true" -->
|
||||
|
||||
@@ -51,7 +51,7 @@ interface IMinistro
|
||||
* "sources" StringArray Sources list from where Ministro will download the libs. Make sure you are using ONLY secure locations.
|
||||
* "repository" String Overwrites the default Ministro repository. Possible values: default, stable, testing and unstable
|
||||
* "required.modules" StringArray Required modules by your application
|
||||
* "application.title" String Application name, used to show more informations to user
|
||||
* "application.title" String Application name, used to show more information to user
|
||||
* "qt.provider" String Qt libs provider, currently only "necessitas" is supported.
|
||||
* "minimum.ministro.api" Integer Minimum Ministro API level, used to check if Ministro service compatible with your application. Current API Level is 3 !
|
||||
* "minimum.qt.version" Integer Minimim Qt version (e.g. 0x040800, which means Qt 4.8.0, check http://qt-project.org/doc/qt-4.8/qtglobal.html#QT_VERSION)!
|
||||
|
||||
@@ -97,7 +97,7 @@ import android.view.ActionMode.Callback;
|
||||
|
||||
public class QtActivity extends Activity
|
||||
{
|
||||
private final static int MINISTRO_INSTALL_REQUEST_CODE = 0xf3ee; // request code used to know when Ministro instalation is finished
|
||||
private final static int MINISTRO_INSTALL_REQUEST_CODE = 0xf3ee; // request code used to know when Ministro installation is finished
|
||||
private static final int MINISTRO_API_LEVEL = 5; // Ministro api level (check IMinistro.aidl file)
|
||||
private static final int NECESSITAS_API_LEVEL = 2; // Necessitas api level used by platform plugin
|
||||
private static final int QT_VERSION = 0x050100; // This app requires at least Qt version 5.1.0
|
||||
|
||||
BIN
qt/i2pd_qt/data/icons/128x128/website.i2pd.i2pd.png
Normal file
BIN
qt/i2pd_qt/data/icons/128x128/website.i2pd.i2pd.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
BIN
qt/i2pd_qt/data/icons/16x16/website.i2pd.i2pd.png
Normal file
BIN
qt/i2pd_qt/data/icons/16x16/website.i2pd.i2pd.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
BIN
qt/i2pd_qt/data/icons/22x22/website.i2pd.i2pd.png
Normal file
BIN
qt/i2pd_qt/data/icons/22x22/website.i2pd.i2pd.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
BIN
qt/i2pd_qt/data/icons/24x24/website.i2pd.i2pd.png
Normal file
BIN
qt/i2pd_qt/data/icons/24x24/website.i2pd.i2pd.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
BIN
qt/i2pd_qt/data/icons/256x256/website.i2pd.i2pd.png
Normal file
BIN
qt/i2pd_qt/data/icons/256x256/website.i2pd.i2pd.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 53 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user