mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-03-07 06:09:42 +00:00
Compare commits
128 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3ab5ac66b6 | ||
|
|
18cb3912e5 | ||
|
|
a818b0ba02 | ||
|
|
3716b6f988 | ||
|
|
c9e4e78f41 | ||
|
|
9b4e8bf64b | ||
|
|
5aebefe73f | ||
|
|
8f2124beab | ||
|
|
8b8b43df28 | ||
|
|
c42b991bc9 | ||
|
|
ec08333bf9 | ||
|
|
9e5b4e14c9 | ||
|
|
1f5ed89a88 | ||
|
|
2304a2bc2e | ||
|
|
dc82105226 | ||
|
|
5221f3ddc9 | ||
|
|
e970deb92b | ||
|
|
9db7ec6bb0 | ||
|
|
2e691b6655 | ||
|
|
f22e10537b | ||
|
|
6e532c494c | ||
|
|
f9ed0d4aa2 | ||
|
|
78b1afcc8c | ||
|
|
40340cf9c2 | ||
|
|
eb6437050f | ||
|
|
45ebfe378b | ||
|
|
1326597226 | ||
|
|
751da92c13 | ||
|
|
e10ca637da | ||
|
|
c5d9d71a8a | ||
|
|
3e0f5d231d | ||
|
|
6990f177ba | ||
|
|
98e713166b | ||
|
|
4c91ae0085 | ||
|
|
43f74d4d5a | ||
|
|
8c3e716c3f | ||
|
|
05946125b5 | ||
|
|
1e2a0a4549 | ||
|
|
f9f5084dd7 | ||
|
|
b7e7c6db7b | ||
|
|
f9d67b28ec | ||
|
|
46b77cc280 | ||
|
|
2f10decf56 | ||
|
|
678a1ae0fb | ||
|
|
51cbffd097 | ||
|
|
207b13dcab | ||
|
|
3052dbd1e8 | ||
|
|
5891b1ceb2 | ||
|
|
07e14ddda8 | ||
|
|
db5e90787c | ||
|
|
67e501f5c7 | ||
|
|
2160001167 | ||
|
|
f5f4150d17 | ||
|
|
887f292612 | ||
|
|
f5f282af97 | ||
|
|
82f9585b7a | ||
|
|
eb561bb0c2 | ||
|
|
81207999eb | ||
|
|
2fef595b83 | ||
|
|
2024e790ca | ||
|
|
f9925c7374 | ||
|
|
dd774b8dfd | ||
|
|
064b8042a5 | ||
|
|
7923ed9567 | ||
|
|
30b83414ef | ||
|
|
990906c57f | ||
|
|
4c323a666a | ||
|
|
a3f165d374 | ||
|
|
4977f9e6b4 | ||
|
|
7d5f51e357 | ||
|
|
371a339b18 | ||
|
|
7e7aee27b6 | ||
|
|
53148fe58f | ||
|
|
56b6de6962 | ||
|
|
44735681af | ||
|
|
ee1c4f4fdc | ||
|
|
fb6ecdde1e | ||
|
|
861166d8a9 | ||
|
|
70dca81c40 | ||
|
|
2774d72888 | ||
|
|
2440ffbfc9 | ||
|
|
77c5dde320 | ||
|
|
aa49cad279 | ||
|
|
f56ae240ab | ||
|
|
e871a30a78 | ||
|
|
30e6984889 | ||
|
|
324932c758 | ||
|
|
421800bc8f | ||
|
|
86fb47b2b4 | ||
|
|
715f83bf84 | ||
|
|
87bf5c2418 | ||
|
|
5c9af1c613 | ||
|
|
765e0e5c6b | ||
|
|
cc296e16dc | ||
|
|
ab9901525b | ||
|
|
3643a46a0c | ||
|
|
d467e6869d | ||
|
|
db36018849 | ||
|
|
3c5c375f71 | ||
|
|
7473d8c9aa | ||
|
|
33645d7f09 | ||
|
|
9f1106b14a | ||
|
|
3dd952b49b | ||
|
|
6b85bd2cb8 | ||
|
|
60b164c853 | ||
|
|
40c8a1bc1d | ||
|
|
22de695f12 | ||
|
|
e91f588cd7 | ||
|
|
7b72d91549 | ||
|
|
b3c2e86436 | ||
|
|
908bdc7624 | ||
|
|
21c1ec9c8c | ||
|
|
6d7d71bb16 | ||
|
|
6eba061c2a | ||
|
|
f184f550b9 | ||
|
|
bb7c0fef20 | ||
|
|
5c15a12116 | ||
|
|
68d015763e | ||
|
|
7faa732f38 | ||
|
|
11f9eeabf1 | ||
|
|
a152f36894 | ||
|
|
d4ede6ff01 | ||
|
|
35542d803c | ||
|
|
f6ba776c12 | ||
|
|
1511dcb309 | ||
|
|
35afa98112 | ||
|
|
df62b40ca7 | ||
|
|
9f1a125ed9 |
38
.github/workflows/build-windows.yml
vendored
38
.github/workflows/build-windows.yml
vendored
@@ -35,3 +35,41 @@ jobs:
|
||||
with:
|
||||
name: i2pd-${{ matrix.arch_short }}.exe
|
||||
path: i2pd.exe
|
||||
build-xp:
|
||||
name: Building for Windows XP
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup MSYS2
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: MINGW32
|
||||
install: base-devel git mingw-w64-i686-gcc mingw-w64-i686-boost mingw-w64-i686-openssl mingw-w64-i686-miniupnpc
|
||||
update: true
|
||||
- name: Build WinXP-capable CRT packages
|
||||
run: |
|
||||
git clone https://github.com/msys2/MINGW-packages
|
||||
pushd MINGW-packages
|
||||
pushd mingw-w64-headers-git
|
||||
sed -i 's/0x601/0x501/' PKGBUILD
|
||||
MINGW_ARCH=mingw32 makepkg-mingw -sCLf --noconfirm
|
||||
pacman --noconfirm -U mingw-w64-i686-headers-git-*-any.pkg.tar.zst
|
||||
popd
|
||||
pushd mingw-w64-crt-git
|
||||
MINGW_ARCH=mingw32 makepkg-mingw -sCLf --noconfirm
|
||||
pacman --noconfirm -U mingw-w64-i686-crt-git-*-any.pkg.tar.zst
|
||||
popd
|
||||
pushd mingw-w64-winpthreads-git
|
||||
MINGW_ARCH=mingw32 makepkg-mingw -sCLf --noconfirm
|
||||
pacman --noconfirm -U mingw-w64-i686-libwinpthread-git-*-any.pkg.tar.zst mingw-w64-i686-winpthreads-git-*-any.pkg.tar.zst
|
||||
popd
|
||||
popd
|
||||
- name: Build application
|
||||
run: |
|
||||
mkdir -p obj/Win32 obj/libi2pd obj/libi2pd_client obj/daemon
|
||||
make USE_UPNP=yes DEBUG=no USE_GIT_VERSION=yes USE_WINXP_FLAGS=yes -j3
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: i2pd-xp.exe
|
||||
path: i2pd.exe
|
||||
|
||||
26
Makefile
26
Makefile
@@ -31,7 +31,6 @@ include filelist.mk
|
||||
|
||||
USE_AESNI := $(or $(USE_AESNI),yes)
|
||||
USE_STATIC := $(or $(USE_STATIC),no)
|
||||
USE_MESHNET := $(or $(USE_MESHNET),no)
|
||||
USE_UPNP := $(or $(USE_UPNP),no)
|
||||
DEBUG := $(or $(DEBUG),yes)
|
||||
|
||||
@@ -41,6 +40,12 @@ USE_GIT_VERSION := $(or $(USE_GIT_VERSION),no)
|
||||
# for MacOS only, waiting for "1", not "yes"
|
||||
HOMEBREW := $(or $(HOMEBREW),0)
|
||||
|
||||
# Client protocols
|
||||
USE_I2PC := $(or $(USE_I2PC),yes)
|
||||
USE_I2CP := $(or $(USE_I2CP),yes)
|
||||
USE_SAM := $(or $(USE_SAM),yes)
|
||||
USE_BOB := $(or $(USE_BOB),yes)
|
||||
|
||||
ifeq ($(DEBUG),yes)
|
||||
CXX_DEBUG = -g
|
||||
else
|
||||
@@ -48,6 +53,19 @@ else
|
||||
LD_DEBUG = -s
|
||||
endif
|
||||
|
||||
ifeq ($(USE_I2PC),yes)
|
||||
NEEDED_CXXFLAGS += -DWITH_I2PC
|
||||
endif
|
||||
ifeq ($(USE_I2CP),yes)
|
||||
NEEDED_CXXFLAGS += -DWITH_I2CP
|
||||
endif
|
||||
ifeq ($(USE_SAM),yes)
|
||||
NEEDED_CXXFLAGS += -DWITH_SAM
|
||||
endif
|
||||
ifeq ($(USE_BOB),yes)
|
||||
NEEDED_CXXFLAGS += -DWITH_BOB
|
||||
endif
|
||||
|
||||
ifneq (, $(findstring darwin, $(SYS)))
|
||||
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
|
||||
ifeq ($(HOMEBREW),1)
|
||||
@@ -62,16 +80,12 @@ else ifneq (, $(findstring freebsd, $(SYS))$(findstring openbsd, $(SYS)))
|
||||
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
|
||||
include Makefile.bsd
|
||||
else ifneq (, $(findstring mingw, $(SYS))$(findstring cygwin, $(SYS)))
|
||||
DAEMON_SRC += Win32/DaemonWin32.cpp Win32/Win32App.cpp Win32/Win32NetState.cpp
|
||||
DAEMON_SRC += Win32/DaemonWin32.cpp Win32/Win32App.cpp Win32/Win32Service.cpp Win32/Win32NetState.cpp
|
||||
include Makefile.mingw
|
||||
else # not supported
|
||||
$(error Not supported platform)
|
||||
endif
|
||||
|
||||
ifeq ($(USE_MESHNET),yes)
|
||||
NEEDED_CXXFLAGS += -DMESHNET
|
||||
endif
|
||||
|
||||
ifeq ($(USE_GIT_VERSION),yes)
|
||||
GIT_VERSION := $(shell git describe --tags)
|
||||
NEEDED_CXXFLAGS += -DGITVER=\"$(GIT_VERSION)\"
|
||||
|
||||
@@ -39,13 +39,14 @@ ifeq ($(USE_AESNI),yes)
|
||||
endif
|
||||
|
||||
install: all
|
||||
install -d ${PREFIX}/bin ${PREFIX}/etc/i2pd ${PREFIX}/share/doc/i2pd ${PREFIX}/share/i2pd ${PREFIX}/share/man/man1 ${PREFIX}/var/lib/i2pd
|
||||
install -d ${PREFIX}/bin ${PREFIX}/etc/i2pd ${PREFIX}/etc/i2pd/tunnels.conf.d ${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 -kf 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/tunnels.conf.d ${PREFIX}/var/lib/i2pd/tunnels.d
|
||||
@ln -sf ${PREFIX}/etc/i2pd/i2pd.conf ${PREFIX}/var/lib/i2pd/i2pd.conf
|
||||
@ln -sf ${PREFIX}/etc/i2pd/subscriptions.txt ${PREFIX}/var/lib/i2pd/subscriptions.txt
|
||||
@ln -sf ${PREFIX}/etc/i2pd/tunnels.conf ${PREFIX}/var/lib/i2pd/tunnels.conf
|
||||
|
||||
@@ -62,3 +62,16 @@ ifneq (, $(findstring i386, $(SYS))$(findstring i686, $(SYS))$(findstring x86_64
|
||||
NEEDED_CXXFLAGS += -D__AES__ -maes
|
||||
endif
|
||||
endif
|
||||
|
||||
install: all
|
||||
install -d ${PREFIX}/bin ${PREFIX}/etc ${PREFIX}/etc/i2pd ${PREFIX}/etc/i2pd/tunnels.conf.d ${PREFIX}/usr ${PREFIX}/usr/share ${PREFIX}/usr/share/doc/i2pd ${PREFIX}/usr/share/i2pd ${PREFIX}/usr/share/man ${PREFIX}/usr/share/man/man1 ${PREFIX}/var/lib ${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}/usr/share/i2pd/
|
||||
install -m 644 ChangeLog LICENSE README.md contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/usr/share/doc/i2pd
|
||||
@gzip -kf debian/i2pd.1 && install debian/i2pd.1.gz ${PREFIX}/usr/share/man/man1
|
||||
@ln -sf ${PREFIX}/usr/share/i2pd/certificates ${PREFIX}/var/lib/i2pd/
|
||||
@ln -sf ${PREFIX}/etc/i2pd/tunnels.conf.d ${PREFIX}/var/lib/i2pd/tunnels.d
|
||||
@ln -sf ${PREFIX}/etc/i2pd/i2pd.conf ${PREFIX}/var/lib/i2pd/i2pd.conf
|
||||
@ln -sf ${PREFIX}/etc/i2pd/subscriptions.txt ${PREFIX}/var/lib/i2pd/subscriptions.txt
|
||||
@ln -sf ${PREFIX}/etc/i2pd/tunnels.conf ${PREFIX}/var/lib/i2pd/tunnels.conf
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "Log.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "Win32Service.h"
|
||||
#ifdef WIN32_APP
|
||||
#include <windows.h>
|
||||
#include "Win32App.h"
|
||||
@@ -39,6 +40,19 @@ namespace util
|
||||
|
||||
if (!Daemon_Singleton::init(argc, argv))
|
||||
return false;
|
||||
|
||||
if (isDaemon)
|
||||
{
|
||||
LogPrint(eLogDebug, "Daemon: running as service");
|
||||
I2PService service((PSTR)SERVICE_NAME);
|
||||
if (!I2PService::Run(service))
|
||||
{
|
||||
LogPrint(eLogError, "Daemon: Service failed to run w/err 0x%08lx\n", GetLastError());
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
283
Win32/Win32Service.cpp
Normal file
283
Win32/Win32Service.cpp
Normal file
@@ -0,0 +1,283 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#include "Win32Service.h"
|
||||
#include <assert.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "Daemon.h"
|
||||
#include "Log.h"
|
||||
|
||||
I2PService *I2PService::s_service = NULL;
|
||||
|
||||
BOOL I2PService::isService()
|
||||
{
|
||||
BOOL bIsService = FALSE;
|
||||
HWINSTA hWinStation = GetProcessWindowStation();
|
||||
if (hWinStation != NULL)
|
||||
{
|
||||
USEROBJECTFLAGS uof = { 0 };
|
||||
if (GetUserObjectInformation(hWinStation, UOI_FLAGS, &uof, sizeof(USEROBJECTFLAGS), NULL) && ((uof.dwFlags & WSF_VISIBLE) == 0))
|
||||
{
|
||||
bIsService = TRUE;
|
||||
}
|
||||
}
|
||||
return bIsService;
|
||||
}
|
||||
|
||||
BOOL I2PService::Run(I2PService &service)
|
||||
{
|
||||
s_service = &service;
|
||||
SERVICE_TABLE_ENTRY serviceTable[] =
|
||||
{
|
||||
{ service.m_name, ServiceMain },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
return StartServiceCtrlDispatcher(serviceTable);
|
||||
}
|
||||
|
||||
void WINAPI I2PService::ServiceMain(DWORD dwArgc, PSTR *pszArgv)
|
||||
{
|
||||
assert(s_service != NULL);
|
||||
s_service->m_statusHandle = RegisterServiceCtrlHandler(
|
||||
s_service->m_name, ServiceCtrlHandler);
|
||||
if (s_service->m_statusHandle == NULL)
|
||||
{
|
||||
throw GetLastError();
|
||||
}
|
||||
s_service->Start(dwArgc, pszArgv);
|
||||
}
|
||||
|
||||
|
||||
void WINAPI I2PService::ServiceCtrlHandler(DWORD dwCtrl)
|
||||
{
|
||||
switch (dwCtrl)
|
||||
{
|
||||
case SERVICE_CONTROL_STOP: s_service->Stop(); break;
|
||||
case SERVICE_CONTROL_PAUSE: s_service->Pause(); break;
|
||||
case SERVICE_CONTROL_CONTINUE: s_service->Continue(); break;
|
||||
case SERVICE_CONTROL_SHUTDOWN: s_service->Shutdown(); break;
|
||||
case SERVICE_CONTROL_INTERROGATE: break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
I2PService::I2PService(PSTR pszServiceName,
|
||||
BOOL fCanStop,
|
||||
BOOL fCanShutdown,
|
||||
BOOL fCanPauseContinue)
|
||||
{
|
||||
m_name = (pszServiceName == NULL) ? (PSTR)"" : pszServiceName;
|
||||
m_statusHandle = NULL;
|
||||
m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
|
||||
m_status.dwCurrentState = SERVICE_START_PENDING;
|
||||
|
||||
DWORD dwControlsAccepted = 0;
|
||||
if (fCanStop)
|
||||
dwControlsAccepted |= SERVICE_ACCEPT_STOP;
|
||||
if (fCanShutdown)
|
||||
dwControlsAccepted |= SERVICE_ACCEPT_SHUTDOWN;
|
||||
if (fCanPauseContinue)
|
||||
dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE;
|
||||
|
||||
m_status.dwControlsAccepted = dwControlsAccepted;
|
||||
m_status.dwWin32ExitCode = NO_ERROR;
|
||||
m_status.dwServiceSpecificExitCode = 0;
|
||||
m_status.dwCheckPoint = 0;
|
||||
m_status.dwWaitHint = 0;
|
||||
m_fStopping = FALSE;
|
||||
// Create a manual-reset event that is not signaled at first to indicate
|
||||
// the stopped signal of the service.
|
||||
m_hStoppedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
if (m_hStoppedEvent == NULL)
|
||||
{
|
||||
throw GetLastError();
|
||||
}
|
||||
}
|
||||
|
||||
I2PService::~I2PService(void)
|
||||
{
|
||||
if (m_hStoppedEvent)
|
||||
{
|
||||
CloseHandle(m_hStoppedEvent);
|
||||
m_hStoppedEvent = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void I2PService::Start(DWORD dwArgc, PSTR *pszArgv)
|
||||
{
|
||||
try
|
||||
{
|
||||
SetServiceStatus(SERVICE_START_PENDING);
|
||||
OnStart(dwArgc, pszArgv);
|
||||
SetServiceStatus(SERVICE_RUNNING);
|
||||
}
|
||||
catch (DWORD dwError)
|
||||
{
|
||||
LogPrint(eLogError, "Win32Service: Start error: ", dwError);
|
||||
SetServiceStatus(SERVICE_STOPPED, dwError);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LogPrint(eLogError, "Win32Service: failed to start: ", EVENTLOG_ERROR_TYPE);
|
||||
SetServiceStatus(SERVICE_STOPPED);
|
||||
}
|
||||
}
|
||||
|
||||
void I2PService::OnStart(DWORD dwArgc, PSTR *pszArgv)
|
||||
{
|
||||
LogPrint(eLogInfo, "Win32Service: in OnStart (", EVENTLOG_INFORMATION_TYPE, ")");
|
||||
Daemon.start();
|
||||
_worker = new std::thread(std::bind(&I2PService::WorkerThread, this));
|
||||
}
|
||||
|
||||
void I2PService::WorkerThread()
|
||||
{
|
||||
while (!m_fStopping)
|
||||
{
|
||||
::Sleep(1000); // Simulate some lengthy operations.
|
||||
}
|
||||
// Signal the stopped event.
|
||||
SetEvent(m_hStoppedEvent);
|
||||
}
|
||||
|
||||
void I2PService::Stop()
|
||||
{
|
||||
DWORD dwOriginalState = m_status.dwCurrentState;
|
||||
try
|
||||
{
|
||||
SetServiceStatus(SERVICE_STOP_PENDING);
|
||||
OnStop();
|
||||
SetServiceStatus(SERVICE_STOPPED);
|
||||
}
|
||||
catch (DWORD dwError)
|
||||
{
|
||||
LogPrint(eLogInfo, "Win32Service: Stop error: ", dwError);
|
||||
SetServiceStatus(dwOriginalState);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LogPrint(eLogError, "Win32Service: Failed to stop: ", EVENTLOG_ERROR_TYPE);
|
||||
SetServiceStatus(dwOriginalState);
|
||||
}
|
||||
}
|
||||
|
||||
void I2PService::OnStop()
|
||||
{
|
||||
// Log a service stop message to the Application log.
|
||||
LogPrint(eLogInfo, "Win32Service: in OnStop (", EVENTLOG_INFORMATION_TYPE, ")");
|
||||
Daemon.stop();
|
||||
m_fStopping = TRUE;
|
||||
if (WaitForSingleObject(m_hStoppedEvent, INFINITE) != WAIT_OBJECT_0)
|
||||
{
|
||||
throw GetLastError();
|
||||
}
|
||||
_worker->join();
|
||||
delete _worker;
|
||||
}
|
||||
|
||||
void I2PService::Pause()
|
||||
{
|
||||
try
|
||||
{
|
||||
SetServiceStatus(SERVICE_PAUSE_PENDING);
|
||||
OnPause();
|
||||
SetServiceStatus(SERVICE_PAUSED);
|
||||
}
|
||||
catch (DWORD dwError)
|
||||
{
|
||||
LogPrint(eLogError, "Win32Service: Pause error: ", dwError);
|
||||
SetServiceStatus(SERVICE_RUNNING);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LogPrint(eLogError, "Win32Service: Failed to pause: ", EVENTLOG_ERROR_TYPE);
|
||||
SetServiceStatus(SERVICE_RUNNING);
|
||||
}
|
||||
}
|
||||
|
||||
void I2PService::OnPause()
|
||||
{
|
||||
}
|
||||
|
||||
void I2PService::Continue()
|
||||
{
|
||||
try
|
||||
{
|
||||
SetServiceStatus(SERVICE_CONTINUE_PENDING);
|
||||
OnContinue();
|
||||
SetServiceStatus(SERVICE_RUNNING);
|
||||
}
|
||||
catch (DWORD dwError)
|
||||
{
|
||||
LogPrint(eLogError, "Win32Service: Continue error: ", dwError);
|
||||
SetServiceStatus(SERVICE_PAUSED);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LogPrint(eLogError, "Win32Service: Failed to resume: ", EVENTLOG_ERROR_TYPE);
|
||||
SetServiceStatus(SERVICE_PAUSED);
|
||||
}
|
||||
}
|
||||
|
||||
void I2PService::OnContinue()
|
||||
{
|
||||
}
|
||||
|
||||
void I2PService::Shutdown()
|
||||
{
|
||||
try
|
||||
{
|
||||
OnShutdown();
|
||||
SetServiceStatus(SERVICE_STOPPED);
|
||||
}
|
||||
catch (DWORD dwError)
|
||||
{
|
||||
LogPrint(eLogError, "Win32Service: Shutdown error: ", dwError);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LogPrint(eLogError, "Win32Service: Failed to shut down: ", EVENTLOG_ERROR_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
void I2PService::OnShutdown()
|
||||
{
|
||||
}
|
||||
|
||||
void I2PService::SetServiceStatus(DWORD dwCurrentState,
|
||||
DWORD dwWin32ExitCode,
|
||||
DWORD dwWaitHint)
|
||||
{
|
||||
static DWORD dwCheckPoint = 1;
|
||||
m_status.dwCurrentState = dwCurrentState;
|
||||
m_status.dwWin32ExitCode = dwWin32ExitCode;
|
||||
m_status.dwWaitHint = dwWaitHint;
|
||||
m_status.dwCheckPoint =
|
||||
((dwCurrentState == SERVICE_RUNNING) ||
|
||||
(dwCurrentState == SERVICE_STOPPED)) ?
|
||||
0 : dwCheckPoint++;
|
||||
|
||||
::SetServiceStatus(m_statusHandle, &m_status);
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
|
||||
void FreeHandles(SC_HANDLE schSCManager, SC_HANDLE schService)
|
||||
{
|
||||
if (schSCManager)
|
||||
{
|
||||
CloseServiceHandle(schSCManager);
|
||||
schSCManager = NULL;
|
||||
}
|
||||
if (schService)
|
||||
{
|
||||
CloseServiceHandle(schService);
|
||||
schService = NULL;
|
||||
}
|
||||
}
|
||||
63
Win32/Win32Service.h
Normal file
63
Win32/Win32Service.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#ifndef WIN_32_SERVICE_H__
|
||||
#define WIN_32_SERVICE_H__
|
||||
|
||||
#include <thread>
|
||||
#include <windows.h>
|
||||
|
||||
#define SERVICE_NAME "i2pdService"
|
||||
|
||||
class I2PService
|
||||
{
|
||||
public:
|
||||
|
||||
I2PService(PSTR pszServiceName,
|
||||
BOOL fCanStop = TRUE,
|
||||
BOOL fCanShutdown = TRUE,
|
||||
BOOL fCanPauseContinue = FALSE);
|
||||
|
||||
virtual ~I2PService(void);
|
||||
|
||||
static BOOL isService();
|
||||
static BOOL Run(I2PService &service);
|
||||
void Stop();
|
||||
|
||||
protected:
|
||||
|
||||
virtual void OnStart(DWORD dwArgc, PSTR *pszArgv);
|
||||
virtual void OnStop();
|
||||
virtual void OnPause();
|
||||
virtual void OnContinue();
|
||||
virtual void OnShutdown();
|
||||
void SetServiceStatus(DWORD dwCurrentState,
|
||||
DWORD dwWin32ExitCode = NO_ERROR,
|
||||
DWORD dwWaitHint = 0);
|
||||
|
||||
private:
|
||||
|
||||
static void WINAPI ServiceMain(DWORD dwArgc, LPSTR *lpszArgv);
|
||||
static void WINAPI ServiceCtrlHandler(DWORD dwCtrl);
|
||||
void WorkerThread();
|
||||
void Start(DWORD dwArgc, PSTR *pszArgv);
|
||||
void Pause();
|
||||
void Continue();
|
||||
void Shutdown();
|
||||
static I2PService* s_service;
|
||||
PSTR m_name;
|
||||
SERVICE_STATUS m_status;
|
||||
SERVICE_STATUS_HANDLE m_statusHandle;
|
||||
|
||||
BOOL m_fStopping;
|
||||
HANDLE m_hStoppedEvent;
|
||||
|
||||
std::thread* _worker;
|
||||
};
|
||||
|
||||
#endif // WIN_32_SERVICE_H__
|
||||
@@ -17,7 +17,6 @@ option(WITH_LIBRARY "Build library" ON)
|
||||
option(WITH_BINARY "Build binary" ON)
|
||||
option(WITH_STATIC "Static build" OFF)
|
||||
option(WITH_UPNP "Include support for UPnP client" OFF)
|
||||
option(WITH_MESHNET "Build for cjdns test network" OFF)
|
||||
option(WITH_ADDRSANITIZER "Build with address sanitizer unix only" OFF)
|
||||
option(WITH_THREADSANITIZER "Build with thread sanitizer unix only" OFF)
|
||||
|
||||
@@ -89,10 +88,6 @@ set(DAEMON_SRC
|
||||
"${DAEMON_SRC_DIR}/UPnP.cpp"
|
||||
)
|
||||
|
||||
if(WITH_MESHNET)
|
||||
add_definitions(-DMESHNET)
|
||||
endif()
|
||||
|
||||
if(WITH_UPNP)
|
||||
add_definitions(-DUSE_UPNP)
|
||||
endif()
|
||||
@@ -235,12 +230,6 @@ endif()
|
||||
# load includes
|
||||
include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR})
|
||||
|
||||
# warn if for meshnet
|
||||
if(WITH_MESHNET)
|
||||
message(STATUS "Building for testnet")
|
||||
message(WARNING "This build will NOT work on mainline i2p")
|
||||
endif()
|
||||
|
||||
include(CheckAtomic)
|
||||
|
||||
# show summary
|
||||
@@ -258,15 +247,10 @@ message(STATUS " LIBRARY : ${WITH_LIBRARY}")
|
||||
message(STATUS " BINARY : ${WITH_BINARY}")
|
||||
message(STATUS " STATIC BUILD : ${WITH_STATIC}")
|
||||
message(STATUS " UPnP : ${WITH_UPNP}")
|
||||
message(STATUS " MESHNET : ${WITH_MESHNET}")
|
||||
message(STATUS " ADDRSANITIZER : ${WITH_ADDRSANITIZER}")
|
||||
message(STATUS " THREADSANITIZER : ${WITH_THREADSANITIZER}")
|
||||
message(STATUS "---------------------------------------")
|
||||
|
||||
if(WITH_MESHNET)
|
||||
message(STATUS "WARNING: Using the MESHNET option will make it impossible to use the application with the main network!!!")
|
||||
endif()
|
||||
|
||||
if(WITH_BINARY)
|
||||
add_executable("${PROJECT_NAME}" ${DAEMON_SRC})
|
||||
|
||||
|
||||
18
contrib/android_binary_only/.gitignore
vendored
18
contrib/android_binary_only/.gitignore
vendored
@@ -1,18 +0,0 @@
|
||||
gen
|
||||
tests
|
||||
bin
|
||||
libs
|
||||
log*
|
||||
obj
|
||||
.gradle
|
||||
.idea
|
||||
.externalNativeBuild
|
||||
ant.properties
|
||||
local.properties
|
||||
build.sh
|
||||
android.iml
|
||||
build
|
||||
gradle
|
||||
gradlew
|
||||
gradlew.bat
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := i2pd
|
||||
LOCAL_CPP_FEATURES := rtti exceptions
|
||||
LOCAL_C_INCLUDES += $(IFADDRS_PATH) $(LIB_SRC_PATH) $(LIB_CLIENT_SRC_PATH) $(DAEMON_SRC_PATH)
|
||||
LOCAL_STATIC_LIBRARIES := \
|
||||
boost_system \
|
||||
boost_date_time \
|
||||
boost_filesystem \
|
||||
boost_program_options \
|
||||
crypto ssl \
|
||||
miniupnpc
|
||||
LOCAL_LDLIBS := -lz
|
||||
|
||||
LOCAL_SRC_FILES := $(IFADDRS_PATH)/ifaddrs.c \
|
||||
$(wildcard $(LIB_SRC_PATH)/*.cpp)\
|
||||
$(wildcard $(LIB_CLIENT_SRC_PATH)/*.cpp)\
|
||||
$(DAEMON_SRC_PATH)/UnixDaemon.cpp \
|
||||
$(DAEMON_SRC_PATH)/Daemon.cpp \
|
||||
$(DAEMON_SRC_PATH)/UPnP.cpp \
|
||||
$(DAEMON_SRC_PATH)/HTTPServer.cpp \
|
||||
$(DAEMON_SRC_PATH)/I2PControl.cpp \
|
||||
$(DAEMON_SRC_PATH)/i2pd.cpp
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := boost_system
|
||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_system.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := boost_date_time
|
||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_date_time.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := boost_filesystem
|
||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_filesystem.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := boost_program_options
|
||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_program_options.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := crypto
|
||||
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/$(TARGET_ARCH_ABI)/lib/libcrypto.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/include
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := ssl
|
||||
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/$(TARGET_ARCH_ABI)/lib/libssl.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/include
|
||||
LOCAL_STATIC_LIBRARIES := crypto
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := miniupnpc
|
||||
LOCAL_SRC_FILES := $(MINIUPNP_PATH)/miniupnpc-2.1/$(TARGET_ARCH_ABI)/lib/libminiupnpc.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(MINIUPNP_PATH)/miniupnpc-2.1/include
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
@@ -1,40 +0,0 @@
|
||||
APP_ABI := all
|
||||
#APP_ABI += x86
|
||||
#APP_ABI += x86_64
|
||||
#APP_ABI += armeabi-v7a
|
||||
#APP_ABI += arm64-v8a
|
||||
#can be android-3 but will fail for x86 since arch-x86 is not present at ndkroot/platforms/android-3/ . libz is taken from there.
|
||||
APP_PLATFORM := android-14
|
||||
|
||||
NDK_TOOLCHAIN_VERSION := clang
|
||||
APP_STL := c++_static
|
||||
|
||||
# Enable c++17 extensions in source code
|
||||
APP_CPPFLAGS += -std=c++17 -fvisibility=default -fPIE
|
||||
|
||||
APP_CPPFLAGS += -DANDROID_BINARY -DANDROID -D__ANDROID__ -DUSE_UPNP
|
||||
APP_LDFLAGS += -rdynamic -fPIE -pie
|
||||
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
|
||||
APP_CPPFLAGS += -DANDROID_ARM7A
|
||||
endif
|
||||
|
||||
# Forcing debug optimization. Use `ndk-build NDK_DEBUG=1` instead.
|
||||
#APP_OPTIM := debug
|
||||
|
||||
# git clone https://github.com/PurpleI2P/Boost-for-Android-Prebuilt.git -b boost-1_72_0
|
||||
# git clone https://github.com/PurpleI2P/OpenSSL-for-Android-Prebuilt.git
|
||||
# git clone https://github.com/PurpleI2P/MiniUPnP-for-Android-Prebuilt.git
|
||||
# git clone https://github.com/PurpleI2P/android-ifaddrs.git
|
||||
# change to your own
|
||||
I2PD_LIBS_PATH = /path/to/libraries
|
||||
BOOST_PATH = $(I2PD_LIBS_PATH)/Boost-for-Android-Prebuilt
|
||||
OPENSSL_PATH = $(I2PD_LIBS_PATH)/OpenSSL-for-Android-Prebuilt
|
||||
MINIUPNP_PATH = $(I2PD_LIBS_PATH)/MiniUPnP-for-Android-Prebuilt
|
||||
IFADDRS_PATH = $(I2PD_LIBS_PATH)/android-ifaddrs
|
||||
|
||||
# don't change me
|
||||
I2PD_SRC_PATH = $(PWD)/../..
|
||||
|
||||
LIB_SRC_PATH = $(I2PD_SRC_PATH)/libi2pd
|
||||
LIB_CLIENT_SRC_PATH = $(I2PD_SRC_PATH)/libi2pd_client
|
||||
DAEMON_SRC_PATH = $(I2PD_SRC_PATH)/daemon
|
||||
2
contrib/android_binary_pack/.gitignore
vendored
2
contrib/android_binary_pack/.gitignore
vendored
@@ -1,2 +0,0 @@
|
||||
archive
|
||||
i2pd_*_android_binary.zip
|
||||
@@ -1,48 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2013-2020, The PurpleI2P Project
|
||||
#
|
||||
# This file is part of Purple i2pd project and licensed under BSD3
|
||||
#
|
||||
# See full license text in LICENSE file at top of project tree
|
||||
|
||||
GITDESC=$(git describe --tags)
|
||||
|
||||
declare -A ABILIST=(
|
||||
["armeabi-v7a"]="armv7l"
|
||||
["arm64-v8a"]="aarch64"
|
||||
["x86"]="x86"
|
||||
["x86_64"]="x86_64"
|
||||
)
|
||||
|
||||
# Remove old files and archives
|
||||
if [ -d archive ]; then
|
||||
rm -r archive
|
||||
fi
|
||||
|
||||
if [ -f ../i2pd_*_android_binary.zip ]; then
|
||||
rm i2pd_*_android_binary.zip
|
||||
fi
|
||||
|
||||
# Prepare files for package
|
||||
mkdir archive
|
||||
|
||||
for ABI in "${!ABILIST[@]}"; do
|
||||
if [ -f ../android_binary_only/libs/${ABI}/i2pd ]; then
|
||||
cp ../android_binary_only/libs/${ABI}/i2pd archive/i2pd-${ABILIST[$ABI]}
|
||||
fi
|
||||
done
|
||||
|
||||
cp i2pd archive/i2pd
|
||||
cp -rH ../android/assets/certificates archive/
|
||||
cp -rH ../android/assets/tunnels.conf.d archive/
|
||||
cp -H ../android/assets/i2pd.conf archive/
|
||||
cp -H ../android/assets/tunnels.conf archive/
|
||||
|
||||
# Compress files
|
||||
cd archive
|
||||
zip -r6 ../i2pd_${GITDESC}_android_binary.zip .
|
||||
|
||||
# Remove temporary folder
|
||||
cd ..
|
||||
rm -r archive
|
||||
@@ -1,33 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright (c) 2013-2020, The PurpleI2P Project
|
||||
#
|
||||
# This file is part of Purple i2pd project and licensed under BSD3
|
||||
#
|
||||
# See full license text in LICENSE file at top of project tree
|
||||
#
|
||||
# That script written for use with Termux.
|
||||
|
||||
# https://stackoverflow.com/a/246128
|
||||
SOURCE="${0}"
|
||||
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
|
||||
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
|
||||
SOURCE="$(readlink "$SOURCE")"
|
||||
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
|
||||
done
|
||||
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
|
||||
|
||||
arch=$(uname -m)
|
||||
|
||||
screenfind=$(which screen)
|
||||
if [ -z $screenfind ]; then
|
||||
echo "Can't find 'screen' installed. That script needs it!";
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
if [ -z i2pd-$arch ]; then
|
||||
echo "Can't find i2pd binary for your archtecture.";
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
screen -AmdS i2pd ./i2pd-$arch --datadir=$DIR
|
||||
14
contrib/certificates/family/stormycloud.crt
Normal file
14
contrib/certificates/family/stormycloud.crt
Normal file
@@ -0,0 +1,14 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICKDCCAc6gAwIBAgIUcPHZXtYSqGNRCD6z8gp79WUFtI0wCgYIKoZIzj0EAwIw
|
||||
gZMxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEPMA0GA1UEBwwGQXVzdGlu
|
||||
MRgwFgYDVQQKDA9TdG9ybXlDbG91ZCBJbmMxIzAhBgNVBAMMGnN0b3JteWNsb3Vk
|
||||
LmZhbWlseS5pMnAubmV0MSQwIgYJKoZIhvcNAQkBFhVhZG1pbkBzdG9ybXljbG91
|
||||
ZC5vcmcwHhcNMjIwMzE5MTU1MjU2WhcNMzIwMzE2MTU1MjU2WjCBkzELMAkGA1UE
|
||||
BhMCVVMxDjAMBgNVBAgMBVRleGFzMQ8wDQYDVQQHDAZBdXN0aW4xGDAWBgNVBAoM
|
||||
D1N0b3JteUNsb3VkIEluYzEjMCEGA1UEAwwac3Rvcm15Y2xvdWQuZmFtaWx5Lmky
|
||||
cC5uZXQxJDAiBgkqhkiG9w0BCQEWFWFkbWluQHN0b3JteWNsb3VkLm9yZzBZMBMG
|
||||
ByqGSM49AgEGCCqGSM49AwEHA0IABFUli0hvJEmowNjJVjbKEIWBJhqe973S4VdL
|
||||
cJuA5yY3dC4Y998abWEox7/Y1BhnBbpJuiodA341bXKkLMXQy/kwCgYIKoZIzj0E
|
||||
AwIDSAAwRQIgD12F/TfY3iV1/WDF7BSKgbD5g2MfELUIy1dtUlJQuJUCIQD69mZw
|
||||
V1Z9j2x0ZsuirS3i6AMfVyTDj0RFS3U1jeHzIQ==
|
||||
-----END CERTIFICATE-----
|
||||
34
contrib/certificates/reseed/i2p-reseed_at_mk16.de.crt
Normal file
34
contrib/certificates/reseed/i2p-reseed_at_mk16.de.crt
Normal file
@@ -0,0 +1,34 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFzTCCA7WgAwIBAgIQeUqFi0fHNQopg6BZlBLhVzANBgkqhkiG9w0BAQsFADBy
|
||||
MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYDVQQK
|
||||
ExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEbMBkGA1UEAwwS
|
||||
aTJwLXJlc2VlZEBtazE2LmRlMB4XDTIyMDIwNTE3MzkzM1oXDTMyMDIwNTE3Mzkz
|
||||
M1owcjELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJYWDEeMBwG
|
||||
A1UEChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxGzAZBgNV
|
||||
BAMMEmkycC1yZXNlZWRAbWsxNi5kZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC
|
||||
AgoCggIBAMYxs2D2xpN/8blGawvAlU9DemHIxApOEwaLNfh8aAvqEdB41NTqcx4U
|
||||
H8VchSormCfkCvezuMHO+K2HX7ihEZ1v6tbr6aX6hY9UZUyDDYsKmJoB1oKEhddv
|
||||
5UYfcWPE2eSykdFsWgTQD6Z+cRQWHEoCzb7qc+Jrw6KcnHMD0VrmBrEQPzTBxMHW
|
||||
4HC97PVkSLJTDArnS6ZiX4IbWRPw/mbpJT6EoVZo8J/it0pdn/X4KodEXDcnEMSe
|
||||
VRulfZH/nSmOOvKhoHPckmgz/u66BlnuSYXEIB0KfDIcAlSYiPDxGnAemTozJYXA
|
||||
UVMeFMs+YE5wiPgzzu+vpC31xtZLq0gyaCfgEi1P9j2ES/8pH3Gw6W2OH4kBx+jO
|
||||
TBsfI+ph6qFZ3WWT23MRVyl3ATuI/GHdczTxD9JaOn74lLI+Hnu8wXnyztVWkTMB
|
||||
4sAnzjdeHkvNDyQ10vSaN0HnGfg6zuAuUSqFQujFF8Vg8ZCcsh8GouWfzYDvi9mj
|
||||
9pfxx8v6UCC719I4J9CgFjWnn2Hqez3fO8fFulY61VPyCCZp4gKWbI2SIQP/n5gz
|
||||
ecYJRrJoem+rYfEQ/fwxROsvm3fCO4D6dt7ILRuX286GDIw2qSvP1zZVAioMwSj3
|
||||
9CAjKLwD/BhTRiMOlpaVv6IWqjtevbiaIKvbHTnoxvkGsDqe3gJhAgMBAAGjXzBd
|
||||
MA4GA1UdDwEB/wQEAwIChDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEw
|
||||
DwYDVR0TAQH/BAUwAwEB/zAbBgNVHQ4EFAQSaTJwLXJlc2VlZEBtazE2LmRlMA0G
|
||||
CSqGSIb3DQEBCwUAA4ICAQAb+x6XpJdjpVYw2bvWIUbatQJwq0YaEW5W61xGLgIG
|
||||
a37oll3YZbSY9Vk+N1cE0f61L3ya4Ioz6zlH/MO2zUG/dEk8vqdgIPUYJvyF7wwF
|
||||
w3/G4VMaDKOJx4bAZNmaiRFGYNhCOhCnZx6uZGrLNIJ2Dc+mflrGmGwYphtXVV3e
|
||||
Iv+ki3gSRgfXuMfKi4B5bLPnz7XDe4TSmwZZSRac4ly4KqmZUyntqbilRxaGTej3
|
||||
VYJ1tac8yppyk5N3VopMQNmBarNZG16wSOTD7CtKgn382jgRW8cR7BMeqhORivp0
|
||||
ZnPJFhzh4uthdlPdXXo6lxfvZjfiwlDPytvEu2QBz3urTgopGqRLcTBnLucWg9li
|
||||
OSy9z7hNEnIN3iIJJAwI1wBdDa7K0h3PFBbIUa7X2ybn81VeNSfO25Lo8YTZEKsc
|
||||
wcThJrNV6qOQv8rM/7aXugi6+VzPlCR+18iKRbebCnlqGR2dT1zFtj3negtOkrjo
|
||||
LH4H6VUr3q2Ie56IubS2hUKiUkDm0ckP3Vum35GGntyEAzl6uyog0hJFOJb3aq30
|
||||
YQLzyVEOz8NnA+32oMRzJJdDxQ7pqG5fgq7EF4d++YSgEfdVXxvfgXQ6m3jAyC7Z
|
||||
p/gX4rlxNsjeGU3Ds51wkmhH4IB1aSQr52PE6RaBhhh3SmADEv6S/3eGvE4F4MN5
|
||||
2Q==
|
||||
-----END CERTIFICATE-----
|
||||
@@ -57,8 +57,14 @@ cd build
|
||||
%endif
|
||||
|
||||
|
||||
%if 0%{?fedora} >= 35
|
||||
%if 0%{?rhel} == 9
|
||||
pushd redhat-linux-build
|
||||
%endif
|
||||
|
||||
%if 0%{?fedora} >= 35
|
||||
%if 0%{?fedora} < 37
|
||||
pushd redhat-linux-build
|
||||
%endif
|
||||
%else
|
||||
%if 0%{?fedora} >= 33
|
||||
pushd %{_target_platform}
|
||||
@@ -71,10 +77,16 @@ pushd build
|
||||
|
||||
make %{?_smp_mflags}
|
||||
|
||||
%if 0%{?fedora} >= 33
|
||||
%if 0%{?rhel} == 9
|
||||
popd
|
||||
%endif
|
||||
|
||||
%if 0%{?fedora} >= 33
|
||||
%if 0%{?fedora} < 37
|
||||
popd
|
||||
%endif
|
||||
%endif
|
||||
|
||||
%if 0%{?mageia} > 7
|
||||
popd
|
||||
%endif
|
||||
@@ -82,8 +94,14 @@ popd
|
||||
%install
|
||||
pushd build
|
||||
|
||||
%if 0%{?fedora} >= 35
|
||||
%if 0%{?rhel} == 9
|
||||
pushd redhat-linux-build
|
||||
%endif
|
||||
|
||||
%if 0%{?fedora} >= 35
|
||||
%if 0%{?fedora} < 37
|
||||
pushd redhat-linux-build
|
||||
%endif
|
||||
%else
|
||||
%if 0%{?fedora} >= 33
|
||||
pushd %{_target_platform}
|
||||
|
||||
@@ -54,8 +54,14 @@ cd build
|
||||
%endif
|
||||
%endif
|
||||
|
||||
%if 0%{?fedora} >= 35
|
||||
%if 0%{?rhel} == 9
|
||||
pushd redhat-linux-build
|
||||
%endif
|
||||
|
||||
%if 0%{?fedora} >= 35
|
||||
%if 0%{?fedora} < 37
|
||||
pushd redhat-linux-build
|
||||
%endif
|
||||
%else
|
||||
%if 0%{?fedora} >= 33
|
||||
pushd %{_target_platform}
|
||||
@@ -68,10 +74,16 @@ pushd build
|
||||
|
||||
make %{?_smp_mflags}
|
||||
|
||||
%if 0%{?fedora} >= 33
|
||||
%if 0%{?rhel} == 9
|
||||
popd
|
||||
%endif
|
||||
|
||||
%if 0%{?fedora} >= 33
|
||||
%if 0%{?fedora} < 37
|
||||
popd
|
||||
%endif
|
||||
%endif
|
||||
|
||||
%if 0%{?mageia} > 7
|
||||
popd
|
||||
%endif
|
||||
@@ -79,8 +91,14 @@ popd
|
||||
%install
|
||||
pushd build
|
||||
|
||||
%if 0%{?fedora} >= 35
|
||||
%if 0%{?rhel} == 9
|
||||
pushd redhat-linux-build
|
||||
%endif
|
||||
|
||||
%if 0%{?fedora} >= 35
|
||||
%if 0%{?fedora} < 37
|
||||
pushd redhat-linux-build
|
||||
%endif
|
||||
%else
|
||||
%if 0%{?fedora} >= 33
|
||||
pushd %{_target_platform}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -26,7 +26,9 @@
|
||||
#include "Streaming.h"
|
||||
#include "Destination.h"
|
||||
#include "HTTPServer.h"
|
||||
#ifdef WITH_I2PC
|
||||
#include "I2PControl.h"
|
||||
#endif
|
||||
#include "ClientContext.h"
|
||||
#include "Crypto.h"
|
||||
#include "UPnP.h"
|
||||
@@ -45,7 +47,9 @@ namespace util
|
||||
~Daemon_Singleton_Private() {};
|
||||
|
||||
std::unique_ptr<i2p::http::HTTPServer> httpServer;
|
||||
#ifdef WITH_I2PC
|
||||
std::unique_ptr<i2p::client::I2PControlService> m_I2PControlService;
|
||||
#endif
|
||||
std::unique_ptr<i2p::transport::UPnP> UPnP;
|
||||
std::unique_ptr<i2p::util::NTPTimeSync> m_NTPSync;
|
||||
};
|
||||
@@ -64,6 +68,12 @@ namespace util
|
||||
return service;
|
||||
}
|
||||
|
||||
void Daemon_Singleton::setDataDir(std::string path)
|
||||
{
|
||||
if (path != "")
|
||||
DaemonDataDir = path;
|
||||
}
|
||||
|
||||
bool Daemon_Singleton::init(int argc, char* argv[]) {
|
||||
return init(argc, argv, nullptr);
|
||||
}
|
||||
@@ -73,8 +83,14 @@ namespace util
|
||||
i2p::config::Init();
|
||||
i2p::config::ParseCmdline(argc, argv);
|
||||
|
||||
std::string config; i2p::config::GetOption("conf", config);
|
||||
std::string datadir; i2p::config::GetOption("datadir", datadir);
|
||||
std::string config; i2p::config::GetOption("conf", config);
|
||||
std::string datadir;
|
||||
if(DaemonDataDir != "") {
|
||||
datadir = DaemonDataDir;
|
||||
} else {
|
||||
i2p::config::GetOption("datadir", datadir);
|
||||
}
|
||||
|
||||
i2p::fs::DetectDataDir(datadir, IsService());
|
||||
i2p::fs::Init();
|
||||
|
||||
@@ -151,11 +167,7 @@ namespace util
|
||||
|
||||
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
|
||||
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
|
||||
#ifdef MESHNET
|
||||
// manual override for meshnet
|
||||
ipv4 = false;
|
||||
ipv6 = true;
|
||||
#endif
|
||||
|
||||
// ifname -> address
|
||||
std::string ifname; i2p::config::GetOption("ifname", ifname);
|
||||
if (ipv4 && i2p::config::IsDefault ("address4"))
|
||||
@@ -244,6 +256,18 @@ namespace util
|
||||
if (!ipv4 && !ipv6)
|
||||
i2p::context.SetStatus (eRouterStatusMesh);
|
||||
}
|
||||
bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2);
|
||||
if (ssu2)
|
||||
{
|
||||
bool published; i2p::config::GetOption("ssu2.published", published);
|
||||
if (published)
|
||||
{
|
||||
uint16_t ssu2port; i2p::config::GetOption("ssu2.port", ssu2port);
|
||||
i2p::context.PublishSSU2Address (ssu2port, true, ipv4, ipv6); // publish
|
||||
}
|
||||
else
|
||||
i2p::context.PublishSSU2Address (0, false, ipv4, ipv6); // unpublish
|
||||
}
|
||||
|
||||
bool transit; i2p::config::GetOption("notransit", transit);
|
||||
i2p::context.SetAcceptsTunnels (!transit);
|
||||
@@ -377,6 +401,7 @@ namespace util
|
||||
}
|
||||
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||
bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2);
|
||||
bool ssu; i2p::config::GetOption("ssu", ssu);
|
||||
bool checkInReserved; i2p::config::GetOption("reservedrange", checkInReserved);
|
||||
LogPrint(eLogInfo, "Daemon: Starting Transports");
|
||||
@@ -384,7 +409,7 @@ namespace util
|
||||
if(!ntcp2) LogPrint(eLogInfo, "Daemon: NTCP2 disabled");
|
||||
|
||||
i2p::transport::transports.SetCheckReserved(checkInReserved);
|
||||
i2p::transport::transports.Start(ntcp2, ssu);
|
||||
i2p::transport::transports.Start(ntcp2, ssu, ssu2);
|
||||
if (i2p::transport::transports.IsBoundSSU() || i2p::transport::transports.IsBoundNTCP2())
|
||||
LogPrint(eLogInfo, "Daemon: Transports started");
|
||||
else
|
||||
@@ -420,6 +445,7 @@ namespace util
|
||||
LogPrint(eLogInfo, "Daemon: Starting Client");
|
||||
i2p::client::context.Start ();
|
||||
|
||||
#ifdef WITH_I2PC
|
||||
// I2P Control Protocol
|
||||
bool i2pcontrol; i2p::config::GetOption("i2pcontrol.enabled", i2pcontrol);
|
||||
if (i2pcontrol) {
|
||||
@@ -437,6 +463,7 @@ namespace util
|
||||
ThrowFatal ("Unable to start I2PControl service at ", i2pcpAddr, ":", i2pcpPort, ": ", ex.what ());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -469,12 +496,14 @@ namespace util
|
||||
d.httpServer->Stop();
|
||||
d.httpServer = nullptr;
|
||||
}
|
||||
#ifdef WITH_I2PC
|
||||
if (d.m_I2PControlService)
|
||||
{
|
||||
LogPrint(eLogInfo, "Daemon: Stopping I2PControl");
|
||||
d.m_I2PControlService->Stop ();
|
||||
d.m_I2PControlService = nullptr;
|
||||
}
|
||||
#endif
|
||||
i2p::crypto::TerminateCrypto ();
|
||||
i2p::log::Logger().Stop();
|
||||
|
||||
|
||||
@@ -20,27 +20,33 @@ namespace util
|
||||
class Daemon_Singleton_Private;
|
||||
class Daemon_Singleton
|
||||
{
|
||||
public:
|
||||
public:
|
||||
|
||||
virtual bool init(int argc, char* argv[], std::shared_ptr<std::ostream> logstream);
|
||||
virtual bool init(int argc, char* argv[]);
|
||||
virtual bool start();
|
||||
virtual bool stop();
|
||||
virtual void run () {};
|
||||
virtual bool init (int argc, char* argv[], std::shared_ptr<std::ostream> logstream);
|
||||
virtual bool init (int argc, char* argv[]);
|
||||
virtual bool start ();
|
||||
virtual bool stop ();
|
||||
virtual void run () {};
|
||||
|
||||
bool isDaemon;
|
||||
bool running;
|
||||
virtual void setDataDir (std::string path);
|
||||
|
||||
protected:
|
||||
bool isDaemon;
|
||||
bool running;
|
||||
|
||||
Daemon_Singleton();
|
||||
virtual ~Daemon_Singleton();
|
||||
protected:
|
||||
|
||||
bool IsService () const;
|
||||
Daemon_Singleton ();
|
||||
virtual ~Daemon_Singleton ();
|
||||
|
||||
// d-pointer for httpServer, httpProxy, etc.
|
||||
class Daemon_Singleton_Private;
|
||||
Daemon_Singleton_Private &d;
|
||||
bool IsService () const;
|
||||
|
||||
// d-pointer for httpServer, httpProxy, etc.
|
||||
class Daemon_Singleton_Private;
|
||||
Daemon_Singleton_Private &d;
|
||||
|
||||
private:
|
||||
|
||||
std::string DaemonDataDir;
|
||||
};
|
||||
|
||||
#if defined(QT_GUI_LIB) // check if QT
|
||||
|
||||
@@ -68,9 +68,13 @@ namespace http {
|
||||
const char HTTP_PAGE_TRANSPORTS[] = "transports";
|
||||
const char HTTP_PAGE_LOCAL_DESTINATIONS[] = "local_destinations";
|
||||
const char HTTP_PAGE_LOCAL_DESTINATION[] = "local_destination";
|
||||
#ifdef WITH_I2CP
|
||||
const char HTTP_PAGE_I2CP_LOCAL_DESTINATION[] = "i2cp_local_destination";
|
||||
#endif
|
||||
#ifdef WITH_SAM
|
||||
const char HTTP_PAGE_SAM_SESSIONS[] = "sam_sessions";
|
||||
const char HTTP_PAGE_SAM_SESSION[] = "sam_session";
|
||||
#endif
|
||||
const char HTTP_PAGE_I2P_TUNNELS[] = "i2p_tunnels";
|
||||
const char HTTP_PAGE_COMMANDS[] = "commands";
|
||||
const char HTTP_PAGE_LEASESETS[] = "leasesets";
|
||||
@@ -87,7 +91,9 @@ namespace http {
|
||||
const char HTTP_COMMAND_GET_REG_STRING[] = "get_reg_string";
|
||||
const char HTTP_COMMAND_SETLANGUAGE[] = "setlanguage";
|
||||
const char HTTP_COMMAND_RELOAD_CSS[] = "reload_css";
|
||||
#ifdef WITH_SAM
|
||||
const char HTTP_PARAM_SAM_SESSION_ID[] = "id";
|
||||
#endif
|
||||
const char HTTP_PARAM_ADDRESS[] = "address";
|
||||
|
||||
static std::string ConvertTime (uint64_t time)
|
||||
@@ -182,7 +188,7 @@ namespace http {
|
||||
" <meta charset=\"UTF-8\">\r\n"
|
||||
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n"
|
||||
" <link rel=\"shortcut icon\" href=\"" << itoopieFavicon << "\">\r\n"
|
||||
" <title>Purple I2P " VERSION " Webconsole</title>\r\n";
|
||||
" <title>Purple I2P Webconsole</title>\r\n";
|
||||
GetStyles(s);
|
||||
s <<
|
||||
"</head>\r\n"
|
||||
@@ -196,12 +202,16 @@ namespace http {
|
||||
if (i2p::context.IsFloodfill ())
|
||||
s << " <a href=\"" << webroot << "?page=" << HTTP_PAGE_LEASESETS << "\">" << tr("LeaseSets") << "</a><br>\r\n";
|
||||
s <<
|
||||
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_TUNNELS << "\">" << tr("Tunnels") << "</a><br>\r\n"
|
||||
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_TRANSIT_TUNNELS << "\">" << tr("Transit Tunnels") << "</a><br>\r\n"
|
||||
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_TUNNELS << "\">" << tr("Tunnels") << "</a><br>\r\n";
|
||||
if (i2p::context.AcceptsTunnels () || i2p::tunnel::tunnels.CountTransitTunnels())
|
||||
s << " <a href=\"" << webroot << "?page=" << HTTP_PAGE_TRANSIT_TUNNELS << "\">" << tr("Transit Tunnels") << "</a><br>\r\n";
|
||||
s <<
|
||||
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_TRANSPORTS << "\">" << tr ("Transports") << "</a><br>\r\n"
|
||||
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_I2P_TUNNELS << "\">" << tr("I2P tunnels") << "</a><br>\r\n";
|
||||
#ifdef WITH_SAM
|
||||
if (i2p::client::context.GetSAMBridge ())
|
||||
s << " <a href=\"" << webroot << "?page=" << HTTP_PAGE_SAM_SESSIONS << "\">" << tr("SAM sessions") << "</a><br>\r\n";
|
||||
#endif
|
||||
s <<
|
||||
"</div>\r\n"
|
||||
"<div class=\"content\">";
|
||||
@@ -295,10 +305,10 @@ namespace http {
|
||||
s << " (" << (double) i2p::transport::transports.GetTransitBandwidth () / 1024 << " " << tr(/* tr: Kibibit/s */ "KiB/s") << ")<br>\r\n";
|
||||
s << "<b>" << tr("Data path") << ":</b> " << i2p::fs::GetUTF8DataDir() << "<br>\r\n";
|
||||
s << "<div class='slide'>";
|
||||
if((outputFormat == OutputFormatEnum::forWebConsole) || !includeHiddenContent) {
|
||||
if ((outputFormat == OutputFormatEnum::forWebConsole) || !includeHiddenContent) {
|
||||
s << "<label for=\"slide-info\">" << tr("Hidden content. Press on text to see.") << "</label>\r\n<input type=\"checkbox\" id=\"slide-info\" />\r\n<div class=\"slidecontent\">\r\n";
|
||||
}
|
||||
if(includeHiddenContent) {
|
||||
if (includeHiddenContent) {
|
||||
s << "<b>" << tr("Router Ident") << ":</b> " << i2p::context.GetRouterInfo().GetIdentHashBase64() << "<br>\r\n";
|
||||
if (!i2p::context.GetRouterInfo().GetProperty("family").empty())
|
||||
s << "<b>" << tr("Router Family") << ":</b> " << i2p::context.GetRouterInfo().GetProperty("family") << "<br>\r\n";
|
||||
@@ -307,41 +317,42 @@ namespace http {
|
||||
s << "<b>"<< tr("Our external address") << ":</b>" << "<br>\r\n<table class=\"extaddr\"><tbody>\r\n";
|
||||
for (const auto& address : i2p::context.GetRouterInfo().GetAddresses())
|
||||
{
|
||||
s << "<tr>\r\n";
|
||||
if (address->IsNTCP2 () && !address->IsPublishedNTCP2 ())
|
||||
{
|
||||
s << "<td>NTCP2";
|
||||
if (address->host.is_v6 ()) s << "v6";
|
||||
s << "</td><td>" << tr("supported") << "</td>\r\n</tr>\r\n";
|
||||
continue;
|
||||
}
|
||||
s << "<tr>\r\n<td>";
|
||||
switch (address->transportStyle)
|
||||
{
|
||||
case i2p::data::RouterInfo::eTransportNTCP:
|
||||
{
|
||||
s << "<td>NTCP";
|
||||
if (address->IsPublishedNTCP2 ()) s << "2";
|
||||
if (address->host.is_v6 ()) s << "v6";
|
||||
s << "</td>\r\n";
|
||||
break;
|
||||
}
|
||||
s << "NTCP2";
|
||||
break;
|
||||
case i2p::data::RouterInfo::eTransportSSU:
|
||||
{
|
||||
s << "<td>SSU";
|
||||
if (address->host.is_v6 ())
|
||||
s << "v6";
|
||||
s << "</td>\r\n";
|
||||
break;
|
||||
}
|
||||
s << "SSU";
|
||||
break;
|
||||
case i2p::data::RouterInfo::eTransportSSU2:
|
||||
s << "SSU2";
|
||||
break;
|
||||
default:
|
||||
s << "<td>" << tr("Unknown") << "</td>\r\n";
|
||||
s << tr("Unknown");
|
||||
}
|
||||
s << "<td>" << address->host.to_string() << ":" << address->port << "</td>\r\n</tr>\r\n";
|
||||
if (address->IsV6 ())
|
||||
{
|
||||
if (address->IsV4 ()) s << "v4";
|
||||
s << "v6";
|
||||
}
|
||||
s << "</td>\r\n";
|
||||
if (address->published)
|
||||
s << "<td>" << address->host.to_string() << ":" << address->port << "</td>\r\n";
|
||||
else
|
||||
{
|
||||
s << "<td>" << tr("supported");
|
||||
if (address->port)
|
||||
s << " :" << address->port;
|
||||
s << "</td>\r\n";
|
||||
}
|
||||
s << "</tr>\r\n";
|
||||
}
|
||||
s << "</tbody></table>\r\n";
|
||||
}
|
||||
s << "</div>\r\n</div>\r\n";
|
||||
if(outputFormat == OutputFormatEnum::forQtUi) {
|
||||
if (outputFormat == OutputFormatEnum::forQtUi) {
|
||||
s << "<br>";
|
||||
}
|
||||
s << "<b>" << tr("Routers") << ":</b> " << i2p::data::netdb.GetNumRouters () << " ";
|
||||
@@ -355,20 +366,28 @@ namespace http {
|
||||
s << "<b>" << tr("Client Tunnels") << ":</b> " << std::to_string(clientTunnelCount) << " ";
|
||||
s << "<b>" << tr("Transit Tunnels") << ":</b> " << std::to_string(transitTunnelCount) << "<br>\r\n<br>\r\n";
|
||||
|
||||
if(outputFormat==OutputFormatEnum::forWebConsole) {
|
||||
if (outputFormat==OutputFormatEnum::forWebConsole) {
|
||||
bool httpproxy = i2p::client::context.GetHttpProxy () ? true : false;
|
||||
bool socksproxy = i2p::client::context.GetSocksProxy () ? true : false;
|
||||
bool bob = i2p::client::context.GetBOBCommandChannel () ? true : false;
|
||||
bool sam = i2p::client::context.GetSAMBridge () ? true : false;
|
||||
bool i2cp = i2p::client::context.GetI2CPServer () ? true : false;
|
||||
bool i2pcontrol; i2p::config::GetOption("i2pcontrol.enabled", i2pcontrol);
|
||||
s << "<table class=\"services\"><caption>" << tr("Services") << "</caption><tbody>\r\n";
|
||||
s << "<tr><td>" << "HTTP " << tr("Proxy") << "</td><td class='" << (httpproxy ? "enabled" : "disabled") << "'>" << (httpproxy ? tr("Enabled") : tr("Disabled")) << "</td></tr>\r\n";
|
||||
s << "<tr><td>" << "SOCKS " << tr("Proxy") << "</td><td class='" << (socksproxy ? "enabled" : "disabled") << "'>" << (socksproxy ? tr("Enabled") : tr("Disabled")) << "</td></tr>\r\n";
|
||||
#ifdef WITH_BOB
|
||||
bool bob = i2p::client::context.GetBOBCommandChannel () ? true : false;
|
||||
s << "<tr><td>" << "BOB" << "</td><td class='" << (bob ? "enabled" : "disabled") << "'>" << (bob ? tr("Enabled") : tr("Disabled")) << "</td></tr>\r\n";
|
||||
#endif
|
||||
#ifdef WITH_SAM
|
||||
bool sam = i2p::client::context.GetSAMBridge () ? true : false;
|
||||
s << "<tr><td>" << "SAM" << "</td><td class='" << (sam ? "enabled" : "disabled") << "'>" << (sam ? tr("Enabled") : tr("Disabled")) << "</td></tr>\r\n";
|
||||
#endif
|
||||
#ifdef WITH_I2CP
|
||||
bool i2cp = i2p::client::context.GetI2CPServer () ? true : false;
|
||||
s << "<tr><td>" << "I2CP" << "</td><td class='" << (i2cp ? "enabled" : "disabled") << "'>" << (i2cp ? tr("Enabled") : tr("Disabled")) << "</td></tr>\r\n";
|
||||
#endif
|
||||
#ifdef WITH_I2PC
|
||||
bool i2pcontrol; i2p::config::GetOption("i2pcontrol.enabled", i2pcontrol);
|
||||
s << "<tr><td>" << "I2PControl" << "</td><td class='" << (i2pcontrol ? "enabled" : "disabled") << "'>" << (i2pcontrol ? tr("Enabled") : tr("Disabled")) << "</td></tr>\r\n";
|
||||
#endif
|
||||
s << "</tbody></table>\r\n";
|
||||
}
|
||||
}
|
||||
@@ -385,6 +404,7 @@ namespace http {
|
||||
}
|
||||
s << "</div>\r\n";
|
||||
|
||||
#ifdef WITH_I2CP
|
||||
auto i2cpServer = i2p::client::context.GetI2CPServer ();
|
||||
if (i2cpServer && !(i2cpServer->GetSessions ().empty ()))
|
||||
{
|
||||
@@ -402,6 +422,7 @@ namespace http {
|
||||
}
|
||||
s << "</div>\r\n";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void ShowLeaseSetDestination (std::stringstream& s, std::shared_ptr<const i2p::client::LeaseSetDestination> dest, uint32_t token)
|
||||
@@ -416,7 +437,7 @@ namespace http {
|
||||
s << "</div>\r\n</div>\r\n";
|
||||
}
|
||||
|
||||
if(dest->IsPublic())
|
||||
if (dest->IsPublic() && token)
|
||||
{
|
||||
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
|
||||
auto base32 = dest->GetIdentHash ().ToBase32 ();
|
||||
@@ -430,7 +451,7 @@ namespace http {
|
||||
"</form>\r\n<small>" << tr("<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.") << "</small>\r\n</div>\r\n</div>\r\n<br>\r\n";
|
||||
}
|
||||
|
||||
if(dest->GetNumRemoteLeaseSets())
|
||||
if (dest->GetNumRemoteLeaseSets())
|
||||
{
|
||||
s << "<div class='slide'><label for='slide-lease'><b>" << tr("LeaseSets") << ":</b> <i>" << dest->GetNumRemoteLeaseSets ()
|
||||
<< "</i></label>\r\n<input type=\"checkbox\" id=\"slide-lease\" />\r\n<div class=\"slidecontent\">\r\n<table><thead><th>"<< tr("Address") << "</th><th>" << tr("Type") << "</th><th>" << tr("EncType") << "</th></thead><tbody class=\"tableitem\">";
|
||||
@@ -446,8 +467,18 @@ namespace http {
|
||||
s << "<b>" << tr("Inbound tunnels") << ":</b><br>\r\n<div class=\"list\">\r\n";
|
||||
for (auto & it : pool->GetInboundTunnels ()) {
|
||||
s << "<div class=\"listitem\">";
|
||||
it->Print(s);
|
||||
if(it->LatencyIsKnown())
|
||||
// for each tunnel hop if not zero-hop
|
||||
if (it->GetNumHops ())
|
||||
{
|
||||
it->VisitTunnelHops(
|
||||
[&s](std::shared_ptr<const i2p::data::IdentityEx> hopIdent)
|
||||
{
|
||||
s << "⇒ " << i2p::data::GetIdentHashAbbreviation (hopIdent->GetIdentHash ()) << " ";
|
||||
}
|
||||
);
|
||||
}
|
||||
s << "⇒ " << it->GetTunnelID () << ":me";
|
||||
if (it->LatencyIsKnown())
|
||||
s << " ( " << it->GetMeanLatency() << tr(/* tr: Milliseconds */ "ms") << " )";
|
||||
ShowTunnelDetails(s, it->GetState (), false, it->GetNumReceivedBytes ());
|
||||
s << "</div>\r\n";
|
||||
@@ -456,8 +487,18 @@ namespace http {
|
||||
s << "<b>" << tr("Outbound tunnels") << ":</b><br>\r\n<div class=\"list\">\r\n";
|
||||
for (auto & it : pool->GetOutboundTunnels ()) {
|
||||
s << "<div class=\"listitem\">";
|
||||
it->Print(s);
|
||||
if(it->LatencyIsKnown())
|
||||
s << it->GetTunnelID () << ":me ⇒";
|
||||
// for each tunnel hop if not zero-hop
|
||||
if (it->GetNumHops ())
|
||||
{
|
||||
it->VisitTunnelHops(
|
||||
[&s](std::shared_ptr<const i2p::data::IdentityEx> hopIdent)
|
||||
{
|
||||
s << " " << i2p::data::GetIdentHashAbbreviation (hopIdent->GetIdentHash ()) << " ⇒";
|
||||
}
|
||||
);
|
||||
}
|
||||
if (it->LatencyIsKnown())
|
||||
s << " ( " << it->GetMeanLatency() << tr("ms") << " )";
|
||||
ShowTunnelDetails(s, it->GetState (), false, it->GetNumSentBytes ());
|
||||
s << "</div>\r\n";
|
||||
@@ -549,6 +590,7 @@ namespace http {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_I2CP
|
||||
void ShowI2CPLocalDestination (std::stringstream& s, const std::string& id)
|
||||
{
|
||||
auto i2cpServer = i2p::client::context.GetI2CPServer ();
|
||||
@@ -564,6 +606,7 @@ namespace http {
|
||||
else
|
||||
ShowError(s, tr("I2CP is not enabled"));
|
||||
}
|
||||
#endif
|
||||
|
||||
void ShowLeasesSets(std::stringstream& s)
|
||||
{
|
||||
@@ -630,8 +673,17 @@ namespace http {
|
||||
s << "<b>" << tr("Inbound tunnels") << ":</b><br>\r\n<div class=\"list\">\r\n";
|
||||
for (auto & it : i2p::tunnel::tunnels.GetInboundTunnels ()) {
|
||||
s << "<div class=\"listitem\">";
|
||||
it->Print(s);
|
||||
if(it->LatencyIsKnown())
|
||||
if (it->GetNumHops ())
|
||||
{
|
||||
it->VisitTunnelHops(
|
||||
[&s](std::shared_ptr<const i2p::data::IdentityEx> hopIdent)
|
||||
{
|
||||
s << "⇒ " << i2p::data::GetIdentHashAbbreviation (hopIdent->GetIdentHash ()) << " ";
|
||||
}
|
||||
);
|
||||
}
|
||||
s << "⇒ " << it->GetTunnelID () << ":me";
|
||||
if (it->LatencyIsKnown())
|
||||
s << " ( " << it->GetMeanLatency() << tr("ms") << " )";
|
||||
ShowTunnelDetails(s, it->GetState (), (it->GetTunnelPool () == ExplPool), it->GetNumReceivedBytes ());
|
||||
s << "</div>\r\n";
|
||||
@@ -640,8 +692,18 @@ namespace http {
|
||||
s << "<b>" << tr("Outbound tunnels") << ":</b><br>\r\n<div class=\"list\">\r\n";
|
||||
for (auto & it : i2p::tunnel::tunnels.GetOutboundTunnels ()) {
|
||||
s << "<div class=\"listitem\">";
|
||||
it->Print(s);
|
||||
if(it->LatencyIsKnown())
|
||||
s << it->GetTunnelID () << ":me ⇒";
|
||||
// for each tunnel hop if not zero-hop
|
||||
if (it->GetNumHops ())
|
||||
{
|
||||
it->VisitTunnelHops(
|
||||
[&s](std::shared_ptr<const i2p::data::IdentityEx> hopIdent)
|
||||
{
|
||||
s << " " << i2p::data::GetIdentHashAbbreviation (hopIdent->GetIdentHash ()) << " ⇒";
|
||||
}
|
||||
);
|
||||
}
|
||||
if (it->LatencyIsKnown())
|
||||
s << " ( " << it->GetMeanLatency() << tr("ms") << " )";
|
||||
ShowTunnelDetails(s, it->GetState (), (it->GetTunnelPool () == ExplPool), it->GetNumSentBytes ());
|
||||
s << "</div>\r\n";
|
||||
@@ -713,7 +775,7 @@ namespace http {
|
||||
|
||||
void ShowTransitTunnels (std::stringstream& s)
|
||||
{
|
||||
if(i2p::tunnel::tunnels.CountTransitTunnels())
|
||||
if (i2p::tunnel::tunnels.CountTransitTunnels())
|
||||
{
|
||||
s << "<b>" << tr("Transit Tunnels") << ":</b><br>\r\n<div class=\"list\">\r\n";
|
||||
for (const auto& it: i2p::tunnel::tunnels.GetTransitTunnels ())
|
||||
@@ -736,7 +798,7 @@ namespace http {
|
||||
}
|
||||
|
||||
template<typename Sessions>
|
||||
static void ShowNTCPTransports (std::stringstream& s, const Sessions& sessions, const std::string name)
|
||||
static void ShowTransportSessions (std::stringstream& s, const Sessions& sessions, const std::string name)
|
||||
{
|
||||
std::stringstream tmp_s, tmp_s6; uint16_t cnt = 0, cnt6 = 0;
|
||||
for (const auto& it: sessions )
|
||||
@@ -786,7 +848,7 @@ namespace http {
|
||||
{
|
||||
auto sessions = ntcp2Server->GetNTCP2Sessions ();
|
||||
if (!sessions.empty ())
|
||||
ShowNTCPTransports (s, sessions, "NTCP2");
|
||||
ShowTransportSessions (s, sessions, "NTCP2");
|
||||
}
|
||||
auto ssuServer = i2p::transport::transports.GetSSUServer ();
|
||||
if (ssuServer)
|
||||
@@ -828,8 +890,16 @@ namespace http {
|
||||
s << "</div>\r\n</div>\r\n";
|
||||
}
|
||||
}
|
||||
auto ssu2Server = i2p::transport::transports.GetSSU2Server ();
|
||||
if (ssu2Server)
|
||||
{
|
||||
auto sessions = ssu2Server->GetSSU2Sessions ();
|
||||
if (!sessions.empty ())
|
||||
ShowTransportSessions (s, sessions, "SSU2");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_SAM
|
||||
void ShowSAMSessions (std::stringstream& s)
|
||||
{
|
||||
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
|
||||
@@ -840,7 +910,7 @@ namespace http {
|
||||
return;
|
||||
}
|
||||
|
||||
if(sam->GetSessions ().size ())
|
||||
if (sam->GetSessions ().size ())
|
||||
{
|
||||
s << "<b>" << tr("SAM sessions") << ":</b><br>\r\n<div class=\"list\">\r\n";
|
||||
for (auto& it: sam->GetSessions ())
|
||||
@@ -892,6 +962,7 @@ namespace http {
|
||||
}
|
||||
s << "</div>\r\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
void ShowI2PTunnels (std::stringstream& s)
|
||||
{
|
||||
@@ -1057,6 +1128,7 @@ namespace http {
|
||||
SendReply(res, content);
|
||||
return;
|
||||
}
|
||||
|
||||
bool strictheaders;
|
||||
i2p::config::GetOption("http.strictheaders", strictheaders);
|
||||
if (strictheaders)
|
||||
@@ -1079,6 +1151,7 @@ namespace http {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// HTML head start
|
||||
ShowPageHead (s);
|
||||
if (req.uri.find("page=") != std::string::npos) {
|
||||
@@ -1143,12 +1216,16 @@ namespace http {
|
||||
uint32_t token = CreateToken ();
|
||||
ShowLocalDestination (s, params["b32"], token);
|
||||
}
|
||||
#ifdef WITH_I2CP
|
||||
else if (page == HTTP_PAGE_I2CP_LOCAL_DESTINATION)
|
||||
ShowI2CPLocalDestination (s, params["i2cp_id"]);
|
||||
#endif
|
||||
#ifdef WITH_SAM
|
||||
else if (page == HTTP_PAGE_SAM_SESSIONS)
|
||||
ShowSAMSessions (s);
|
||||
else if (page == HTTP_PAGE_SAM_SESSION)
|
||||
ShowSAMSession (s, params["sam_id"]);
|
||||
#endif
|
||||
else if (page == HTTP_PAGE_I2P_TUNNELS)
|
||||
ShowI2PTunnels (s);
|
||||
else if (page == HTTP_PAGE_LEASESETS)
|
||||
@@ -1199,7 +1276,7 @@ namespace http {
|
||||
else if (cmd == HTTP_COMMAND_SHUTDOWN_CANCEL)
|
||||
{
|
||||
i2p::context.SetAcceptsTunnels (true);
|
||||
#if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY))
|
||||
#if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY))
|
||||
Daemon.gracefulShutdownInterval = 0;
|
||||
#elif defined(WIN32_APP)
|
||||
i2p::win32::StopGracefulShutdown ();
|
||||
@@ -1231,7 +1308,7 @@ namespace http {
|
||||
{
|
||||
if (dest)
|
||||
{
|
||||
if(dest->DeleteStream (streamID))
|
||||
if (dest->DeleteStream (streamID))
|
||||
s << "<b>" << tr("SUCCESS") << "</b>: " << tr("Stream closed") << "<br>\r\n<br>\r\n";
|
||||
else
|
||||
s << "<b>" << tr("ERROR") << "</b>: " << tr("Stream not found or already was closed") << "<br>\r\n<br>\r\n";
|
||||
@@ -1437,7 +1514,7 @@ namespace http {
|
||||
CreateConnection(newSocket);
|
||||
else
|
||||
{
|
||||
if(newSocket) newSocket->close();
|
||||
if (newSocket) newSocket->close();
|
||||
LogPrint(eLogError, "HTTP Server: Error handling accept: ", ecode.message());
|
||||
}
|
||||
Accept ();
|
||||
|
||||
@@ -95,11 +95,15 @@ namespace http
|
||||
void ShowTunnels (std::stringstream& s);
|
||||
void ShowTransitTunnels (std::stringstream& s);
|
||||
void ShowTransports (std::stringstream& s);
|
||||
void ShowSAMSessions (std::stringstream& s);
|
||||
void ShowI2PTunnels (std::stringstream& s);
|
||||
void ShowLocalDestination (std::stringstream& s, const std::string& b32, uint32_t token);
|
||||
void ShowSAMSession (std::stringstream& s, const std::string& id);
|
||||
void ShowI2CPLocalDestination (std::stringstream& s, const std::string& id);
|
||||
#ifdef WITH_SAM
|
||||
void ShowSAMSessions (std::stringstream& s);
|
||||
void ShowSAMSession (std::stringstream& s, const std::string& id);
|
||||
#endif
|
||||
#ifdef WITH_I2CP
|
||||
void ShowI2CPLocalDestination (std::stringstream& s, const std::string& id);
|
||||
#endif
|
||||
} // http
|
||||
} // i2p
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#ifdef WITH_I2PC
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sstream>
|
||||
#include <openssl/x509.h>
|
||||
@@ -87,8 +89,7 @@ namespace client
|
||||
m_RouterInfoHandlers["i2p.router.net.bw.outbound.1s"] = &I2PControlService::OutboundBandwidth1S;
|
||||
m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlService::NetStatusHandler;
|
||||
m_RouterInfoHandlers["i2p.router.net.tunnels.participating"] = &I2PControlService::TunnelsParticipatingHandler;
|
||||
m_RouterInfoHandlers["i2p.router.net.tunnels.successrate"] =
|
||||
&I2PControlService::TunnelsSuccessRateHandler;
|
||||
m_RouterInfoHandlers["i2p.router.net.tunnels.successrate"] = &I2PControlService::TunnelsSuccessRateHandler;
|
||||
m_RouterInfoHandlers["i2p.router.net.total.received.bytes"] = &I2PControlService::NetTotalReceivedBytes;
|
||||
m_RouterInfoHandlers["i2p.router.net.total.sent.bytes"] = &I2PControlService::NetTotalSentBytes;
|
||||
|
||||
@@ -105,9 +106,15 @@ namespace client
|
||||
m_ClientServicesInfoHandlers["I2PTunnel"] = &I2PControlService::I2PTunnelInfoHandler;
|
||||
m_ClientServicesInfoHandlers["HTTPProxy"] = &I2PControlService::HTTPProxyInfoHandler;
|
||||
m_ClientServicesInfoHandlers["SOCKS"] = &I2PControlService::SOCKSInfoHandler;
|
||||
#ifdef WITH_SAM
|
||||
m_ClientServicesInfoHandlers["SAM"] = &I2PControlService::SAMInfoHandler;
|
||||
#endif
|
||||
#ifdef WITH_BOB
|
||||
m_ClientServicesInfoHandlers["BOB"] = &I2PControlService::BOBInfoHandler;
|
||||
#endif
|
||||
#ifdef WITH_I2CP
|
||||
m_ClientServicesInfoHandlers["I2CP"] = &I2PControlService::I2CPInfoHandler;
|
||||
#endif
|
||||
}
|
||||
|
||||
I2PControlService::~I2PControlService ()
|
||||
@@ -346,8 +353,7 @@ namespace client
|
||||
}
|
||||
}
|
||||
|
||||
// handlers
|
||||
|
||||
// handlers
|
||||
void I2PControlService::AuthenticateHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
|
||||
{
|
||||
int api = params.get<int> ("API");
|
||||
@@ -372,8 +378,7 @@ namespace client
|
||||
}
|
||||
|
||||
|
||||
// I2PControl
|
||||
|
||||
// I2PControl
|
||||
void I2PControlService::I2PControlHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
|
||||
{
|
||||
for (auto& it: params)
|
||||
@@ -507,7 +512,7 @@ namespace client
|
||||
m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(1)); // 1 second to make sure response has been sent
|
||||
m_ShutdownTimer.async_wait (
|
||||
[](const boost::system::error_code& ecode)
|
||||
{
|
||||
{
|
||||
Daemon.running = 0;
|
||||
});
|
||||
}
|
||||
@@ -521,7 +526,7 @@ namespace client
|
||||
m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(timeout + 1)); // + 1 second
|
||||
m_ShutdownTimer.async_wait (
|
||||
[](const boost::system::error_code& ecode)
|
||||
{
|
||||
{
|
||||
Daemon.running = 0;
|
||||
});
|
||||
}
|
||||
@@ -533,7 +538,7 @@ namespace client
|
||||
i2p::data::netdb.Reseed ();
|
||||
}
|
||||
|
||||
// network setting
|
||||
// network setting
|
||||
void I2PControlService::NetworkSettingHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
|
||||
{
|
||||
for (auto it = params.begin (); it != params.end (); it++)
|
||||
@@ -613,8 +618,7 @@ namespace client
|
||||
EVP_PKEY_free (pkey);
|
||||
}
|
||||
|
||||
// ClientServicesInfo
|
||||
|
||||
// ClientServicesInfo
|
||||
void I2PControlService::ClientServicesInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
|
||||
{
|
||||
for (auto it = params.begin (); it != params.end (); it++)
|
||||
@@ -720,6 +724,7 @@ namespace client
|
||||
InsertParam (results, "SOCKS", pt);
|
||||
}
|
||||
|
||||
#ifdef WITH_SAM
|
||||
void I2PControlService::SAMInfoHandler (std::ostringstream& results)
|
||||
{
|
||||
boost::property_tree::ptree pt;
|
||||
@@ -755,7 +760,9 @@ namespace client
|
||||
|
||||
InsertParam (results, "SAM", pt);
|
||||
}
|
||||
#endif // WITH_SAM
|
||||
|
||||
#ifdef WITH_BOB
|
||||
void I2PControlService::BOBInfoHandler (std::ostringstream& results)
|
||||
{
|
||||
boost::property_tree::ptree pt;
|
||||
@@ -770,7 +777,9 @@ namespace client
|
||||
|
||||
InsertParam (results, "BOB", pt);
|
||||
}
|
||||
#endif // WITH_BOB
|
||||
|
||||
#ifdef WITH_I2CP
|
||||
void I2PControlService::I2CPInfoHandler (std::ostringstream& results)
|
||||
{
|
||||
boost::property_tree::ptree pt;
|
||||
@@ -785,5 +794,7 @@ namespace client
|
||||
|
||||
InsertParam (results, "I2CP", pt);
|
||||
}
|
||||
#endif // WITH_I2CP
|
||||
}
|
||||
}
|
||||
#endif // WITH_I2PC
|
||||
@@ -6,6 +6,8 @@
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#ifdef WITH_I2PC
|
||||
|
||||
#ifndef I2P_CONTROL_H__
|
||||
#define I2P_CONTROL_H__
|
||||
|
||||
@@ -114,9 +116,15 @@ namespace client
|
||||
void I2PTunnelInfoHandler (std::ostringstream& results);
|
||||
void HTTPProxyInfoHandler (std::ostringstream& results);
|
||||
void SOCKSInfoHandler (std::ostringstream& results);
|
||||
#ifdef WITH_SAM
|
||||
void SAMInfoHandler (std::ostringstream& results);
|
||||
#endif
|
||||
#ifdef WITH_BOB
|
||||
void BOBInfoHandler (std::ostringstream& results);
|
||||
#endif
|
||||
#ifdef WITH_I2CP
|
||||
void I2CPInfoHandler (std::ostringstream& results);
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
@@ -141,3 +149,4 @@ namespace client
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // WITH_I2PC
|
||||
6
debian/patches/02-upnp.patch
vendored
6
debian/patches/02-upnp.patch
vendored
@@ -2,14 +2,14 @@ Description: Enable UPnP usage in package
|
||||
Author: r4sas <r4sas@i2pmail.org>
|
||||
|
||||
Reviewed-By: r4sas <r4sas@i2pmail.org>
|
||||
Last-Update: 2021-10-22
|
||||
Last-Update: 2022-03-23
|
||||
|
||||
--- i2pd.orig/Makefile
|
||||
+++ i2pd/Makefile
|
||||
@@ -32,7 +32,7 @@ include filelist.mk
|
||||
@@ -31,7 +31,7 @@ include filelist.mk
|
||||
|
||||
USE_AESNI := $(or $(USE_AESNI),yes)
|
||||
USE_STATIC := $(or $(USE_STATIC),no)
|
||||
USE_MESHNET := $(or $(USE_MESHNET),no)
|
||||
-USE_UPNP := $(or $(USE_UPNP),no)
|
||||
+USE_UPNP := $(or $(USE_UPNP),yes)
|
||||
DEBUG := $(or $(DEBUG),yes)
|
||||
|
||||
2
debian/rules
vendored
2
debian/rules
vendored
@@ -14,3 +14,5 @@ export DEB_LDFLAGS_MAINT_APPEND =
|
||||
|
||||
%:
|
||||
dh $@ --parallel
|
||||
|
||||
override_dh_auto_install:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -146,7 +146,10 @@ namespace data
|
||||
m_PublicKey.resize (len);
|
||||
memcpy (m_PublicKey.data (), identity->GetSigningPublicKeyBuffer (), len);
|
||||
m_SigType = identity->GetSigningKeyType ();
|
||||
m_BlindedSigType = m_SigType;
|
||||
if (m_SigType == i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519)
|
||||
m_BlindedSigType = i2p::data::SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519; // 7 -> 11
|
||||
else
|
||||
m_BlindedSigType = m_SigType;
|
||||
}
|
||||
|
||||
BlindedPublicKey::BlindedPublicKey (const std::string& b33):
|
||||
|
||||
@@ -109,6 +109,8 @@ namespace config {
|
||||
("httpproxy.outbound.length", value<std::string>()->default_value("3"), "HTTP proxy outbound tunnel length")
|
||||
("httpproxy.inbound.quantity", value<std::string>()->default_value("5"), "HTTP proxy inbound tunnels quantity")
|
||||
("httpproxy.outbound.quantity", value<std::string>()->default_value("5"), "HTTP proxy outbound tunnels quantity")
|
||||
("httpproxy.inbound.lengthVariance", value<std::string>()->default_value("0"), "HTTP proxy inbound tunnels length variance")
|
||||
("httpproxy.outbound.lengthVariance", value<std::string>()->default_value("0"), "HTTP proxy outbound tunnels length variance")
|
||||
("httpproxy.latency.min", value<std::string>()->default_value("0"), "HTTP proxy min latency for tunnels")
|
||||
("httpproxy.latency.max", value<std::string>()->default_value("0"), "HTTP proxy max latency for tunnels")
|
||||
("httpproxy.outproxy", value<std::string>()->default_value(""), "HTTP proxy upstream out proxy url")
|
||||
@@ -130,6 +132,8 @@ namespace config {
|
||||
("socksproxy.outbound.length", value<std::string>()->default_value("3"), "SOCKS proxy outbound tunnel length")
|
||||
("socksproxy.inbound.quantity", value<std::string>()->default_value("5"), "SOCKS proxy inbound tunnels quantity")
|
||||
("socksproxy.outbound.quantity", value<std::string>()->default_value("5"), "SOCKS proxy outbound tunnels quantity")
|
||||
("socksproxy.inbound.lengthVariance", value<std::string>()->default_value("0"), "SOCKS proxy inbound tunnels length variance")
|
||||
("socksproxy.outbound.lengthVariance", value<std::string>()->default_value("0"), "SOCKS proxy outbound tunnels length variance")
|
||||
("socksproxy.latency.min", value<std::string>()->default_value("0"), "SOCKS proxy min latency for tunnels")
|
||||
("socksproxy.latency.max", value<std::string>()->default_value("0"), "SOCKS proxy max latency for tunnels")
|
||||
("socksproxy.outproxy.enabled", value<bool>()->default_value(false), "Enable or disable SOCKS outproxy")
|
||||
@@ -211,13 +215,16 @@ namespace config {
|
||||
"https://i2pseed.creativecowpat.net:8443/,"
|
||||
"https://reseed.i2pgit.org/,"
|
||||
"https://i2p.novg.net/,"
|
||||
"https://banana.incognet.io/"
|
||||
"https://banana.incognet.io/,"
|
||||
"https://reseed-pl.i2pd.xyz/,"
|
||||
"https://www2.mk16.de/"
|
||||
), "Reseed URLs, separated by comma")
|
||||
("reseed.yggurls", value<std::string>()->default_value(
|
||||
"http://[324:71e:281a:9ed3::ace]:7070/,"
|
||||
"http://[301:65b9:c7cd:9a36::1]:18801/,"
|
||||
"http://[320:8936:ec1a:31f1::216]/,"
|
||||
"http://[306:3834:97b9:a00a::1]/"
|
||||
"http://[306:3834:97b9:a00a::1]/,"
|
||||
"http://[316:f9e0:f22e:a74f::216]/"
|
||||
), "Reseed URLs through the Yggdrasil, separated by comma")
|
||||
;
|
||||
|
||||
@@ -264,6 +271,13 @@ namespace config {
|
||||
("ntcp2.proxy", value<std::string>()->default_value(""), "Proxy URL for NTCP2 transport")
|
||||
;
|
||||
|
||||
options_description ssu2("SSU2 Options");
|
||||
ntcp2.add_options()
|
||||
("ssu2.enabled", value<bool>()->default_value(false), "Enable SSU2 (default: disabled)")
|
||||
("ssu2.published", value<bool>()->default_value(false), "Publish SSU2 (default: disabled)")
|
||||
("ssu2.port", value<uint16_t>()->default_value(0), "Port to listen for incoming SSU2 packets (default: auto)")
|
||||
;
|
||||
|
||||
options_description nettime("Time sync options");
|
||||
nettime.add_options()
|
||||
("nettime.enabled", value<bool>()->default_value(false), "Disable time sync (default: disabled)")
|
||||
@@ -314,6 +328,7 @@ namespace config {
|
||||
.add(websocket) // deprecated
|
||||
.add(exploratory)
|
||||
.add(ntcp2)
|
||||
.add(ssu2)
|
||||
.add(nettime)
|
||||
.add(persist)
|
||||
.add(cpuext)
|
||||
|
||||
@@ -1305,6 +1305,16 @@ namespace crypto
|
||||
SHA256_Final (m_H, &ctx);
|
||||
}
|
||||
|
||||
void NoiseSymmetricState::MixHash (const std::vector<std::pair<uint8_t *, size_t> >& bufs)
|
||||
{
|
||||
SHA256_CTX ctx;
|
||||
SHA256_Init (&ctx);
|
||||
SHA256_Update (&ctx, m_H, 32);
|
||||
for (const auto& it: bufs)
|
||||
SHA256_Update (&ctx, it.first, it.second);
|
||||
SHA256_Final (m_H, &ctx);
|
||||
}
|
||||
|
||||
void NoiseSymmetricState::MixKey (const uint8_t * sharedSecret)
|
||||
{
|
||||
HKDF (m_CK, sharedSecret, 32, "", m_CK);
|
||||
|
||||
@@ -317,6 +317,7 @@ namespace crypto
|
||||
uint8_t m_H[32] /*h*/, m_CK[64] /*[ck, k]*/;
|
||||
|
||||
void MixHash (const uint8_t * buf, size_t len);
|
||||
void MixHash (const std::vector<std::pair<uint8_t *, size_t> >& bufs);
|
||||
void MixKey (const uint8_t * sharedSecret);
|
||||
};
|
||||
|
||||
|
||||
@@ -35,6 +35,8 @@ namespace client
|
||||
int inQty = DEFAULT_INBOUND_TUNNELS_QUANTITY;
|
||||
int outLen = DEFAULT_OUTBOUND_TUNNEL_LENGTH;
|
||||
int outQty = DEFAULT_OUTBOUND_TUNNELS_QUANTITY;
|
||||
int inVar = DEFAULT_INBOUND_TUNNELS_LENGTH_VARIANCE;
|
||||
int outVar = DEFAULT_OUTBOUND_TUNNELS_LENGTH_VARIANCE;
|
||||
int numTags = DEFAULT_TAGS_TO_SEND;
|
||||
std::shared_ptr<std::vector<i2p::data::IdentHash> > explicitPeers;
|
||||
try
|
||||
@@ -53,6 +55,12 @@ namespace client
|
||||
it = params->find (I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY);
|
||||
if (it != params->end ())
|
||||
outQty = std::stoi(it->second);
|
||||
it = params->find (I2CP_PARAM_INBOUND_TUNNELS_LENGTH_VARIANCE);
|
||||
if (it != params->end ())
|
||||
inVar = std::stoi(it->second);
|
||||
it = params->find (I2CP_PARAM_OUTBOUND_TUNNELS_LENGTH_VARIANCE);
|
||||
if (it != params->end ())
|
||||
outVar = std::stoi(it->second);
|
||||
it = params->find (I2CP_PARAM_TAGS_TO_SEND);
|
||||
if (it != params->end ())
|
||||
numTags = std::stoi(it->second);
|
||||
@@ -123,7 +131,7 @@ namespace client
|
||||
LogPrint(eLogError, "Destination: Unable to parse parameters for destination: ", ex.what());
|
||||
}
|
||||
SetNumTags (numTags);
|
||||
m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (inLen, outLen, inQty, outQty);
|
||||
m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (inLen, outLen, inQty, outQty, inVar, outVar);
|
||||
if (explicitPeers)
|
||||
m_Pool->SetExplicitPeers (explicitPeers);
|
||||
if(params)
|
||||
@@ -331,6 +339,22 @@ namespace client
|
||||
return true;
|
||||
}
|
||||
|
||||
void LeaseSetDestination::SubmitECIESx25519Key (const uint8_t * key, uint64_t tag)
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8_t k[32];
|
||||
uint64_t t;
|
||||
} data;
|
||||
memcpy (data.k, key, 32);
|
||||
data.t = tag;
|
||||
auto s = shared_from_this ();
|
||||
m_Service.post ([s,data](void)
|
||||
{
|
||||
s->AddECIESx25519Key (data.k, data.t);
|
||||
});
|
||||
}
|
||||
|
||||
void LeaseSetDestination::ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg)
|
||||
{
|
||||
m_Service.post (std::bind (&LeaseSetDestination::HandleGarlicMessage, shared_from_this (), msg));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -53,6 +53,10 @@ namespace client
|
||||
const int DEFAULT_INBOUND_TUNNELS_QUANTITY = 5;
|
||||
const char I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY[] = "outbound.quantity";
|
||||
const int DEFAULT_OUTBOUND_TUNNELS_QUANTITY = 5;
|
||||
const char I2CP_PARAM_INBOUND_TUNNELS_LENGTH_VARIANCE[] = "inbound.lengthVariance";
|
||||
const int DEFAULT_INBOUND_TUNNELS_LENGTH_VARIANCE = 0;
|
||||
const char I2CP_PARAM_OUTBOUND_TUNNELS_LENGTH_VARIANCE[] = "outbound.lengthVariance";
|
||||
const int DEFAULT_OUTBOUND_TUNNELS_LENGTH_VARIANCE = 0;
|
||||
const char I2CP_PARAM_EXPLICIT_PEERS[] = "explicitPeers";
|
||||
const int STREAM_REQUEST_TIMEOUT = 60; //in seconds
|
||||
const char I2CP_PARAM_TAGS_TO_SEND[] = "crypto.tagsToSend";
|
||||
@@ -134,6 +138,7 @@ namespace client
|
||||
|
||||
// override GarlicDestination
|
||||
bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag);
|
||||
void SubmitECIESx25519Key (const uint8_t * key, uint64_t tag);
|
||||
void ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg);
|
||||
void ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);
|
||||
void SetLeaseSetUpdated ();
|
||||
@@ -314,5 +319,4 @@ namespace client
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -88,7 +88,7 @@ namespace data
|
||||
}
|
||||
EVP_PKEY_free (pkey);
|
||||
if (verifier && cn)
|
||||
m_SigningKeys[cn] = verifier;
|
||||
m_SigningKeys.emplace (cn, std::make_pair(verifier, m_SigningKeys.size () + 1));
|
||||
}
|
||||
SSL_free (ssl);
|
||||
}
|
||||
@@ -121,7 +121,7 @@ namespace data
|
||||
}
|
||||
|
||||
bool Families::VerifyFamily (const std::string& family, const IdentHash& ident,
|
||||
const char * signature, const char * key)
|
||||
const char * signature, const char * key) const
|
||||
{
|
||||
uint8_t buf[100], signatureBuf[64];
|
||||
size_t len = family.length (), signatureLen = strlen (signature);
|
||||
@@ -137,11 +137,19 @@ namespace data
|
||||
Base64ToByteStream (signature, signatureLen, signatureBuf, 64);
|
||||
auto it = m_SigningKeys.find (family);
|
||||
if (it != m_SigningKeys.end ())
|
||||
return it->second->Verify (buf, len, signatureBuf);
|
||||
return it->second.first->Verify (buf, len, signatureBuf);
|
||||
// TODO: process key
|
||||
return true;
|
||||
}
|
||||
|
||||
FamilyID Families::GetFamilyID (const std::string& family) const
|
||||
{
|
||||
auto it = m_SigningKeys.find (family);
|
||||
if (it != m_SigningKeys.end ())
|
||||
return it->second.second;
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string CreateFamilySignature (const std::string& family, const IdentHash& ident)
|
||||
{
|
||||
auto filename = i2p::fs::DataDirPath("family", (family + ".key"));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -19,6 +19,7 @@ namespace i2p
|
||||
{
|
||||
namespace data
|
||||
{
|
||||
typedef int FamilyID;
|
||||
class Families
|
||||
{
|
||||
public:
|
||||
@@ -27,7 +28,8 @@ namespace data
|
||||
~Families ();
|
||||
void LoadCertificates ();
|
||||
bool VerifyFamily (const std::string& family, const IdentHash& ident,
|
||||
const char * signature, const char * key = nullptr);
|
||||
const char * signature, const char * key = nullptr) const;
|
||||
FamilyID GetFamilyID (const std::string& family) const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -35,7 +37,7 @@ namespace data
|
||||
|
||||
private:
|
||||
|
||||
std::map<std::string, std::shared_ptr<i2p::crypto::Verifier> > m_SigningKeys;
|
||||
std::map<std::string, std::pair<std::shared_ptr<i2p::crypto::Verifier>, FamilyID> > m_SigningKeys; // family -> (verifier, id)
|
||||
};
|
||||
|
||||
std::string CreateFamilySignature (const std::string& family, const IdentHash& ident);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -484,6 +484,11 @@ namespace garlic
|
||||
return true;
|
||||
}
|
||||
|
||||
void GarlicDestination::SubmitECIESx25519Key (const uint8_t * key, uint64_t tag)
|
||||
{
|
||||
AddECIESx25519Key (key, tag);
|
||||
}
|
||||
|
||||
void GarlicDestination::HandleGarlicMessage (std::shared_ptr<I2NPMessage> msg)
|
||||
{
|
||||
uint8_t * buf = msg->GetPayload ();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -245,6 +245,7 @@ namespace garlic
|
||||
void AddSessionKey (const uint8_t * key, const uint8_t * tag); // one tag
|
||||
void AddECIESx25519Key (const uint8_t * key, uint64_t tag); // one tag
|
||||
virtual bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag); // from different thread
|
||||
virtual void SubmitECIESx25519Key (const uint8_t * key, uint64_t tag); // from different thread
|
||||
void DeliveryStatusSent (GarlicRoutingSessionPtr session, uint32_t msgID);
|
||||
uint64_t AddECIESx25519SessionNextTag (ReceiveRatchetTagSetPtr tagset);
|
||||
void AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session);
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "HTTP.h"
|
||||
#include "util.h"
|
||||
|
||||
#ifdef __linux__
|
||||
#if defined(__linux__) && !defined(_NETINET_IN_H)
|
||||
#include <linux/in6.h>
|
||||
#endif
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace transport
|
||||
|
||||
void NTCP2Establisher::KDF1Bob ()
|
||||
{
|
||||
KeyDerivationFunction1 (GetRemotePub (), i2p::context.GetStaticKeys (), i2p::context.GetNTCP2StaticPublicKey (), GetRemotePub ());
|
||||
KeyDerivationFunction1 (GetRemotePub (), i2p::context.GetNTCP2StaticKeys (), i2p::context.GetNTCP2StaticPublicKey (), GetRemotePub ());
|
||||
}
|
||||
|
||||
void NTCP2Establisher::KeyDerivationFunction2 (const uint8_t * sessionRequest, size_t sessionRequestLen, const uint8_t * epub)
|
||||
@@ -91,7 +91,7 @@ namespace transport
|
||||
void NTCP2Establisher::KDF3Alice ()
|
||||
{
|
||||
uint8_t inputKeyMaterial[32];
|
||||
i2p::context.GetStaticKeys ().Agree (GetRemotePub (), inputKeyMaterial);
|
||||
i2p::context.GetNTCP2StaticKeys ().Agree (GetRemotePub (), inputKeyMaterial);
|
||||
MixKey (inputKeyMaterial);
|
||||
}
|
||||
|
||||
@@ -757,7 +757,7 @@ namespace transport
|
||||
if (IsTerminated ()) return;
|
||||
#ifdef __linux__
|
||||
const int one = 1;
|
||||
setsockopt(m_Socket.native_handle(), IPPROTO_TCP, TCP_QUICKACK, &one, sizeof(one));
|
||||
setsockopt(m_Socket.native_handle(), IPPROTO_TCP, TCP_QUICKACK, &one, sizeof(one));
|
||||
#endif
|
||||
boost::asio::async_read (m_Socket, boost::asio::buffer(&m_NextReceivedLen, 2), boost::asio::transfer_all (),
|
||||
std::bind(&NTCP2Session::HandleReceivedLength, shared_from_this (), std::placeholders::_1, std::placeholders::_2));
|
||||
@@ -1243,7 +1243,7 @@ namespace transport
|
||||
m_NTCP2V6Acceptor->open (boost::asio::ip::tcp::v6());
|
||||
m_NTCP2V6Acceptor->set_option (boost::asio::ip::v6_only (true));
|
||||
m_NTCP2V6Acceptor->set_option (boost::asio::socket_base::reuse_address (true));
|
||||
#ifdef __linux__
|
||||
#if defined(__linux__) && !defined(_NETINET_IN_H)
|
||||
if (!m_Address6 && !m_YggdrasilAddress) // only if not binded to address
|
||||
{
|
||||
// Set preference to use public IPv6 address -- tested on linux, not works on windows, and not tested on others
|
||||
|
||||
@@ -1364,7 +1364,8 @@ namespace data
|
||||
return res;
|
||||
}
|
||||
|
||||
std::shared_ptr<const RouterInfo> NetDb::GetRandomRouterInFamily(const std::string & fam) const {
|
||||
std::shared_ptr<const RouterInfo> NetDb::GetRandomRouterInFamily (FamilyID fam) const
|
||||
{
|
||||
return GetRandomRouter(
|
||||
[fam](std::shared_ptr<const RouterInfo> router)->bool
|
||||
{
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace data
|
||||
std::vector<IdentHash> GetClosestFloodfills (const IdentHash& destination, size_t num,
|
||||
std::set<IdentHash>& excluded, bool closeThanUsOnly = false) const;
|
||||
std::shared_ptr<const RouterInfo> GetClosestNonFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded) const;
|
||||
std::shared_ptr<const RouterInfo> GetRandomRouterInFamily(const std::string & fam) const;
|
||||
std::shared_ptr<const RouterInfo> GetRandomRouterInFamily (FamilyID fam) const;
|
||||
void SetUnreachable (const IdentHash& ident, bool unreachable);
|
||||
|
||||
void PostI2NPMsg (std::shared_ptr<const I2NPMessage> msg);
|
||||
|
||||
@@ -69,11 +69,14 @@ namespace i2p
|
||||
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
|
||||
bool ssu; i2p::config::GetOption("ssu", ssu);
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||
bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2);
|
||||
bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg);
|
||||
bool nat; i2p::config::GetOption("nat", nat);
|
||||
|
||||
if ((ntcp2 || ygg) && !m_NTCP2Keys)
|
||||
NewNTCP2Keys ();
|
||||
if (ssu2 && !m_SSU2Keys)
|
||||
NewSSU2Keys ();
|
||||
bool ntcp2Published = false;
|
||||
if (ntcp2)
|
||||
{
|
||||
@@ -84,6 +87,9 @@ namespace i2p
|
||||
if (!ntcp2proxy.empty ()) ntcp2Published = false;
|
||||
}
|
||||
}
|
||||
bool ssu2Published = false;
|
||||
if (ssu2)
|
||||
i2p::config::GetOption("ssu2.published", ssu2Published);
|
||||
uint8_t caps = 0, addressCaps = 0;
|
||||
if (ipv4)
|
||||
{
|
||||
@@ -112,6 +118,16 @@ namespace i2p
|
||||
routerInfo.AddSSUAddress (host.c_str(), port, nullptr);
|
||||
caps |= i2p::data::RouterInfo::eReachable; // R
|
||||
}
|
||||
if (ssu2)
|
||||
{
|
||||
if (ssu2Published)
|
||||
routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, boost::asio::ip::address_v4::from_string (host), port);
|
||||
else
|
||||
{
|
||||
addressCaps |= i2p::data::RouterInfo::AddressCaps::eV4;
|
||||
routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ipv6)
|
||||
{
|
||||
@@ -147,6 +163,17 @@ namespace i2p
|
||||
routerInfo.AddSSUAddress (host.c_str(), port, nullptr);
|
||||
caps |= i2p::data::RouterInfo::eReachable; // R
|
||||
}
|
||||
if (ssu2)
|
||||
{
|
||||
if (ssu2Published)
|
||||
routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, boost::asio::ip::address_v6::from_string (host), port);
|
||||
else
|
||||
{
|
||||
if (!ipv4) // no other ssu2 addresses yet
|
||||
routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro);
|
||||
addressCaps |= i2p::data::RouterInfo::AddressCaps::eV6;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ygg)
|
||||
{
|
||||
@@ -174,17 +201,30 @@ namespace i2p
|
||||
|
||||
void RouterContext::NewNTCP2Keys ()
|
||||
{
|
||||
m_StaticKeys.reset (new i2p::crypto::X25519Keys ());
|
||||
m_StaticKeys->GenerateKeys ();
|
||||
m_NTCP2StaticKeys.reset (new i2p::crypto::X25519Keys ());
|
||||
m_NTCP2StaticKeys->GenerateKeys ();
|
||||
m_NTCP2Keys.reset (new NTCP2PrivateKeys ());
|
||||
m_StaticKeys->GetPrivateKey (m_NTCP2Keys->staticPrivateKey);
|
||||
memcpy (m_NTCP2Keys->staticPublicKey, m_StaticKeys->GetPublicKey (), 32);
|
||||
m_NTCP2StaticKeys->GetPrivateKey (m_NTCP2Keys->staticPrivateKey);
|
||||
memcpy (m_NTCP2Keys->staticPublicKey, m_NTCP2StaticKeys->GetPublicKey (), 32);
|
||||
RAND_bytes (m_NTCP2Keys->iv, 16);
|
||||
// save
|
||||
std::ofstream fk (i2p::fs::DataDirPath (NTCP2_KEYS), std::ofstream::binary | std::ofstream::out);
|
||||
fk.write ((char *)m_NTCP2Keys.get (), sizeof (NTCP2PrivateKeys));
|
||||
}
|
||||
|
||||
void RouterContext::NewSSU2Keys ()
|
||||
{
|
||||
m_SSU2StaticKeys.reset (new i2p::crypto::X25519Keys ());
|
||||
m_SSU2StaticKeys->GenerateKeys ();
|
||||
m_SSU2Keys.reset (new SSU2PrivateKeys ());
|
||||
m_SSU2StaticKeys->GetPrivateKey (m_SSU2Keys->staticPrivateKey);
|
||||
memcpy (m_SSU2Keys->staticPublicKey, m_SSU2StaticKeys->GetPublicKey (), 32);
|
||||
RAND_bytes (m_SSU2Keys->intro, 32);
|
||||
// save
|
||||
std::ofstream fk (i2p::fs::DataDirPath (SSU2_KEYS), std::ofstream::binary | std::ofstream::out);
|
||||
fk.write ((char *)m_SSU2Keys.get (), sizeof (SSU2PrivateKeys));
|
||||
}
|
||||
|
||||
void RouterContext::SetStatus (RouterStatus status)
|
||||
{
|
||||
if (status != m_Status)
|
||||
@@ -229,7 +269,7 @@ namespace i2p
|
||||
bool updated = false;
|
||||
for (auto& address : m_RouterInfo.GetAddresses ())
|
||||
{
|
||||
if (!address->IsNTCP2 () && address->port != port)
|
||||
if (!address->IsNTCP2 () && !address->IsSSU2 () && address->port != port)
|
||||
{
|
||||
address->port = port;
|
||||
updated = true;
|
||||
@@ -300,6 +340,59 @@ namespace i2p
|
||||
UpdateRouterInfo ();
|
||||
}
|
||||
|
||||
void RouterContext::PublishSSU2Address (int port, bool publish, bool v4, bool v6)
|
||||
{
|
||||
if (!m_SSU2Keys || (publish && !port)) return;
|
||||
bool updated = false;
|
||||
for (auto& address : m_RouterInfo.GetAddresses ())
|
||||
{
|
||||
if (address->IsSSU2 () && (address->port != port || address->published != publish) &&
|
||||
((v4 && address->IsV4 ()) || (v6 && address->IsV6 ())))
|
||||
{
|
||||
address->port = port;
|
||||
address->published = publish;
|
||||
if (publish)
|
||||
address->caps |= i2p::data::RouterInfo::eSSUIntroducer;
|
||||
else
|
||||
address->caps &= ~i2p::data::RouterInfo::eSSUIntroducer;
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
if (updated)
|
||||
UpdateRouterInfo ();
|
||||
}
|
||||
|
||||
void RouterContext::UpdateSSU2Address (bool enable)
|
||||
{
|
||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
||||
bool found = false, updated = false;
|
||||
for (auto it = addresses.begin (); it != addresses.end (); ++it)
|
||||
{
|
||||
if ((*it)->IsSSU2 ())
|
||||
{
|
||||
found = true;
|
||||
if (!enable)
|
||||
{
|
||||
addresses.erase (it);
|
||||
updated= true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (enable && !found)
|
||||
{
|
||||
uint8_t addressCaps = 0;
|
||||
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
|
||||
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
|
||||
if (ipv4) addressCaps |= i2p::data::RouterInfo::AddressCaps::eV4;
|
||||
if (ipv6) addressCaps |= i2p::data::RouterInfo::AddressCaps::eV6;
|
||||
m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, addressCaps);
|
||||
updated = true;
|
||||
}
|
||||
if (updated)
|
||||
UpdateRouterInfo ();
|
||||
}
|
||||
|
||||
void RouterContext::UpdateAddress (const boost::asio::ip::address& host)
|
||||
{
|
||||
bool updated = false;
|
||||
@@ -475,7 +568,7 @@ namespace i2p
|
||||
// delete previous introducers
|
||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
||||
for (auto& addr : addresses)
|
||||
if (addr->ssu && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ())))
|
||||
if (addr->ssu && !addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ())))
|
||||
{
|
||||
addr->published = false;
|
||||
addr->caps &= ~i2p::data::RouterInfo::eSSUIntroducer; // can't be introducer
|
||||
@@ -507,7 +600,7 @@ namespace i2p
|
||||
// delete previous introducers
|
||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
||||
for (auto& addr : addresses)
|
||||
if (addr->ssu && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ())))
|
||||
if (addr->ssu && !addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ())))
|
||||
{
|
||||
addr->published = true;
|
||||
addr->caps |= i2p::data::RouterInfo::eSSUIntroducer;
|
||||
@@ -536,17 +629,26 @@ namespace i2p
|
||||
if (supportsV6)
|
||||
{
|
||||
// insert v6 addresses if necessary
|
||||
bool foundSSU = false, foundNTCP2 = false;
|
||||
bool foundSSU = false, foundNTCP2 = false, foundSSU2 = false;
|
||||
uint16_t port = 0;
|
||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
||||
for (auto& addr: addresses)
|
||||
{
|
||||
if (addr->IsV6 () && !i2p::util::net::IsYggdrasilAddress (addr->host))
|
||||
{
|
||||
if (addr->transportStyle == i2p::data::RouterInfo::eTransportSSU)
|
||||
foundSSU = true;
|
||||
else if (addr->transportStyle == i2p::data::RouterInfo::eTransportNTCP)
|
||||
foundNTCP2 = true;
|
||||
switch (addr->transportStyle)
|
||||
{
|
||||
case i2p::data::RouterInfo::eTransportSSU:
|
||||
foundSSU = true;
|
||||
break;
|
||||
case i2p::data::RouterInfo::eTransportNTCP:
|
||||
foundNTCP2 = true;
|
||||
break;
|
||||
case i2p::data::RouterInfo::eTransportSSU2:
|
||||
foundSSU2 = true;
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
port = addr->port;
|
||||
}
|
||||
@@ -583,6 +685,22 @@ namespace i2p
|
||||
m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address(), 0, i2p::data::RouterInfo::eV6);
|
||||
}
|
||||
}
|
||||
// SSU2
|
||||
if (!foundSSU2)
|
||||
{
|
||||
bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2);
|
||||
if (ssu2)
|
||||
{
|
||||
bool ssu2Published; i2p::config::GetOption("ssu2.published", ssu2Published);
|
||||
if (ssu2Published)
|
||||
{
|
||||
uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port);
|
||||
m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, boost::asio::ip::address::from_string ("::1"), ssu2Port);
|
||||
}
|
||||
else
|
||||
m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, i2p::data::RouterInfo::eV6);
|
||||
}
|
||||
}
|
||||
m_RouterInfo.EnableV6 ();
|
||||
}
|
||||
else
|
||||
@@ -598,7 +716,7 @@ namespace i2p
|
||||
// update
|
||||
if (supportsV4)
|
||||
{
|
||||
bool foundSSU = false, foundNTCP2 = false;
|
||||
bool foundSSU = false, foundNTCP2 = false, foundSSU2 = false;
|
||||
std::string host = "127.0.0.1";
|
||||
uint16_t port = 0;
|
||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
||||
@@ -606,10 +724,19 @@ namespace i2p
|
||||
{
|
||||
if (addr->IsV4 ())
|
||||
{
|
||||
if (addr->transportStyle == i2p::data::RouterInfo::eTransportSSU)
|
||||
foundSSU = true;
|
||||
else if (addr->transportStyle == i2p::data::RouterInfo::eTransportNTCP)
|
||||
foundNTCP2 = true;
|
||||
switch (addr->transportStyle)
|
||||
{
|
||||
case i2p::data::RouterInfo::eTransportSSU:
|
||||
foundSSU = true;
|
||||
break;
|
||||
case i2p::data::RouterInfo::eTransportNTCP:
|
||||
foundNTCP2 = true;
|
||||
break;
|
||||
case i2p::data::RouterInfo::eTransportSSU2:
|
||||
foundSSU2 = true;
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
if (addr->port) port = addr->port;
|
||||
}
|
||||
@@ -638,6 +765,22 @@ namespace i2p
|
||||
m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address(), 0, i2p::data::RouterInfo::eV4);
|
||||
}
|
||||
}
|
||||
// SSU2
|
||||
if (!foundSSU2)
|
||||
{
|
||||
bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2);
|
||||
if (ssu2)
|
||||
{
|
||||
bool ssu2Published; i2p::config::GetOption("ssu2.published", ssu2Published);
|
||||
if (ssu2Published)
|
||||
{
|
||||
uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port);
|
||||
m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, boost::asio::ip::address::from_string ("127.0.0.1"), ssu2Port);
|
||||
}
|
||||
else
|
||||
m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, i2p::data::RouterInfo::eV6);
|
||||
}
|
||||
}
|
||||
m_RouterInfo.EnableV4 ();
|
||||
}
|
||||
else
|
||||
@@ -794,6 +937,30 @@ namespace i2p
|
||||
else
|
||||
UpdateNTCP2Address (false); // disable NTCP2
|
||||
|
||||
// read SSU2
|
||||
bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2);
|
||||
if (ssu2)
|
||||
{
|
||||
// read SSU2 keys if available
|
||||
std::ifstream s2k (i2p::fs::DataDirPath (SSU2_KEYS), std::ifstream::in | std::ifstream::binary);
|
||||
if (s2k)
|
||||
{
|
||||
s2k.seekg (0, std::ios::end);
|
||||
size_t len = s2k.tellg();
|
||||
s2k.seekg (0, std::ios::beg);
|
||||
if (len == sizeof (SSU2PrivateKeys))
|
||||
{
|
||||
m_SSU2Keys.reset (new SSU2PrivateKeys ());
|
||||
s2k.read ((char *)m_SSU2Keys.get (), sizeof (SSU2PrivateKeys));
|
||||
}
|
||||
s2k.close ();
|
||||
}
|
||||
if (!m_SSU2Keys) NewSSU2Keys ();
|
||||
UpdateSSU2Address (true); // enable SSU2
|
||||
}
|
||||
else
|
||||
UpdateSSU2Address (false); // disable SSU2
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -910,17 +1077,31 @@ namespace i2p
|
||||
return DecryptECIESTunnelBuildRecord (encrypted, data, SHORT_REQUEST_RECORD_CLEAR_TEXT_SIZE);
|
||||
}
|
||||
|
||||
i2p::crypto::X25519Keys& RouterContext::GetStaticKeys ()
|
||||
i2p::crypto::X25519Keys& RouterContext::GetNTCP2StaticKeys ()
|
||||
{
|
||||
if (!m_StaticKeys)
|
||||
if (!m_NTCP2StaticKeys)
|
||||
{
|
||||
if (!m_NTCP2Keys) NewNTCP2Keys ();
|
||||
auto x = new i2p::crypto::X25519Keys (m_NTCP2Keys->staticPrivateKey, m_NTCP2Keys->staticPublicKey);
|
||||
if (!m_StaticKeys)
|
||||
m_StaticKeys.reset (x);
|
||||
if (!m_NTCP2StaticKeys)
|
||||
m_NTCP2StaticKeys.reset (x);
|
||||
else
|
||||
delete x;
|
||||
}
|
||||
return *m_StaticKeys;
|
||||
return *m_NTCP2StaticKeys;
|
||||
}
|
||||
|
||||
i2p::crypto::X25519Keys& RouterContext::GetSSU2StaticKeys ()
|
||||
{
|
||||
if (!m_SSU2StaticKeys)
|
||||
{
|
||||
if (!m_SSU2Keys) NewSSU2Keys ();
|
||||
auto x = new i2p::crypto::X25519Keys (m_SSU2Keys->staticPrivateKey, m_SSU2Keys->staticPublicKey);
|
||||
if (!m_SSU2StaticKeys)
|
||||
m_SSU2StaticKeys.reset (x);
|
||||
else
|
||||
delete x;
|
||||
}
|
||||
return *m_SSU2StaticKeys;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace garlic
|
||||
const char ROUTER_INFO[] = "router.info";
|
||||
const char ROUTER_KEYS[] = "router.keys";
|
||||
const char NTCP2_KEYS[] = "ntcp2.keys";
|
||||
const char SSU2_KEYS[] = "ssu2.keys";
|
||||
const int ROUTER_INFO_UPDATE_INTERVAL = 1800; // 30 minutes
|
||||
|
||||
enum RouterStatus
|
||||
@@ -61,6 +62,13 @@ namespace garlic
|
||||
uint8_t iv[16];
|
||||
};
|
||||
|
||||
struct SSU2PrivateKeys
|
||||
{
|
||||
uint8_t staticPublicKey[32];
|
||||
uint8_t staticPrivateKey[32];
|
||||
uint8_t intro[32];
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
RouterContext ();
|
||||
@@ -78,10 +86,16 @@ namespace garlic
|
||||
return std::shared_ptr<i2p::garlic::GarlicDestination> (this,
|
||||
[](i2p::garlic::GarlicDestination *) {});
|
||||
}
|
||||
|
||||
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 ();
|
||||
i2p::crypto::X25519Keys& GetNTCP2StaticKeys ();
|
||||
|
||||
const uint8_t * GetSSU2StaticPublicKey () const { return m_SSU2Keys ? m_SSU2Keys->staticPublicKey : nullptr; };
|
||||
const uint8_t * GetSSU2StaticPrivateKey () const { return m_SSU2Keys ? m_SSU2Keys->staticPrivateKey : nullptr; };
|
||||
const uint8_t * GetSSU2IntroKey () const { return m_SSU2Keys ? m_SSU2Keys->intro : nullptr; };
|
||||
i2p::crypto::X25519Keys& GetSSU2StaticKeys ();
|
||||
|
||||
uint32_t GetUptime () const; // in seconds
|
||||
uint64_t GetLastUpdateTime () const { return m_LastUpdateTime; };
|
||||
@@ -102,6 +116,8 @@ namespace garlic
|
||||
void UpdateAddress (const boost::asio::ip::address& host); // called from SSU or Daemon
|
||||
void PublishNTCP2Address (int port, bool publish, bool v4, bool v6, bool ygg);
|
||||
void UpdateNTCP2Address (bool enable);
|
||||
void PublishSSU2Address (int port, bool publish, bool v4, bool v6);
|
||||
void UpdateSSU2Address (bool enable);
|
||||
void RemoveNTCPAddress (bool v4only = true); // delete NTCP address for older routers. TODO: remove later
|
||||
bool AddIntroducer (const i2p::data::RouterInfo::Introducer& introducer);
|
||||
void RemoveIntroducer (const boost::asio::ip::udp::endpoint& e);
|
||||
@@ -156,6 +172,7 @@ namespace garlic
|
||||
void NewRouterInfo ();
|
||||
void UpdateRouterInfo ();
|
||||
void NewNTCP2Keys ();
|
||||
void NewSSU2Keys ();
|
||||
bool Load ();
|
||||
void SaveKeys ();
|
||||
|
||||
@@ -177,7 +194,8 @@ namespace garlic
|
||||
int m_NetID;
|
||||
std::mutex m_GarlicMutex;
|
||||
std::unique_ptr<NTCP2PrivateKeys> m_NTCP2Keys;
|
||||
std::unique_ptr<i2p::crypto::X25519Keys> m_StaticKeys;
|
||||
std::unique_ptr<SSU2PrivateKeys> m_SSU2Keys;
|
||||
std::unique_ptr<i2p::crypto::X25519Keys> m_NTCP2StaticKeys, m_SSU2StaticKeys;
|
||||
// for ECIESx25519
|
||||
i2p::crypto::NoiseSymmetricState m_InitialNoiseState, m_CurrentNoiseState;
|
||||
};
|
||||
|
||||
@@ -41,18 +41,19 @@ namespace data
|
||||
}
|
||||
|
||||
RouterInfo::RouterInfo (const std::string& fullPath):
|
||||
m_IsUpdated (false), m_IsUnreachable (false),
|
||||
m_FamilyID (0), m_IsUpdated (false), m_IsUnreachable (false),
|
||||
m_SupportedTransports (0),m_ReachableTransports (0),
|
||||
m_Caps (0), m_Version (0)
|
||||
{
|
||||
m_Addresses = boost::make_shared<Addresses>(); // create empty list
|
||||
m_Buffer = netdb.NewRouterInfoBuffer ();
|
||||
m_Buffer = NewBuffer (); // always RouterInfo's
|
||||
ReadFromFile (fullPath);
|
||||
}
|
||||
|
||||
RouterInfo::RouterInfo (std::shared_ptr<Buffer>&& buf, size_t len):
|
||||
m_IsUpdated (true), m_IsUnreachable (false), m_SupportedTransports (0),
|
||||
m_ReachableTransports (0), m_Caps (0), m_Version (0)
|
||||
m_FamilyID (0), m_IsUpdated (true), m_IsUnreachable (false),
|
||||
m_SupportedTransports (0), m_ReachableTransports (0),
|
||||
m_Caps (0), m_Version (0)
|
||||
{
|
||||
if (len <= MAX_RI_BUFFER_SIZE)
|
||||
{
|
||||
@@ -134,7 +135,7 @@ namespace data
|
||||
}
|
||||
s.seekg(0, std::ios::beg);
|
||||
if (!m_Buffer)
|
||||
m_Buffer = netdb.NewRouterInfoBuffer ();
|
||||
m_Buffer = NewBuffer ();
|
||||
s.read((char *)m_Buffer->data (), m_BufferLen);
|
||||
}
|
||||
else
|
||||
@@ -216,14 +217,15 @@ namespace data
|
||||
uint8_t cost; // ignore
|
||||
s.read ((char *)&cost, sizeof (cost));
|
||||
s.read ((char *)&address->date, sizeof (address->date));
|
||||
bool isHost = false, isIntroKey = false, isStaticKey = false;
|
||||
bool isHost = false, isIntroKey = false, isStaticKey = false, isV2 = false;
|
||||
Tag<32> iV2; // for 'i' field in SSU, TODO: remove later
|
||||
char transportStyle[6];
|
||||
ReadString (transportStyle, 6, s);
|
||||
if (!strncmp (transportStyle, "NTCP", 4)) // NTCP or NTCP2
|
||||
address->transportStyle = eTransportNTCP;
|
||||
else if (!strcmp (transportStyle, "SSU"))
|
||||
else if (!strncmp (transportStyle, "SSU", 3)) // SSU or SSU2
|
||||
{
|
||||
address->transportStyle = eTransportSSU;
|
||||
address->transportStyle = (transportStyle[3] == '2') ? eTransportSSU2 : eTransportSSU;
|
||||
address->ssu.reset (new SSUExt ());
|
||||
address->ssu->mtu = 0;
|
||||
}
|
||||
@@ -234,6 +236,12 @@ namespace data
|
||||
uint16_t size, r = 0;
|
||||
s.read ((char *)&size, sizeof (size)); if (!s) return;
|
||||
size = be16toh (size);
|
||||
if (address->transportStyle == eTransportUnknown)
|
||||
{
|
||||
// skip unknown address
|
||||
s.seekg (size, std::ios_base::cur);
|
||||
if (s) continue; else return;
|
||||
}
|
||||
while (r < size)
|
||||
{
|
||||
char key[255], value[255];
|
||||
@@ -266,15 +274,29 @@ namespace data
|
||||
}
|
||||
else if (!strcmp (key, "caps"))
|
||||
address->caps = ExtractAddressCaps (value);
|
||||
else if (!strcmp (key, "s")) // ntcp2 static key
|
||||
else if (!strcmp (key, "s")) // ntcp2 or ssu2 static key
|
||||
{
|
||||
Base64ToByteStream (value, strlen (value), address->s, 32);
|
||||
isStaticKey = true;
|
||||
}
|
||||
else if (!strcmp (key, "i")) // ntcp2 iv
|
||||
else if (!strcmp (key, "i")) // ntcp2 iv or ssu2 intro
|
||||
{
|
||||
Base64ToByteStream (value, strlen (value), address->i, 16);
|
||||
address->published = true; // presence if "i" means "published"
|
||||
if (address->IsNTCP2 ())
|
||||
{
|
||||
Base64ToByteStream (value, strlen (value), address->i, 16);
|
||||
address->published = true; // presence of "i" means "published" NTCP2
|
||||
}
|
||||
else if (address->IsSSU2 ())
|
||||
Base64ToByteStream (value, strlen (value), address->i, 32);
|
||||
else
|
||||
Base64ToByteStream (value, strlen (value), iV2, 32);
|
||||
}
|
||||
else if (!strcmp (key, "v"))
|
||||
{
|
||||
if (!strcmp (value, "2"))
|
||||
isV2 = true;
|
||||
else
|
||||
LogPrint (eLogWarning, "RouterInfo: Unexpected value ", value, " for v");
|
||||
}
|
||||
else if (key[0] == 'i')
|
||||
{
|
||||
@@ -308,7 +330,7 @@ namespace data
|
||||
introducer.iPort = boost::lexical_cast<int>(value);
|
||||
else if (!strcmp (key, "itag"))
|
||||
introducer.iTag = boost::lexical_cast<uint32_t>(value);
|
||||
else if (!strcmp (key, "ikey"))
|
||||
else if (!strcmp (key, "ikey") || !strcmp (key, "ih"))
|
||||
Base64ToByteStream (value, strlen (value), introducer.iKey, 32);
|
||||
else if (!strcmp (key, "iexp"))
|
||||
introducer.iExp = boost::lexical_cast<uint32_t>(value);
|
||||
@@ -378,10 +400,37 @@ namespace data
|
||||
}
|
||||
}
|
||||
}
|
||||
if (address->transportStyle == eTransportSSU2 || (isV2 && address->transportStyle == eTransportSSU))
|
||||
{
|
||||
if (address->IsV4 ()) supportedTransports |= eSSU2V4;
|
||||
if (address->IsV6 ()) supportedTransports |= eSSU2V6;
|
||||
if (address->port)
|
||||
{
|
||||
if (address->host.is_v4 ()) m_ReachableTransports |= eSSU2V4;
|
||||
if (address->host.is_v6 ()) m_ReachableTransports |= eSSU2V6;
|
||||
}
|
||||
}
|
||||
if (supportedTransports)
|
||||
{
|
||||
if (!(m_SupportedTransports & supportedTransports)) // avoid duplicates
|
||||
{
|
||||
addresses->push_back(address);
|
||||
if (address->transportStyle == eTransportSSU && isV2)
|
||||
{
|
||||
// create additional SSU2 address. TODO: remove later
|
||||
auto ssu2addr = std::make_shared<Address> ();
|
||||
ssu2addr->transportStyle = eTransportSSU2;
|
||||
ssu2addr->host = address->host; ssu2addr->port = address->port;
|
||||
ssu2addr->s = address->s; ssu2addr->i = iV2;
|
||||
ssu2addr->date = address->date; ssu2addr->caps = address->caps;
|
||||
ssu2addr->published = address->published;
|
||||
ssu2addr->ssu.reset (new SSUExt ()); ssu2addr->ssu->mtu = address->ssu->mtu;
|
||||
for (const auto& introducer: address->ssu->introducers)
|
||||
if (!introducer.iPort) // SSU2
|
||||
ssu2addr->ssu->introducers.push_back (introducer);
|
||||
addresses->push_back(ssu2addr);
|
||||
}
|
||||
}
|
||||
m_SupportedTransports |= supportedTransports;
|
||||
}
|
||||
}
|
||||
@@ -397,6 +446,7 @@ namespace data
|
||||
// read properties
|
||||
m_Version = 0;
|
||||
bool isNetId = false;
|
||||
std::string family;
|
||||
uint16_t size, r = 0;
|
||||
s.read ((char *)&size, sizeof (size)); if (!s) return;
|
||||
size = be16toh (size);
|
||||
@@ -441,16 +491,15 @@ namespace data
|
||||
// family
|
||||
else if (!strcmp (key, ROUTER_INFO_PROPERTY_FAMILY))
|
||||
{
|
||||
m_Family = value;
|
||||
boost::to_lower (m_Family);
|
||||
family = value;
|
||||
boost::to_lower (family);
|
||||
}
|
||||
else if (!strcmp (key, ROUTER_INFO_PROPERTY_FAMILY_SIG))
|
||||
{
|
||||
if (!netdb.GetFamilies ().VerifyFamily (m_Family, GetIdentHash (), value))
|
||||
{
|
||||
LogPrint (eLogWarning, "RouterInfo: Family signature verification failed");
|
||||
m_Family.clear ();
|
||||
}
|
||||
if (netdb.GetFamilies ().VerifyFamily (family, GetIdentHash (), value))
|
||||
m_FamilyID = netdb.GetFamilies ().GetFamilyID (family);
|
||||
else
|
||||
LogPrint (eLogWarning, "RouterInfo: Family ", family, " signature verification failed");
|
||||
}
|
||||
|
||||
if (!s) return;
|
||||
@@ -460,9 +509,9 @@ namespace data
|
||||
SetUnreachable (true);
|
||||
}
|
||||
|
||||
bool RouterInfo::IsFamily(const std::string & fam) const
|
||||
bool RouterInfo::IsFamily (FamilyID famid) const
|
||||
{
|
||||
return m_Family == fam;
|
||||
return m_FamilyID == famid;
|
||||
}
|
||||
|
||||
void RouterInfo::ExtractCaps (const char * value)
|
||||
@@ -627,6 +676,48 @@ namespace data
|
||||
m_Addresses->push_back(std::move(addr));
|
||||
}
|
||||
|
||||
void RouterInfo::AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey, uint8_t caps)
|
||||
{
|
||||
auto addr = std::make_shared<Address>();
|
||||
addr->transportStyle = eTransportSSU2;
|
||||
addr->caps = caps;
|
||||
addr->date = 0;
|
||||
addr->ssu.reset (new SSUExt ());
|
||||
addr->ssu->mtu = 0;
|
||||
memcpy (addr->s, staticKey, 32);
|
||||
memcpy (addr->i, introKey, 32);
|
||||
if (addr->IsV4 ()) m_SupportedTransports |= eSSU2V4;
|
||||
if (addr->IsV6 ()) m_SupportedTransports |= eSSU2V6;
|
||||
m_Addresses->push_back(std::move(addr));
|
||||
}
|
||||
|
||||
void RouterInfo::AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey,
|
||||
const boost::asio::ip::address& host, int port)
|
||||
{
|
||||
auto addr = std::make_shared<Address>();
|
||||
addr->transportStyle = eTransportSSU2;
|
||||
addr->host = host;
|
||||
addr->port = port;
|
||||
addr->published = true;
|
||||
addr->caps = 0;
|
||||
addr->date = 0;
|
||||
addr->ssu.reset (new SSUExt ());
|
||||
addr->ssu->mtu = 0;
|
||||
memcpy (addr->s, staticKey, 32);
|
||||
memcpy (addr->i, introKey, 32);
|
||||
if (addr->IsV4 ())
|
||||
{
|
||||
m_SupportedTransports |= eSSU2V4;
|
||||
m_ReachableTransports |= eSSU2V4;
|
||||
}
|
||||
if (addr->IsV6 ())
|
||||
{
|
||||
m_SupportedTransports |= eSSU2V6;
|
||||
m_ReachableTransports |= eSSU2V6;
|
||||
}
|
||||
m_Addresses->push_back(std::move(addr));
|
||||
}
|
||||
|
||||
bool RouterInfo::AddIntroducer (const Introducer& introducer)
|
||||
{
|
||||
for (auto& addr : *m_Addresses)
|
||||
@@ -672,11 +763,6 @@ namespace data
|
||||
return m_SupportedTransports & (eSSUV4 | eSSUV6);
|
||||
}
|
||||
|
||||
bool RouterInfo::IsSSUV6 () const
|
||||
{
|
||||
return m_SupportedTransports & eSSUV6;
|
||||
}
|
||||
|
||||
bool RouterInfo::IsNTCP2 (bool v4only) const
|
||||
{
|
||||
if (v4only)
|
||||
@@ -685,25 +771,6 @@ namespace data
|
||||
return m_SupportedTransports & (eNTCP2V4 | eNTCP2V6);
|
||||
}
|
||||
|
||||
bool RouterInfo::IsNTCP2V6 () const
|
||||
{
|
||||
return m_SupportedTransports & eNTCP2V6;
|
||||
}
|
||||
|
||||
bool RouterInfo::IsV6 () const
|
||||
{
|
||||
return m_SupportedTransports & (eSSUV6 | eNTCP2V6);
|
||||
}
|
||||
|
||||
bool RouterInfo::IsV4 () const
|
||||
{
|
||||
return m_SupportedTransports & (eSSUV4 | eNTCP2V4);
|
||||
}
|
||||
|
||||
bool RouterInfo::IsMesh () const
|
||||
{
|
||||
return m_SupportedTransports & eNTCP2V6Mesh;
|
||||
}
|
||||
|
||||
void RouterInfo::EnableV6 ()
|
||||
{
|
||||
@@ -820,6 +887,24 @@ namespace data
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSU2V4Address () const
|
||||
{
|
||||
return GetAddress (
|
||||
[](std::shared_ptr<const RouterInfo::Address> address)->bool
|
||||
{
|
||||
return (address->transportStyle == eTransportSSU2) && address->IsV4();
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSU2V6Address () const
|
||||
{
|
||||
return GetAddress (
|
||||
[](std::shared_ptr<const RouterInfo::Address> address)->bool
|
||||
{
|
||||
return (address->transportStyle == eTransportSSU2) && address->IsV6();
|
||||
});
|
||||
}
|
||||
|
||||
template<typename Filter>
|
||||
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetAddress (Filter filter) const
|
||||
{
|
||||
@@ -845,6 +930,16 @@ namespace data
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSU2AddressWithStaticKey (const uint8_t * key, bool isV6) const
|
||||
{
|
||||
if (!key) return nullptr;
|
||||
return GetAddress (
|
||||
[key, isV6](std::shared_ptr<const RouterInfo::Address> address)->bool
|
||||
{
|
||||
return address->IsSSU2 () && !memcmp (address->s, key, 32) && address->IsV6 () == isV6;
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetPublishedNTCP2V4Address () const
|
||||
{
|
||||
return GetAddress (
|
||||
@@ -921,7 +1016,7 @@ namespace data
|
||||
for (auto& addr: *m_Addresses)
|
||||
{
|
||||
// TODO: implement SSU
|
||||
if (addr->transportStyle == eTransportNTCP && !addr->IsPublishedNTCP2 ())
|
||||
if (!addr->published && (addr->transportStyle == eTransportNTCP || addr->transportStyle == eTransportSSU2))
|
||||
{
|
||||
addr->caps &= ~(eV4 | eV6);
|
||||
addr->caps |= transports;
|
||||
@@ -958,12 +1053,17 @@ namespace data
|
||||
void RouterInfo::UpdateBuffer (const uint8_t * buf, size_t len)
|
||||
{
|
||||
if (!m_Buffer)
|
||||
m_Buffer = netdb.NewRouterInfoBuffer ();
|
||||
m_Buffer = NewBuffer ();
|
||||
if (len > m_Buffer->size ()) len = m_Buffer->size ();
|
||||
memcpy (m_Buffer->data (), buf, len);
|
||||
m_BufferLen = len;
|
||||
}
|
||||
|
||||
std::shared_ptr<RouterInfo::Buffer> RouterInfo::NewBuffer () const
|
||||
{
|
||||
return netdb.NewRouterInfoBuffer ();
|
||||
}
|
||||
|
||||
void RouterInfo::RefreshTimestamp ()
|
||||
{
|
||||
m_Timestamp = i2p::util::GetMillisecondsSinceEpoch ();
|
||||
@@ -1041,6 +1141,8 @@ namespace data
|
||||
cost = address.published ? COST_NTCP2_PUBLISHED : COST_NTCP2_NON_PUBLISHED;
|
||||
else if (address.transportStyle == eTransportSSU)
|
||||
cost = address.published ? COST_SSU_DIRECT : COST_SSU_THROUGH_INTRODUCERS;
|
||||
else if (address.transportStyle == eTransportSSU2)
|
||||
cost = address.published ? COST_SSU2_DIRECT : COST_SSU2_NON_PUBLISHED;
|
||||
s.write ((const char *)&cost, sizeof (cost));
|
||||
s.write ((const char *)&address.date, sizeof (address.date));
|
||||
std::stringstream properties;
|
||||
@@ -1104,6 +1206,30 @@ namespace data
|
||||
WriteString (caps, properties);
|
||||
properties << ';';
|
||||
}
|
||||
else if (address.transportStyle == eTransportSSU2)
|
||||
{
|
||||
WriteString ("SSU2", s);
|
||||
// caps
|
||||
std::string caps;
|
||||
if (address.published)
|
||||
{
|
||||
isPublished = true;
|
||||
if (address.IsIntroducer ()) caps += CAPS_FLAG_SSU_INTRODUCER;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (address.IsV4 ()) caps += CAPS_FLAG_V4;
|
||||
if (address.IsV6 ()) caps += CAPS_FLAG_V6;
|
||||
if (caps.empty ()) caps += CAPS_FLAG_V4;
|
||||
}
|
||||
if (!caps.empty ())
|
||||
{
|
||||
WriteString ("caps", properties);
|
||||
properties << '=';
|
||||
WriteString (caps, properties);
|
||||
properties << ';';
|
||||
}
|
||||
}
|
||||
else
|
||||
WriteString ("", s);
|
||||
|
||||
@@ -1114,10 +1240,17 @@ namespace data
|
||||
WriteString (address.host.to_string (), properties);
|
||||
properties << ';';
|
||||
}
|
||||
if (address.transportStyle == eTransportSSU)
|
||||
if ((address.IsNTCP2 () && isPublished) || address.IsSSU2 ())
|
||||
{
|
||||
// publish i for NTCP2 or SSU2
|
||||
WriteString ("i", properties); properties << '=';
|
||||
size_t len = address.IsSSU2 () ? 32 : 16;
|
||||
WriteString (address.i.ToBase64 (len), properties); properties << ';';
|
||||
}
|
||||
if (address.transportStyle == eTransportSSU || address.IsSSU2 ())
|
||||
{
|
||||
// write introducers if any
|
||||
if (!address.ssu->introducers.empty())
|
||||
if (address.ssu && !address.ssu->introducers.empty())
|
||||
{
|
||||
int i = 0;
|
||||
for (const auto& introducer: address.ssu->introducers)
|
||||
@@ -1131,19 +1264,25 @@ namespace data
|
||||
}
|
||||
i++;
|
||||
}
|
||||
i = 0;
|
||||
for (const auto& introducer: address.ssu->introducers)
|
||||
if (address.transportStyle == eTransportSSU)
|
||||
{
|
||||
WriteString ("ihost" + boost::lexical_cast<std::string>(i), properties);
|
||||
properties << '=';
|
||||
WriteString (introducer.iHost.to_string (), properties);
|
||||
properties << ';';
|
||||
i++;
|
||||
i = 0;
|
||||
for (const auto& introducer: address.ssu->introducers)
|
||||
{
|
||||
WriteString ("ihost" + boost::lexical_cast<std::string>(i), properties);
|
||||
properties << '=';
|
||||
WriteString (introducer.iHost.to_string (), properties);
|
||||
properties << ';';
|
||||
i++;
|
||||
}
|
||||
}
|
||||
i = 0;
|
||||
for (const auto& introducer: address.ssu->introducers)
|
||||
{
|
||||
WriteString ("ikey" + boost::lexical_cast<std::string>(i), properties);
|
||||
if (address.IsSSU2 ())
|
||||
WriteString ("ih" + boost::lexical_cast<std::string>(i), properties);
|
||||
else
|
||||
WriteString ("ikey" + boost::lexical_cast<std::string>(i), properties);
|
||||
properties << '=';
|
||||
char value[64];
|
||||
size_t l = ByteStreamToBase64 (introducer.iKey, 32, value, 64);
|
||||
@@ -1152,14 +1291,17 @@ namespace data
|
||||
properties << ';';
|
||||
i++;
|
||||
}
|
||||
i = 0;
|
||||
for (const auto& introducer: address.ssu->introducers)
|
||||
if (address.transportStyle == eTransportSSU)
|
||||
{
|
||||
WriteString ("iport" + boost::lexical_cast<std::string>(i), properties);
|
||||
properties << '=';
|
||||
WriteString (boost::lexical_cast<std::string>(introducer.iPort), properties);
|
||||
properties << ';';
|
||||
i++;
|
||||
i = 0;
|
||||
for (const auto& introducer: address.ssu->introducers)
|
||||
{
|
||||
WriteString ("iport" + boost::lexical_cast<std::string>(i), properties);
|
||||
properties << '=';
|
||||
WriteString (boost::lexical_cast<std::string>(introducer.iPort), properties);
|
||||
properties << ';';
|
||||
i++;
|
||||
}
|
||||
}
|
||||
i = 0;
|
||||
for (const auto& introducer: address.ssu->introducers)
|
||||
@@ -1171,6 +1313,9 @@ namespace data
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (address.transportStyle == eTransportSSU)
|
||||
{
|
||||
// write intro key
|
||||
WriteString ("key", properties);
|
||||
properties << '=';
|
||||
@@ -1179,8 +1324,11 @@ namespace data
|
||||
value[l] = 0;
|
||||
WriteString (value, properties);
|
||||
properties << ';';
|
||||
}
|
||||
if (address.transportStyle == eTransportSSU || address.IsSSU2 ())
|
||||
{
|
||||
// write mtu
|
||||
if (address.ssu->mtu)
|
||||
if (address.ssu && address.ssu->mtu)
|
||||
{
|
||||
WriteString ("mtu", properties);
|
||||
properties << '=';
|
||||
@@ -1188,24 +1336,16 @@ namespace data
|
||||
properties << ';';
|
||||
}
|
||||
}
|
||||
|
||||
if (address.IsNTCP2 () && isPublished)
|
||||
{
|
||||
// publish i for NTCP2
|
||||
WriteString ("i", properties); properties << '=';
|
||||
WriteString (address.i.ToBase64 (16), properties); properties << ';';
|
||||
}
|
||||
|
||||
if (isPublished || address.ssu)
|
||||
if (isPublished || (address.ssu && !address.IsSSU2 ()))
|
||||
{
|
||||
WriteString ("port", properties);
|
||||
properties << '=';
|
||||
WriteString (boost::lexical_cast<std::string>(address.port), properties);
|
||||
properties << ';';
|
||||
}
|
||||
if (address.IsNTCP2 ())
|
||||
if (address.IsNTCP2 () || address.IsSSU2 ())
|
||||
{
|
||||
// publish s and v for NTCP2
|
||||
// publish s and v for NTCP2 or SSU2
|
||||
WriteString ("s", properties); properties << '=';
|
||||
WriteString (address.s.ToBase64 (), properties); properties << ';';
|
||||
WriteString ("v", properties); properties << '=';
|
||||
@@ -1259,5 +1399,10 @@ namespace data
|
||||
s.write ((char *)&len, 1);
|
||||
s.write (str.c_str (), len);
|
||||
}
|
||||
|
||||
std::shared_ptr<RouterInfo::Buffer> LocalRouterInfo::NewBuffer () const
|
||||
{
|
||||
return std::make_shared<Buffer> ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include "Identity.h"
|
||||
#include "Profiling.h"
|
||||
#include "Family.h"
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
@@ -51,10 +52,12 @@ namespace data
|
||||
|
||||
const uint8_t COST_NTCP2_PUBLISHED = 3;
|
||||
const uint8_t COST_NTCP2_NON_PUBLISHED = 14;
|
||||
const uint8_t COST_SSU2_DIRECT = 8;
|
||||
const uint8_t COST_SSU_DIRECT = 9;
|
||||
const uint8_t COST_SSU_THROUGH_INTRODUCERS = 11;
|
||||
const uint8_t COST_SSU2_NON_PUBLISHED = 15;
|
||||
|
||||
const size_t MAX_RI_BUFFER_SIZE = 2048; // if RouterInfo exceeds 2048 we consider it as malformed, might be changed later
|
||||
const size_t MAX_RI_BUFFER_SIZE = 3072; // if RouterInfo exceeds 3K we consider it as malformed, might extend later
|
||||
class RouterInfo: public RoutingDestination
|
||||
{
|
||||
public:
|
||||
@@ -66,6 +69,8 @@ namespace data
|
||||
eSSUV4 = 0x04,
|
||||
eSSUV6 = 0x08,
|
||||
eNTCP2V6Mesh = 0x10,
|
||||
eSSU2V4 = 0x20,
|
||||
eSSU2V6 = 0x40,
|
||||
eAllTransports = 0xFF
|
||||
};
|
||||
typedef uint8_t CompatibleTransports;
|
||||
@@ -92,7 +97,8 @@ namespace data
|
||||
{
|
||||
eTransportUnknown = 0,
|
||||
eTransportNTCP,
|
||||
eTransportSSU
|
||||
eTransportSSU,
|
||||
eTransportSSU2
|
||||
};
|
||||
|
||||
typedef Tag<32> IntroKey; // should be castable to MacKey and AESKey
|
||||
@@ -101,7 +107,7 @@ namespace data
|
||||
Introducer (): iPort (0), iExp (0) {};
|
||||
boost::asio::ip::address iHost;
|
||||
int iPort;
|
||||
IntroKey iKey;
|
||||
IntroKey iKey; // or ih for SSU2
|
||||
uint32_t iTag;
|
||||
uint32_t iExp;
|
||||
};
|
||||
@@ -131,7 +137,7 @@ namespace data
|
||||
|
||||
bool operator==(const Address& other) const
|
||||
{
|
||||
return transportStyle == other.transportStyle && IsNTCP2 () == other.IsNTCP2 () &&
|
||||
return transportStyle == other.transportStyle &&
|
||||
host == other.host && port == other.port;
|
||||
}
|
||||
|
||||
@@ -141,8 +147,9 @@ namespace data
|
||||
}
|
||||
|
||||
bool IsNTCP2 () const { return transportStyle == eTransportNTCP; };
|
||||
bool IsSSU2 () const { return transportStyle == eTransportSSU2; };
|
||||
bool IsPublishedNTCP2 () const { return IsNTCP2 () && published; };
|
||||
bool IsReachableSSU () const { return (bool)ssu && (published || !ssu->introducers.empty ()); };
|
||||
bool IsReachableSSU () const { return (bool)ssu && (published || UsesIntroducer ()); };
|
||||
bool UsesIntroducer () const { return (bool)ssu && !ssu->introducers.empty (); };
|
||||
|
||||
bool IsIntroducer () const { return caps & eSSUIntroducer; };
|
||||
@@ -178,15 +185,21 @@ namespace data
|
||||
virtual void ClearProperties () {};
|
||||
Addresses& GetAddresses () { return *m_Addresses; }; // should be called for local RI only, otherwise must return shared_ptr
|
||||
std::shared_ptr<const Address> GetNTCP2AddressWithStaticKey (const uint8_t * key) const;
|
||||
std::shared_ptr<const Address> GetSSU2AddressWithStaticKey (const uint8_t * key, bool isV6) const;
|
||||
std::shared_ptr<const Address> GetPublishedNTCP2V4Address () const;
|
||||
std::shared_ptr<const Address> GetPublishedNTCP2V6Address () const;
|
||||
std::shared_ptr<const Address> GetSSUAddress (bool v4only = true) const;
|
||||
std::shared_ptr<const Address> GetSSUV6Address () const;
|
||||
std::shared_ptr<const Address> GetYggdrasilAddress () const;
|
||||
std::shared_ptr<const Address> GetSSU2V4Address () const;
|
||||
std::shared_ptr<const Address> GetSSU2V6Address () const;
|
||||
|
||||
void AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu = 0);
|
||||
void AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv,
|
||||
const boost::asio::ip::address& host = boost::asio::ip::address(), int port = 0, uint8_t caps = 0);
|
||||
void AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey, uint8_t caps = 0); // non published
|
||||
void AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey,
|
||||
const boost::asio::ip::address& host, int port); // published
|
||||
bool AddIntroducer (const Introducer& introducer);
|
||||
bool RemoveIntroducer (const boost::asio::ip::udp::endpoint& e);
|
||||
void SetUnreachableAddressesTransportCaps (uint8_t transports); // bitmask of AddressCaps
|
||||
@@ -195,12 +208,14 @@ namespace data
|
||||
bool IsReachable () const { return m_Caps & Caps::eReachable; };
|
||||
bool IsECIES () const { return m_RouterIdentity->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD; };
|
||||
bool IsSSU (bool v4only = true) const;
|
||||
bool IsSSUV6 () const;
|
||||
bool IsSSUV6 () const { return m_SupportedTransports & eSSUV6; };
|
||||
bool IsNTCP2 (bool v4only = true) const;
|
||||
bool IsNTCP2V6 () const;
|
||||
bool IsV6 () const;
|
||||
bool IsV4 () const;
|
||||
bool IsMesh () const;
|
||||
bool IsNTCP2V6 () const { return m_SupportedTransports & eNTCP2V6; };
|
||||
bool IsSSU2V4 () const { return m_SupportedTransports & eSSU2V4; };
|
||||
bool IsSSU2V6 () const { return m_SupportedTransports & eSSU2V6; };
|
||||
bool IsV6 () const { return m_SupportedTransports & (eSSUV6 | eNTCP2V6 | eSSU2V6); };
|
||||
bool IsV4 () const { return m_SupportedTransports & (eSSUV4 | eNTCP2V4 | eSSU2V4); };
|
||||
bool IsMesh () const { return m_SupportedTransports & eNTCP2V6Mesh; };
|
||||
void EnableV6 ();
|
||||
void DisableV6 ();
|
||||
void EnableV4 ();
|
||||
@@ -241,7 +256,7 @@ namespace data
|
||||
bool IsNewer (const uint8_t * buf, size_t len) const;
|
||||
|
||||
/** return true if we are in a router family and the signature is valid */
|
||||
bool IsFamily(const std::string & fam) const;
|
||||
bool IsFamily (FamilyID famid) const;
|
||||
|
||||
// implements RoutingDestination
|
||||
std::shared_ptr<const IdentityEx> GetIdentity () const { return m_RouterIdentity; };
|
||||
@@ -269,10 +284,11 @@ namespace data
|
||||
uint8_t ExtractAddressCaps (const char * value) const;
|
||||
template<typename Filter>
|
||||
std::shared_ptr<const Address> GetAddress (Filter filter) const;
|
||||
virtual std::shared_ptr<Buffer> NewBuffer () const;
|
||||
|
||||
private:
|
||||
|
||||
std::string m_Family;
|
||||
FamilyID m_FamilyID;
|
||||
std::shared_ptr<const IdentityEx> m_RouterIdentity;
|
||||
std::shared_ptr<Buffer> m_Buffer;
|
||||
size_t m_BufferLen;
|
||||
@@ -303,6 +319,7 @@ namespace data
|
||||
void WriteToStream (std::ostream& s) const;
|
||||
void UpdateCapsProperty ();
|
||||
void WriteString (const std::string& str, std::ostream& s) const;
|
||||
std::shared_ptr<Buffer> NewBuffer () const override;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "util.h"
|
||||
#include "SSU.h"
|
||||
|
||||
#ifdef __linux__
|
||||
#if defined(__linux__) && !defined(_NETINET_IN_H)
|
||||
#include <linux/in6.h>
|
||||
#endif
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace transport
|
||||
m_SocketV6.set_option (boost::asio::ip::v6_only (true));
|
||||
m_SocketV6.set_option (boost::asio::socket_base::receive_buffer_size (SSU_SOCKET_RECEIVE_BUFFER_SIZE));
|
||||
m_SocketV6.set_option (boost::asio::socket_base::send_buffer_size (SSU_SOCKET_SEND_BUFFER_SIZE));
|
||||
#ifdef __linux__
|
||||
#if defined(__linux__) && !defined(_NETINET_IN_H)
|
||||
if (m_EndpointV6.address() == boost::asio::ip::address().from_string("::")) // only if not binded to address
|
||||
{
|
||||
// Set preference to use public IPv6 address -- tested on linux, not works on windows, and not tested on others
|
||||
|
||||
1974
libi2pd/SSU2.cpp
1974
libi2pd/SSU2.cpp
File diff suppressed because it is too large
Load Diff
283
libi2pd/SSU2.h
283
libi2pd/SSU2.h
@@ -10,6 +10,11 @@
|
||||
#define SSU2_H__
|
||||
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <boost/asio.hpp>
|
||||
#include "Crypto.h"
|
||||
#include "RouterInfo.h"
|
||||
#include "TransportSession.h"
|
||||
@@ -18,13 +23,85 @@ namespace i2p
|
||||
{
|
||||
namespace transport
|
||||
{
|
||||
const int SSU2_CONNECT_TIMEOUT = 5; // 5 seconds
|
||||
const int SSU2_TERMINATION_TIMEOUT = 330; // 5.5 minutes
|
||||
const int SSU2_TERMINATION_CHECK_TIMEOUT = 30; // 30 seconds
|
||||
const int SSU2_TOKEN_EXPIRATION_TIMEOUT = 9; // in seconds
|
||||
const int SSU2_RELAY_NONCE_EXPIRATION_TIMEOUT = 10; // in seconds
|
||||
const size_t SSU2_SOCKET_RECEIVE_BUFFER_SIZE = 0x1FFFF; // 128K
|
||||
const size_t SSU2_SOCKET_SEND_BUFFER_SIZE = 0x1FFFF; // 128K
|
||||
const size_t SSU2_MTU = 1488;
|
||||
const size_t SSU2_MAX_PAYLOAD_SIZE = SSU2_MTU - 32;
|
||||
const int SSU2_RESEND_INTERVAL = 3; // in seconds
|
||||
const int SSU2_MAX_NUM_RESENDS = 5;
|
||||
const int SSU2_INCOMPLETE_MESSAGES_CLEANUP_TIMEOUT = 30; // in seconds
|
||||
const size_t SSU2_MAX_WINDOW_SIZE = 128; // in packets
|
||||
|
||||
enum SSU2MessageType
|
||||
{
|
||||
eSSU2SessionRequest = 0
|
||||
eSSU2SessionRequest = 0,
|
||||
eSSU2SessionCreated = 1,
|
||||
eSSU2SessionConfirmed = 2,
|
||||
eSSU2Data = 6,
|
||||
eSSU2Retry = 9,
|
||||
eSSU2TokenRequest = 10
|
||||
};
|
||||
|
||||
enum SSU2BlockType
|
||||
{
|
||||
eSSU2BlkDateTime = 0,
|
||||
eSSU2BlkOptions, // 1
|
||||
eSSU2BlkRouterInfo, // 2
|
||||
eSSU2BlkI2NPMessage, // 3
|
||||
eSSU2BlkFirstFragment, // 4
|
||||
eSSU2BlkFollowOnFragment, // 5
|
||||
eSSU2BlkTermination, // 6
|
||||
eSSU2BlkRelayRequest, // 7
|
||||
eSSU2BlkRelayResponse, // 8
|
||||
eSSU2BlkRelayIntro, // 9
|
||||
eSSU2BlkPeerTest, // 10
|
||||
eSSU2BlkNextNonce, // 11
|
||||
eSSU2BlkAck, // 12
|
||||
eSSU2BlkAddress, // 13
|
||||
eSSU2BlkIntroKey, // 14
|
||||
eSSU2BlkRelayTagRequest, // 15
|
||||
eSSU2BlkRelayTag, // 16
|
||||
eSSU2BlkNewToken, // 17
|
||||
eSSU2BlkPathChallenge, // 18
|
||||
eSSU2BlkPathResponse, // 19
|
||||
eSSU2BlkFirstPacketNumber, // 20
|
||||
eSSU2BlkPadding = 254
|
||||
};
|
||||
|
||||
enum SSU2SessionState
|
||||
{
|
||||
eSSU2SessionStateUnknown,
|
||||
eSSU2SessionStateIntroduced,
|
||||
eSSU2SessionStateEstablished,
|
||||
eSSU2SessionStateTerminated,
|
||||
eSSU2SessionStateFailed
|
||||
};
|
||||
|
||||
struct SSU2IncompleteMessage
|
||||
{
|
||||
struct Fragment
|
||||
{
|
||||
uint8_t buf[SSU2_MTU];
|
||||
size_t len;
|
||||
bool isLast;
|
||||
};
|
||||
|
||||
std::shared_ptr<I2NPMessage> msg;
|
||||
int nextFragmentNum;
|
||||
uint32_t lastFragmentInsertTime; // in seconds
|
||||
std::map<int, std::shared_ptr<Fragment> > outOfSequenceFragments;
|
||||
};
|
||||
|
||||
// RouterInfo flags
|
||||
const uint8_t SSU2_ROUTER_INFO_FLAG_REQUEST_FLOOD = 0x01;
|
||||
const uint8_t SSU2_ROUTER_INFO_FLAG_GZIP = 0x02;
|
||||
|
||||
class SSU2Server;
|
||||
class SSU2Session: public TransportSession, public std::enable_shared_from_this<SSU2Session>
|
||||
{
|
||||
union Header
|
||||
@@ -33,36 +110,214 @@ namespace transport
|
||||
uint8_t buf[16];
|
||||
struct
|
||||
{
|
||||
uint8_t connID[8];
|
||||
uint8_t packetNum[4];
|
||||
uint64_t connID;
|
||||
uint32_t packetNum;
|
||||
uint8_t type;
|
||||
uint8_t flags[3];
|
||||
} h;
|
||||
};
|
||||
|
||||
struct SentPacket
|
||||
{
|
||||
uint8_t payload[SSU2_MAX_PAYLOAD_SIZE];
|
||||
size_t payloadSize = 0;
|
||||
uint32_t nextResendTime; // in seconds
|
||||
int numResends = 0;
|
||||
};
|
||||
|
||||
struct SessionConfirmedFragment
|
||||
{
|
||||
Header header;
|
||||
uint8_t payload[SSU2_MAX_PAYLOAD_SIZE];
|
||||
size_t payloadSize;
|
||||
};
|
||||
|
||||
typedef std::function<void ()> OnEstablished;
|
||||
|
||||
public:
|
||||
|
||||
SSU2Session (std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter = nullptr,
|
||||
std::shared_ptr<const i2p::data::RouterInfo::Address> addr = nullptr, bool peerTest = false);
|
||||
SSU2Session (SSU2Server& server, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter = nullptr,
|
||||
std::shared_ptr<const i2p::data::RouterInfo::Address> addr = nullptr);
|
||||
~SSU2Session ();
|
||||
|
||||
private:
|
||||
void SetRemoteEndpoint (const boost::asio::ip::udp::endpoint& ep) { m_RemoteEndpoint = ep; };
|
||||
const boost::asio::ip::udp::endpoint& GetRemoteEndpoint () const { return m_RemoteEndpoint; };
|
||||
void SetOnEstablished (OnEstablished e) { m_OnEstablished = e; };
|
||||
|
||||
void SendSessionRequest ();
|
||||
void EncryptHeader (Header& h);
|
||||
void CreateHeaderMask (const uint8_t * kh1, const uint8_t * nonce1, const uint8_t * kh2, const uint8_t * nonce2);
|
||||
void Connect ();
|
||||
bool Introduce (std::shared_ptr<SSU2Session> session, uint32_t relayTag);
|
||||
void Terminate ();
|
||||
void TerminateByTimeout ();
|
||||
void CleanUp (uint64_t ts);
|
||||
void FlushData ();
|
||||
void Done () override;
|
||||
void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs) override;
|
||||
void Resend (uint64_t ts);
|
||||
bool IsEstablished () const { return m_State == eSSU2SessionStateEstablished; };
|
||||
uint64_t GetConnID () const { return m_SourceConnID; };
|
||||
SSU2SessionState GetState () const { return m_State; };
|
||||
void SetState (SSU2SessionState state) { m_State = state; };
|
||||
|
||||
bool ProcessFirstIncomingMessage (uint64_t connID, uint8_t * buf, size_t len);
|
||||
bool ProcessSessionCreated (uint8_t * buf, size_t len);
|
||||
bool ProcessSessionConfirmed (uint8_t * buf, size_t len);
|
||||
bool ProcessRetry (uint8_t * buf, size_t len);
|
||||
void ProcessData (uint8_t * buf, size_t len);
|
||||
|
||||
private:
|
||||
|
||||
void Established ();
|
||||
void PostI2NPMessages (std::vector<std::shared_ptr<I2NPMessage> > msgs);
|
||||
bool SendQueue ();
|
||||
void SendFragmentedMessage (std::shared_ptr<I2NPMessage> msg);
|
||||
|
||||
void ProcessSessionRequest (Header& header, uint8_t * buf, size_t len);
|
||||
void ProcessTokenRequest (Header& header, uint8_t * buf, size_t len);
|
||||
|
||||
void SendSessionRequest (uint64_t token = 0);
|
||||
void SendSessionCreated (const uint8_t * X);
|
||||
void SendSessionConfirmed (const uint8_t * Y);
|
||||
void KDFDataPhase (uint8_t * keydata_ab, uint8_t * keydata_ba);
|
||||
void SendTokenRequest ();
|
||||
void SendRetry ();
|
||||
uint32_t SendData (const uint8_t * buf, size_t len); // returns packet num
|
||||
void SendQuickAck ();
|
||||
void SendTermination ();
|
||||
|
||||
void HandlePayload (const uint8_t * buf, size_t len);
|
||||
void HandleAck (const uint8_t * buf, size_t len);
|
||||
void HandleAckRange (uint32_t firstPacketNum, uint32_t lastPacketNum);
|
||||
bool ExtractEndpoint (const uint8_t * buf, size_t size, boost::asio::ip::udp::endpoint& ep);
|
||||
size_t CreateEndpoint (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& ep);
|
||||
std::shared_ptr<const i2p::data::RouterInfo> ExtractRouterInfo (const uint8_t * buf, size_t size);
|
||||
void CreateNonce (uint64_t seqn, uint8_t * nonce);
|
||||
bool UpdateReceivePacketNum (uint32_t packetNum); // for Ack, returns false if duplicate
|
||||
void HandleFirstFragment (const uint8_t * buf, size_t len);
|
||||
void HandleFollowOnFragment (const uint8_t * buf, size_t len);
|
||||
bool ConcatOutOfSequenceFragments (std::shared_ptr<SSU2IncompleteMessage> m); // true if message complete
|
||||
void HandleRelayRequest (const uint8_t * buf, size_t len);
|
||||
void HandleRelayIntro (const uint8_t * buf, size_t len);
|
||||
void HandleRelayResponse (const uint8_t * buf, size_t len);
|
||||
|
||||
size_t CreateAddressBlock (const boost::asio::ip::udp::endpoint& ep, uint8_t * buf, size_t len);
|
||||
size_t CreateAckBlock (uint8_t * buf, size_t len);
|
||||
size_t CreatePaddingBlock (uint8_t * buf, size_t len, size_t minSize = 0);
|
||||
size_t CreateI2NPBlock (uint8_t * buf, size_t len, std::shared_ptr<I2NPMessage>&& msg);
|
||||
size_t CreateFirstFragmentBlock (uint8_t * buf, size_t len, std::shared_ptr<I2NPMessage> msg);
|
||||
size_t CreateFollowOnFragmentBlock (uint8_t * buf, size_t len, std::shared_ptr<I2NPMessage> msg, uint8_t& fragmentNum, uint32_t msgID);
|
||||
size_t CreateRelayIntroBlock (uint8_t * buf, size_t len, const uint8_t * introData, size_t introDataLen);
|
||||
size_t CreateRelayResponseBlock (uint8_t * buf, size_t len, uint32_t nonce); // Charlie
|
||||
|
||||
private:
|
||||
|
||||
SSU2Server& m_Server;
|
||||
std::shared_ptr<i2p::crypto::X25519Keys> m_EphemeralKeys;
|
||||
std::unique_ptr<i2p::crypto::NoiseSymmetricState> m_NoiseState;
|
||||
std::unique_ptr<SessionConfirmedFragment> m_SessionConfirmedFragment1; // for Bob if applicable
|
||||
std::shared_ptr<const i2p::data::RouterInfo::Address> m_Address;
|
||||
boost::asio::ip::udp::endpoint m_RemoteEndpoint;
|
||||
uint64_t m_DestConnID, m_SourceConnID;
|
||||
SSU2SessionState m_State;
|
||||
uint8_t m_KeyDataSend[64], m_KeyDataReceive[64];
|
||||
uint32_t m_SendPacketNum, m_ReceivePacketNum;
|
||||
std::set<uint32_t> m_OutOfSequencePackets; // packet nums > receive packet num
|
||||
std::map<uint32_t, std::shared_ptr<SentPacket> > m_SentPackets; // packetNum -> packet
|
||||
std::map<uint32_t, std::shared_ptr<SSU2IncompleteMessage> > m_IncompleteMessages; // I2NP
|
||||
std::map<uint32_t, std::pair <std::shared_ptr<SSU2Session>, uint64_t > > m_RelaySessions; // nonce->(Alice, timestamp) for Bob or nonce->(Charlie, timestamp) for Alice
|
||||
std::list<std::shared_ptr<I2NPMessage> > m_SendQueue;
|
||||
i2p::I2NPMessagesHandler m_Handler;
|
||||
bool m_IsDataReceived;
|
||||
size_t m_WindowSize;
|
||||
uint32_t m_RelayTag; // between Bob and Charlie
|
||||
OnEstablished m_OnEstablished; // callback from Established
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
uint64_t ll[2];
|
||||
uint8_t buf[16];
|
||||
} m_HeaderMask;
|
||||
class SSU2Server: private i2p::util::RunnableServiceWithWork
|
||||
{
|
||||
struct Packet
|
||||
{
|
||||
uint8_t buf[SSU2_MTU];
|
||||
size_t len;
|
||||
boost::asio::ip::udp::endpoint from;
|
||||
};
|
||||
|
||||
class ReceiveService: public i2p::util::RunnableService
|
||||
{
|
||||
public:
|
||||
|
||||
ReceiveService (const std::string& name): RunnableService (name) {};
|
||||
boost::asio::io_service& GetService () { return GetIOService (); };
|
||||
void Start () { StartIOService (); };
|
||||
void Stop () { StopIOService (); };
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
SSU2Server ();
|
||||
~SSU2Server () {};
|
||||
|
||||
void Start ();
|
||||
void Stop ();
|
||||
boost::asio::io_service& GetService () { return GetIOService (); };
|
||||
|
||||
void AddSession (std::shared_ptr<SSU2Session> session);
|
||||
void RemoveSession (uint64_t connID);
|
||||
void AddSessionByRouterHash (std::shared_ptr<SSU2Session> session);
|
||||
void AddPendingOutgoingSession (std::shared_ptr<SSU2Session> session);
|
||||
|
||||
void AddRelay (uint32_t tag, std::shared_ptr<SSU2Session> relay);
|
||||
void RemoveRelay (uint32_t tag);
|
||||
std::shared_ptr<SSU2Session> FindRelaySession (uint32_t tag);
|
||||
|
||||
void Send (const uint8_t * header, size_t headerLen, const uint8_t * payload, size_t payloadLen,
|
||||
const boost::asio::ip::udp::endpoint& to);
|
||||
void Send (const uint8_t * header, size_t headerLen, const uint8_t * headerX, size_t headerXLen,
|
||||
const uint8_t * payload, size_t payloadLen, const boost::asio::ip::udp::endpoint& to);
|
||||
void SendHolePunch (const boost::asio::ip::udp::endpoint& to);
|
||||
|
||||
bool CreateSession (std::shared_ptr<const i2p::data::RouterInfo> router,
|
||||
std::shared_ptr<const i2p::data::RouterInfo::Address> address);
|
||||
|
||||
void UpdateOutgoingToken (const boost::asio::ip::udp::endpoint& ep, uint64_t token, uint32_t exp);
|
||||
uint64_t FindOutgoingToken (const boost::asio::ip::udp::endpoint& ep) const;
|
||||
uint64_t GetIncomingToken (const boost::asio::ip::udp::endpoint& ep);
|
||||
|
||||
private:
|
||||
|
||||
boost::asio::ip::udp::socket& OpenSocket (const boost::asio::ip::udp::endpoint& localEndpoint);
|
||||
void Receive (boost::asio::ip::udp::socket& socket);
|
||||
void HandleReceivedFrom (const boost::system::error_code& ecode, size_t bytes_transferred,
|
||||
Packet * packet, boost::asio::ip::udp::socket& socket);
|
||||
void HandleReceivedPacket (Packet * packet);
|
||||
void HandleReceivedPackets (std::vector<Packet *> packets);
|
||||
void ProcessNextPacket (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint);
|
||||
|
||||
void ScheduleTermination ();
|
||||
void HandleTerminationTimer (const boost::system::error_code& ecode);
|
||||
|
||||
void ScheduleResend ();
|
||||
void HandleResendTimer (const boost::system::error_code& ecode);
|
||||
|
||||
void ConnectThroughIntroducer (std::shared_ptr<const i2p::data::RouterInfo> router,
|
||||
std::shared_ptr<const i2p::data::RouterInfo::Address> address);
|
||||
|
||||
private:
|
||||
|
||||
ReceiveService m_ReceiveService;
|
||||
boost::asio::ip::udp::socket m_SocketV4, m_SocketV6;
|
||||
std::unordered_map<uint64_t, std::shared_ptr<SSU2Session> > m_Sessions;
|
||||
std::map<i2p::data::IdentHash, std::shared_ptr<SSU2Session> > m_SessionsByRouterHash;
|
||||
std::map<boost::asio::ip::udp::endpoint, std::shared_ptr<SSU2Session> > m_PendingOutgoingSessions;
|
||||
std::map<boost::asio::ip::udp::endpoint, std::pair<uint64_t, uint32_t> > m_IncomingTokens, m_OutgoingTokens; // remote endpoint -> (token, expires in seconds)
|
||||
std::map<uint32_t, std::shared_ptr<SSU2Session> > m_Relays; // we are introducer, relay tag -> session
|
||||
i2p::util::MemoryPoolMt<Packet> m_PacketsPool;
|
||||
boost::asio::deadline_timer m_TerminationTimer, m_ResendTimer;
|
||||
std::shared_ptr<SSU2Session> m_LastSession;
|
||||
|
||||
public:
|
||||
|
||||
// for HTTP/I2PControl
|
||||
const decltype(m_Sessions)& GetSSU2Sessions () const { return m_Sessions; };
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,11 +26,7 @@ namespace transport
|
||||
{
|
||||
|
||||
const size_t SSU_MTU_V4 = 1484;
|
||||
#ifdef MESHNET
|
||||
const size_t SSU_MTU_V6 = 1286;
|
||||
#else
|
||||
const size_t SSU_MTU_V6 = 1488;
|
||||
#endif
|
||||
const size_t IPV4_HEADER_SIZE = 20;
|
||||
const size_t IPV6_HEADER_SIZE = 40;
|
||||
const size_t UDP_HEADER_SIZE = 8;
|
||||
|
||||
@@ -136,7 +136,7 @@ namespace transport
|
||||
Transports::Transports ():
|
||||
m_IsOnline (true), m_IsRunning (false), m_IsNAT (true), m_CheckReserved(true), m_Thread (nullptr),
|
||||
m_Service (nullptr), m_Work (nullptr), m_PeerCleanupTimer (nullptr), m_PeerTestTimer (nullptr),
|
||||
m_SSUServer (nullptr), m_NTCP2Server (nullptr),
|
||||
m_SSUServer (nullptr), m_SSU2Server (nullptr), m_NTCP2Server (nullptr),
|
||||
m_X25519KeysPairSupplier (15), // 15 pre-generated keys
|
||||
m_TotalSentBytes(0), m_TotalReceivedBytes(0), m_TotalTransitTransmittedBytes (0),
|
||||
m_InBandwidth (0), m_OutBandwidth (0), m_TransitBandwidth(0),
|
||||
@@ -157,7 +157,7 @@ namespace transport
|
||||
}
|
||||
}
|
||||
|
||||
void Transports::Start (bool enableNTCP2, bool enableSSU)
|
||||
void Transports::Start (bool enableNTCP2, bool enableSSU, bool enableSSU2)
|
||||
{
|
||||
if (!m_Service)
|
||||
{
|
||||
@@ -217,6 +217,8 @@ namespace transport
|
||||
}
|
||||
}
|
||||
}
|
||||
// create SSU2 server
|
||||
if (enableSSU2) m_SSU2Server = new SSU2Server ();
|
||||
|
||||
// bind to interfaces
|
||||
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
|
||||
@@ -282,6 +284,7 @@ namespace transport
|
||||
}
|
||||
if (m_SSUServer) DetectExternalIP ();
|
||||
}
|
||||
if (m_SSU2Server) m_SSU2Server->Start ();
|
||||
|
||||
m_PeerCleanupTimer->expires_from_now (boost::posix_time::seconds(5*SESSION_CREATION_TIMEOUT));
|
||||
m_PeerCleanupTimer->async_wait (std::bind (&Transports::HandlePeerCleanupTimer, this, std::placeholders::_1));
|
||||
@@ -305,6 +308,13 @@ namespace transport
|
||||
m_SSUServer = nullptr;
|
||||
}
|
||||
|
||||
if (m_SSU2Server)
|
||||
{
|
||||
m_SSU2Server->Stop ();
|
||||
delete m_SSU2Server;
|
||||
m_SSU2Server = nullptr;
|
||||
}
|
||||
|
||||
if (m_NTCP2Server)
|
||||
{
|
||||
m_NTCP2Server->Stop ();
|
||||
@@ -526,6 +536,40 @@ namespace transport
|
||||
}
|
||||
}
|
||||
}
|
||||
if (peer.numAttempts == 5 || peer.numAttempts == 6) // SSU2
|
||||
{
|
||||
if (m_SSU2Server)
|
||||
{
|
||||
std::shared_ptr<const RouterInfo::Address> address;
|
||||
if (peer.numAttempts == 5) // SSU2 ipv6
|
||||
{
|
||||
if (context.GetRouterInfo ().IsSSU2V6 () && peer.router->IsReachableBy (RouterInfo::eSSU2V6))
|
||||
{
|
||||
address = peer.router->GetSSU2V6Address ();
|
||||
if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host))
|
||||
address = nullptr;
|
||||
}
|
||||
peer.numAttempts++;
|
||||
}
|
||||
if (!address && peer.numAttempts == 6) // SSU2 ipv4
|
||||
{
|
||||
if (context.GetRouterInfo ().IsSSU2V4 () && peer.router->IsReachableBy (RouterInfo::eSSU2V4))
|
||||
{
|
||||
address = peer.router->GetSSU2V4Address ();
|
||||
if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host))
|
||||
address = nullptr;
|
||||
}
|
||||
peer.numAttempts++;
|
||||
}
|
||||
if (address && address->IsReachableSSU ())
|
||||
{
|
||||
if (m_SSU2Server->CreateSession (peer.router, address))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
peer.numAttempts += 2;
|
||||
}
|
||||
LogPrint (eLogInfo, "Transports: No compatble NTCP2 or SSU addresses available");
|
||||
i2p::data::netdb.SetUnreachable (ident, true); // we are here because all connection attempts failed
|
||||
peer.Done ();
|
||||
@@ -785,12 +829,18 @@ namespace transport
|
||||
}
|
||||
return i2p::data::netdb.FindRouter (ident);
|
||||
}
|
||||
void Transports::RestrictRoutesToFamilies(std::set<std::string> families)
|
||||
|
||||
void Transports::RestrictRoutesToFamilies(const std::set<std::string>& families)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_FamilyMutex);
|
||||
m_TrustedFamilies.clear();
|
||||
for ( const auto& fam : families )
|
||||
m_TrustedFamilies.push_back(fam);
|
||||
for (auto fam : families)
|
||||
{
|
||||
boost::to_lower (fam);
|
||||
auto id = i2p::data::netdb.GetFamilies ().GetFamilyID (fam);
|
||||
if (id)
|
||||
m_TrustedFamilies.push_back (id);
|
||||
}
|
||||
}
|
||||
|
||||
void Transports::RestrictRoutesToRouters(std::set<i2p::data::IdentHash> routers)
|
||||
@@ -812,20 +862,19 @@ namespace transport
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> l(m_FamilyMutex);
|
||||
std::string fam;
|
||||
i2p::data::FamilyID fam = 0;
|
||||
auto sz = m_TrustedFamilies.size();
|
||||
if(sz > 1)
|
||||
{
|
||||
auto it = m_TrustedFamilies.begin ();
|
||||
std::advance(it, rand() % sz);
|
||||
fam = *it;
|
||||
boost::to_lower(fam);
|
||||
}
|
||||
else if (sz == 1)
|
||||
{
|
||||
fam = m_TrustedFamilies[0];
|
||||
}
|
||||
if (fam.size())
|
||||
if (fam)
|
||||
return i2p::data::netdb.GetRandomRouterInFamily(fam);
|
||||
}
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <boost/asio.hpp>
|
||||
#include "TransportSession.h"
|
||||
#include "SSU.h"
|
||||
#include "SSU2.h"
|
||||
#include "NTCP2.h"
|
||||
#include "RouterInfo.h"
|
||||
#include "I2NPProtocol.h"
|
||||
@@ -86,7 +87,7 @@ namespace transport
|
||||
Transports ();
|
||||
~Transports ();
|
||||
|
||||
void Start (bool enableNTCP2=true, bool enableSSU=true);
|
||||
void Start (bool enableNTCP2=true, bool enableSSU=true, bool enableSSU2=false);
|
||||
void Stop ();
|
||||
|
||||
bool IsBoundSSU() const { return m_SSUServer != nullptr; }
|
||||
@@ -125,7 +126,7 @@ namespace transport
|
||||
/** do we want to use restricted routes? */
|
||||
bool RoutesRestricted() const;
|
||||
/** restrict routes to use only these router families for first hops */
|
||||
void RestrictRoutesToFamilies(std::set<std::string> families);
|
||||
void RestrictRoutesToFamilies(const std::set<std::string>& families);
|
||||
/** restrict routes to use only these routers for first hops */
|
||||
void RestrictRoutesToRouters(std::set<i2p::data::IdentHash> routers);
|
||||
|
||||
@@ -159,6 +160,7 @@ namespace transport
|
||||
boost::asio::deadline_timer * m_PeerCleanupTimer, * m_PeerTestTimer;
|
||||
|
||||
SSUServer * m_SSUServer;
|
||||
SSU2Server * m_SSU2Server;
|
||||
NTCP2Server * m_NTCP2Server;
|
||||
mutable std::mutex m_PeersMutex;
|
||||
std::unordered_map<i2p::data::IdentHash, Peer> m_Peers;
|
||||
@@ -171,7 +173,7 @@ namespace transport
|
||||
uint64_t m_LastBandwidthUpdateTime;
|
||||
|
||||
/** which router families to trust for first hops */
|
||||
std::vector<std::string> m_TrustedFamilies;
|
||||
std::vector<i2p::data::FamilyID> m_TrustedFamilies;
|
||||
mutable std::mutex m_FamilyMutex;
|
||||
|
||||
/** which routers for first hop to trust */
|
||||
@@ -185,6 +187,7 @@ namespace transport
|
||||
// for HTTP only
|
||||
const SSUServer * GetSSUServer () const { return m_SSUServer; };
|
||||
const NTCP2Server * GetNTCP2Server () const { return m_NTCP2Server; };
|
||||
const SSU2Server * GetSSU2Server () const { return m_SSU2Server; };
|
||||
const decltype(m_Peers)& GetPeers () const { return m_Peers; };
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -114,7 +114,7 @@ namespace tunnel
|
||||
uint8_t key[32];
|
||||
uint64_t tag = m_Config->GetLastHop ()->GetGarlicKey (key);
|
||||
if (m_Pool && m_Pool->GetLocalDestination ())
|
||||
m_Pool->GetLocalDestination ()->AddECIESx25519Key (key, tag);
|
||||
m_Pool->GetLocalDestination ()->SubmitECIESx25519Key (key, tag);
|
||||
else
|
||||
i2p::context.AddECIESx25519Key (key, tag);
|
||||
}
|
||||
@@ -235,15 +235,11 @@ namespace tunnel
|
||||
m_State = state;
|
||||
}
|
||||
|
||||
|
||||
void Tunnel::PrintHops (std::stringstream& s) const
|
||||
void Tunnel::VisitTunnelHops(TunnelHopVisitor v)
|
||||
{
|
||||
// hops are in inverted order, we must print in direct order
|
||||
// hops are in inverted order, we must return in direct order
|
||||
for (auto it = m_Hops.rbegin (); it != m_Hops.rend (); it++)
|
||||
{
|
||||
s << " ⇒ ";
|
||||
s << i2p::data::GetIdentHashAbbreviation ((*it).ident->GetIdentHash ());
|
||||
}
|
||||
v((*it).ident);
|
||||
}
|
||||
|
||||
void InboundTunnel::HandleTunnelDataMsg (std::shared_ptr<I2NPMessage>&& msg)
|
||||
@@ -254,12 +250,6 @@ namespace tunnel
|
||||
m_Endpoint.HandleDecryptedTunnelDataMsg (msg);
|
||||
}
|
||||
|
||||
void InboundTunnel::Print (std::stringstream& s) const
|
||||
{
|
||||
PrintHops (s);
|
||||
s << " ⇒ " << GetTunnelID () << ":me";
|
||||
}
|
||||
|
||||
ZeroHopsInboundTunnel::ZeroHopsInboundTunnel ():
|
||||
InboundTunnel (std::make_shared<ZeroHopsTunnelConfig> ()),
|
||||
m_NumReceivedBytes (0)
|
||||
@@ -276,11 +266,6 @@ namespace tunnel
|
||||
}
|
||||
}
|
||||
|
||||
void ZeroHopsInboundTunnel::Print (std::stringstream& s) const
|
||||
{
|
||||
s << " ⇒ " << GetTunnelID () << ":me";
|
||||
}
|
||||
|
||||
void OutboundTunnel::SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, std::shared_ptr<i2p::I2NPMessage> msg)
|
||||
{
|
||||
TunnelMessageBlock block;
|
||||
@@ -315,13 +300,6 @@ namespace tunnel
|
||||
LogPrint (eLogError, "Tunnel: Incoming message for outbound tunnel ", GetTunnelID ());
|
||||
}
|
||||
|
||||
void OutboundTunnel::Print (std::stringstream& s) const
|
||||
{
|
||||
s << GetTunnelID () << ":me";
|
||||
PrintHops (s);
|
||||
s << " ⇒ ";
|
||||
}
|
||||
|
||||
ZeroHopsOutboundTunnel::ZeroHopsOutboundTunnel ():
|
||||
OutboundTunnel (std::make_shared<ZeroHopsTunnelConfig> ()),
|
||||
m_NumSentBytes (0)
|
||||
@@ -351,11 +329,6 @@ namespace tunnel
|
||||
}
|
||||
}
|
||||
|
||||
void ZeroHopsOutboundTunnel::Print (std::stringstream& s) const
|
||||
{
|
||||
s << GetTunnelID () << ":me ⇒ ";
|
||||
}
|
||||
|
||||
Tunnels tunnels;
|
||||
|
||||
Tunnels::Tunnels (): m_IsRunning (false), m_Thread (nullptr),
|
||||
@@ -430,10 +403,10 @@ namespace tunnel
|
||||
return tunnel;
|
||||
}
|
||||
|
||||
std::shared_ptr<TunnelPool> Tunnels::CreateTunnelPool (int numInboundHops,
|
||||
int numOutboundHops, int numInboundTunnels, int numOutboundTunnels)
|
||||
std::shared_ptr<TunnelPool> Tunnels::CreateTunnelPool (int numInboundHops, int numOutboundHops,
|
||||
int numInboundTunnels, int numOutboundTunnels, int inboundVariance, int outboundVariance)
|
||||
{
|
||||
auto pool = std::make_shared<TunnelPool> (numInboundHops, numOutboundHops, numInboundTunnels, numOutboundTunnels);
|
||||
auto pool = std::make_shared<TunnelPool> (numInboundHops, numOutboundHops, numInboundTunnels, numOutboundTunnels, inboundVariance, outboundVariance);
|
||||
std::unique_lock<std::mutex> l(m_PoolsMutex);
|
||||
m_Pools.push_back (pool);
|
||||
return pool;
|
||||
@@ -783,7 +756,7 @@ namespace tunnel
|
||||
int obLen; i2p::config::GetOption("exploratory.outbound.length", obLen);
|
||||
int ibNum; i2p::config::GetOption("exploratory.inbound.quantity", ibNum);
|
||||
int obNum; i2p::config::GetOption("exploratory.outbound.quantity", obNum);
|
||||
m_ExploratoryPool = CreateTunnelPool (ibLen, obLen, ibNum, obNum);
|
||||
m_ExploratoryPool = CreateTunnelPool (ibLen, obLen, ibNum, obNum, 0, 0);
|
||||
m_ExploratoryPool->SetLocalDestination (i2p::context.GetSharedDestination ());
|
||||
}
|
||||
return;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -67,6 +67,9 @@ namespace tunnel
|
||||
|
||||
public:
|
||||
|
||||
/** function for visiting a hops stored in a tunnel */
|
||||
typedef std::function<void(std::shared_ptr<const i2p::data::IdentityEx>)> TunnelHopVisitor;
|
||||
|
||||
Tunnel (std::shared_ptr<const TunnelConfig> config);
|
||||
~Tunnel ();
|
||||
|
||||
@@ -91,8 +94,6 @@ namespace tunnel
|
||||
|
||||
bool HandleTunnelBuildResponse (uint8_t * msg, size_t len);
|
||||
|
||||
virtual void Print (std::stringstream&) const {};
|
||||
|
||||
// implements TunnelBase
|
||||
void SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg);
|
||||
void EncryptTunnelMsg (std::shared_ptr<const I2NPMessage> in, std::shared_ptr<I2NPMessage> out);
|
||||
@@ -107,9 +108,8 @@ namespace tunnel
|
||||
bool LatencyIsKnown() const { return m_Latency > 0; }
|
||||
bool IsSlow () const { return LatencyIsKnown() && (int)m_Latency > HIGH_LATENCY_PER_HOP*GetNumHops (); }
|
||||
|
||||
protected:
|
||||
|
||||
void PrintHops (std::stringstream& s) const;
|
||||
/** visit all hops we currently store */
|
||||
void VisitTunnelHops(TunnelHopVisitor v);
|
||||
|
||||
private:
|
||||
|
||||
@@ -134,7 +134,6 @@ namespace tunnel
|
||||
virtual void SendTunnelDataMsg (const std::vector<TunnelMessageBlock>& msgs); // multiple messages
|
||||
const i2p::data::IdentHash& GetEndpointIdentHash () const { return m_EndpointIdentHash; };
|
||||
virtual size_t GetNumSentBytes () const { return m_Gateway.GetNumSentBytes (); };
|
||||
void Print (std::stringstream& s) const;
|
||||
|
||||
// implements TunnelBase
|
||||
void HandleTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage>&& tunnelMsg);
|
||||
@@ -155,7 +154,6 @@ namespace tunnel
|
||||
InboundTunnel (std::shared_ptr<const TunnelConfig> config): Tunnel (config), m_Endpoint (true) {};
|
||||
void HandleTunnelDataMsg (std::shared_ptr<I2NPMessage>&& msg);
|
||||
virtual size_t GetNumReceivedBytes () const { return m_Endpoint.GetNumReceivedBytes (); };
|
||||
void Print (std::stringstream& s) const;
|
||||
bool IsInbound() const { return true; }
|
||||
|
||||
// override TunnelBase
|
||||
@@ -172,7 +170,6 @@ namespace tunnel
|
||||
|
||||
ZeroHopsInboundTunnel ();
|
||||
void SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg);
|
||||
void Print (std::stringstream& s) const;
|
||||
size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; };
|
||||
|
||||
private:
|
||||
@@ -186,7 +183,6 @@ namespace tunnel
|
||||
|
||||
ZeroHopsOutboundTunnel ();
|
||||
void SendTunnelDataMsg (const std::vector<TunnelMessageBlock>& msgs);
|
||||
void Print (std::stringstream& s) const;
|
||||
size_t GetNumSentBytes () const { return m_NumSentBytes; };
|
||||
|
||||
private:
|
||||
@@ -219,8 +215,8 @@ namespace tunnel
|
||||
void PostTunnelData (const std::vector<std::shared_ptr<I2NPMessage> >& msgs);
|
||||
void AddPendingTunnel (uint32_t replyMsgID, std::shared_ptr<InboundTunnel> tunnel);
|
||||
void AddPendingTunnel (uint32_t replyMsgID, std::shared_ptr<OutboundTunnel> tunnel);
|
||||
std::shared_ptr<TunnelPool> CreateTunnelPool (int numInboundHops,
|
||||
int numOuboundHops, int numInboundTunnels, int numOutboundTunnels);
|
||||
std::shared_ptr<TunnelPool> CreateTunnelPool (int numInboundHops, int numOuboundHops,
|
||||
int numInboundTunnels, int numOutboundTunnels, int inboundVariance, int outboundVariance);
|
||||
void DeleteTunnelPool (std::shared_ptr<TunnelPool> pool);
|
||||
void StopTunnelPool (std::shared_ptr<TunnelPool> pool);
|
||||
|
||||
|
||||
@@ -40,15 +40,25 @@ namespace tunnel
|
||||
std::reverse (peers.begin (), peers.end ());
|
||||
}
|
||||
|
||||
TunnelPool::TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, int numOutboundTunnels):
|
||||
TunnelPool::TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels,
|
||||
int numOutboundTunnels, int inboundVariance, int outboundVariance):
|
||||
m_NumInboundHops (numInboundHops), m_NumOutboundHops (numOutboundHops),
|
||||
m_NumInboundTunnels (numInboundTunnels), m_NumOutboundTunnels (numOutboundTunnels),
|
||||
m_InboundVariance (inboundVariance), m_OutboundVariance (outboundVariance),
|
||||
m_IsActive (true), m_CustomPeerSelector(nullptr)
|
||||
{
|
||||
if (m_NumInboundTunnels > TUNNEL_POOL_MAX_INBOUND_TUNNELS_QUANTITY)
|
||||
m_NumInboundTunnels = TUNNEL_POOL_MAX_INBOUND_TUNNELS_QUANTITY;
|
||||
if (m_NumOutboundTunnels > TUNNEL_POOL_MAX_OUTBOUND_TUNNELS_QUANTITY)
|
||||
m_NumOutboundTunnels = TUNNEL_POOL_MAX_OUTBOUND_TUNNELS_QUANTITY;
|
||||
if (m_InboundVariance < 0 && m_NumInboundHops + m_InboundVariance <= 0)
|
||||
m_InboundVariance = m_NumInboundHops ? -m_NumInboundHops + 1 : 0;
|
||||
if (m_OutboundVariance < 0 && m_NumOutboundHops + m_OutboundVariance <= 0)
|
||||
m_OutboundVariance = m_NumOutboundHops ? -m_NumOutboundHops + 1 : 0;
|
||||
if (m_InboundVariance > 0 && m_NumInboundHops + m_InboundVariance > STANDARD_NUM_RECORDS)
|
||||
m_InboundVariance = (m_NumInboundHops < STANDARD_NUM_RECORDS) ? STANDARD_NUM_RECORDS - m_NumInboundHops : 0;
|
||||
if (m_OutboundVariance > 0 && m_NumOutboundHops + m_OutboundVariance > STANDARD_NUM_RECORDS)
|
||||
m_OutboundVariance = (m_NumOutboundHops < STANDARD_NUM_RECORDS) ? STANDARD_NUM_RECORDS - m_NumOutboundHops : 0;
|
||||
m_NextManageTime = i2p::util::GetSecondsSinceEpoch () + rand () % TUNNEL_POOL_MANAGE_INTERVAL;
|
||||
}
|
||||
|
||||
@@ -372,7 +382,7 @@ namespace tunnel
|
||||
|
||||
void TunnelPool::ManageTunnels (uint64_t ts)
|
||||
{
|
||||
if (ts > m_NextManageTime)
|
||||
if (ts > m_NextManageTime || ts + 2*TUNNEL_POOL_MANAGE_INTERVAL < m_NextManageTime) // in case if clock was adjusted
|
||||
{
|
||||
CreateTunnels ();
|
||||
TestTunnels ();
|
||||
@@ -411,13 +421,18 @@ namespace tunnel
|
||||
{
|
||||
uint64_t dlt = i2p::util::GetMillisecondsSinceEpoch () - timestamp;
|
||||
LogPrint (eLogDebug, "Tunnels: Test of ", msgID, " successful. ", dlt, " milliseconds");
|
||||
uint64_t latency = dlt / 2;
|
||||
int numHops = 0;
|
||||
if (test.first) numHops += test.first->GetNumHops ();
|
||||
if (test.second) numHops += test.second->GetNumHops ();
|
||||
// restore from test failed state if any
|
||||
if (test.first)
|
||||
{
|
||||
if (test.first->GetState () == eTunnelStateTestFailed)
|
||||
test.first->SetState (eTunnelStateEstablished);
|
||||
// update latency
|
||||
uint64_t latency = 0;
|
||||
if (numHops) latency = dlt*test.first->GetNumHops ()/numHops;
|
||||
if (!latency) latency = dlt/2;
|
||||
test.first->AddLatencySample(latency);
|
||||
}
|
||||
if (test.second)
|
||||
@@ -425,6 +440,9 @@ namespace tunnel
|
||||
if (test.second->GetState () == eTunnelStateTestFailed)
|
||||
test.second->SetState (eTunnelStateEstablished);
|
||||
// update latency
|
||||
uint64_t latency = 0;
|
||||
if (numHops) latency = dlt*test.second->GetNumHops ()/numHops;
|
||||
if (!latency) latency = dlt/2;
|
||||
test.second->AddLatencySample(latency);
|
||||
}
|
||||
}
|
||||
@@ -507,7 +525,30 @@ namespace tunnel
|
||||
|
||||
bool TunnelPool::SelectPeers (Path& path, bool isInbound)
|
||||
{
|
||||
int numHops = isInbound ? m_NumInboundHops : m_NumOutboundHops;
|
||||
// explicit peers in use
|
||||
if (m_ExplicitPeers) return SelectExplicitPeers (path, isInbound);
|
||||
// calculate num hops
|
||||
int numHops;
|
||||
if (isInbound)
|
||||
{
|
||||
numHops = m_NumInboundHops;
|
||||
if (m_InboundVariance)
|
||||
{
|
||||
int offset = rand () % (std::abs (m_InboundVariance) + 1);
|
||||
if (m_InboundVariance < 0) offset = -offset;
|
||||
numHops += offset;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
numHops = m_NumOutboundHops;
|
||||
if (m_OutboundVariance)
|
||||
{
|
||||
int offset = rand () % (std::abs (m_OutboundVariance) + 1);
|
||||
if (m_OutboundVariance < 0) offset = -offset;
|
||||
numHops += offset;
|
||||
}
|
||||
}
|
||||
// peers is empty
|
||||
if (numHops <= 0) return true;
|
||||
// custom peer selector in use ?
|
||||
@@ -516,8 +557,6 @@ namespace tunnel
|
||||
if (m_CustomPeerSelector)
|
||||
return m_CustomPeerSelector->SelectPeers(path, numHops, isInbound);
|
||||
}
|
||||
// explicit peers in use
|
||||
if (m_ExplicitPeers) return SelectExplicitPeers (path, isInbound);
|
||||
return StandardSelectPeers(path, numHops, isInbound, std::bind(&TunnelPool::SelectNextHop, this, std::placeholders::_1, std::placeholders::_2));
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,8 @@ namespace tunnel
|
||||
{
|
||||
public:
|
||||
|
||||
TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, int numOutboundTunnels);
|
||||
TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels,
|
||||
int numOutboundTunnels, int inboundVariance, int outboundVariance);
|
||||
~TunnelPool ();
|
||||
|
||||
std::shared_ptr<i2p::garlic::GarlicDestination> GetLocalDestination () const { return m_LocalDestination; };
|
||||
@@ -130,7 +131,8 @@ namespace tunnel
|
||||
private:
|
||||
|
||||
std::shared_ptr<i2p::garlic::GarlicDestination> m_LocalDestination;
|
||||
int m_NumInboundHops, m_NumOutboundHops, m_NumInboundTunnels, m_NumOutboundTunnels;
|
||||
int m_NumInboundHops, m_NumOutboundHops, m_NumInboundTunnels, m_NumOutboundTunnels,
|
||||
m_InboundVariance, m_OutboundVariance;
|
||||
std::shared_ptr<std::vector<i2p::data::IdentHash> > m_ExplicitPeers;
|
||||
mutable std::mutex m_InboundTunnelsMutex;
|
||||
std::set<std::shared_ptr<InboundTunnel>, TunnelCreationTimeCmp> m_InboundTunnels; // recent tunnel appears first
|
||||
|
||||
@@ -27,11 +27,7 @@
|
||||
|
||||
#define VERSION I2PD_VERSION
|
||||
|
||||
#ifdef MESHNET
|
||||
#define I2PD_NET_ID 3
|
||||
#else
|
||||
#define I2PD_NET_ID 2
|
||||
#endif
|
||||
|
||||
#define I2P_VERSION_MAJOR 0
|
||||
#define I2P_VERSION_MINOR 9
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#ifdef WITH_BOB
|
||||
|
||||
#include <string.h>
|
||||
#include "Log.h"
|
||||
#include "ClientContext.h"
|
||||
@@ -884,3 +886,4 @@ namespace client
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // WITH_BOB
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#ifdef WITH_BOB
|
||||
|
||||
#ifndef BOB_H__
|
||||
#define BOB_H__
|
||||
|
||||
@@ -277,5 +279,5 @@ namespace client
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // WITH_BOB
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -26,8 +26,16 @@ namespace client
|
||||
ClientContext context;
|
||||
|
||||
ClientContext::ClientContext (): m_SharedLocalDestination (nullptr),
|
||||
m_HttpProxy (nullptr), m_SocksProxy (nullptr), m_SamBridge (nullptr),
|
||||
m_BOBCommandChannel (nullptr), m_I2CPServer (nullptr)
|
||||
m_HttpProxy (nullptr), m_SocksProxy (nullptr)
|
||||
#ifdef WITH_SAM
|
||||
, m_SamBridge (nullptr)
|
||||
#endif
|
||||
#ifdef WITH_BOB
|
||||
, m_BOBCommandChannel (nullptr)
|
||||
#endif
|
||||
#ifdef WITH_I2CP
|
||||
, m_I2CPServer (nullptr)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
@@ -35,9 +43,15 @@ namespace client
|
||||
{
|
||||
delete m_HttpProxy;
|
||||
delete m_SocksProxy;
|
||||
#ifdef WITH_SAM
|
||||
delete m_SamBridge;
|
||||
#endif
|
||||
#ifdef WITH_BOB
|
||||
delete m_BOBCommandChannel;
|
||||
#endif
|
||||
#ifdef WITH_I2CP
|
||||
delete m_I2CPServer;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ClientContext::Start ()
|
||||
@@ -58,6 +72,7 @@ namespace client
|
||||
// I2P tunnels
|
||||
ReadTunnels ();
|
||||
|
||||
#ifdef WITH_SAM
|
||||
// SAM
|
||||
bool sam; i2p::config::GetOption("sam.enabled", sam);
|
||||
if (sam)
|
||||
@@ -77,7 +92,9 @@ namespace client
|
||||
ThrowFatal ("Unable to start SAM bridge at ", samAddr, ":", samPort, ": ", e.what ());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_BOB
|
||||
// BOB
|
||||
bool bob; i2p::config::GetOption("bob.enabled", bob);
|
||||
if (bob) {
|
||||
@@ -95,7 +112,9 @@ namespace client
|
||||
ThrowFatal ("Unable to start BOB bridge at ", bobAddr, ":", bobPort, ": ", e.what ());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_I2CP
|
||||
// I2CP
|
||||
bool i2cp; i2p::config::GetOption("i2cp.enabled", i2cp);
|
||||
if (i2cp)
|
||||
@@ -115,6 +134,7 @@ namespace client
|
||||
ThrowFatal ("Unable to start I2CP at ", i2cpAddr, ":", i2cpPort, ": ", e.what ());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
m_AddressBook.StartResolvers ();
|
||||
|
||||
@@ -158,6 +178,7 @@ namespace client
|
||||
}
|
||||
m_ServerTunnels.clear ();
|
||||
|
||||
#ifdef WITH_SAM
|
||||
if (m_SamBridge)
|
||||
{
|
||||
LogPrint(eLogInfo, "Clients: Stopping SAM bridge");
|
||||
@@ -165,7 +186,9 @@ namespace client
|
||||
delete m_SamBridge;
|
||||
m_SamBridge = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_BOB
|
||||
if (m_BOBCommandChannel)
|
||||
{
|
||||
LogPrint(eLogInfo, "Clients: Stopping BOB command channel");
|
||||
@@ -173,7 +196,9 @@ namespace client
|
||||
delete m_BOBCommandChannel;
|
||||
m_BOBCommandChannel = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_I2CP
|
||||
if (m_I2CPServer)
|
||||
{
|
||||
LogPrint(eLogInfo, "Clients: Stopping I2CP");
|
||||
@@ -181,6 +206,7 @@ namespace client
|
||||
delete m_I2CPServer;
|
||||
m_I2CPServer = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
LogPrint(eLogInfo, "Clients: Stopping AddressBook");
|
||||
m_AddressBook.Stop ();
|
||||
@@ -455,6 +481,8 @@ namespace client
|
||||
options[I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH] = GetI2CPOption (section, I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, DEFAULT_OUTBOUND_TUNNEL_LENGTH);
|
||||
options[I2CP_PARAM_INBOUND_TUNNELS_QUANTITY] = GetI2CPOption (section, I2CP_PARAM_INBOUND_TUNNELS_QUANTITY, DEFAULT_INBOUND_TUNNELS_QUANTITY);
|
||||
options[I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY] = GetI2CPOption (section, I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY, DEFAULT_OUTBOUND_TUNNELS_QUANTITY);
|
||||
options[I2CP_PARAM_INBOUND_TUNNELS_LENGTH_VARIANCE] = GetI2CPOption (section, I2CP_PARAM_INBOUND_TUNNELS_LENGTH_VARIANCE, DEFAULT_INBOUND_TUNNELS_LENGTH_VARIANCE);
|
||||
options[I2CP_PARAM_OUTBOUND_TUNNELS_LENGTH_VARIANCE] = GetI2CPOption (section, I2CP_PARAM_OUTBOUND_TUNNELS_LENGTH_VARIANCE, DEFAULT_OUTBOUND_TUNNELS_LENGTH_VARIANCE);
|
||||
options[I2CP_PARAM_TAGS_TO_SEND] = GetI2CPOption (section, I2CP_PARAM_TAGS_TO_SEND, DEFAULT_TAGS_TO_SEND);
|
||||
options[I2CP_PARAM_MIN_TUNNEL_LATENCY] = GetI2CPOption(section, I2CP_PARAM_MIN_TUNNEL_LATENCY, DEFAULT_MIN_TUNNEL_LATENCY);
|
||||
options[I2CP_PARAM_MAX_TUNNEL_LATENCY] = GetI2CPOption(section, I2CP_PARAM_MAX_TUNNEL_LATENCY, DEFAULT_MAX_TUNNEL_LATENCY);
|
||||
@@ -487,10 +515,14 @@ namespace client
|
||||
options[I2CP_PARAM_INBOUND_TUNNEL_LENGTH] = value;
|
||||
if (i2p::config::GetOption(prefix + I2CP_PARAM_INBOUND_TUNNELS_QUANTITY, value))
|
||||
options[I2CP_PARAM_INBOUND_TUNNELS_QUANTITY] = value;
|
||||
if (i2p::config::GetOption(prefix + I2CP_PARAM_INBOUND_TUNNELS_LENGTH_VARIANCE, value))
|
||||
options[I2CP_PARAM_INBOUND_TUNNELS_LENGTH_VARIANCE] = value;
|
||||
if (i2p::config::GetOption(prefix + I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, value))
|
||||
options[I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH] = value;
|
||||
if (i2p::config::GetOption(prefix + I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY, value))
|
||||
options[I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY] = value;
|
||||
if (i2p::config::GetOption(prefix + I2CP_PARAM_OUTBOUND_TUNNELS_LENGTH_VARIANCE, value))
|
||||
options[I2CP_PARAM_OUTBOUND_TUNNELS_LENGTH_VARIANCE] = value;
|
||||
if (i2p::config::GetOption(prefix + I2CP_PARAM_MIN_TUNNEL_LATENCY, value))
|
||||
options[I2CP_PARAM_MIN_TUNNEL_LATENCY] = value;
|
||||
if (i2p::config::GetOption(prefix + I2CP_PARAM_MAX_TUNNEL_LATENCY, value))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -18,9 +18,19 @@
|
||||
#include "HTTPProxy.h"
|
||||
#include "SOCKS.h"
|
||||
#include "I2PTunnel.h"
|
||||
|
||||
#ifdef WITH_SAM
|
||||
#include "SAM.h"
|
||||
#endif
|
||||
|
||||
#ifdef WITH_BOB
|
||||
#include "BOB.h"
|
||||
#endif
|
||||
|
||||
#ifdef WITH_I2CP
|
||||
#include "I2CP.h"
|
||||
#endif
|
||||
|
||||
#include "AddressBook.h"
|
||||
#include "I18N_langs.h"
|
||||
|
||||
@@ -76,31 +86,45 @@ namespace client
|
||||
void ReloadConfig ();
|
||||
|
||||
std::shared_ptr<ClientDestination> GetSharedLocalDestination () const { return m_SharedLocalDestination; };
|
||||
std::shared_ptr<ClientDestination> CreateNewLocalDestination (bool isPublic = false, // transient
|
||||
|
||||
std::shared_ptr<ClientDestination> CreateNewLocalDestination (
|
||||
bool isPublic = false, // transient
|
||||
i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519,
|
||||
i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL,
|
||||
const std::map<std::string, std::string> * params = nullptr); // used by SAM only
|
||||
|
||||
std::shared_ptr<ClientDestination> CreateNewLocalDestination (boost::asio::io_service& service,
|
||||
bool isPublic = false, i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519,
|
||||
i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL,
|
||||
const std::map<std::string, std::string> * params = nullptr); // same as previous but on external io_service
|
||||
|
||||
std::shared_ptr<ClientDestination> CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic = true,
|
||||
const std::map<std::string, std::string> * params = nullptr);
|
||||
|
||||
std::shared_ptr<ClientDestination> CreateNewLocalDestination (boost::asio::io_service& service,
|
||||
const i2p::data::PrivateKeys& keys, bool isPublic = true,
|
||||
const std::map<std::string, std::string> * params = nullptr); // same as previous but on external io_service
|
||||
|
||||
std::shared_ptr<ClientDestination> CreateNewMatchedTunnelDestination(const i2p::data::PrivateKeys &keys,
|
||||
const std::string & name, const std::map<std::string, std::string> * params = nullptr);
|
||||
|
||||
void DeleteLocalDestination (std::shared_ptr<ClientDestination> destination);
|
||||
std::shared_ptr<ClientDestination> FindLocalDestination (const i2p::data::IdentHash& destination) const;
|
||||
|
||||
bool LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename,
|
||||
i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519,
|
||||
i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL);
|
||||
|
||||
AddressBook& GetAddressBook () { return m_AddressBook; };
|
||||
#ifdef WITH_BOB
|
||||
const BOBCommandChannel * GetBOBCommandChannel () const { return m_BOBCommandChannel; };
|
||||
#endif
|
||||
#ifdef WITH_SAM
|
||||
const SAMBridge * GetSAMBridge () const { return m_SamBridge; };
|
||||
#endif
|
||||
#ifdef WITH_I2CP
|
||||
const I2CPServer * GetI2CPServer () const { return m_I2CPServer; };
|
||||
#endif
|
||||
|
||||
std::vector<std::shared_ptr<DatagramSessionInfo> > GetForwardInfosFor(const i2p::data::IdentHash & destination);
|
||||
|
||||
@@ -149,9 +173,15 @@ namespace client
|
||||
std::map<boost::asio::ip::udp::endpoint, std::shared_ptr<I2PUDPClientTunnel> > m_ClientForwards; // local endpoint -> udp tunnel
|
||||
std::map<std::pair<i2p::data::IdentHash, int>, std::shared_ptr<I2PUDPServerTunnel> > m_ServerForwards; // <destination,port> -> udp tunnel
|
||||
|
||||
#ifdef WITH_SAM
|
||||
SAMBridge * m_SamBridge;
|
||||
#endif
|
||||
#ifdef WITH_BOB
|
||||
BOBCommandChannel * m_BOBCommandChannel;
|
||||
#endif
|
||||
#ifdef WITH_I2CP
|
||||
I2CPServer * m_I2CPServer;
|
||||
#endif
|
||||
|
||||
std::unique_ptr<boost::asio::deadline_timer> m_CleanupUDPTimer;
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#ifdef WITH_I2CP
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <openssl/rand.h>
|
||||
@@ -524,21 +526,31 @@ namespace client
|
||||
|
||||
void I2CPSession::CreateSessionMessageHandler (const uint8_t * buf, size_t len)
|
||||
{
|
||||
if (m_Destination || !m_Owner.InsertSession (shared_from_this ()))
|
||||
{
|
||||
LogPrint (eLogError, "I2CP: Session already exists");
|
||||
SendSessionStatusMessage (eI2CPSessionStatusRefused); // refused
|
||||
return;
|
||||
}
|
||||
|
||||
RAND_bytes ((uint8_t *)&m_SessionID, 2);
|
||||
auto identity = std::make_shared<i2p::data::IdentityEx>();
|
||||
size_t offset = identity->FromBuffer (buf, len);
|
||||
|
||||
if (!offset)
|
||||
{
|
||||
LogPrint (eLogError, "I2CP: Create session malformed identity");
|
||||
SendSessionStatusMessage (eI2CPSessionStatusInvalid); // invalid
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_Owner.FindSessionByIdentHash (identity->GetIdentHash ()))
|
||||
{
|
||||
LogPrint (eLogError, "I2CP: Create session duplicate address ", identity->GetIdentHash ().ToBase32 ());
|
||||
SendSessionStatusMessage (eI2CPSessionStatusInvalid); // invalid
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t optionsSize = bufbe16toh (buf + offset);
|
||||
offset += 2;
|
||||
if (optionsSize > len - offset)
|
||||
@@ -547,42 +559,27 @@ namespace client
|
||||
SendSessionStatusMessage (eI2CPSessionStatusInvalid); // invalid
|
||||
return;
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> params;
|
||||
ExtractMapping (buf + offset, optionsSize, params);
|
||||
offset += optionsSize; // options
|
||||
if (params[I2CP_PARAM_MESSAGE_RELIABILITY] == "none") m_IsSendAccepted = false;
|
||||
|
||||
offset += 8; // date
|
||||
if (identity->Verify (buf, offset, buf + offset)) // signature
|
||||
{
|
||||
if (!m_Destination)
|
||||
{
|
||||
m_Destination = m_Owner.IsSingleThread () ?
|
||||
std::make_shared<I2CPDestination>(m_Owner.GetService (), shared_from_this (), identity, true, params):
|
||||
std::make_shared<RunnableI2CPDestination>(shared_from_this (), identity, true, params);
|
||||
if (m_Owner.InsertSession (shared_from_this ()))
|
||||
{
|
||||
SendSessionStatusMessage (eI2CPSessionStatusCreated); // created
|
||||
LogPrint (eLogDebug, "I2CP: Session ", m_SessionID, " created");
|
||||
m_Destination->Start ();
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogError, "I2CP: Session already exists");
|
||||
SendSessionStatusMessage (eI2CPSessionStatusRefused);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogError, "I2CP: Session already exists");
|
||||
SendSessionStatusMessage (eI2CPSessionStatusRefused); // refused
|
||||
}
|
||||
}
|
||||
else
|
||||
if (!identity->Verify (buf, offset, buf + offset)) // signature
|
||||
{
|
||||
LogPrint (eLogError, "I2CP: Create session signature verification failed");
|
||||
SendSessionStatusMessage (eI2CPSessionStatusInvalid); // invalid
|
||||
return;
|
||||
}
|
||||
|
||||
m_Destination = m_Owner.IsSingleThread () ?
|
||||
std::make_shared<I2CPDestination>(m_Owner.GetService (), shared_from_this (), identity, true, params):
|
||||
std::make_shared<RunnableI2CPDestination>(shared_from_this (), identity, true, params);
|
||||
|
||||
SendSessionStatusMessage (eI2CPSessionStatusCreated); // created
|
||||
LogPrint (eLogDebug, "I2CP: Session ", m_SessionID, " created");
|
||||
m_Destination->Start ();
|
||||
}
|
||||
|
||||
void I2CPSession::DestroySessionMessageHandler (const uint8_t * buf, size_t len)
|
||||
@@ -1040,3 +1037,4 @@ namespace client
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // WITH_I2CP
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#ifdef WITH_I2CP
|
||||
|
||||
#ifndef I2CP_H__
|
||||
#define I2CP_H__
|
||||
|
||||
@@ -249,3 +251,4 @@ namespace client
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // WITH_I2CP
|
||||
|
||||
@@ -991,6 +991,10 @@ namespace client
|
||||
|
||||
void I2PUDPClientTunnel::HandleRecvFromLocal(const boost::system::error_code & ec, std::size_t transferred)
|
||||
{
|
||||
if(m_cancel_resolve) {
|
||||
LogPrint(eLogDebug, "UDP Client: Ignoring incomming data: stopping");
|
||||
return;
|
||||
}
|
||||
if(ec) {
|
||||
LogPrint(eLogError, "UDP Client: Reading from socket error: ", ec.message(), ". Restarting listener...");
|
||||
RecvFromLocal(); // Restart listener and continue work
|
||||
@@ -1107,14 +1111,13 @@ namespace client
|
||||
{
|
||||
auto dgram = m_LocalDest->GetDatagramDestination();
|
||||
if (dgram) dgram->ResetReceiver();
|
||||
m_cancel_resolve = true;
|
||||
|
||||
m_Sessions.clear();
|
||||
|
||||
if(m_LocalSocket.is_open())
|
||||
m_LocalSocket.close();
|
||||
|
||||
m_cancel_resolve = true;
|
||||
|
||||
if(m_ResolveThread)
|
||||
{
|
||||
m_ResolveThread->join();
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#ifdef WITH_SAM
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#ifdef _MSC_VER
|
||||
@@ -154,11 +156,7 @@ namespace client
|
||||
|
||||
if (SAMVersionAcceptable(version))
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
size_t l = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_HANDSHAKE_REPLY, version.c_str ());
|
||||
#else
|
||||
size_t l = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_HANDSHAKE_REPLY, version.c_str ());
|
||||
#endif
|
||||
boost::asio::async_write (m_Socket, boost::asio::buffer (m_Buffer, l), boost::asio::transfer_all (),
|
||||
std::bind(&SAMSocket::HandleHandshakeReplySent, shared_from_this (),
|
||||
std::placeholders::_1, std::placeholders::_2));
|
||||
@@ -465,11 +463,7 @@ namespace client
|
||||
size_t l = session->GetLocalDestination ()->GetPrivateKeys ().ToBuffer (buf, 1024);
|
||||
size_t l1 = i2p::data::ByteStreamToBase64 (buf, l, priv, 1024);
|
||||
priv[l1] = 0;
|
||||
#ifdef _MSC_VER
|
||||
size_t l2 = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_CREATE_REPLY_OK, priv);
|
||||
#else
|
||||
size_t l2 = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_CREATE_REPLY_OK, priv);
|
||||
#endif
|
||||
SendMessageReply (m_Buffer, l2, false);
|
||||
}
|
||||
}
|
||||
@@ -710,13 +704,8 @@ namespace client
|
||||
}
|
||||
}
|
||||
auto keys = i2p::data::PrivateKeys::CreateRandomKeys (signatureType, cryptoType);
|
||||
#ifdef _MSC_VER
|
||||
size_t l = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_DEST_REPLY,
|
||||
keys.GetPublic ()->ToBase64 ().c_str (), keys.ToBase64 ().c_str ());
|
||||
#else
|
||||
size_t l = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_DEST_REPLY,
|
||||
keys.GetPublic ()->ToBase64 ().c_str (), keys.ToBase64 ().c_str ());
|
||||
#endif
|
||||
SendMessageReply (m_Buffer, l, false);
|
||||
}
|
||||
|
||||
@@ -754,11 +743,7 @@ namespace client
|
||||
else
|
||||
{
|
||||
LogPrint (eLogError, "SAM: Naming failed, unknown address ", name);
|
||||
#ifdef _MSC_VER
|
||||
size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY, name.c_str());
|
||||
#else
|
||||
size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY, name.c_str());
|
||||
#endif
|
||||
SendMessageReply (m_Buffer, len, false);
|
||||
}
|
||||
}
|
||||
@@ -833,11 +818,7 @@ namespace client
|
||||
void SAMSocket::SendI2PError(const std::string & msg)
|
||||
{
|
||||
LogPrint (eLogError, "SAM: I2P error: ", msg);
|
||||
#ifdef _MSC_VER
|
||||
size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_STATUS_I2P_ERROR, msg.c_str());
|
||||
#else
|
||||
size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_STATUS_I2P_ERROR, msg.c_str());
|
||||
#endif
|
||||
SendMessageReply (m_Buffer, len, true);
|
||||
}
|
||||
|
||||
@@ -851,11 +832,7 @@ namespace client
|
||||
else
|
||||
{
|
||||
LogPrint (eLogError, "SAM: Naming lookup failed. LeaseSet for ", name, " not found");
|
||||
#ifdef _MSC_VER
|
||||
size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY, name.c_str());
|
||||
#else
|
||||
size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY, name.c_str());
|
||||
#endif
|
||||
SendMessageReply (m_Buffer, len, false);
|
||||
}
|
||||
}
|
||||
@@ -863,11 +840,7 @@ namespace client
|
||||
void SAMSocket::SendNamingLookupReply (const std::string& name, std::shared_ptr<const i2p::data::IdentityEx> identity)
|
||||
{
|
||||
auto base64 = identity->ToBase64 ();
|
||||
#ifdef _MSC_VER
|
||||
size_t l = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY, name.c_str (), base64.c_str ());
|
||||
#else
|
||||
size_t l = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY, name.c_str (), base64.c_str ());
|
||||
#endif
|
||||
SendMessageReply (m_Buffer, l, false);
|
||||
}
|
||||
|
||||
@@ -1121,11 +1094,7 @@ namespace client
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
size_t l = sprintf_s ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_DATAGRAM_RECEIVED, base64.c_str (), (long unsigned int)len);
|
||||
#else
|
||||
size_t l = snprintf ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_DATAGRAM_RECEIVED, base64.c_str (), (long unsigned int)len);
|
||||
#endif
|
||||
if (len < SAM_SOCKET_BUFFER_SIZE - l)
|
||||
{
|
||||
memcpy (m_StreamBuffer + l, buf, len);
|
||||
@@ -1149,11 +1118,7 @@ namespace client
|
||||
m_Owner.SendTo({ {buf, len} }, *ep);
|
||||
else
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
size_t l = sprintf_s ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_RAW_RECEIVED, (long unsigned int)len);
|
||||
#else
|
||||
size_t l = snprintf ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_RAW_RECEIVED, (long unsigned int)len);
|
||||
#endif
|
||||
if (len < SAM_SOCKET_BUFFER_SIZE - l)
|
||||
{
|
||||
memcpy (m_StreamBuffer + l, buf, len);
|
||||
@@ -1528,3 +1493,4 @@ namespace client
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // WITH_SAM
|
||||
@@ -6,6 +6,8 @@
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#ifdef WITH_SAM
|
||||
|
||||
#ifndef SAM_H__
|
||||
#define SAM_H__
|
||||
|
||||
@@ -286,3 +288,4 @@ namespace client
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // WITH_SAM
|
||||
Reference in New Issue
Block a user