Merge pull request #1223 from PurpleI2P/openssl

recent changes
This commit is contained in:
orignal 2018-08-14 13:50:44 -04:00 committed by GitHub
commit 8490e7ca7c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
54 changed files with 1905 additions and 814 deletions

2
.gitignore vendored
View File

@ -8,7 +8,7 @@ netDb
/i2pd
/libi2pd.a
/libi2pdclient.a
i2pd.exe
*.exe
# Autotools

View File

@ -68,7 +68,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 +168,7 @@
- Initial iOS support
### Changed
- Reduced file descriptiors usage
- Reduced file descriptors usage
- Strict reseed checks enabled by default
## Fixed

View File

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

View File

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

View File

@ -3,8 +3,9 @@ BREWROOT = /usr/local
BOOSTROOT = ${BREWROOT}/opt/boost
SSLROOT = ${BREWROOT}/opt/libressl
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,7 +35,7 @@ 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

View File

@ -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)
@ -64,7 +64,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

View File

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

View File

@ -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 := ${LD_DEBUG} -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

9
android/.gitignore vendored
View File

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

View File

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

1
android/assets/certificates Symbolic link
View File

@ -0,0 +1 @@
../../contrib/certificates

78
android/assets/i2pd.conf Normal file
View File

@ -0,0 +1,78 @@
## Configuration file for a typical i2pd user
## See https://i2pd.readthedocs.org/en/latest/configuration.html
## for more options you can use in this file.
#logfile = /sdcard/i2pd/i2pd.log
loglevel = none
# host = 1.2.3.4
# port = 4567
ipv4 = true
ipv6 = false
# ntcp = true
# ntcpproxy = http://127.0.0.1:8118
# ssu = true
bandwidth = O
# share = 100
# notransit = true
# floodfill = 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

View 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

View 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/

View File

@ -18,17 +18,22 @@ repositories {
}
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"
ndk {
abiFilters 'armeabi-v7a'
//abiFilters 'x86'
abiFilters 'x86'
}
externalNativeBuild {
ndkBuild {
arguments "-j4"
}
}
}
sourceSets {
@ -37,6 +42,7 @@ android {
java.srcDirs = ['src']
res.srcDirs = ['res']
jniLibs.srcDirs = ['libs']
assets.srcDirs = ['assets']
}
}
signingConfigs {

View File

@ -0,0 +1 @@
org.gradle.parallel=true

View File

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

@ -0,0 +1 @@
rootProject.name = "i2pd"

View File

@ -1,5 +1,10 @@
package org.purplei2p.i2pd;
import java.io.File;
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 +15,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;
@ -36,7 +43,7 @@ public class I2PDActivity extends Activity {
@Override
public void run() {
try {
if(textView==null)return;
if(textView==null) return;
Throwable tr = daemon.getLastThrowable();
if(tr!=null) {
textView.setText(throwableToString(tr));
@ -72,12 +79,18 @@ public class I2PDActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// copy assets
copyAsset("certificates");
copyAsset("i2pd.conf");
copyAsset("subsciptions.txt");
copyAsset("tunnels.conf");
textView = new TextView(this);
setContentView(textView);
daemon.addStateChangeListener(daemonStateUpdatedListener);
daemonStateUpdatedListener.daemonStateUpdate();
//set the app be foreground
// set the app be foreground
doBindService();
final Timer gracefulQuitTimer = getGracefulQuitTimer();
@ -119,7 +132,7 @@ public class I2PDActivity extends Activity {
return sw.toString();
}
// private LocalService mBoundService;
// private LocalService mBoundService;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
@ -128,11 +141,11 @@ public class I2PDActivity extends Activity {
// 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();
// mBoundService = ((LocalService.LocalBinder)service).getService();
// Tell the user about this for our demo.
// Toast.makeText(Binding.this, R.string.local_service_connected,
// Toast.LENGTH_SHORT).show();
// Toast.makeText(Binding.this, R.string.local_service_connected,
// Toast.LENGTH_SHORT).show();
}
public void onServiceDisconnected(ComponentName className) {
@ -140,9 +153,9 @@ public class I2PDActivity extends Activity {
// 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();
// mBoundService = null;
// Toast.makeText(Binding.this, R.string.local_service_disconnected,
// Toast.LENGTH_SHORT).show();
}
};
@ -282,4 +295,65 @@ public class I2PDActivity extends Activity {
private static void setGracefulQuitTimer(Timer 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(Environment.getExternalStorageDirectory().getAbsolutePath() + "/i2pd/", 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(Environment.getExternalStorageDirectory().getAbsolutePath() + "/i2pd/", path);
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);
}
}
}

18
android_binary_only/.gitignore vendored Normal file
View 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

View File

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

View File

@ -62,12 +62,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 i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates && make clean" > build/build_win%bitness%_avx_aesni.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 i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates && make clean" > build/build_win%bitness%_avx.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 i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates && make clean" > build/build_win%bitness%_aesni.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 i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates && make clean" > build/build_win%bitness%.log 2>&1
:EOF

View File

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

View File

@ -5,6 +5,7 @@
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/algorithm/string.hpp>
#include "Base.h"
#include "FS.h"
@ -259,14 +260,21 @@ 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&nbsp;&nbsp; supported <br>\r\n";
continue;
}
switch (address->transportStyle)
{
case i2p::data::RouterInfo::eTransportNTCP:
if (address->host.is_v6 ())
s << "NTCP6&nbsp;&nbsp;";
else
s << "NTCP&nbsp;&nbsp;";
{
s << "NTCP";
if (address->IsPublishedNTCP2 ()) s << "2";
if (address->host.is_v6 ()) s << "6";
s << "&nbsp;&nbsp;";
break;
}
case i2p::data::RouterInfo::eTransportSSU:
if (address->host.is_v6 ())
s << "SSU6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
@ -540,14 +548,8 @@ namespace http {
}
}
void ShowTransports (std::stringstream& s)
{
s << "<b>Transports:</b><br>\r\n<br>\r\n";
auto ntcpServer = i2p::transport::transports.GetNTCPServer ();
if (ntcpServer)
{
auto sessions = ntcpServer->GetNTCPSessions ();
if (!sessions.empty ())
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 )
@ -576,15 +578,32 @@ namespace http {
}
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 << "<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_ntcp6'><b>NTCP6</b> ( " << cnt6 << " )</label>\r\n<input type='checkbox' id='slide_ntcp6'/>\r\n<p class='content'>";
s << "<div class='slide'><label for='slide_ntcp6'><b>" << name << "6</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";
}
}
void ShowTransports (std::stringstream& s)
{
s << "<b>Transports:</b><br>\r\n<br>\r\n";
auto ntcpServer = i2p::transport::transports.GetNTCPServer ();
if (ntcpServer)
{
auto sessions = ntcpServer->GetNTCPSessions ();
if (!sessions.empty ())
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)
@ -862,7 +881,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;
}

2
debian/i2pd.1 vendored
View File

@ -96,7 +96,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"

2
debian/rules vendored
View File

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

View File

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

View File

@ -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__)
}
}
}

View File

@ -59,7 +59,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 +231,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(false), "Enable NTCP2 (default: disabled)")
("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 +255,7 @@ namespace config {
.add(trust)
.add(websocket)
.add(exploratory)
.add(ntcp2)
;
}

View File

@ -522,9 +522,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 +543,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 +579,7 @@ namespace crypto
}
// AES
#ifdef AESNI
#ifdef __AES__
#ifdef ARM64AES
void init_aesenc(void){
// TODO: Implementation
@ -632,7 +611,7 @@ namespace crypto
"movaps %%xmm3, "#round1"(%[sched]) \n"
#endif
#ifdef AESNI
#ifdef __AES__
void ECBCryptoAESNI::ExpandKey (const AESKey& key)
{
__asm__
@ -673,7 +652,7 @@ namespace crypto
#endif
#if AESNI
#ifdef __AES__
#define EncryptAES256(sched) \
"pxor (%["#sched"]), %%xmm0 \n" \
"aesenc 16(%["#sched"]), %%xmm0 \n" \
@ -694,9 +673,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 +683,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 +712,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 +722,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 +739,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 +753,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 +775,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 +786,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 +808,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 +831,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 +847,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 +878,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 +901,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 +917,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 +953,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 +966,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 +995,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 +1018,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 +1035,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 +1092,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);

View File

@ -69,9 +69,9 @@ namespace crypto
void operator^=(const ChipherBlock& other) // XOR
{
#ifdef __AVX__
if (i2p::cpu::avx)
{
#ifdef AVX
__asm__
(
"vmovups (%[buf]), %%xmm0 \n"
@ -82,12 +82,9 @@ 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++)
@ -123,7 +120,7 @@ namespace crypto
};
#ifdef AESNI
#ifdef __AES__
#ifdef ARM64AES
void init_aesenc(void) __attribute__((constructor));
#endif
@ -143,7 +140,7 @@ namespace crypto
};
#endif
#ifdef AESNI
#ifdef __AES__
class ECBEncryption: public ECBCryptoAESNI
#else
class ECBEncryption
@ -159,7 +156,7 @@ namespace crypto
AES_KEY m_Key;
};
#ifdef AESNI
#ifdef __AES__
class ECBDecryption: public ECBCryptoAESNI
#else
class ECBDecryption
@ -265,7 +262,12 @@ 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
#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
#endif
#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)

View File

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

View File

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

View File

@ -719,7 +719,9 @@ namespace data
XORMetric operator^(const IdentHash& key1, const IdentHash& key2)
{
XORMetric m;
#if defined(__AVX__) // for AVX
#ifdef __AVX__
if(i2p::cpu::avx)
{
__asm__
(
"vmovups %1, %%ymm0 \n"
@ -730,13 +732,16 @@ namespace data
: "m"(*key1), "m"(*key2)
: "memory", "%xmm0", "%xmm1" // should be replaced by %ymm0/1 once supported by compiler
);
#else
}
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];
#endif
}
return m;
}

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,12 @@
#include <inttypes.h>
#include <memory>
#include <thread>
#include <list>
#include <map>
#include <array>
#include <openssl/bn.h>
#include <boost/asio.hpp>
#include "util.h"
#include "RouterInfo.h"
#include "TransportSession.h"
@ -12,6 +17,91 @@ 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
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_EphemeralPublicKey; };
const uint8_t * GetPriv () const { return m_EphemeralPrivateKey; };
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, uint8_t * derived);
void KeyDerivationFunction1 (const uint8_t * pub, const uint8_t * 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);
BN_CTX * m_Ctx;
uint8_t m_EphemeralPrivateKey[32], m_EphemeralPublicKey[32], 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 +110,28 @@ 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 ();
// establish
void CreateEphemeralKey (uint8_t * pub);
void SendSessionRequest ();
void SendSessionCreated ();
void SendSessionConfirmed ();
@ -50,6 +143,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 +154,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 +166,23 @@ 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, * m_SendSipKey, * m_ReceiveSipKey;
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 +195,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 +224,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; };
};
}
}

View File

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

View File

@ -734,7 +734,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)

View File

@ -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);
}

View File

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

View File

@ -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,7 +69,9 @@ namespace i2p
if(ifname4.size())
host = i2p::util::net::GetInterfaceAddress(ifname4, false).to_string();
if (ssu)
routerInfo.AddSSUAddress (host.c_str(), port, routerInfo.GetIdentHash ());
if (ntcp)
routerInfo.AddNTCPAddress (host.c_str(), port);
}
if (ipv6)
@ -81,7 +85,9 @@ namespace i2p
if(ifname6.size())
host = i2p::util::net::GetInterfaceAddress(ifname6, true).to_string();
if (ssu)
routerInfo.AddSSUAddress (host.c_str(), port, routerInfo.GetIdentHash ());
if (ntcp)
routerInfo.AddNTCPAddress (host.c_str(), port);
}
@ -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 ()
@ -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,50 @@ namespace i2p
UpdateRouterInfo ();
}
void RouterContext::PublishNTCP2Address (int port, bool publish)
{
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->ntcp2->isPublished = publish;
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 +342,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,8 +369,10 @@ namespace i2p
caps |= i2p::data::RouterInfo::eFloodfill;
m_RouterInfo.SetCaps (caps);
// insert NTCP back
auto& addresses = m_RouterInfo.GetAddresses ();
// insert NTCP back
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
if (ntcp) {
for (const auto& addr : addresses)
{
if (addr->transportStyle == i2p::data::RouterInfo::eTransportSSU &&
@ -330,6 +383,7 @@ namespace i2p
break;
}
}
}
// delete previous introducers
for (auto& addr : addresses)
if (addr->ssu)
@ -429,7 +483,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 +520,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;
}

View File

@ -78,6 +78,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;

View File

@ -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;
@ -455,7 +457,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 +539,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 +560,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 ());
@ -665,7 +673,7 @@ namespace data
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)
@ -698,6 +706,7 @@ namespace data
addr->cost = 14;
addr->date = 0;
addr->ntcp2.reset (new NTCP2Ext ());
addr->ntcp2->isNTCP2Only = true; // NTCP2 only address
memcpy (addr->ntcp2->staticKey, staticKey, 32);
memcpy (addr->ntcp2->iv, iv, 16);
m_Addresses->push_back(std::move(addr));
@ -853,37 +862,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)

View File

@ -94,6 +94,8 @@ namespace data
{
Tag<32> staticKey;
Tag<16> iv;
bool isPublished = false;
bool isNTCP2Only = false;
};
struct Address
@ -124,6 +126,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,6 +144,7 @@ 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;
@ -213,7 +218,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:

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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");

View File

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

View File

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

View File

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