mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-04-23 17:36:37 +02:00
commit
fde79eecc6
39 changed files with 618 additions and 778 deletions
0
.gitmodules
vendored
0
.gitmodules
vendored
28
ChangeLog
28
ChangeLog
|
@ -1,6 +1,34 @@
|
||||||
# for this file format description,
|
# for this file format description,
|
||||||
# see https://github.com/olivierlacan/keep-a-changelog
|
# see https://github.com/olivierlacan/keep-a-changelog
|
||||||
|
|
||||||
|
## [2.37.0] - 2021-03-15
|
||||||
|
### Added
|
||||||
|
- Address registration line for reg.i2p and stats.i2p through the web console
|
||||||
|
- "4" and "6" caps for addresses without published IP address
|
||||||
|
- Mesh and Proxy network statuses
|
||||||
|
- Symmetric NAT network status error
|
||||||
|
- Bind server tunnel connection to specified address
|
||||||
|
- lookuplocal BOB extended command
|
||||||
|
- address4 and address6 parameters to bind outgoing connections to
|
||||||
|
- Rekey of low-bandwidth routers to ECIES
|
||||||
|
- Popup notification windows when unable to parse config for Windows
|
||||||
|
### Changed
|
||||||
|
- Floodfills with "U" cap are not ignored anymore
|
||||||
|
- Check transports reachability between tunnel peers and between router and floodfill
|
||||||
|
- NTCP2 and reseed HTTP proxy support authorization now
|
||||||
|
- Show actual IP addresses for proxy connections
|
||||||
|
- Publish and handle SSU addreses without host
|
||||||
|
- Outbound tunnel endpoint must be ipv4 compatible
|
||||||
|
- Logging optimization
|
||||||
|
- Removed Windows service
|
||||||
|
### Fixed
|
||||||
|
- Incoming SSU session terminates after 5 seconds
|
||||||
|
- Outgoing NTCP2 ipv4 session even if ipv4 is disabled
|
||||||
|
- No incoming Yggdrasil connection if connected through NTCP2 proxy
|
||||||
|
- Race condition between tunnel build and floodfill requests decryption for ECIES routers
|
||||||
|
- Numeric bandwidth limitation
|
||||||
|
- Yggdrasil for Android
|
||||||
|
|
||||||
## [2.36.0] - 2021-02-15
|
## [2.36.0] - 2021-02-15
|
||||||
### Added
|
### Added
|
||||||
- Encrypted lookup and publications to ECIES-x25519 floodfiils
|
- Encrypted lookup and publications to ECIES-x25519 floodfiils
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -39,7 +39,7 @@ else ifneq (, $(findstring freebsd, $(SYS))$(findstring openbsd, $(SYS)))
|
||||||
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
|
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
|
||||||
include Makefile.bsd
|
include Makefile.bsd
|
||||||
else ifneq (, $(findstring mingw, $(SYS))$(findstring cygwin, $(SYS)))
|
else ifneq (, $(findstring mingw, $(SYS))$(findstring cygwin, $(SYS)))
|
||||||
DAEMON_SRC += Win32/DaemonWin32.cpp Win32/Win32Service.cpp Win32/Win32App.cpp Win32/Win32NetState.cpp
|
DAEMON_SRC += Win32/DaemonWin32.cpp Win32/Win32App.cpp Win32/Win32NetState.cpp
|
||||||
include Makefile.mingw
|
include Makefile.mingw
|
||||||
else # not supported
|
else # not supported
|
||||||
$(error Not supported platform)
|
$(error Not supported platform)
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include "Win32Service.h"
|
|
||||||
#ifdef WIN32_APP
|
#ifdef WIN32_APP
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include "Win32App.h"
|
#include "Win32App.h"
|
||||||
|
@ -35,45 +34,11 @@ namespace util
|
||||||
i2p::log::SetThrowFunction ([](const std::string& s)
|
i2p::log::SetThrowFunction ([](const std::string& s)
|
||||||
{
|
{
|
||||||
MessageBox(0, TEXT(s.c_str ()), TEXT("i2pd"), MB_ICONERROR | MB_TASKMODAL | MB_OK );
|
MessageBox(0, TEXT(s.c_str ()), TEXT("i2pd"), MB_ICONERROR | MB_TASKMODAL | MB_OK );
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
if (!Daemon_Singleton::init(argc, argv))
|
if (!Daemon_Singleton::init(argc, argv))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::string serviceControl; i2p::config::GetOption("svcctl", serviceControl);
|
|
||||||
if (serviceControl == "install")
|
|
||||||
{
|
|
||||||
LogPrint(eLogInfo, "WinSVC: installing ", SERVICE_NAME, " as service");
|
|
||||||
InstallService(
|
|
||||||
SERVICE_NAME, // Name of service
|
|
||||||
SERVICE_DISPLAY_NAME, // Name to display
|
|
||||||
SERVICE_START_TYPE, // Service start type
|
|
||||||
SERVICE_DEPENDENCIES, // Dependencies
|
|
||||||
SERVICE_ACCOUNT, // Service running account
|
|
||||||
SERVICE_PASSWORD // Password of the account
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (serviceControl == "remove")
|
|
||||||
{
|
|
||||||
LogPrint(eLogInfo, "WinSVC: uninstalling ", SERVICE_NAME, " service");
|
|
||||||
UninstallService(SERVICE_NAME);
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
LogPrint(eLogDebug, "Daemon: running as user");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,9 +51,6 @@ namespace util
|
||||||
setlocale(LC_TIME, "C");
|
setlocale(LC_TIME, "C");
|
||||||
#ifdef WIN32_APP
|
#ifdef WIN32_APP
|
||||||
if (!i2p::win32::StartWin32App ()) return false;
|
if (!i2p::win32::StartWin32App ()) return false;
|
||||||
|
|
||||||
// override log
|
|
||||||
i2p::config::SetOption("log", std::string ("file"));
|
|
||||||
#endif
|
#endif
|
||||||
bool ret = Daemon_Singleton::start();
|
bool ret = Daemon_Singleton::start();
|
||||||
if (ret && i2p::log::Logger().GetLogType() == eLogFile)
|
if (ret && i2p::log::Logger().GetLogType() == eLogFile)
|
||||||
|
|
|
@ -1,414 +0,0 @@
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define _CRT_SECURE_NO_WARNINGS // to use freopen
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "Win32Service.h"
|
|
||||||
#include <assert.h>
|
|
||||||
//#include <strsafe.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", 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();
|
|
||||||
//i2p::util::config::OptionParser(dwArgc, pszArgv);
|
|
||||||
//i2p::util::filesystem::ReadConfigFile(i2p::util::config::mapArgs, i2p::util::config::mapMultiArgs);
|
|
||||||
//i2p::context.OverrideNTCPAddress(i2p::util::config::GetCharArg("-host", "127.0.0.1"),
|
|
||||||
// i2p::util::config::GetArg("-port", 17070));
|
|
||||||
_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", 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", 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", 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", 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void InstallService(PCSTR pszServiceName, PCSTR pszDisplayName, DWORD dwStartType, PCSTR pszDependencies, PCSTR pszAccount, PCSTR pszPassword)
|
|
||||||
{
|
|
||||||
printf("Try to install Win32Service (%s).\n", pszServiceName);
|
|
||||||
|
|
||||||
char szPath[MAX_PATH];
|
|
||||||
SC_HANDLE schSCManager = NULL;
|
|
||||||
SC_HANDLE schService = NULL;
|
|
||||||
|
|
||||||
if (GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath)) == 0)
|
|
||||||
{
|
|
||||||
printf("GetModuleFileName failed w/err 0x%08lx\n", GetLastError());
|
|
||||||
FreeHandles(schSCManager, schService);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
char SvcOpt[] = " --daemon";
|
|
||||||
strncat(szPath, SvcOpt, strlen(SvcOpt));
|
|
||||||
|
|
||||||
// Open the local default service control manager database
|
|
||||||
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE);
|
|
||||||
if (schSCManager == NULL)
|
|
||||||
{
|
|
||||||
printf("OpenSCManager failed w/err 0x%08lx\n", GetLastError());
|
|
||||||
FreeHandles(schSCManager, schService);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Install the service into SCM by calling CreateService
|
|
||||||
schService = CreateService(
|
|
||||||
schSCManager, // SCManager database
|
|
||||||
pszServiceName, // Name of service
|
|
||||||
pszDisplayName, // Name to display
|
|
||||||
SERVICE_QUERY_STATUS, // Desired access
|
|
||||||
SERVICE_WIN32_OWN_PROCESS, // Service type
|
|
||||||
dwStartType, // Service start type
|
|
||||||
SERVICE_ERROR_NORMAL, // Error control type
|
|
||||||
szPath, // Service's binary
|
|
||||||
NULL, // No load ordering group
|
|
||||||
NULL, // No tag identifier
|
|
||||||
pszDependencies, // Dependencies
|
|
||||||
pszAccount, // Service running account
|
|
||||||
pszPassword // Password of the account
|
|
||||||
);
|
|
||||||
|
|
||||||
if (schService == NULL)
|
|
||||||
{
|
|
||||||
printf("CreateService failed w/err 0x%08lx\n", GetLastError());
|
|
||||||
FreeHandles(schSCManager, schService);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Win32Service is installed as %s.\n", pszServiceName);
|
|
||||||
|
|
||||||
// Centralized cleanup for all allocated resources.
|
|
||||||
FreeHandles(schSCManager, schService);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UninstallService(PCSTR pszServiceName)
|
|
||||||
{
|
|
||||||
printf("Try to uninstall Win32Service (%s).\n", pszServiceName);
|
|
||||||
|
|
||||||
SC_HANDLE schSCManager = NULL;
|
|
||||||
SC_HANDLE schService = NULL;
|
|
||||||
SERVICE_STATUS ssSvcStatus = {};
|
|
||||||
|
|
||||||
// Open the local default service control manager database
|
|
||||||
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
|
|
||||||
if (schSCManager == NULL)
|
|
||||||
{
|
|
||||||
printf("OpenSCManager failed w/err 0x%08lx\n", GetLastError());
|
|
||||||
FreeHandles(schSCManager, schService);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open the service with delete, stop, and query status permissions
|
|
||||||
schService = OpenService(schSCManager, pszServiceName, SERVICE_STOP | SERVICE_QUERY_STATUS | DELETE);
|
|
||||||
if (schService == NULL)
|
|
||||||
{
|
|
||||||
printf("OpenService failed w/err 0x%08lx\n", GetLastError());
|
|
||||||
FreeHandles(schSCManager, schService);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to stop the service
|
|
||||||
if (ControlService(schService, SERVICE_CONTROL_STOP, &ssSvcStatus))
|
|
||||||
{
|
|
||||||
printf("Stopping %s.\n", pszServiceName);
|
|
||||||
Sleep(1000);
|
|
||||||
|
|
||||||
while (QueryServiceStatus(schService, &ssSvcStatus))
|
|
||||||
{
|
|
||||||
if (ssSvcStatus.dwCurrentState == SERVICE_STOP_PENDING)
|
|
||||||
{
|
|
||||||
printf(".");
|
|
||||||
Sleep(1000);
|
|
||||||
}
|
|
||||||
else break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ssSvcStatus.dwCurrentState == SERVICE_STOPPED)
|
|
||||||
{
|
|
||||||
printf("\n%s is stopped.\n", pszServiceName);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("\n%s failed to stop.\n", pszServiceName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now remove the service by calling DeleteService.
|
|
||||||
if (!DeleteService(schService))
|
|
||||||
{
|
|
||||||
printf("DeleteService failed w/err 0x%08lx\n", GetLastError());
|
|
||||||
FreeHandles(schSCManager, schService);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("%s is removed.\n", pszServiceName);
|
|
||||||
|
|
||||||
// Centralized cleanup for all allocated resources.
|
|
||||||
FreeHandles(schSCManager, schService);
|
|
||||||
}
|
|
|
@ -1,92 +0,0 @@
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef WIN_32_SERVICE_H__
|
|
||||||
#define WIN_32_SERVICE_H__
|
|
||||||
|
|
||||||
#include <thread>
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
// Internal name of the service
|
|
||||||
#define SERVICE_NAME "i2pdService"
|
|
||||||
|
|
||||||
// Displayed name of the service
|
|
||||||
#define SERVICE_DISPLAY_NAME "i2pd router service"
|
|
||||||
|
|
||||||
// Service start options.
|
|
||||||
#define SERVICE_START_TYPE SERVICE_DEMAND_START
|
|
||||||
|
|
||||||
// List of service dependencies - "dep1\0dep2\0\0"
|
|
||||||
#define SERVICE_DEPENDENCIES ""
|
|
||||||
|
|
||||||
// The name of the account under which the service should run
|
|
||||||
#define SERVICE_ACCOUNT "NT AUTHORITY\\LocalService"
|
|
||||||
|
|
||||||
// The password to the service account name
|
|
||||||
#define SERVICE_PASSWORD NULL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
void InstallService(
|
|
||||||
PCSTR pszServiceName,
|
|
||||||
PCSTR pszDisplayName,
|
|
||||||
DWORD dwStartType,
|
|
||||||
PCSTR pszDependencies,
|
|
||||||
PCSTR pszAccount,
|
|
||||||
PCSTR pszPassword
|
|
||||||
);
|
|
||||||
|
|
||||||
void UninstallService(PCSTR pszServiceName);
|
|
||||||
|
|
||||||
#endif // WIN_32_SERVICE_H__
|
|
|
@ -1,4 +1,4 @@
|
||||||
version: 2.36.0.{build}
|
version: 2.37.0.{build}
|
||||||
pull_requests:
|
pull_requests:
|
||||||
do_not_increment_build_number: true
|
do_not_increment_build_number: true
|
||||||
branches:
|
branches:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
%define git_hash %(git rev-parse HEAD | cut -c -7)
|
%define git_hash %(git rev-parse HEAD | cut -c -7)
|
||||||
|
|
||||||
Name: i2pd-git
|
Name: i2pd-git
|
||||||
Version: 2.36.0
|
Version: 2.37.0
|
||||||
Release: git%{git_hash}%{?dist}
|
Release: git%{git_hash}%{?dist}
|
||||||
Summary: I2P router written in C++
|
Summary: I2P router written in C++
|
||||||
Conflicts: i2pd
|
Conflicts: i2pd
|
||||||
|
@ -137,6 +137,9 @@ getent passwd i2pd >/dev/null || \
|
||||||
|
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Mon Mar 15 2021 orignal <i2porignal@yandex.ru> - 2.37.0
|
||||||
|
- update to 2.37.0
|
||||||
|
|
||||||
* Mon Feb 15 2021 orignal <i2porignal@yandex.ru> - 2.36.0
|
* Mon Feb 15 2021 orignal <i2porignal@yandex.ru> - 2.36.0
|
||||||
- update to 2.36.0
|
- update to 2.36.0
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
Name: i2pd
|
Name: i2pd
|
||||||
Version: 2.36.0
|
Version: 2.37.0
|
||||||
Release: 1%{?dist}
|
Release: 1%{?dist}
|
||||||
Summary: I2P router written in C++
|
Summary: I2P router written in C++
|
||||||
Conflicts: i2pd-git
|
Conflicts: i2pd-git
|
||||||
|
@ -135,6 +135,9 @@ getent passwd i2pd >/dev/null || \
|
||||||
|
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Mon Mar 15 2021 orignal <i2porignal@yandex.ru> - 2.37.0
|
||||||
|
- update to 2.37.0
|
||||||
|
|
||||||
* Mon Feb 15 2021 orignal <i2porignal@yandex.ru> - 2.36.0
|
* Mon Feb 15 2021 orignal <i2porignal@yandex.ru> - 2.36.0
|
||||||
- update to 2.36.0
|
- update to 2.36.0
|
||||||
|
|
||||||
|
|
|
@ -102,8 +102,13 @@ namespace util
|
||||||
if (logclftime)
|
if (logclftime)
|
||||||
i2p::log::Logger().SetTimeFormat ("[%d/%b/%Y:%H:%M:%S %z]");
|
i2p::log::Logger().SetTimeFormat ("[%d/%b/%Y:%H:%M:%S %z]");
|
||||||
|
|
||||||
|
#ifdef WIN32_APP
|
||||||
|
// Win32 app with GUI supports only logging to file
|
||||||
|
logs = "file";
|
||||||
|
#else
|
||||||
if (isDaemon && (logs == "" || logs == "stdout"))
|
if (isDaemon && (logs == "" || logs == "stdout"))
|
||||||
logs = "file";
|
logs = "file";
|
||||||
|
#endif
|
||||||
|
|
||||||
i2p::log::Logger().SetLogLevel(loglevel);
|
i2p::log::Logger().SetLogLevel(loglevel);
|
||||||
if (logstream) {
|
if (logstream) {
|
||||||
|
@ -123,7 +128,7 @@ namespace util
|
||||||
// use stdout -- default
|
// use stdout -- default
|
||||||
}
|
}
|
||||||
|
|
||||||
LogPrint(eLogInfo, "i2pd v", VERSION, " starting");
|
LogPrint(eLogNone, "i2pd v", VERSION, " starting");
|
||||||
LogPrint(eLogDebug, "FS: main config file: ", config);
|
LogPrint(eLogDebug, "FS: main config file: ", config);
|
||||||
LogPrint(eLogDebug, "FS: data directory: ", datadir);
|
LogPrint(eLogDebug, "FS: data directory: ", datadir);
|
||||||
|
|
||||||
|
@ -144,6 +149,25 @@ namespace util
|
||||||
ipv4 = false;
|
ipv4 = false;
|
||||||
ipv6 = true;
|
ipv6 = true;
|
||||||
#endif
|
#endif
|
||||||
|
// ifname -> address
|
||||||
|
std::string ifname; i2p::config::GetOption("ifname", ifname);
|
||||||
|
if (ipv4 && i2p::config::IsDefault ("address4"))
|
||||||
|
{
|
||||||
|
std::string ifname4; i2p::config::GetOption("ifname4", ifname4);
|
||||||
|
if (!ifname4.empty ())
|
||||||
|
i2p::config::SetOption ("address4", i2p::util::net::GetInterfaceAddress(ifname4, false).to_string ()); // v4
|
||||||
|
else if (!ifname.empty ())
|
||||||
|
i2p::config::SetOption ("address4", i2p::util::net::GetInterfaceAddress(ifname, false).to_string ()); // v4
|
||||||
|
}
|
||||||
|
if (ipv6 && i2p::config::IsDefault ("address6"))
|
||||||
|
{
|
||||||
|
std::string ifname6; i2p::config::GetOption("ifname6", ifname6);
|
||||||
|
if (!ifname6.empty ())
|
||||||
|
i2p::config::SetOption ("address6", i2p::util::net::GetInterfaceAddress(ifname6, true).to_string ()); // v6
|
||||||
|
else if (!ifname.empty ())
|
||||||
|
i2p::config::SetOption ("address6", i2p::util::net::GetInterfaceAddress(ifname, true).to_string ()); // v6
|
||||||
|
}
|
||||||
|
|
||||||
bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg);
|
bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg);
|
||||||
boost::asio::ip::address_v6 yggaddr;
|
boost::asio::ip::address_v6 yggaddr;
|
||||||
if (ygg)
|
if (ygg)
|
||||||
|
@ -186,6 +210,11 @@ namespace util
|
||||||
{
|
{
|
||||||
bool published; i2p::config::GetOption("ntcp2.published", published);
|
bool published; i2p::config::GetOption("ntcp2.published", published);
|
||||||
if (published)
|
if (published)
|
||||||
|
{
|
||||||
|
std::string ntcp2proxy; i2p::config::GetOption("ntcp2.proxy", ntcp2proxy);
|
||||||
|
if (!ntcp2proxy.empty ()) published = false;
|
||||||
|
}
|
||||||
|
if (published)
|
||||||
{
|
{
|
||||||
uint16_t ntcp2port; i2p::config::GetOption("ntcp2.port", ntcp2port);
|
uint16_t ntcp2port; i2p::config::GetOption("ntcp2.port", ntcp2port);
|
||||||
if (!ntcp2port) ntcp2port = port; // use standard port
|
if (!ntcp2port) ntcp2port = port; // use standard port
|
||||||
|
@ -206,6 +235,8 @@ namespace util
|
||||||
if (!ntcp2)
|
if (!ntcp2)
|
||||||
i2p::context.PublishNTCP2Address (port, true);
|
i2p::context.PublishNTCP2Address (port, true);
|
||||||
i2p::context.UpdateNTCP2V6Address (yggaddr);
|
i2p::context.UpdateNTCP2V6Address (yggaddr);
|
||||||
|
if (!ipv4 && !ipv6)
|
||||||
|
i2p::context.SetStatus (eRouterStatusMesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool transit; i2p::config::GetOption("notransit", transit);
|
bool transit; i2p::config::GetOption("notransit", transit);
|
||||||
|
@ -343,7 +374,7 @@ namespace util
|
||||||
if(!ntcp2) LogPrint(eLogInfo, "Daemon: ntcp2 disabled");
|
if(!ntcp2) LogPrint(eLogInfo, "Daemon: ntcp2 disabled");
|
||||||
|
|
||||||
i2p::transport::transports.SetCheckReserved(checkInReserved);
|
i2p::transport::transports.SetCheckReserved(checkInReserved);
|
||||||
i2p::transport::transports.Start(ntcp2 || i2p::context.SupportsMesh (), ssu);
|
i2p::transport::transports.Start(ntcp2, ssu);
|
||||||
if (i2p::transport::transports.IsBoundSSU() || i2p::transport::transports.IsBoundNTCP2())
|
if (i2p::transport::transports.IsBoundSSU() || i2p::transport::transports.IsBoundNTCP2())
|
||||||
LogPrint(eLogInfo, "Daemon: Transports started");
|
LogPrint(eLogInfo, "Daemon: Transports started");
|
||||||
else
|
else
|
||||||
|
|
|
@ -123,6 +123,7 @@ namespace http {
|
||||||
const char HTTP_COMMAND_LOGLEVEL[] = "set_loglevel";
|
const char HTTP_COMMAND_LOGLEVEL[] = "set_loglevel";
|
||||||
const char HTTP_COMMAND_KILLSTREAM[] = "closestream";
|
const char HTTP_COMMAND_KILLSTREAM[] = "closestream";
|
||||||
const char HTTP_COMMAND_LIMITTRANSIT[] = "limittransit";
|
const char HTTP_COMMAND_LIMITTRANSIT[] = "limittransit";
|
||||||
|
const char HTTP_COMMAND_GET_REG_STRING[] = "get_reg_string";
|
||||||
const char HTTP_PARAM_SAM_SESSION_ID[] = "id";
|
const char HTTP_PARAM_SAM_SESSION_ID[] = "id";
|
||||||
const char HTTP_PARAM_ADDRESS[] = "address";
|
const char HTTP_PARAM_ADDRESS[] = "address";
|
||||||
|
|
||||||
|
@ -252,6 +253,9 @@ namespace http {
|
||||||
case eRouterStatusOK: s << "OK"; break;
|
case eRouterStatusOK: s << "OK"; break;
|
||||||
case eRouterStatusTesting: s << "Testing"; break;
|
case eRouterStatusTesting: s << "Testing"; break;
|
||||||
case eRouterStatusFirewalled: s << "Firewalled"; break;
|
case eRouterStatusFirewalled: s << "Firewalled"; break;
|
||||||
|
case eRouterStatusUnknown: s << "Unknown"; break;
|
||||||
|
case eRouterStatusProxy: s << "Proxy"; break;
|
||||||
|
case eRouterStatusMesh: s << "Mesh"; break;
|
||||||
case eRouterStatusError:
|
case eRouterStatusError:
|
||||||
{
|
{
|
||||||
s << "Error";
|
s << "Error";
|
||||||
|
@ -405,9 +409,9 @@ namespace http {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ShowLeaseSetDestination (std::stringstream& s, std::shared_ptr<const i2p::client::LeaseSetDestination> dest)
|
static void ShowLeaseSetDestination (std::stringstream& s, std::shared_ptr<const i2p::client::LeaseSetDestination> dest, uint32_t token)
|
||||||
{
|
{
|
||||||
s << "<b>Base64:</b><br>\r\n<textarea readonly cols=\"80\" rows=\"8\" wrap=\"on\">";
|
s << "<b>Base64:</b><br>\r\n<textarea readonly cols=\"80\" rows=\"8\">";
|
||||||
s << dest->GetIdentity ()->ToBase64 () << "</textarea><br>\r\n<br>\r\n";
|
s << dest->GetIdentity ()->ToBase64 () << "</textarea><br>\r\n<br>\r\n";
|
||||||
if (dest->IsEncryptedLeaseSet ())
|
if (dest->IsEncryptedLeaseSet ())
|
||||||
{
|
{
|
||||||
|
@ -417,6 +421,20 @@ namespace http {
|
||||||
s << "</div>\r\n</div>\r\n";
|
s << "</div>\r\n</div>\r\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(dest->IsPublic())
|
||||||
|
{
|
||||||
|
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
|
||||||
|
auto base32 = dest->GetIdentHash ().ToBase32 ();
|
||||||
|
s << "<div class='slide'><label for='slide-regaddr'><b>Address registration line</b></label>\r\n<input type=\"checkbox\" id=\"slide-regaddr\" />\r\n<div class=\"slidecontent\">\r\n"
|
||||||
|
"<form method=\"get\" action=\"" << webroot << "\">\r\n"
|
||||||
|
" <input type=\"hidden\" name=\"cmd\" value=\"" << HTTP_COMMAND_GET_REG_STRING << "\">\r\n"
|
||||||
|
" <input type=\"hidden\" name=\"token\" value=\"" << token << "\">\r\n"
|
||||||
|
" <input type=\"hidden\" name=\"b32\" value=\"" << base32 << "\">\r\n"
|
||||||
|
" <b>Domain:</b>\r\n<input type=\"text\" maxlength=\"67\" name=\"name\" placeholder=\"domain.i2p\" required>\r\n"
|
||||||
|
" <button type=\"submit\">Generate</button>\r\n"
|
||||||
|
"</form>\r\n<small><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>LeaseSets:</b> <i>" << dest->GetNumRemoteLeaseSets ()
|
s << "<div class='slide'><label for='slide-lease'><b>LeaseSets:</b> <i>" << dest->GetNumRemoteLeaseSets ()
|
||||||
|
@ -492,7 +510,7 @@ namespace http {
|
||||||
|
|
||||||
if (dest)
|
if (dest)
|
||||||
{
|
{
|
||||||
ShowLeaseSetDestination (s, dest);
|
ShowLeaseSetDestination (s, dest, token);
|
||||||
// show streams
|
// show streams
|
||||||
s << "<table>\r\n<caption>Streams</caption>\r\n<thead>\r\n<tr>";
|
s << "<table>\r\n<caption>Streams</caption>\r\n<thead>\r\n<tr>";
|
||||||
s << "<th style=\"width:25px;\">StreamID</th>";
|
s << "<th style=\"width:25px;\">StreamID</th>";
|
||||||
|
@ -535,7 +553,7 @@ namespace http {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShowI2CPLocalDestination (std::stringstream& s, const std::string& id)
|
void ShowI2CPLocalDestination (std::stringstream& s, const std::string& id)
|
||||||
{
|
{
|
||||||
auto i2cpServer = i2p::client::context.GetI2CPServer ();
|
auto i2cpServer = i2p::client::context.GetI2CPServer ();
|
||||||
if (i2cpServer)
|
if (i2cpServer)
|
||||||
|
@ -543,7 +561,7 @@ namespace http {
|
||||||
s << "<b>I2CP Local Destination:</b><br>\r\n<br>\r\n";
|
s << "<b>I2CP Local Destination:</b><br>\r\n<br>\r\n";
|
||||||
auto it = i2cpServer->GetSessions ().find (std::stoi (id));
|
auto it = i2cpServer->GetSessions ().find (std::stoi (id));
|
||||||
if (it != i2cpServer->GetSessions ().end ())
|
if (it != i2cpServer->GetSessions ().end ())
|
||||||
ShowLeaseSetDestination (s, it->second->GetDestination ());
|
ShowLeaseSetDestination (s, it->second->GetDestination (), 0);
|
||||||
else
|
else
|
||||||
ShowError(s, "I2CP session not found");
|
ShowError(s, "I2CP session not found");
|
||||||
}
|
}
|
||||||
|
@ -823,7 +841,7 @@ namespace http {
|
||||||
s << "<b>SAM Sessions:</b> no sessions currently running.<br>\r\n";
|
s << "<b>SAM Sessions:</b> no sessions currently running.<br>\r\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShowSAMSession (std::stringstream& s, const std::string& id)
|
void ShowSAMSession (std::stringstream& s, const std::string& id)
|
||||||
{
|
{
|
||||||
auto sam = i2p::client::context.GetSAMBridge ();
|
auto sam = i2p::client::context.GetSAMBridge ();
|
||||||
if (!sam) {
|
if (!sam) {
|
||||||
|
@ -1208,15 +1226,15 @@ namespace http {
|
||||||
if (dest)
|
if (dest)
|
||||||
{
|
{
|
||||||
if(dest->DeleteStream (streamID))
|
if(dest->DeleteStream (streamID))
|
||||||
s << "<b>SUCCESS</b>: Stream closed<br><br>\r\n";
|
s << "<b>SUCCESS</b>: Stream closed<br>\r\n<br>\r\n";
|
||||||
else
|
else
|
||||||
s << "<b>ERROR</b>: Stream not found or already was closed<br><br>\r\n";
|
s << "<b>ERROR</b>: Stream not found or already was closed<br>\r\n<br>\r\n";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
s << "<b>ERROR</b>: Destination not found<br><br>\r\n";
|
s << "<b>ERROR</b>: Destination not found<br>\r\n<br>\r\n";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
s << "<b>ERROR</b>: StreamID can be null<br><br>\r\n";
|
s << "<b>ERROR</b>: StreamID can be null<br>\r\n<br>\r\n";
|
||||||
|
|
||||||
s << "<a href=\"" << webroot << "?page=local_destination&b32=" << b32 << "\">Return to destination page</a><br>\r\n";
|
s << "<a href=\"" << webroot << "?page=local_destination&b32=" << b32 << "\">Return to destination page</a><br>\r\n";
|
||||||
s << "<p>You will be redirected back in 5 seconds</b>";
|
s << "<p>You will be redirected back in 5 seconds</b>";
|
||||||
|
@ -1230,13 +1248,62 @@ namespace http {
|
||||||
if (limit > 0 && limit <= 65535)
|
if (limit > 0 && limit <= 65535)
|
||||||
SetMaxNumTransitTunnels (limit);
|
SetMaxNumTransitTunnels (limit);
|
||||||
else {
|
else {
|
||||||
s << "<b>ERROR</b>: Transit tunnels count must not exceed 65535<br><br>\r\n";
|
s << "<b>ERROR</b>: Transit tunnels count must not exceed 65535\r\n<br>\r\n<br>\r\n";
|
||||||
s << "<a href=\"" << webroot << "?page=commands\">Back to commands list</a><br>\r\n";
|
s << "<a href=\"" << webroot << "?page=commands\">Back to commands list</a>\r\n<br>\r\n";
|
||||||
s << "<p>You will be redirected back in 5 seconds</b>";
|
s << "<p>You will be redirected back in 5 seconds</b>";
|
||||||
res.add_header("Refresh", redirect.c_str());
|
res.add_header("Refresh", redirect.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (cmd == HTTP_COMMAND_GET_REG_STRING)
|
||||||
|
{
|
||||||
|
std::string b32 = params["b32"];
|
||||||
|
std::string name = params["name"];
|
||||||
|
|
||||||
|
i2p::data::IdentHash ident;
|
||||||
|
ident.FromBase32 (b32);
|
||||||
|
auto dest = i2p::client::context.FindLocalDestination (ident);
|
||||||
|
|
||||||
|
if (dest)
|
||||||
|
{
|
||||||
|
std::size_t pos;
|
||||||
|
pos = name.find (".i2p");
|
||||||
|
if (pos == (name.length () - 4))
|
||||||
|
{
|
||||||
|
pos = name.find (".b32.i2p");
|
||||||
|
if (pos == std::string::npos)
|
||||||
|
{
|
||||||
|
auto signatureLen = dest->GetIdentity ()->GetSignatureLen ();
|
||||||
|
uint8_t * signature = new uint8_t[signatureLen];
|
||||||
|
char * sig = new char[signatureLen*2];
|
||||||
|
std::stringstream out;
|
||||||
|
|
||||||
|
out << name << "=" << dest->GetIdentity ()->ToBase64 ();
|
||||||
|
dest->Sign ((uint8_t *)out.str ().c_str (), out.str ().length (), signature);
|
||||||
|
auto len = i2p::data::ByteStreamToBase64 (signature, signatureLen, sig, signatureLen*2);
|
||||||
|
sig[len] = 0;
|
||||||
|
out << "#!sig=" << sig;
|
||||||
|
s << "<b>SUCCESS</b>:<br>\r\n<form action=\"http://shx5vqsw7usdaunyzr2qmes2fq37oumybpudrd4jjj4e4vk4uusa.b32.i2p/add\" method=\"post\" rel=\"noreferrer\" target=\"_blank\">\r\n"
|
||||||
|
"<textarea readonly name=\"record\" cols=\"80\" rows=\"10\">" << out.str () << "</textarea>\r\n<br>\r\n<br>\r\n"
|
||||||
|
"<b>Register at reg.i2p:</b>\r\n<br>\r\n"
|
||||||
|
"<b>Description:</b>\r\n<input type=\"text\" maxlength=\"64\" name=\"desc\" placeholder=\"A bit information about service on domain\">\r\n"
|
||||||
|
"<input type=\"submit\" value=\"Submit\">\r\n"
|
||||||
|
"</form>\r\n<br>\r\n";
|
||||||
|
delete[] signature;
|
||||||
|
delete[] sig;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
s << "<b>ERROR</b>: Domain can't end with .b32.i2p\r\n<br>\r\n<br>\r\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
s << "<b>ERROR</b>: Domain must end with .i2p\r\n<br>\r\n<br>\r\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
s << "<b>ERROR</b>: Such destination is not found\r\n<br>\r\n<br>\r\n";
|
||||||
|
|
||||||
|
s << "<a href=\"" << webroot << "?page=local_destination&b32=" << b32 << "\">Return to destination page</a>\r\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
res.code = 400;
|
res.code = 400;
|
||||||
|
|
6
debian/changelog
vendored
6
debian/changelog
vendored
|
@ -1,3 +1,9 @@
|
||||||
|
i2pd (2.37.0-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* updated to version 2.37.0
|
||||||
|
|
||||||
|
-- orignal <orignal@i2pmail.org> Mon, 15 Mar 2021 16:00:00 +0000
|
||||||
|
|
||||||
i2pd (2.36.0-1) unstable; urgency=high
|
i2pd (2.36.0-1) unstable; urgency=high
|
||||||
|
|
||||||
* updated to version 2.36.0/0.9.49
|
* updated to version 2.36.0/0.9.49
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "Identity.h"
|
#include "Identity.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
#include "Log.h"
|
||||||
|
|
||||||
using namespace boost::program_options;
|
using namespace boost::program_options;
|
||||||
|
|
||||||
|
@ -65,7 +66,7 @@ namespace config {
|
||||||
("ssu", bool_switch()->default_value(true), "Enable SSU transport (default: enabled)")
|
("ssu", bool_switch()->default_value(true), "Enable SSU transport (default: enabled)")
|
||||||
("ntcpproxy", value<std::string>()->default_value(""), "Ignored")
|
("ntcpproxy", value<std::string>()->default_value(""), "Ignored")
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
("svcctl", value<std::string>()->default_value(""), "Windows service management ('install' or 'remove')")
|
("svcctl", value<std::string>()->default_value(""), "Ignored")
|
||||||
("insomnia", bool_switch()->default_value(false), "Prevent system from sleeping (default: disabled)")
|
("insomnia", bool_switch()->default_value(false), "Prevent system from sleeping (default: disabled)")
|
||||||
("close", value<std::string>()->default_value("ask"), "Action on close: minimize, exit, ask")
|
("close", value<std::string>()->default_value("ask"), "Action on close: minimize, exit, ask")
|
||||||
#endif
|
#endif
|
||||||
|
@ -209,7 +210,7 @@ namespace config {
|
||||||
), "Reseed URLs, separated by comma")
|
), "Reseed URLs, separated by comma")
|
||||||
("reseed.yggurls", value<std::string>()->default_value(
|
("reseed.yggurls", value<std::string>()->default_value(
|
||||||
"http://[324:9de3:fea4:f6ac::ace]:7070/"
|
"http://[324:9de3:fea4:f6ac::ace]:7070/"
|
||||||
), "Reseed URLs through the Yggdrasil, separated by comma")
|
), "Reseed URLs through the Yggdrasil, separated by comma")
|
||||||
;
|
;
|
||||||
|
|
||||||
options_description addressbook("AddressBook options");
|
options_description addressbook("AddressBook options");
|
||||||
|
@ -218,12 +219,12 @@ namespace config {
|
||||||
"http://shx5vqsw7usdaunyzr2qmes2fq37oumybpudrd4jjj4e4vk4uusa.b32.i2p/hosts.txt"
|
"http://shx5vqsw7usdaunyzr2qmes2fq37oumybpudrd4jjj4e4vk4uusa.b32.i2p/hosts.txt"
|
||||||
), "AddressBook subscription URL for initial setup")
|
), "AddressBook subscription URL for initial setup")
|
||||||
("addressbook.subscriptions", value<std::string>()->default_value(""), "AddressBook subscriptions URLs, separated by comma")
|
("addressbook.subscriptions", value<std::string>()->default_value(""), "AddressBook subscriptions URLs, separated by comma")
|
||||||
("addressbook.hostsfile", value<std::string>()->default_value(""), "File to dump addresses in hosts.txt format");
|
("addressbook.hostsfile", value<std::string>()->default_value(""), "File to dump addresses in hosts.txt format");
|
||||||
|
|
||||||
options_description trust("Trust options");
|
options_description trust("Trust options");
|
||||||
trust.add_options()
|
trust.add_options()
|
||||||
("trust.enabled", value<bool>()->default_value(false), "Enable explicit trust options")
|
("trust.enabled", value<bool>()->default_value(false), "Enable explicit trust options")
|
||||||
("trust.family", value<std::string>()->default_value(""), "Router Familiy to trust for first hops")
|
("trust.family", value<std::string>()->default_value(""), "Router Family to trust for first hops")
|
||||||
("trust.routers", value<std::string>()->default_value(""), "Only Connect to these routers")
|
("trust.routers", value<std::string>()->default_value(""), "Only Connect to these routers")
|
||||||
("trust.hidden", value<bool>()->default_value(false), "Should we hide our router from other routers?")
|
("trust.hidden", value<bool>()->default_value(false), "Should we hide our router from other routers?")
|
||||||
;
|
;
|
||||||
|
@ -281,9 +282,9 @@ namespace config {
|
||||||
options_description meshnets("Meshnet transports options");
|
options_description meshnets("Meshnet transports options");
|
||||||
meshnets.add_options()
|
meshnets.add_options()
|
||||||
("meshnets.yggdrasil", bool_switch()->default_value(false), "Support transports through the Yggdrasil (deafult: false)")
|
("meshnets.yggdrasil", bool_switch()->default_value(false), "Support transports through the Yggdrasil (deafult: false)")
|
||||||
("meshnets.yggaddress", value<std::string>()->default_value(""), "Yggdrasil address to publish")
|
("meshnets.yggaddress", value<std::string>()->default_value(""), "Yggdrasil address to publish")
|
||||||
;
|
;
|
||||||
|
|
||||||
m_OptionsDesc
|
m_OptionsDesc
|
||||||
.add(general)
|
.add(general)
|
||||||
.add(limits)
|
.add(limits)
|
||||||
|
@ -314,7 +315,7 @@ namespace config {
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto style = boost::program_options::command_line_style::unix_style
|
auto style = boost::program_options::command_line_style::unix_style
|
||||||
| boost::program_options::command_line_style::allow_long_disguise;
|
| boost::program_options::command_line_style::allow_long_disguise;
|
||||||
style &= ~ boost::program_options::command_line_style::allow_guessing;
|
style &= ~ boost::program_options::command_line_style::allow_guessing;
|
||||||
if (ignoreUnknown)
|
if (ignoreUnknown)
|
||||||
store(command_line_parser(argc, argv).options(m_OptionsDesc).style (style).allow_unregistered().run(), m_Options);
|
store(command_line_parser(argc, argv).options(m_OptionsDesc).style (style).allow_unregistered().run(), m_Options);
|
||||||
|
@ -323,6 +324,7 @@ namespace config {
|
||||||
}
|
}
|
||||||
catch (boost::program_options::error& e)
|
catch (boost::program_options::error& e)
|
||||||
{
|
{
|
||||||
|
ThrowFatal ("Error while parsing arguments: ", e.what());
|
||||||
std::cerr << "args: " << e.what() << std::endl;
|
std::cerr << "args: " << e.what() << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
@ -360,6 +362,7 @@ namespace config {
|
||||||
|
|
||||||
if (!config.is_open())
|
if (!config.is_open())
|
||||||
{
|
{
|
||||||
|
ThrowFatal ("Missing or unreadable config file: ", path);
|
||||||
std::cerr << "missing/unreadable config file: " << path << std::endl;
|
std::cerr << "missing/unreadable config file: " << path << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
@ -370,6 +373,7 @@ namespace config {
|
||||||
}
|
}
|
||||||
catch (boost::program_options::error& e)
|
catch (boost::program_options::error& e)
|
||||||
{
|
{
|
||||||
|
ThrowFatal ("Error while parsing config file: ", e.what());
|
||||||
std::cerr << e.what() << std::endl;
|
std::cerr << e.what() << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
};
|
};
|
||||||
|
|
|
@ -137,6 +137,8 @@ namespace client
|
||||||
void ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);
|
void ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);
|
||||||
void SetLeaseSetUpdated ();
|
void SetLeaseSetUpdated ();
|
||||||
|
|
||||||
|
bool IsPublic () const { return m_IsPublic; };
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// implements GarlicDestination
|
// implements GarlicDestination
|
||||||
|
@ -147,7 +149,6 @@ namespace client
|
||||||
int GetLeaseSetType () const { return m_LeaseSetType; };
|
int GetLeaseSetType () const { return m_LeaseSetType; };
|
||||||
void SetLeaseSetType (int leaseSetType) { m_LeaseSetType = leaseSetType; };
|
void SetLeaseSetType (int leaseSetType) { m_LeaseSetType = leaseSetType; };
|
||||||
int GetAuthType () const { return m_AuthType; };
|
int GetAuthType () const { return m_AuthType; };
|
||||||
bool IsPublic () const { return m_IsPublic; };
|
|
||||||
virtual void CleanupDestination () {}; // additional clean up in derived classes
|
virtual void CleanupDestination () {}; // additional clean up in derived classes
|
||||||
// I2CP
|
// I2CP
|
||||||
virtual void HandleDataMessage (const uint8_t * buf, size_t len) = 0;
|
virtual void HandleDataMessage (const uint8_t * buf, size_t len) = 0;
|
||||||
|
|
|
@ -227,7 +227,7 @@ namespace garlic
|
||||||
if (!GetOwner ()) return false;
|
if (!GetOwner ()) return false;
|
||||||
// we are Bob
|
// we are Bob
|
||||||
// KDF1
|
// KDF1
|
||||||
i2p::crypto::InitNoiseIKState (*this, GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)); // bpk
|
i2p::crypto::InitNoiseIKState (GetNoiseState (), GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)); // bpk
|
||||||
|
|
||||||
if (!i2p::crypto::GetElligator ()->Decode (buf, m_Aepk))
|
if (!i2p::crypto::GetElligator ()->Decode (buf, m_Aepk))
|
||||||
{
|
{
|
||||||
|
@ -460,7 +460,7 @@ namespace garlic
|
||||||
offset += 32;
|
offset += 32;
|
||||||
|
|
||||||
// KDF1
|
// KDF1
|
||||||
i2p::crypto::InitNoiseIKState (*this, m_RemoteStaticKey); // bpk
|
i2p::crypto::InitNoiseIKState (GetNoiseState (), m_RemoteStaticKey); // bpk
|
||||||
MixHash (m_EphemeralKeys->GetPublicKey (), 32); // h = SHA256(h || aepk)
|
MixHash (m_EphemeralKeys->GetPublicKey (), 32); // h = SHA256(h || aepk)
|
||||||
uint8_t sharedSecret[32];
|
uint8_t sharedSecret[32];
|
||||||
if (!m_EphemeralKeys->Agree (m_RemoteStaticKey, sharedSecret)) // x25519(aesk, bpk)
|
if (!m_EphemeralKeys->Agree (m_RemoteStaticKey, sharedSecret)) // x25519(aesk, bpk)
|
||||||
|
@ -520,7 +520,7 @@ namespace garlic
|
||||||
bool ECIESX25519AEADRatchetSession::NewOutgoingMessageForRouter (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
|
bool ECIESX25519AEADRatchetSession::NewOutgoingMessageForRouter (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
|
||||||
{
|
{
|
||||||
// we are Alice, router's bpk is m_RemoteStaticKey
|
// we are Alice, router's bpk is m_RemoteStaticKey
|
||||||
i2p::crypto::InitNoiseNState (*this, m_RemoteStaticKey);
|
i2p::crypto::InitNoiseNState (GetNoiseState (), m_RemoteStaticKey);
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
m_EphemeralKeys = i2p::transport::transports.GetNextX25519KeysPair ();
|
m_EphemeralKeys = i2p::transport::transports.GetNextX25519KeysPair ();
|
||||||
memcpy (out + offset, m_EphemeralKeys->GetPublicKey (), 32);
|
memcpy (out + offset, m_EphemeralKeys->GetPublicKey (), 32);
|
||||||
|
@ -656,7 +656,7 @@ namespace garlic
|
||||||
}
|
}
|
||||||
buf += 32; len -= 32;
|
buf += 32; len -= 32;
|
||||||
// KDF for Reply Key Section
|
// KDF for Reply Key Section
|
||||||
i2p::util::SaveStateHelper<i2p::crypto::NoiseSymmetricState> s(*this); // restore noise state on exit
|
i2p::util::SaveStateHelper<i2p::crypto::NoiseSymmetricState> s(GetNoiseState ()); // restore noise state on exit
|
||||||
MixHash (tag, 8); // h = SHA256(h || tag)
|
MixHash (tag, 8); // h = SHA256(h || tag)
|
||||||
MixHash (bepk, 32); // h = SHA256(h || bepk)
|
MixHash (bepk, 32); // h = SHA256(h || bepk)
|
||||||
uint8_t sharedSecret[32];
|
uint8_t sharedSecret[32];
|
||||||
|
@ -820,32 +820,6 @@ namespace garlic
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ECIESX25519AEADRatchetSession::HandleNextMessageForRouter (const uint8_t * buf, size_t len)
|
|
||||||
{
|
|
||||||
if (!GetOwner ()) return false;
|
|
||||||
// we are Bob
|
|
||||||
i2p::crypto::InitNoiseNState (*this, GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)); // bpk
|
|
||||||
MixHash (buf, 32);
|
|
||||||
uint8_t sharedSecret[32];
|
|
||||||
if (!GetOwner ()->Decrypt (buf, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) // x25519(bsk, aepk)
|
|
||||||
{
|
|
||||||
LogPrint (eLogWarning, "Garlic: Incorrect N ephemeral public key");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
MixKey (sharedSecret);
|
|
||||||
buf += 32; len -= 32;
|
|
||||||
uint8_t nonce[12];
|
|
||||||
CreateNonce (0, nonce);
|
|
||||||
std::vector<uint8_t> payload (len - 16);
|
|
||||||
if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_H, 32, m_CK + 32, nonce, payload.data (), len - 16, false)) // decrypt
|
|
||||||
{
|
|
||||||
LogPrint (eLogWarning, "Garlic: Payload for router AEAD verification failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
HandlePayload (payload.data (), len - 16, nullptr, 0);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<I2NPMessage> ECIESX25519AEADRatchetSession::WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg)
|
std::shared_ptr<I2NPMessage> ECIESX25519AEADRatchetSession::WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg)
|
||||||
{
|
{
|
||||||
|
@ -1124,6 +1098,38 @@ namespace garlic
|
||||||
ts*1000 > m_LastSentTimestamp + ECIESX25519_SEND_EXPIRATION_TIMEOUT*1000; // milliseconds
|
ts*1000 > m_LastSentTimestamp + ECIESX25519_SEND_EXPIRATION_TIMEOUT*1000; // milliseconds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RouterIncomingRatchetSession::RouterIncomingRatchetSession (const i2p::crypto::NoiseSymmetricState& initState):
|
||||||
|
ECIESX25519AEADRatchetSession (&i2p::context, false)
|
||||||
|
{
|
||||||
|
SetNoiseState (initState);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RouterIncomingRatchetSession::HandleNextMessage (const uint8_t * buf, size_t len)
|
||||||
|
{
|
||||||
|
if (!GetOwner ()) return false;
|
||||||
|
i2p::crypto::NoiseSymmetricState state (GetNoiseState ());
|
||||||
|
// we are Bob
|
||||||
|
state.MixHash (buf, 32);
|
||||||
|
uint8_t sharedSecret[32];
|
||||||
|
if (!GetOwner ()->Decrypt (buf, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) // x25519(bsk, aepk)
|
||||||
|
{
|
||||||
|
LogPrint (eLogWarning, "Garlic: Incorrect N ephemeral public key");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
state.MixKey (sharedSecret);
|
||||||
|
buf += 32; len -= 32;
|
||||||
|
uint8_t nonce[12];
|
||||||
|
CreateNonce (0, nonce);
|
||||||
|
std::vector<uint8_t> payload (len - 16);
|
||||||
|
if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, state.m_H, 32, state.m_CK + 32, nonce, payload.data (), len - 16, false)) // decrypt
|
||||||
|
{
|
||||||
|
LogPrint (eLogWarning, "Garlic: Payload for router AEAD verification failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
HandlePayload (payload.data (), len - 16, nullptr, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<I2NPMessage> WrapECIESX25519AEADRatchetMessage (std::shared_ptr<const I2NPMessage> msg, const uint8_t * key, uint64_t tag)
|
std::shared_ptr<I2NPMessage> WrapECIESX25519AEADRatchetMessage (std::shared_ptr<const I2NPMessage> msg, const uint8_t * key, uint64_t tag)
|
||||||
{
|
{
|
||||||
auto m = NewI2NPMessage ();
|
auto m = NewI2NPMessage ();
|
||||||
|
|
|
@ -164,7 +164,6 @@ namespace garlic
|
||||||
~ECIESX25519AEADRatchetSession ();
|
~ECIESX25519AEADRatchetSession ();
|
||||||
|
|
||||||
bool HandleNextMessage (uint8_t * buf, size_t len, std::shared_ptr<ReceiveRatchetTagSet> receiveTagset, int index = 0);
|
bool HandleNextMessage (uint8_t * buf, size_t len, std::shared_ptr<ReceiveRatchetTagSet> receiveTagset, int index = 0);
|
||||||
bool HandleNextMessageForRouter (const uint8_t * buf, size_t len);
|
|
||||||
std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg);
|
std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg);
|
||||||
std::shared_ptr<I2NPMessage> WrapOneTimeMessage (std::shared_ptr<const I2NPMessage> msg, bool isForRouter = false);
|
std::shared_ptr<I2NPMessage> WrapOneTimeMessage (std::shared_ptr<const I2NPMessage> msg, bool isForRouter = false);
|
||||||
|
|
||||||
|
@ -186,16 +185,21 @@ namespace garlic
|
||||||
bool IsTerminated () const { return m_IsTerminated; }
|
bool IsTerminated () const { return m_IsTerminated; }
|
||||||
uint64_t GetLastActivityTimestamp () const { return m_LastActivityTimestamp; };
|
uint64_t GetLastActivityTimestamp () const { return m_LastActivityTimestamp; };
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
i2p::crypto::NoiseSymmetricState& GetNoiseState () { return *this; };
|
||||||
|
void SetNoiseState (const i2p::crypto::NoiseSymmetricState& state) { GetNoiseState () = state; };
|
||||||
|
void CreateNonce (uint64_t seqn, uint8_t * nonce);
|
||||||
|
void HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr<ReceiveRatchetTagSet>& receiveTagset, int index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void CreateNonce (uint64_t seqn, uint8_t * nonce);
|
|
||||||
bool GenerateEphemeralKeysAndEncode (uint8_t * buf); // buf is 32 bytes
|
bool GenerateEphemeralKeysAndEncode (uint8_t * buf); // buf is 32 bytes
|
||||||
void InitNewSessionTagset (std::shared_ptr<RatchetTagSet> tagsetNsr) const;
|
void InitNewSessionTagset (std::shared_ptr<RatchetTagSet> tagsetNsr) const;
|
||||||
|
|
||||||
bool HandleNewIncomingSession (const uint8_t * buf, size_t len);
|
bool HandleNewIncomingSession (const uint8_t * buf, size_t len);
|
||||||
bool HandleNewOutgoingSessionReply (uint8_t * buf, size_t len);
|
bool HandleNewOutgoingSessionReply (uint8_t * buf, size_t len);
|
||||||
bool HandleExistingSessionMessage (uint8_t * buf, size_t len, std::shared_ptr<ReceiveRatchetTagSet> receiveTagset, int index);
|
bool HandleExistingSessionMessage (uint8_t * buf, size_t len, std::shared_ptr<ReceiveRatchetTagSet> receiveTagset, int index);
|
||||||
void HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr<ReceiveRatchetTagSet>& receiveTagset, int index);
|
|
||||||
void HandleNextKey (const uint8_t * buf, size_t len, const std::shared_ptr<ReceiveRatchetTagSet>& receiveTagset);
|
void HandleNextKey (const uint8_t * buf, size_t len, const std::shared_ptr<ReceiveRatchetTagSet>& receiveTagset);
|
||||||
|
|
||||||
bool NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen, bool isStatic = true);
|
bool NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen, bool isStatic = true);
|
||||||
|
@ -237,6 +241,15 @@ namespace garlic
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// single session for all incoming messages
|
||||||
|
class RouterIncomingRatchetSession: public ECIESX25519AEADRatchetSession
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
RouterIncomingRatchetSession (const i2p::crypto::NoiseSymmetricState& initState);
|
||||||
|
bool HandleNextMessage (const uint8_t * buf, size_t len);
|
||||||
|
};
|
||||||
|
|
||||||
std::shared_ptr<I2NPMessage> WrapECIESX25519AEADRatchetMessage (std::shared_ptr<const I2NPMessage> msg, const uint8_t * key, uint64_t tag);
|
std::shared_ptr<I2NPMessage> WrapECIESX25519AEADRatchetMessage (std::shared_ptr<const I2NPMessage> msg, const uint8_t * key, uint64_t tag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -9,12 +9,15 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "util.h"
|
|
||||||
#include "HTTP.h"
|
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
#include "util.h"
|
||||||
|
#include "Base.h"
|
||||||
|
#include "HTTP.h"
|
||||||
|
|
||||||
namespace i2p {
|
namespace i2p
|
||||||
namespace http {
|
{
|
||||||
|
namespace http
|
||||||
|
{
|
||||||
const std::vector<std::string> HTTP_METHODS = {
|
const std::vector<std::string> HTTP_METHODS = {
|
||||||
"GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "CONNECT", // HTTP basic methods
|
"GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "CONNECT", // HTTP basic methods
|
||||||
"COPY", "LOCK", "MKCOL", "MOVE", "PROPFIND", "PROPPATCH", "UNLOCK", "SEARCH" // WebDAV methods, for SEARCH see rfc5323
|
"COPY", "LOCK", "MKCOL", "MOVE", "PROPFIND", "PROPPATCH", "UNLOCK", "SEARCH" // WebDAV methods, for SEARCH see rfc5323
|
||||||
|
@ -471,12 +474,15 @@ namespace http {
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string UrlDecode(const std::string& data, bool allow_null) {
|
std::string UrlDecode(const std::string& data, bool allow_null)
|
||||||
|
{
|
||||||
std::string decoded(data);
|
std::string decoded(data);
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
while ((pos = decoded.find('%', pos)) != std::string::npos) {
|
while ((pos = decoded.find('%', pos)) != std::string::npos)
|
||||||
|
{
|
||||||
char c = strtol(decoded.substr(pos + 1, 2).c_str(), NULL, 16);
|
char c = strtol(decoded.substr(pos + 1, 2).c_str(), NULL, 16);
|
||||||
if (c == '\0' && !allow_null) {
|
if (c == '\0' && !allow_null)
|
||||||
|
{
|
||||||
pos += 3;
|
pos += 3;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -486,9 +492,11 @@ namespace http {
|
||||||
return decoded;
|
return decoded;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MergeChunkedResponse (std::istream& in, std::ostream& out) {
|
bool MergeChunkedResponse (std::istream& in, std::ostream& out)
|
||||||
|
{
|
||||||
std::string hexLen;
|
std::string hexLen;
|
||||||
while (!in.eof ()) {
|
while (!in.eof ())
|
||||||
|
{
|
||||||
std::getline (in, hexLen);
|
std::getline (in, hexLen);
|
||||||
errno = 0;
|
errno = 0;
|
||||||
long int len = strtoul(hexLen.c_str(), (char **) NULL, 16);
|
long int len = strtoul(hexLen.c_str(), (char **) NULL, 16);
|
||||||
|
@ -506,5 +514,12 @@ namespace http {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string CreateBasicAuthorizationString (const std::string& user, const std::string& pass)
|
||||||
|
{
|
||||||
|
if (user.empty () && pass.empty ()) return "";
|
||||||
|
return "Basic " + i2p::data::ToBase64Standard (user + ":" + pass);
|
||||||
|
}
|
||||||
|
|
||||||
} // http
|
} // http
|
||||||
} // i2p
|
} // i2p
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -166,6 +166,9 @@ namespace http
|
||||||
* @return true on success, false otherwise
|
* @return true on success, false otherwise
|
||||||
*/
|
*/
|
||||||
bool MergeChunkedResponse (std::istream& in, std::ostream& out);
|
bool MergeChunkedResponse (std::istream& in, std::ostream& out);
|
||||||
|
|
||||||
|
std::string CreateBasicAuthorizationString (const std::string& user, const std::string& pass);
|
||||||
|
|
||||||
} // http
|
} // http
|
||||||
} // i2p
|
} // i2p
|
||||||
|
|
||||||
|
|
|
@ -148,7 +148,7 @@ namespace log {
|
||||||
LogLevel level; /**< message level */
|
LogLevel level; /**< message level */
|
||||||
std::thread::id tid; /**< id of thread that generated message */
|
std::thread::id tid; /**< id of thread that generated message */
|
||||||
|
|
||||||
LogMsg (LogLevel lvl, std::time_t ts, const std::string & txt): timestamp(ts), text(txt), level(lvl) {};
|
LogMsg (LogLevel lvl, std::time_t ts, std::string&& txt): timestamp(ts), text(std::move(txt)), level(lvl) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
Log & Logger();
|
Log & Logger();
|
||||||
|
@ -189,7 +189,7 @@ void LogPrint (LogLevel level, TArgs&&... args) noexcept
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// fold message to single string
|
// fold message to single string
|
||||||
std::stringstream ss("");
|
std::stringstream ss;
|
||||||
|
|
||||||
#if (__cplusplus >= 201703L) // C++ 17 or higher
|
#if (__cplusplus >= 201703L) // C++ 17 or higher
|
||||||
(LogPrint (ss, std::forward<TArgs>(args)), ...);
|
(LogPrint (ss, std::forward<TArgs>(args)), ...);
|
||||||
|
@ -197,7 +197,7 @@ void LogPrint (LogLevel level, TArgs&&... args) noexcept
|
||||||
LogPrint (ss, std::forward<TArgs>(args)...);
|
LogPrint (ss, std::forward<TArgs>(args)...);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto msg = std::make_shared<i2p::log::LogMsg>(level, std::time(nullptr), ss.str());
|
auto msg = std::make_shared<i2p::log::LogMsg>(level, std::time(nullptr), std::move(ss).str());
|
||||||
msg->tid = std::this_thread::get_id();
|
msg->tid = std::this_thread::get_id();
|
||||||
log.Append(msg);
|
log.Append(msg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1158,54 +1158,53 @@ namespace transport
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
LogPrint(eLogInfo, "NTCP2: Proxy is not used");
|
LogPrint(eLogInfo, "NTCP2: Proxy is not used");
|
||||||
auto& addresses = context.GetRouterInfo ().GetAddresses ();
|
// start acceptors
|
||||||
for (const auto& address: addresses)
|
auto& addresses = context.GetRouterInfo ().GetAddresses ();
|
||||||
|
for (const auto& address: addresses)
|
||||||
|
{
|
||||||
|
if (!address) continue;
|
||||||
|
if (address->IsPublishedNTCP2 () && address->port)
|
||||||
{
|
{
|
||||||
if (!address) continue;
|
if (address->host.is_v4())
|
||||||
if (address->IsPublishedNTCP2 ())
|
|
||||||
{
|
{
|
||||||
if (address->host.is_v4())
|
try
|
||||||
{
|
{
|
||||||
try
|
auto ep = m_Address4 ? boost::asio::ip::tcp::endpoint (m_Address4->address(), address->port):
|
||||||
{
|
boost::asio::ip::tcp::endpoint (boost::asio::ip::tcp::v4(), address->port);
|
||||||
auto ep = m_Address4 ? boost::asio::ip::tcp::endpoint (m_Address4->address(), address->port):
|
m_NTCP2Acceptor.reset (new boost::asio::ip::tcp::acceptor (GetService (), ep));
|
||||||
boost::asio::ip::tcp::endpoint (boost::asio::ip::tcp::v4(), address->port);
|
|
||||||
m_NTCP2Acceptor.reset (new boost::asio::ip::tcp::acceptor (GetService (), ep));
|
|
||||||
}
|
|
||||||
catch ( std::exception & ex )
|
|
||||||
{
|
|
||||||
LogPrint(eLogError, "NTCP2: Failed to bind to v4 port ", address->port, ex.what());
|
|
||||||
ThrowFatal ("Unable to start IPv4 NTCP2 transport at port ", address->port, ": ", ex.what ());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
LogPrint (eLogInfo, "NTCP2: Start listening v4 TCP port ", address->port);
|
|
||||||
auto conn = std::make_shared<NTCP2Session>(*this);
|
|
||||||
m_NTCP2Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAccept, this, conn, std::placeholders::_1));
|
|
||||||
}
|
}
|
||||||
else if (address->host.is_v6() && (context.SupportsV6 () || context.SupportsMesh ()))
|
catch ( std::exception & ex )
|
||||||
{
|
{
|
||||||
m_NTCP2V6Acceptor.reset (new boost::asio::ip::tcp::acceptor (GetService ()));
|
LogPrint(eLogError, "NTCP2: Failed to bind to v4 port ", address->port, ex.what());
|
||||||
try
|
ThrowFatal ("Unable to start IPv4 NTCP2 transport at port ", address->port, ": ", ex.what ());
|
||||||
{
|
continue;
|
||||||
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));
|
|
||||||
m_NTCP2V6Acceptor->bind (boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v6(), address->port));
|
|
||||||
m_NTCP2V6Acceptor->listen ();
|
|
||||||
|
|
||||||
LogPrint (eLogInfo, "NTCP2: Start listening v6 TCP port ", address->port);
|
LogPrint (eLogInfo, "NTCP2: Start listening v4 TCP port ", address->port);
|
||||||
auto conn = std::make_shared<NTCP2Session> (*this);
|
auto conn = std::make_shared<NTCP2Session>(*this);
|
||||||
m_NTCP2V6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAcceptV6, this, conn, std::placeholders::_1));
|
m_NTCP2Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAccept, this, conn, std::placeholders::_1));
|
||||||
}
|
}
|
||||||
catch ( std::exception & ex )
|
else if (address->host.is_v6() && (context.SupportsV6 () || context.SupportsMesh ()))
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "NTCP2: failed to bind to v6 port ", address->port, ": ", ex.what());
|
m_NTCP2V6Acceptor.reset (new boost::asio::ip::tcp::acceptor (GetService ()));
|
||||||
ThrowFatal ("Unable to start IPv6 NTCP2 transport at port ", address->port, ": ", ex.what ());
|
try
|
||||||
continue;
|
{
|
||||||
}
|
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));
|
||||||
|
m_NTCP2V6Acceptor->bind (boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v6(), address->port));
|
||||||
|
m_NTCP2V6Acceptor->listen ();
|
||||||
|
|
||||||
|
LogPrint (eLogInfo, "NTCP2: Start listening v6 TCP port ", address->port);
|
||||||
|
auto conn = std::make_shared<NTCP2Session> (*this);
|
||||||
|
m_NTCP2V6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAcceptV6, this, conn, std::placeholders::_1));
|
||||||
|
}
|
||||||
|
catch ( std::exception & ex )
|
||||||
|
{
|
||||||
|
LogPrint(eLogError, "NTCP2: failed to bind to v6 port ", address->port, ": ", ex.what());
|
||||||
|
ThrowFatal ("Unable to start IPv6 NTCP2 transport at port ", address->port, ": ", ex.what ());
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1466,11 +1465,14 @@ namespace transport
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void NTCP2Server::UseProxy(ProxyType proxytype, const std::string & addr, uint16_t port)
|
void NTCP2Server::UseProxy(ProxyType proxytype, const std::string& addr, uint16_t port,
|
||||||
|
const std::string& user, const std::string& pass)
|
||||||
{
|
{
|
||||||
m_ProxyType = proxytype;
|
m_ProxyType = proxytype;
|
||||||
m_ProxyAddress = addr;
|
m_ProxyAddress = addr;
|
||||||
m_ProxyPort = port;
|
m_ProxyPort = port;
|
||||||
|
if (m_ProxyType == eHTTPProxy )
|
||||||
|
m_ProxyAuthorization = i2p::http::CreateBasicAuthorizationString (user, pass);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NTCP2Server::HandleProxyConnect(const boost::system::error_code& ecode, std::shared_ptr<NTCP2Session> conn, std::shared_ptr<boost::asio::deadline_timer> timer)
|
void NTCP2Server::HandleProxyConnect(const boost::system::error_code& ecode, std::shared_ptr<NTCP2Session> conn, std::shared_ptr<boost::asio::deadline_timer> timer)
|
||||||
|
@ -1539,8 +1541,10 @@ namespace transport
|
||||||
if(ep.address ().is_v6 ())
|
if(ep.address ().is_v6 ())
|
||||||
req.uri = "[" + ep.address ().to_string() + "]:" + std::to_string(ep.port ());
|
req.uri = "[" + ep.address ().to_string() + "]:" + std::to_string(ep.port ());
|
||||||
else
|
else
|
||||||
req.uri = ep.address ().to_string() + ":" + std::to_string(ep.port ());
|
req.uri = ep.address ().to_string() + ":" + std::to_string(ep.port ());
|
||||||
|
if (!m_ProxyAuthorization.empty ())
|
||||||
|
req.AddHeader("Proxy-Authorization", m_ProxyAuthorization);
|
||||||
|
|
||||||
boost::asio::streambuf writebuff;
|
boost::asio::streambuf writebuff;
|
||||||
std::ostream out(&writebuff);
|
std::ostream out(&writebuff);
|
||||||
out << req.to_string();
|
out << req.to_string();
|
||||||
|
|
|
@ -246,7 +246,7 @@ namespace transport
|
||||||
void Connect(std::shared_ptr<NTCP2Session> conn);
|
void Connect(std::shared_ptr<NTCP2Session> conn);
|
||||||
|
|
||||||
bool UsingProxy() const { return m_ProxyType != eNoProxy; };
|
bool UsingProxy() const { return m_ProxyType != eNoProxy; };
|
||||||
void UseProxy(ProxyType proxy, const std::string & address, uint16_t port);
|
void UseProxy(ProxyType proxy, const std::string& address, uint16_t port, const std::string& user, const std::string& pass);
|
||||||
|
|
||||||
void SetLocalAddress (const boost::asio::ip::address& localAddress);
|
void SetLocalAddress (const boost::asio::ip::address& localAddress);
|
||||||
|
|
||||||
|
@ -271,7 +271,7 @@ namespace transport
|
||||||
std::list<std::shared_ptr<NTCP2Session> > m_PendingIncomingSessions;
|
std::list<std::shared_ptr<NTCP2Session> > m_PendingIncomingSessions;
|
||||||
|
|
||||||
ProxyType m_ProxyType;
|
ProxyType m_ProxyType;
|
||||||
std::string m_ProxyAddress;
|
std::string m_ProxyAddress, m_ProxyAuthorization;
|
||||||
uint16_t m_ProxyPort;
|
uint16_t m_ProxyPort;
|
||||||
boost::asio::ip::tcp::resolver m_Resolver;
|
boost::asio::ip::tcp::resolver m_Resolver;
|
||||||
std::unique_ptr<boost::asio::ip::tcp::endpoint> m_ProxyEndpoint;
|
std::unique_ptr<boost::asio::ip::tcp::endpoint> m_ProxyEndpoint;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -57,7 +57,7 @@ namespace data
|
||||||
uint16_t threshold; i2p::config::GetOption("reseed.threshold", threshold);
|
uint16_t threshold; i2p::config::GetOption("reseed.threshold", threshold);
|
||||||
if (m_RouterInfos.size () < threshold) // reseed if # of router less than threshold
|
if (m_RouterInfos.size () < threshold) // reseed if # of router less than threshold
|
||||||
Reseed ();
|
Reseed ();
|
||||||
else if (!GetRandomRouter (i2p::context.GetSharedRouterInfo ()))
|
else if (!GetRandomRouter (i2p::context.GetSharedRouterInfo (), false))
|
||||||
Reseed (); // we don't have a router we can connect to. Trying to reseed
|
Reseed (); // we don't have a router we can connect to. Trying to reseed
|
||||||
|
|
||||||
i2p::config::GetOption("persist.profiles", m_PersistProfiles);
|
i2p::config::GetOption("persist.profiles", m_PersistProfiles);
|
||||||
|
@ -645,7 +645,9 @@ namespace data
|
||||||
auto floodfill = GetClosestFloodfill (destination, dest->GetExcludedPeers ());
|
auto floodfill = GetClosestFloodfill (destination, dest->GetExcludedPeers ());
|
||||||
if (floodfill)
|
if (floodfill)
|
||||||
{
|
{
|
||||||
if (direct && !floodfill->IsCompatible (i2p::context.GetRouterInfo ())) direct = false; // check if fllodfill is reachable
|
if (direct && !floodfill->IsReachableFrom (i2p::context.GetRouterInfo ()) &&
|
||||||
|
!i2p::transport::transports.IsConnected (floodfill->GetIdentHash ()))
|
||||||
|
direct = false; // floodfill can't be reached directly
|
||||||
if (direct)
|
if (direct)
|
||||||
transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ()));
|
transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ()));
|
||||||
else
|
else
|
||||||
|
@ -1090,7 +1092,8 @@ namespace data
|
||||||
LogPrint (eLogInfo, "NetDb: Publishing our RouterInfo to ", i2p::data::GetIdentHashAbbreviation(floodfill->GetIdentHash ()), ". reply token=", replyToken);
|
LogPrint (eLogInfo, "NetDb: Publishing our RouterInfo to ", i2p::data::GetIdentHashAbbreviation(floodfill->GetIdentHash ()), ". reply token=", replyToken);
|
||||||
m_PublishExcluded.insert (floodfill->GetIdentHash ());
|
m_PublishExcluded.insert (floodfill->GetIdentHash ());
|
||||||
m_PublishReplyToken = replyToken;
|
m_PublishReplyToken = replyToken;
|
||||||
if (floodfill->IsCompatible (i2p::context.GetRouterInfo ())) // able to connect?
|
if (floodfill->IsReachableFrom (i2p::context.GetRouterInfo ()) || // are we able to connect?
|
||||||
|
i2p::transport::transports.IsConnected (floodfill->GetIdentHash ())) // already connected ?
|
||||||
// send directly
|
// send directly
|
||||||
transports.SendMessage (floodfill->GetIdentHash (), CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken));
|
transports.SendMessage (floodfill->GetIdentHash (), CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken));
|
||||||
else
|
else
|
||||||
|
@ -1135,13 +1138,14 @@ namespace data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<const RouterInfo> NetDb::GetRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith) const
|
std::shared_ptr<const RouterInfo> NetDb::GetRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith, bool reverse) const
|
||||||
{
|
{
|
||||||
return GetRandomRouter (
|
return GetRandomRouter (
|
||||||
[compatibleWith](std::shared_ptr<const RouterInfo> router)->bool
|
[compatibleWith, reverse](std::shared_ptr<const RouterInfo> router)->bool
|
||||||
{
|
{
|
||||||
return !router->IsHidden () && router != compatibleWith &&
|
return !router->IsHidden () && router != compatibleWith &&
|
||||||
router->IsCompatible (*compatibleWith);
|
(reverse ? compatibleWith->IsReachableFrom (*router) :
|
||||||
|
router->IsReachableFrom (*compatibleWith));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1168,17 +1172,18 @@ namespace data
|
||||||
return GetRandomRouter (
|
return GetRandomRouter (
|
||||||
[](std::shared_ptr<const RouterInfo> router)->bool
|
[](std::shared_ptr<const RouterInfo> router)->bool
|
||||||
{
|
{
|
||||||
return !router->IsHidden () && router->IsIntroducer ();
|
return router->IsIntroducer () && !router->IsHidden () && !router->IsFloodfill (); // floodfills don't send relay tag
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<const RouterInfo> NetDb::GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith) const
|
std::shared_ptr<const RouterInfo> NetDb::GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith, bool reverse) const
|
||||||
{
|
{
|
||||||
return GetRandomRouter (
|
return GetRandomRouter (
|
||||||
[compatibleWith](std::shared_ptr<const RouterInfo> router)->bool
|
[compatibleWith, reverse](std::shared_ptr<const RouterInfo> router)->bool
|
||||||
{
|
{
|
||||||
return !router->IsHidden () && router != compatibleWith &&
|
return !router->IsHidden () && router != compatibleWith &&
|
||||||
router->IsCompatible (*compatibleWith) &&
|
(reverse ? compatibleWith->IsReachableFrom (*router) :
|
||||||
|
router->IsReachableFrom (*compatibleWith)) &&
|
||||||
(router->GetCaps () & RouterInfo::eHighBandwidth) &&
|
(router->GetCaps () & RouterInfo::eHighBandwidth) &&
|
||||||
router->GetVersion () >= NETDB_MIN_HIGHBANDWIDTH_VERSION;
|
router->GetVersion () >= NETDB_MIN_HIGHBANDWIDTH_VERSION;
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -83,8 +83,8 @@ namespace data
|
||||||
void HandleDeliveryStatusMsg (std::shared_ptr<const I2NPMessage> msg);
|
void HandleDeliveryStatusMsg (std::shared_ptr<const I2NPMessage> msg);
|
||||||
|
|
||||||
std::shared_ptr<const RouterInfo> GetRandomRouter () const;
|
std::shared_ptr<const RouterInfo> GetRandomRouter () const;
|
||||||
std::shared_ptr<const RouterInfo> GetRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith) const;
|
std::shared_ptr<const RouterInfo> GetRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith, bool reverse) const;
|
||||||
std::shared_ptr<const RouterInfo> GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith) const;
|
std::shared_ptr<const RouterInfo> GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith, bool reverse) const;
|
||||||
std::shared_ptr<const RouterInfo> GetRandomPeerTestRouter (bool v4only = true) const;
|
std::shared_ptr<const RouterInfo> GetRandomPeerTestRouter (bool v4only = true) const;
|
||||||
std::shared_ptr<const RouterInfo> GetRandomSSUV6Router () const; // TODO: change to v6 peer test later
|
std::shared_ptr<const RouterInfo> GetRandomSSUV6Router () const; // TODO: change to v6 peer test later
|
||||||
std::shared_ptr<const RouterInfo> GetRandomIntroducer () const;
|
std::shared_ptr<const RouterInfo> GetRandomIntroducer () const;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -574,9 +574,11 @@ namespace data
|
||||||
proxyReq.method = "CONNECT";
|
proxyReq.method = "CONNECT";
|
||||||
proxyReq.version = "HTTP/1.1";
|
proxyReq.version = "HTTP/1.1";
|
||||||
proxyReq.uri = url.host + ":" + std::to_string(url.port);
|
proxyReq.uri = url.host + ":" + std::to_string(url.port);
|
||||||
|
auto auth = i2p::http::CreateBasicAuthorizationString (proxyUrl.user, proxyUrl.pass);
|
||||||
|
if (!auth.empty ())
|
||||||
|
proxyReq.AddHeader("Proxy-Authorization", auth);
|
||||||
|
|
||||||
boost::asio::streambuf writebuf, readbuf;
|
boost::asio::streambuf writebuf, readbuf;
|
||||||
|
|
||||||
std::ostream out(&writebuf);
|
std::ostream out(&writebuf);
|
||||||
out << proxyReq.to_string();
|
out << proxyReq.to_string();
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@ namespace i2p
|
||||||
auto initState = new i2p::crypto::NoiseSymmetricState ();
|
auto initState = new i2p::crypto::NoiseSymmetricState ();
|
||||||
i2p::crypto::InitNoiseNState (*initState, GetIdentity ()->GetEncryptionPublicKey ());
|
i2p::crypto::InitNoiseNState (*initState, GetIdentity ()->GetEncryptionPublicKey ());
|
||||||
m_InitialNoiseState.reset (initState);
|
m_InitialNoiseState.reset (initState);
|
||||||
|
m_ECIESSession = std::make_shared<i2p::garlic::RouterIncomingRatchetSession>(*initState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,33 +76,41 @@ namespace i2p
|
||||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||||
bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg);
|
bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg);
|
||||||
bool nat; i2p::config::GetOption("nat", nat);
|
bool nat; i2p::config::GetOption("nat", nat);
|
||||||
std::string ifname; i2p::config::GetOption("ifname", ifname);
|
|
||||||
std::string ifname4; i2p::config::GetOption("ifname4", ifname4);
|
|
||||||
std::string ifname6; i2p::config::GetOption("ifname6", ifname6);
|
|
||||||
|
|
||||||
if ((ntcp2 || ygg) && !m_NTCP2Keys)
|
if ((ntcp2 || ygg) && !m_NTCP2Keys)
|
||||||
NewNTCP2Keys ();
|
NewNTCP2Keys ();
|
||||||
bool ntcp2Published = false;
|
bool ntcp2Published = false;
|
||||||
if (ntcp2)
|
if (ntcp2)
|
||||||
|
{
|
||||||
i2p::config::GetOption("ntcp2.published", ntcp2Published);
|
i2p::config::GetOption("ntcp2.published", ntcp2Published);
|
||||||
uint8_t caps = 0;
|
if (ntcp2Published)
|
||||||
|
{
|
||||||
|
std::string ntcp2proxy; i2p::config::GetOption("ntcp2.proxy", ntcp2proxy);
|
||||||
|
if (!ntcp2proxy.empty ()) ntcp2Published = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint8_t caps = 0, addressCaps = 0;
|
||||||
if (ipv4)
|
if (ipv4)
|
||||||
{
|
{
|
||||||
std::string host = "127.0.0.1";
|
std::string host = "127.0.0.1";
|
||||||
if (!i2p::config::IsDefault("host"))
|
if (!i2p::config::IsDefault("host"))
|
||||||
i2p::config::GetOption("host", host);
|
i2p::config::GetOption("host", host);
|
||||||
else if (!nat && !ifname.empty())
|
else if (!nat)
|
||||||
/* bind to interface, we have no NAT so set external address too */
|
{
|
||||||
host = i2p::util::net::GetInterfaceAddress(ifname, false).to_string(); // v4
|
// we have no NAT so set external address from local address
|
||||||
if(ifname4.size())
|
std::string address4; i2p::config::GetOption("address4", address4);
|
||||||
host = i2p::util::net::GetInterfaceAddress(ifname4, false).to_string();
|
if (!address4.empty ()) host = address4;
|
||||||
|
}
|
||||||
|
|
||||||
if (ntcp2)
|
if (ntcp2)
|
||||||
{
|
{
|
||||||
if (ntcp2Published)
|
if (ntcp2Published)
|
||||||
routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address_v4::from_string (host), port);
|
routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address_v4::from_string (host), port);
|
||||||
else // add non-published NTCP2 address
|
else // add non-published NTCP2 address
|
||||||
|
{
|
||||||
|
addressCaps = i2p::data::RouterInfo::AddressCaps::eV4;
|
||||||
routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv);
|
routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (ssu)
|
if (ssu)
|
||||||
{
|
{
|
||||||
|
@ -114,10 +123,11 @@ namespace i2p
|
||||||
std::string host = "::1";
|
std::string host = "::1";
|
||||||
if (!i2p::config::IsDefault("host") && !ipv4) // override if v6 only
|
if (!i2p::config::IsDefault("host") && !ipv4) // override if v6 only
|
||||||
i2p::config::GetOption("host", host);
|
i2p::config::GetOption("host", host);
|
||||||
else if (!ifname.empty())
|
else
|
||||||
host = i2p::util::net::GetInterfaceAddress(ifname, true).to_string(); // v6
|
{
|
||||||
if(ifname6.size())
|
std::string address6; i2p::config::GetOption("address6", address6);
|
||||||
host = i2p::util::net::GetInterfaceAddress(ifname6, true).to_string();
|
if (!address6.empty ()) host = address6;
|
||||||
|
}
|
||||||
|
|
||||||
if (ntcp2)
|
if (ntcp2)
|
||||||
{
|
{
|
||||||
|
@ -130,8 +140,12 @@ namespace i2p
|
||||||
ntcp2Host = host;
|
ntcp2Host = host;
|
||||||
routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address_v6::from_string (ntcp2Host), port);
|
routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address_v6::from_string (ntcp2Host), port);
|
||||||
}
|
}
|
||||||
else if (!ipv4) // no other ntcp2 addresses yet
|
else
|
||||||
routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv);
|
{
|
||||||
|
if (!ipv4) // no other ntcp2 addresses yet
|
||||||
|
routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv);
|
||||||
|
addressCaps |= i2p::data::RouterInfo::AddressCaps::eV6;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (ssu)
|
if (ssu)
|
||||||
{
|
{
|
||||||
|
@ -145,7 +159,9 @@ namespace i2p
|
||||||
if (!yggaddr.is_unspecified ())
|
if (!yggaddr.is_unspecified ())
|
||||||
routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, yggaddr, port);
|
routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, yggaddr, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (addressCaps)
|
||||||
|
routerInfo.SetUnreachableAddressesTransportCaps (addressCaps);
|
||||||
routerInfo.SetCaps (caps); // caps + L
|
routerInfo.SetCaps (caps); // caps + L
|
||||||
routerInfo.SetProperty ("netId", std::to_string (m_NetID));
|
routerInfo.SetProperty ("netId", std::to_string (m_NetID));
|
||||||
routerInfo.SetProperty ("router.version", I2P_VERSION);
|
routerInfo.SetProperty ("router.version", I2P_VERSION);
|
||||||
|
@ -215,7 +231,7 @@ namespace i2p
|
||||||
bool updated = false;
|
bool updated = false;
|
||||||
for (auto& address : m_RouterInfo.GetAddresses ())
|
for (auto& address : m_RouterInfo.GetAddresses ())
|
||||||
{
|
{
|
||||||
if (address->IsNTCP2 () && (address->port != port || address->ntcp2->isPublished != publish) && (!v4only || address->host.is_v4 ()))
|
if (address->IsNTCP2 () && (address->port != port || address->ntcp2->isPublished != publish) && (!v4only || address->IsV4 ()))
|
||||||
{
|
{
|
||||||
if (!port && !address->port)
|
if (!port && !address->port)
|
||||||
{
|
{
|
||||||
|
@ -388,6 +404,7 @@ namespace i2p
|
||||||
else if (limit > 48) { SetBandwidth('M'); }
|
else if (limit > 48) { SetBandwidth('M'); }
|
||||||
else if (limit > 12) { SetBandwidth('L'); }
|
else if (limit > 12) { SetBandwidth('L'); }
|
||||||
else { SetBandwidth('K'); }
|
else { SetBandwidth('K'); }
|
||||||
|
m_BandwidthLimit = limit; // set precise limit
|
||||||
}
|
}
|
||||||
|
|
||||||
void RouterContext::SetShareRatio (int percents)
|
void RouterContext::SetShareRatio (int percents)
|
||||||
|
@ -485,14 +502,13 @@ namespace i2p
|
||||||
{
|
{
|
||||||
if (supportsV6)
|
if (supportsV6)
|
||||||
{
|
{
|
||||||
m_RouterInfo.EnableV6 ();
|
|
||||||
// insert v6 addresses if necessary
|
// insert v6 addresses if necessary
|
||||||
bool foundSSU = false, foundNTCP2 = false;
|
bool foundSSU = false, foundNTCP2 = false;
|
||||||
uint16_t port = 0;
|
uint16_t port = 0;
|
||||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
auto& addresses = m_RouterInfo.GetAddresses ();
|
||||||
for (auto& addr: addresses)
|
for (auto& addr: addresses)
|
||||||
{
|
{
|
||||||
if (addr->host.is_v6 ())
|
if (addr->IsV6 () && !i2p::util::net::IsYggdrasilAddress (addr->host))
|
||||||
{
|
{
|
||||||
if (addr->transportStyle == i2p::data::RouterInfo::eTransportSSU)
|
if (addr->transportStyle == i2p::data::RouterInfo::eTransportSSU)
|
||||||
foundSSU = true;
|
foundSSU = true;
|
||||||
|
@ -529,6 +545,7 @@ namespace i2p
|
||||||
m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address::from_string (ntcp2Host), ntcp2Port);
|
m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address::from_string (ntcp2Host), ntcp2Port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_RouterInfo.EnableV6 ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_RouterInfo.DisableV6 ();
|
m_RouterInfo.DisableV6 ();
|
||||||
|
@ -537,8 +554,54 @@ namespace i2p
|
||||||
|
|
||||||
void RouterContext::SetSupportsV4 (bool supportsV4)
|
void RouterContext::SetSupportsV4 (bool supportsV4)
|
||||||
{
|
{
|
||||||
|
// check if updates
|
||||||
|
if (supportsV4 && SupportsV4 ()) return;
|
||||||
|
if (!supportsV4 && !SupportsV4 ()) return;
|
||||||
|
// update
|
||||||
if (supportsV4)
|
if (supportsV4)
|
||||||
|
{
|
||||||
|
bool foundSSU = false, foundNTCP2 = false;
|
||||||
|
std::string host = "127.0.0.1";
|
||||||
|
uint16_t port = 0;
|
||||||
|
auto& addresses = m_RouterInfo.GetAddresses ();
|
||||||
|
for (auto& addr: addresses)
|
||||||
|
{
|
||||||
|
if (addr->IsV4 ())
|
||||||
|
{
|
||||||
|
if (addr->transportStyle == i2p::data::RouterInfo::eTransportSSU)
|
||||||
|
foundSSU = true;
|
||||||
|
else if (addr->transportStyle == i2p::data::RouterInfo::eTransportNTCP)
|
||||||
|
foundNTCP2 = true;
|
||||||
|
}
|
||||||
|
if (addr->port) port = addr->port;
|
||||||
|
}
|
||||||
|
if (!port) i2p::config::GetOption("port", port);
|
||||||
|
// SSU
|
||||||
|
if (!foundSSU)
|
||||||
|
{
|
||||||
|
bool ssu; i2p::config::GetOption("ssu", ssu);
|
||||||
|
if (ssu)
|
||||||
|
m_RouterInfo.AddSSUAddress (host.c_str (), port, nullptr);
|
||||||
|
}
|
||||||
|
// NTCP2
|
||||||
|
if (!foundNTCP2)
|
||||||
|
{
|
||||||
|
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||||
|
if (ntcp2)
|
||||||
|
{
|
||||||
|
bool ntcp2Published; i2p::config::GetOption("ntcp2.published", ntcp2Published);
|
||||||
|
if (ntcp2Published)
|
||||||
|
{
|
||||||
|
uint16_t ntcp2Port; i2p::config::GetOption ("ntcp2.port", ntcp2Port);
|
||||||
|
if (!ntcp2Port) ntcp2Port = port;
|
||||||
|
m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address::from_string (host), ntcp2Port);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv);
|
||||||
|
}
|
||||||
|
}
|
||||||
m_RouterInfo.EnableV4 ();
|
m_RouterInfo.EnableV4 ();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
m_RouterInfo.DisableV4 ();
|
m_RouterInfo.DisableV4 ();
|
||||||
UpdateRouterInfo ();
|
UpdateRouterInfo ();
|
||||||
|
@ -638,7 +701,14 @@ namespace i2p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::shared_ptr<const i2p::data::IdentityEx> oldIdentity;
|
std::shared_ptr<const i2p::data::IdentityEx> oldIdentity;
|
||||||
if (m_Keys.GetPublic ()->GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1)
|
bool rekey = m_Keys.GetPublic ()->GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1;
|
||||||
|
if (!rekey && m_Keys.GetPublic ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL)
|
||||||
|
{
|
||||||
|
// rekey routers with bandwidth = L (or default) this time
|
||||||
|
std::string bandwidth; i2p::config::GetOption("bandwidth", bandwidth);
|
||||||
|
if (bandwidth.empty () || bandwidth[0] == 'L') rekey = true;
|
||||||
|
}
|
||||||
|
if (rekey)
|
||||||
{
|
{
|
||||||
// update keys
|
// update keys
|
||||||
LogPrint (eLogInfo, "Router: router keys are obsolete. Creating new");
|
LogPrint (eLogInfo, "Router: router keys are obsolete. Creating new");
|
||||||
|
@ -669,8 +739,8 @@ namespace i2p
|
||||||
m_RouterInfo.Update (routerInfo.GetBuffer (), routerInfo.GetBufferLen ());
|
m_RouterInfo.Update (routerInfo.GetBuffer (), routerInfo.GetBufferLen ());
|
||||||
if (oldIdentity)
|
if (oldIdentity)
|
||||||
m_RouterInfo.SetRouterIdentity (GetIdentity ()); // from new keys
|
m_RouterInfo.SetRouterIdentity (GetIdentity ()); // from new keys
|
||||||
m_RouterInfo.SetProperty ("coreVersion", I2P_VERSION);
|
|
||||||
m_RouterInfo.SetProperty ("router.version", I2P_VERSION);
|
m_RouterInfo.SetProperty ("router.version", I2P_VERSION);
|
||||||
|
m_RouterInfo.DeleteProperty ("coreVersion"); // TODO: remove later
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -738,8 +808,10 @@ namespace i2p
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
buf += 4;
|
buf += 4;
|
||||||
auto session = std::make_shared<i2p::garlic::ECIESX25519AEADRatchetSession>(this, false);
|
if (m_ECIESSession)
|
||||||
session->HandleNextMessageForRouter (buf, len);
|
m_ECIESSession->HandleNextMessage (buf, len);
|
||||||
|
else
|
||||||
|
LogPrint (eLogError, "Router: Session is not set for ECIES router");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
i2p::garlic::GarlicDestination::ProcessGarlicMessage (msg);
|
i2p::garlic::GarlicDestination::ProcessGarlicMessage (msg);
|
||||||
|
|
|
@ -21,6 +21,11 @@
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
|
namespace garlic
|
||||||
|
{
|
||||||
|
class RouterIncomingRatchetSession;
|
||||||
|
}
|
||||||
|
|
||||||
const char ROUTER_INFO[] = "router.info";
|
const char ROUTER_INFO[] = "router.info";
|
||||||
const char ROUTER_KEYS[] = "router.keys";
|
const char ROUTER_KEYS[] = "router.keys";
|
||||||
const char NTCP2_KEYS[] = "ntcp2.keys";
|
const char NTCP2_KEYS[] = "ntcp2.keys";
|
||||||
|
@ -32,7 +37,9 @@ namespace i2p
|
||||||
eRouterStatusTesting = 1,
|
eRouterStatusTesting = 1,
|
||||||
eRouterStatusFirewalled = 2,
|
eRouterStatusFirewalled = 2,
|
||||||
eRouterStatusError = 3,
|
eRouterStatusError = 3,
|
||||||
eRouterStatusUnknown = 4
|
eRouterStatusUnknown = 4,
|
||||||
|
eRouterStatusProxy = 5,
|
||||||
|
eRouterStatusMesh = 6
|
||||||
};
|
};
|
||||||
|
|
||||||
enum RouterError
|
enum RouterError
|
||||||
|
@ -42,7 +49,7 @@ namespace i2p
|
||||||
eRouterErrorOffline = 2,
|
eRouterErrorOffline = 2,
|
||||||
eRouterErrorSymmetricNAT = 3
|
eRouterErrorSymmetricNAT = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
class RouterContext: public i2p::garlic::GarlicDestination
|
class RouterContext: public i2p::garlic::GarlicDestination
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -155,6 +162,7 @@ namespace i2p
|
||||||
i2p::data::RouterInfo m_RouterInfo;
|
i2p::data::RouterInfo m_RouterInfo;
|
||||||
i2p::data::PrivateKeys m_Keys;
|
i2p::data::PrivateKeys m_Keys;
|
||||||
std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> m_Decryptor, m_TunnelDecryptor;
|
std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> m_Decryptor, m_TunnelDecryptor;
|
||||||
|
std::shared_ptr<i2p::garlic::RouterIncomingRatchetSession> m_ECIESSession;
|
||||||
uint64_t m_LastUpdateTime; // in seconds
|
uint64_t m_LastUpdateTime; // in seconds
|
||||||
bool m_AcceptsTunnels, m_IsFloodfill;
|
bool m_AcceptsTunnels, m_IsFloodfill;
|
||||||
std::chrono::time_point<std::chrono::steady_clock> m_StartupTime;
|
std::chrono::time_point<std::chrono::steady_clock> m_StartupTime;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -193,7 +193,6 @@ namespace data
|
||||||
auto addresses = boost::make_shared<Addresses>();
|
auto addresses = boost::make_shared<Addresses>();
|
||||||
uint8_t numAddresses;
|
uint8_t numAddresses;
|
||||||
s.read ((char *)&numAddresses, sizeof (numAddresses)); if (!s) return;
|
s.read ((char *)&numAddresses, sizeof (numAddresses)); if (!s) return;
|
||||||
bool introducers = false;
|
|
||||||
for (int i = 0; i < numAddresses; i++)
|
for (int i = 0; i < numAddresses; i++)
|
||||||
{
|
{
|
||||||
uint8_t supportedTransports = 0;
|
uint8_t supportedTransports = 0;
|
||||||
|
@ -271,7 +270,6 @@ namespace data
|
||||||
LogPrint (eLogError, "RouterInfo: Introducer is presented for non-SSU address. Skipped");
|
LogPrint (eLogError, "RouterInfo: Introducer is presented for non-SSU address. Skipped");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
introducers = true;
|
|
||||||
size_t l = strlen(key);
|
size_t l = strlen(key);
|
||||||
unsigned char index = key[l-1] - '0'; // TODO:
|
unsigned char index = key[l-1] - '0'; // TODO:
|
||||||
key[l-1] = 0;
|
key[l-1] = 0;
|
||||||
|
@ -314,8 +312,8 @@ namespace data
|
||||||
{
|
{
|
||||||
if (address->caps)
|
if (address->caps)
|
||||||
{
|
{
|
||||||
if (address->caps | AddressCaps::eV4) supportedTransports |= eNTCP2V4;
|
if (address->caps & AddressCaps::eV4) supportedTransports |= eNTCP2V4;
|
||||||
if (address->caps | AddressCaps::eV6) supportedTransports |= eNTCP2V6;
|
if (address->caps & AddressCaps::eV6) supportedTransports |= eNTCP2V6;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
supportedTransports |= eNTCP2V4; // most likely, since we don't have host
|
supportedTransports |= eNTCP2V4; // most likely, since we don't have host
|
||||||
|
@ -328,8 +326,13 @@ namespace data
|
||||||
{
|
{
|
||||||
if (isHost)
|
if (isHost)
|
||||||
supportedTransports |= address->host.is_v4 () ? eSSUV4 : eSSUV6;
|
supportedTransports |= address->host.is_v4 () ? eSSUV4 : eSSUV6;
|
||||||
|
else if (address->caps & AddressCaps::eV6)
|
||||||
|
{
|
||||||
|
supportedTransports |= eSSUV6;
|
||||||
|
if (address->caps & AddressCaps::eV4) supportedTransports |= eSSUV4; // in additional to v6
|
||||||
|
}
|
||||||
else
|
else
|
||||||
if (introducers) supportedTransports |= eSSUV4; // in case if host is not presented
|
supportedTransports |= eSSUV4; // in case if host or 6 caps is not preasented, we assume 4
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (supportedTransports)
|
if (supportedTransports)
|
||||||
|
@ -403,7 +406,7 @@ namespace data
|
||||||
if (!s) return;
|
if (!s) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_SupportedTransports || !m_Addresses->size() || (UsesIntroducer () && !introducers))
|
if (!m_SupportedTransports)
|
||||||
SetUnreachable (true);
|
SetUnreachable (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -519,7 +522,7 @@ namespace data
|
||||||
if (address.IsNTCP2 ())
|
if (address.IsNTCP2 ())
|
||||||
{
|
{
|
||||||
WriteString ("NTCP2", s);
|
WriteString ("NTCP2", s);
|
||||||
if (address.IsPublishedNTCP2 ())
|
if (address.IsPublishedNTCP2 () && !address.host.is_unspecified ())
|
||||||
isPublished = true;
|
isPublished = true;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -542,13 +545,26 @@ namespace data
|
||||||
// caps
|
// caps
|
||||||
WriteString ("caps", properties);
|
WriteString ("caps", properties);
|
||||||
properties << '=';
|
properties << '=';
|
||||||
std::string caps;
|
std::string caps;
|
||||||
if (address.IsPeerTesting ()) caps += CAPS_FLAG_SSU_TESTING;
|
if (address.IsPeerTesting ()) caps += CAPS_FLAG_SSU_TESTING;
|
||||||
if (address.IsIntroducer ()) caps += CAPS_FLAG_SSU_INTRODUCER;
|
if (address.host.is_v4 ())
|
||||||
if (IsReachable ())
|
{
|
||||||
|
if (IsReachable ())
|
||||||
|
{
|
||||||
|
isPublished = true;
|
||||||
|
if (address.IsIntroducer ()) caps += CAPS_FLAG_SSU_INTRODUCER;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
caps += CAPS_FLAG_V4;
|
||||||
|
}
|
||||||
|
else if (address.host.is_v6 ())
|
||||||
isPublished = true;
|
isPublished = true;
|
||||||
else
|
else
|
||||||
caps += CAPS_FLAG_V4;
|
{
|
||||||
|
if (address.caps & AddressCaps::eV4) caps += CAPS_FLAG_V4;
|
||||||
|
if (address.caps & AddressCaps::eV6) caps += CAPS_FLAG_V6;
|
||||||
|
if (caps.empty ()) caps += CAPS_FLAG_V4;
|
||||||
|
}
|
||||||
WriteString (caps, properties);
|
WriteString (caps, properties);
|
||||||
properties << ';';
|
properties << ';';
|
||||||
}
|
}
|
||||||
|
@ -637,7 +653,7 @@ namespace data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (address.IsPublishedNTCP2 ())
|
if (address.IsNTCP2 () && isPublished)
|
||||||
{
|
{
|
||||||
// publish i for NTCP2
|
// publish i for NTCP2
|
||||||
WriteString ("i", properties); properties << '=';
|
WriteString ("i", properties); properties << '=';
|
||||||
|
@ -785,9 +801,6 @@ namespace data
|
||||||
if (*it == *addr) return;
|
if (*it == *addr) return;
|
||||||
m_SupportedTransports |= addr->host.is_v6 () ? eSSUV6 : eSSUV4;
|
m_SupportedTransports |= addr->host.is_v6 () ? eSSUV6 : eSSUV4;
|
||||||
m_Addresses->push_back(std::move(addr));
|
m_Addresses->push_back(std::move(addr));
|
||||||
|
|
||||||
m_Caps |= eSSUTesting;
|
|
||||||
m_Caps |= eSSUIntroducer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RouterInfo::AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv, const boost::asio::ip::address& host, int port)
|
void RouterInfo::AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv, const boost::asio::ip::address& host, int port)
|
||||||
|
@ -913,13 +926,23 @@ namespace data
|
||||||
void RouterInfo::EnableV6 ()
|
void RouterInfo::EnableV6 ()
|
||||||
{
|
{
|
||||||
if (!IsV6 ())
|
if (!IsV6 ())
|
||||||
|
{
|
||||||
m_SupportedTransports |= eSSUV6 | eNTCP2V6;
|
m_SupportedTransports |= eSSUV6 | eNTCP2V6;
|
||||||
|
uint8_t addressCaps = AddressCaps::eV6;
|
||||||
|
if (IsV4 ()) addressCaps |= AddressCaps::eV4;
|
||||||
|
SetUnreachableAddressesTransportCaps (addressCaps);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RouterInfo::EnableV4 ()
|
void RouterInfo::EnableV4 ()
|
||||||
{
|
{
|
||||||
if (!IsV4 ())
|
if (!IsV4 ())
|
||||||
|
{
|
||||||
m_SupportedTransports |= eSSUV4 | eNTCP2V4;
|
m_SupportedTransports |= eSSUV4 | eNTCP2V4;
|
||||||
|
uint8_t addressCaps = AddressCaps::eV4;
|
||||||
|
if (IsV6 ()) addressCaps |= AddressCaps::eV6;
|
||||||
|
SetUnreachableAddressesTransportCaps (addressCaps);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -931,6 +954,7 @@ namespace data
|
||||||
for (auto it = m_Addresses->begin (); it != m_Addresses->end ();)
|
for (auto it = m_Addresses->begin (); it != m_Addresses->end ();)
|
||||||
{
|
{
|
||||||
auto addr = *it;
|
auto addr = *it;
|
||||||
|
addr->caps &= ~AddressCaps::eV6;
|
||||||
if (addr->host.is_v6 ())
|
if (addr->host.is_v6 ())
|
||||||
it = m_Addresses->erase (it);
|
it = m_Addresses->erase (it);
|
||||||
else
|
else
|
||||||
|
@ -947,6 +971,7 @@ namespace data
|
||||||
for (auto it = m_Addresses->begin (); it != m_Addresses->end ();)
|
for (auto it = m_Addresses->begin (); it != m_Addresses->end ();)
|
||||||
{
|
{
|
||||||
auto addr = *it;
|
auto addr = *it;
|
||||||
|
addr->caps &= ~AddressCaps::eV4;
|
||||||
if (addr->host.is_v4 ())
|
if (addr->host.is_v4 ())
|
||||||
it = m_Addresses->erase (it);
|
it = m_Addresses->erase (it);
|
||||||
else
|
else
|
||||||
|
@ -1069,8 +1094,9 @@ namespace data
|
||||||
|
|
||||||
bool RouterInfo::IsEligibleFloodfill () const
|
bool RouterInfo::IsEligibleFloodfill () const
|
||||||
{
|
{
|
||||||
// floodfill must be reachable, >= 0.9.28 and not DSA
|
// floodfill must be reachable somehow, >= 0.9.28 and not DSA
|
||||||
return IsReachable () && m_Version >= NETDB_MIN_FLOODFILL_VERSION &&
|
return (IsReachable () || (m_SupportedTransports & eSSUV4)) &&
|
||||||
|
m_Version >= NETDB_MIN_FLOODFILL_VERSION &&
|
||||||
GetIdentity ()->GetSigningKeyType () != SIGNING_KEY_TYPE_DSA_SHA1;
|
GetIdentity ()->GetSigningKeyType () != SIGNING_KEY_TYPE_DSA_SHA1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1079,22 +1105,57 @@ namespace data
|
||||||
auto supportedTransports = m_SupportedTransports & (eSSUV4 | eSSUV6);
|
auto supportedTransports = m_SupportedTransports & (eSSUV4 | eSSUV6);
|
||||||
if (!supportedTransports) return false; // no SSU
|
if (!supportedTransports) return false; // no SSU
|
||||||
if (v4only && !(supportedTransports & eSSUV4)) return false; // no SSU v4
|
if (v4only && !(supportedTransports & eSSUV4)) return false; // no SSU v4
|
||||||
return GetAddress (
|
return (bool)GetAddress (
|
||||||
[](std::shared_ptr<const RouterInfo::Address> address)->bool
|
[](std::shared_ptr<const RouterInfo::Address> address)->bool
|
||||||
{
|
{
|
||||||
return (address->transportStyle == eTransportSSU) && address->IsPeerTesting ();
|
return (address->transportStyle == eTransportSSU) && address->IsPeerTesting ();
|
||||||
}) != nullptr;
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RouterInfo::IsIntroducer () const
|
bool RouterInfo::IsIntroducer () const
|
||||||
{
|
{
|
||||||
// TODO: support ipv6
|
// TODO: support ipv6
|
||||||
if (!(m_SupportedTransports & eSSUV4)) return false;
|
if (!(m_SupportedTransports & eSSUV4)) return false;
|
||||||
return GetAddress (
|
return (bool)GetAddress (
|
||||||
[](std::shared_ptr<const RouterInfo::Address> address)->bool
|
[](std::shared_ptr<const RouterInfo::Address> address)->bool
|
||||||
{
|
{
|
||||||
return (address->transportStyle == eTransportSSU) && address->IsIntroducer ();
|
return (address->transportStyle == eTransportSSU) && address->IsIntroducer ();
|
||||||
}) != nullptr;
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RouterInfo::IsReachableFrom (const RouterInfo& other) const
|
||||||
|
{
|
||||||
|
auto commonTransports = m_SupportedTransports & other.m_SupportedTransports;
|
||||||
|
if (!commonTransports) return false;
|
||||||
|
if (commonTransports & eNTCP2V6Mesh) return true;
|
||||||
|
return (bool)GetAddress (
|
||||||
|
[commonTransports](std::shared_ptr<const RouterInfo::Address> address)->bool
|
||||||
|
{
|
||||||
|
if (address->IsPublishedNTCP2 ())
|
||||||
|
{
|
||||||
|
if ((commonTransports & eNTCP2V4) && address->IsV4 ()) return true;
|
||||||
|
if ((commonTransports & eNTCP2V6) && address->IsV6 ()) return true;
|
||||||
|
}
|
||||||
|
else if (address->IsReachableSSU ())
|
||||||
|
{
|
||||||
|
if ((commonTransports & eSSUV4) && address->IsV4 ()) return true;
|
||||||
|
if ((commonTransports & eSSUV6) && address->IsV6 ()) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void RouterInfo::SetUnreachableAddressesTransportCaps (uint8_t transports)
|
||||||
|
{
|
||||||
|
for (auto& addr: *m_Addresses)
|
||||||
|
{
|
||||||
|
// TODO: implement SSU
|
||||||
|
if (addr->transportStyle == eTransportNTCP && (!addr->IsPublishedNTCP2 () || addr->port))
|
||||||
|
{
|
||||||
|
addr->caps &= ~(eV4 | eV6);
|
||||||
|
addr->caps |= transports;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -130,8 +130,8 @@ namespace data
|
||||||
|
|
||||||
bool IsCompatible (const boost::asio::ip::address& other) const
|
bool IsCompatible (const boost::asio::ip::address& other) const
|
||||||
{
|
{
|
||||||
return (host.is_v4 () && other.is_v4 ()) ||
|
return (IsV4 () && other.is_v4 ()) ||
|
||||||
(host.is_v6 () && other.is_v6 ());
|
(IsV6 () && other.is_v6 ());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const Address& other) const
|
bool operator==(const Address& other) const
|
||||||
|
@ -147,9 +147,13 @@ namespace data
|
||||||
|
|
||||||
bool IsNTCP2 () const { return (bool)ntcp2; };
|
bool IsNTCP2 () const { return (bool)ntcp2; };
|
||||||
bool IsPublishedNTCP2 () const { return IsNTCP2 () && ntcp2->isPublished; };
|
bool IsPublishedNTCP2 () const { return IsNTCP2 () && ntcp2->isPublished; };
|
||||||
|
bool IsReachableSSU () const { return (bool)ssu && (!host.is_unspecified () || !ssu->introducers.empty ()); };
|
||||||
|
|
||||||
bool IsIntroducer () const { return caps & eSSUIntroducer; };
|
bool IsIntroducer () const { return caps & eSSUIntroducer; };
|
||||||
bool IsPeerTesting () const { return caps & eSSUTesting; };
|
bool IsPeerTesting () const { return caps & eSSUTesting; };
|
||||||
|
|
||||||
|
bool IsV4 () const { return (caps & AddressCaps::eV4) || host.is_v4 (); };
|
||||||
|
bool IsV6 () const { return (caps & AddressCaps::eV6) || host.is_v6 (); };
|
||||||
};
|
};
|
||||||
typedef std::list<std::shared_ptr<Address> > Addresses;
|
typedef std::list<std::shared_ptr<Address> > Addresses;
|
||||||
|
|
||||||
|
@ -181,6 +185,7 @@ namespace data
|
||||||
void DeleteProperty (const std::string& key); // called from RouterContext only
|
void DeleteProperty (const std::string& key); // called from RouterContext only
|
||||||
std::string GetProperty (const std::string& key) const; // called from RouterContext only
|
std::string GetProperty (const std::string& key) const; // called from RouterContext only
|
||||||
void ClearProperties () { m_Properties.clear (); };
|
void ClearProperties () { m_Properties.clear (); };
|
||||||
|
void SetUnreachableAddressesTransportCaps (uint8_t transports); // bitmask of AddressCaps
|
||||||
bool IsFloodfill () const { return m_Caps & Caps::eFloodfill; };
|
bool IsFloodfill () const { return m_Caps & Caps::eFloodfill; };
|
||||||
bool IsReachable () const { return m_Caps & Caps::eReachable; };
|
bool IsReachable () const { return m_Caps & Caps::eReachable; };
|
||||||
bool IsSSU (bool v4only = true) const;
|
bool IsSSU (bool v4only = true) const;
|
||||||
|
@ -196,7 +201,8 @@ namespace data
|
||||||
void DisableV4 ();
|
void DisableV4 ();
|
||||||
void EnableMesh ();
|
void EnableMesh ();
|
||||||
void DisableMesh ();
|
void DisableMesh ();
|
||||||
bool IsCompatible (const RouterInfo& other) const { return m_SupportedTransports & other.m_SupportedTransports; };
|
bool IsCompatible (const RouterInfo& other) const { return m_SupportedTransports & other.m_SupportedTransports; };
|
||||||
|
bool IsReachableFrom (const RouterInfo& other) const;
|
||||||
bool HasValidAddresses () const { return m_SupportedTransports; };
|
bool HasValidAddresses () const { return m_SupportedTransports; };
|
||||||
bool UsesIntroducer () const;
|
bool UsesIntroducer () const;
|
||||||
bool IsHidden () const { return m_Caps & eHidden; };
|
bool IsHidden () const { return m_Caps & eHidden; };
|
||||||
|
|
|
@ -653,6 +653,14 @@ namespace transport
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SSUServer::RescheduleIntroducersUpdateTimer ()
|
||||||
|
{
|
||||||
|
m_IntroducersUpdateTimer.cancel ();
|
||||||
|
m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(SSU_KEEP_ALIVE_INTERVAL/2));
|
||||||
|
m_IntroducersUpdateTimer.async_wait (std::bind (&SSUServer::HandleIntroducersUpdateTimer,
|
||||||
|
this, std::placeholders::_1));
|
||||||
|
}
|
||||||
|
|
||||||
void SSUServer::ScheduleIntroducersUpdateTimer ()
|
void SSUServer::ScheduleIntroducersUpdateTimer ()
|
||||||
{
|
{
|
||||||
m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(SSU_KEEP_ALIVE_INTERVAL));
|
m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(SSU_KEEP_ALIVE_INTERVAL));
|
||||||
|
@ -671,7 +679,12 @@ namespace transport
|
||||||
ScheduleIntroducersUpdateTimer ();
|
ScheduleIntroducersUpdateTimer ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (i2p::context.GetStatus () == eRouterStatusOK) return; // we don't need introducers anymore
|
if (i2p::context.GetStatus () != eRouterStatusFirewalled)
|
||||||
|
{
|
||||||
|
// we don't need introducers
|
||||||
|
m_Introducers.clear ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
// we are firewalled
|
// we are firewalled
|
||||||
if (!i2p::context.IsUnreachable ()) i2p::context.SetUnreachable ();
|
if (!i2p::context.IsUnreachable ()) i2p::context.SetUnreachable ();
|
||||||
std::list<boost::asio::ip::udp::endpoint> newList;
|
std::list<boost::asio::ip::udp::endpoint> newList;
|
||||||
|
@ -712,9 +725,24 @@ namespace transport
|
||||||
m_Introducers = newList;
|
m_Introducers = newList;
|
||||||
if (m_Introducers.size () < SSU_MAX_NUM_INTRODUCERS)
|
if (m_Introducers.size () < SSU_MAX_NUM_INTRODUCERS)
|
||||||
{
|
{
|
||||||
auto introducer = i2p::data::netdb.GetRandomIntroducer ();
|
std::set<std::shared_ptr<const i2p::data::RouterInfo> > requested;
|
||||||
if (introducer)
|
for (auto i = m_Introducers.size (); i < SSU_MAX_NUM_INTRODUCERS; i++)
|
||||||
CreateSession (introducer);
|
{
|
||||||
|
auto introducer = i2p::data::netdb.GetRandomIntroducer ();
|
||||||
|
if (introducer && !requested.count (introducer)) // not requested already
|
||||||
|
{
|
||||||
|
auto address = introducer->GetSSUAddress (true); // v4
|
||||||
|
if (address && !address->host.is_unspecified ())
|
||||||
|
{
|
||||||
|
boost::asio::ip::udp::endpoint ep (address->host, address->port);
|
||||||
|
if (std::find (m_Introducers.begin (), m_Introducers.end (), ep) == m_Introducers.end ()) // not connected yet
|
||||||
|
{
|
||||||
|
CreateDirectSession (introducer, ep, false);
|
||||||
|
requested.insert (introducer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ScheduleIntroducersUpdateTimer ();
|
ScheduleIntroducersUpdateTimer ();
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,8 @@ namespace transport
|
||||||
void AddRelay (uint32_t tag, std::shared_ptr<SSUSession> relay);
|
void AddRelay (uint32_t tag, std::shared_ptr<SSUSession> relay);
|
||||||
void RemoveRelay (uint32_t tag);
|
void RemoveRelay (uint32_t tag);
|
||||||
std::shared_ptr<SSUSession> FindRelaySession (uint32_t tag);
|
std::shared_ptr<SSUSession> FindRelaySession (uint32_t tag);
|
||||||
|
void RescheduleIntroducersUpdateTimer ();
|
||||||
|
|
||||||
void NewPeerTest (uint32_t nonce, PeerTestParticipant role, std::shared_ptr<SSUSession> session = nullptr);
|
void NewPeerTest (uint32_t nonce, PeerTestParticipant role, std::shared_ptr<SSUSession> session = nullptr);
|
||||||
PeerTestParticipant GetPeerTestParticipant (uint32_t nonce);
|
PeerTestParticipant GetPeerTestParticipant (uint32_t nonce);
|
||||||
std::shared_ptr<SSUSession> GetPeerTestSession (uint32_t nonce);
|
std::shared_ptr<SSUSession> GetPeerTestSession (uint32_t nonce);
|
||||||
|
|
|
@ -685,7 +685,12 @@ namespace transport
|
||||||
LogPrint (eLogInfo, "SSU: Our external address is ", ourIP.to_string (), ":", ourPort);
|
LogPrint (eLogInfo, "SSU: Our external address is ", ourIP.to_string (), ":", ourPort);
|
||||||
i2p::context.UpdateAddress (ourIP);
|
i2p::context.UpdateAddress (ourIP);
|
||||||
if (ourPort != m_Server.GetPort ())
|
if (ourPort != m_Server.GetPort ())
|
||||||
i2p::context.SetError (eRouterErrorSymmetricNAT);
|
{
|
||||||
|
if (i2p::context.GetStatus () == eRouterStatusTesting)
|
||||||
|
i2p::context.SetError (eRouterErrorSymmetricNAT);
|
||||||
|
}
|
||||||
|
else if (i2p::context.GetStatus () == eRouterStatusError && i2p::context.GetError () == eRouterErrorSymmetricNAT)
|
||||||
|
i2p::context.SetStatus (eRouterStatusTesting);
|
||||||
uint32_t nonce = bufbe32toh (buf);
|
uint32_t nonce = bufbe32toh (buf);
|
||||||
buf += 4; // nonce
|
buf += 4; // nonce
|
||||||
auto it = m_RelayRequests.find (nonce);
|
auto it = m_RelayRequests.find (nonce);
|
||||||
|
@ -999,7 +1004,10 @@ namespace transport
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "SSU: peer test from Bob. We are Alice");
|
LogPrint (eLogDebug, "SSU: peer test from Bob. We are Alice");
|
||||||
if (i2p::context.GetStatus () == eRouterStatusTesting) // still not OK
|
if (i2p::context.GetStatus () == eRouterStatusTesting) // still not OK
|
||||||
|
{
|
||||||
i2p::context.SetStatus (eRouterStatusFirewalled);
|
i2p::context.SetStatus (eRouterStatusFirewalled);
|
||||||
|
m_Server.RescheduleIntroducersUpdateTimer ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -174,9 +174,9 @@ namespace transport
|
||||||
std::string ntcp2proxy; i2p::config::GetOption("ntcp2.proxy", ntcp2proxy);
|
std::string ntcp2proxy; i2p::config::GetOption("ntcp2.proxy", ntcp2proxy);
|
||||||
i2p::http::URL proxyurl;
|
i2p::http::URL proxyurl;
|
||||||
// create NTCP2. TODO: move to acceptor
|
// create NTCP2. TODO: move to acceptor
|
||||||
if (enableNTCP2)
|
if (enableNTCP2 || i2p::context.SupportsMesh ())
|
||||||
{
|
{
|
||||||
if(!ntcp2proxy.empty())
|
if(!ntcp2proxy.empty() && enableNTCP2)
|
||||||
{
|
{
|
||||||
if(proxyurl.parse(ntcp2proxy))
|
if(proxyurl.parse(ntcp2proxy))
|
||||||
{
|
{
|
||||||
|
@ -188,14 +188,14 @@ namespace transport
|
||||||
if (proxyurl.schema == "http")
|
if (proxyurl.schema == "http")
|
||||||
proxytype = NTCP2Server::eHTTPProxy;
|
proxytype = NTCP2Server::eHTTPProxy;
|
||||||
|
|
||||||
m_NTCP2Server->UseProxy(proxytype, proxyurl.host, proxyurl.port);
|
m_NTCP2Server->UseProxy(proxytype, proxyurl.host, proxyurl.port, proxyurl.user, proxyurl.pass);
|
||||||
|
i2p::context.SetStatus (eRouterStatusProxy);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint(eLogError, "Transports: unsupported NTCP2 proxy URL ", ntcp2proxy);
|
LogPrint(eLogError, "Transports: unsupported NTCP2 proxy URL ", ntcp2proxy);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint(eLogError, "Transports: invalid NTCP2 proxy url ", ntcp2proxy);
|
LogPrint(eLogError, "Transports: invalid NTCP2 proxy url ", ntcp2proxy);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_NTCP2Server = new NTCP2Server ();
|
m_NTCP2Server = new NTCP2Server ();
|
||||||
|
@ -503,7 +503,7 @@ namespace transport
|
||||||
}
|
}
|
||||||
peer.numAttempts++;
|
peer.numAttempts++;
|
||||||
}
|
}
|
||||||
if (address)
|
if (address && address->IsReachableSSU ())
|
||||||
{
|
{
|
||||||
m_SSUServer->CreateSession (peer.router, address);
|
m_SSUServer->CreateSession (peer.router, address);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -698,7 +698,7 @@ namespace tunnel
|
||||||
auto inboundTunnel = GetNextInboundTunnel ();
|
auto inboundTunnel = GetNextInboundTunnel ();
|
||||||
auto router = i2p::transport::transports.RoutesRestricted() ?
|
auto router = i2p::transport::transports.RoutesRestricted() ?
|
||||||
i2p::transport::transports.GetRestrictedPeer() :
|
i2p::transport::transports.GetRestrictedPeer() :
|
||||||
i2p::data::netdb.GetRandomRouter ();
|
i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false); // reachable by us
|
||||||
if (!inboundTunnel || !router) return;
|
if (!inboundTunnel || !router) return;
|
||||||
LogPrint (eLogDebug, "Tunnel: creating one hop outbound tunnel");
|
LogPrint (eLogDebug, "Tunnel: creating one hop outbound tunnel");
|
||||||
CreateTunnel<OutboundTunnel> (
|
CreateTunnel<OutboundTunnel> (
|
||||||
|
@ -771,7 +771,8 @@ namespace tunnel
|
||||||
// trying to create one more inbound tunnel
|
// trying to create one more inbound tunnel
|
||||||
auto router = i2p::transport::transports.RoutesRestricted() ?
|
auto router = i2p::transport::transports.RoutesRestricted() ?
|
||||||
i2p::transport::transports.GetRestrictedPeer() :
|
i2p::transport::transports.GetRestrictedPeer() :
|
||||||
i2p::data::netdb.GetRandomRouter ();
|
// should be reachable by us because we send build request directly
|
||||||
|
i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false);
|
||||||
if (!router) {
|
if (!router) {
|
||||||
LogPrint (eLogWarning, "Tunnel: can't find any router, skip creating tunnel");
|
LogPrint (eLogWarning, "Tunnel: can't find any router, skip creating tunnel");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -393,14 +393,14 @@ namespace tunnel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<const i2p::data::RouterInfo> TunnelPool::SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop) const
|
std::shared_ptr<const i2p::data::RouterInfo> TunnelPool::SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop, bool reverse) const
|
||||||
{
|
{
|
||||||
bool isExploratory = (i2p::tunnel::tunnels.GetExploratoryPool () == shared_from_this ());
|
bool isExploratory = (i2p::tunnel::tunnels.GetExploratoryPool () == shared_from_this ());
|
||||||
auto hop = isExploratory ? i2p::data::netdb.GetRandomRouter (prevHop):
|
auto hop = isExploratory ? i2p::data::netdb.GetRandomRouter (prevHop, reverse):
|
||||||
i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop);
|
i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop, reverse);
|
||||||
|
|
||||||
if (!hop || hop->GetProfile ()->IsBad ())
|
if (!hop || hop->GetProfile ()->IsBad ())
|
||||||
hop = i2p::data::netdb.GetRandomRouter (prevHop);
|
hop = i2p::data::netdb.GetRandomRouter (prevHop, reverse);
|
||||||
return hop;
|
return hop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,7 +419,7 @@ namespace tunnel
|
||||||
{
|
{
|
||||||
auto r = i2p::transport::transports.GetRandomPeer ();
|
auto r = i2p::transport::transports.GetRandomPeer ();
|
||||||
if (r && !r->GetProfile ()->IsBad () &&
|
if (r && !r->GetProfile ()->IsBad () &&
|
||||||
(numHops > 1 || !inbound || r->IsReachable ())) // first must be reachable
|
(numHops > 1 || (!inbound && r->IsV4 ()) || r->IsReachable ())) // first inbound must be reachable
|
||||||
{
|
{
|
||||||
prevHop = r;
|
prevHop = r;
|
||||||
peers.push_back (r->GetRouterIdentity ());
|
peers.push_back (r->GetRouterIdentity ());
|
||||||
|
@ -429,16 +429,22 @@ namespace tunnel
|
||||||
|
|
||||||
for(int i = 0; i < numHops; i++ )
|
for(int i = 0; i < numHops; i++ )
|
||||||
{
|
{
|
||||||
auto hop = nextHop (prevHop);
|
auto hop = nextHop (prevHop, inbound);
|
||||||
|
if (!hop && !i) // if no suitable peer found for first hop, try already connected
|
||||||
|
{
|
||||||
|
LogPrint (eLogInfo, "Tunnels: Can't select first hop for a tunnel. Trying already connected");
|
||||||
|
hop = i2p::transport::transports.GetRandomPeer ();
|
||||||
|
}
|
||||||
if (!hop)
|
if (!hop)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Tunnels: Can't select next hop for ", prevHop->GetIdentHashBase64 ());
|
LogPrint (eLogError, "Tunnels: Can't select next hop for ", prevHop->GetIdentHashBase64 ());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (inbound && (i == numHops - 1) && !hop->IsReachable ())
|
if ((i == numHops - 1) &&
|
||||||
|
((inbound && !hop->IsReachable ()) || // IBGW is not reachable
|
||||||
|
(!inbound && !hop->IsV4 ()))) // OBEP is not ipv4
|
||||||
{
|
{
|
||||||
// if first is not reachable try again
|
auto hop1 = nextHop (prevHop, true);
|
||||||
auto hop1 = nextHop (prevHop);
|
|
||||||
if (hop1) hop = hop1;
|
if (hop1) hop = hop1;
|
||||||
}
|
}
|
||||||
prevHop = hop;
|
prevHop = hop;
|
||||||
|
@ -460,7 +466,7 @@ namespace tunnel
|
||||||
}
|
}
|
||||||
// explicit peers in use
|
// explicit peers in use
|
||||||
if (m_ExplicitPeers) return SelectExplicitPeers (peers, isInbound);
|
if (m_ExplicitPeers) return SelectExplicitPeers (peers, isInbound);
|
||||||
return StandardSelectPeers(peers, numHops, isInbound, std::bind(&TunnelPool::SelectNextHop, this, std::placeholders::_1));
|
return StandardSelectPeers(peers, numHops, isInbound, std::bind(&TunnelPool::SelectNextHop, this, std::placeholders::_1, std::placeholders::_2));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TunnelPool::SelectExplicitPeers (std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& peers, bool isInbound)
|
bool TunnelPool::SelectExplicitPeers (std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& peers, bool isInbound)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -46,7 +46,7 @@ namespace tunnel
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef std::function<std::shared_ptr<const i2p::data::RouterInfo>(std::shared_ptr<const i2p::data::RouterInfo>)> SelectHopFunc;
|
typedef std::function<std::shared_ptr<const i2p::data::RouterInfo>(std::shared_ptr<const i2p::data::RouterInfo>, bool)> SelectHopFunc;
|
||||||
// standard peer selection algorithm
|
// standard peer selection algorithm
|
||||||
bool StandardSelectPeers(Path & path, int hops, bool inbound, SelectHopFunc nextHop);
|
bool StandardSelectPeers(Path & path, int hops, bool inbound, SelectHopFunc nextHop);
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ namespace tunnel
|
||||||
std::shared_ptr<OutboundTunnel> GetLowestLatencyOutboundTunnel(std::shared_ptr<OutboundTunnel> exclude = nullptr) const;
|
std::shared_ptr<OutboundTunnel> GetLowestLatencyOutboundTunnel(std::shared_ptr<OutboundTunnel> exclude = nullptr) const;
|
||||||
|
|
||||||
// for overriding tunnel peer selection
|
// for overriding tunnel peer selection
|
||||||
std::shared_ptr<const i2p::data::RouterInfo> SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop) const;
|
std::shared_ptr<const i2p::data::RouterInfo> SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop, bool reverse) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -67,8 +67,12 @@ int inet_pton_xp (int af, const char *src, void *dst)
|
||||||
}
|
}
|
||||||
#else /* !_WIN32 => UNIX */
|
#else /* !_WIN32 => UNIX */
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#ifdef ANDROID
|
||||||
|
#include "ifaddrs.h"
|
||||||
|
#else
|
||||||
#include <ifaddrs.h>
|
#include <ifaddrs.h>
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#define address_pair_v4(a,b) { boost::asio::ip::address_v4::from_string (a).to_ulong (), boost::asio::ip::address_v4::from_string (b).to_ulong () }
|
#define address_pair_v4(a,b) { boost::asio::ip::address_v4::from_string (a).to_ulong (), boost::asio::ip::address_v4::from_string (b).to_ulong () }
|
||||||
#define address_pair_v6(a,b) { boost::asio::ip::address_v6::from_string (a).to_bytes (), boost::asio::ip::address_v6::from_string (b).to_bytes () }
|
#define address_pair_v6(a,b) { boost::asio::ip::address_v6::from_string (a).to_bytes (), boost::asio::ip::address_v6::from_string (b).to_bytes () }
|
||||||
|
@ -380,11 +384,11 @@ namespace net
|
||||||
return boost::asio::ip::address::from_string("127.0.0.1");
|
return boost::asio::ip::address::from_string("127.0.0.1");
|
||||||
#else
|
#else
|
||||||
int af = (ipv6 ? AF_INET6 : AF_INET);
|
int af = (ipv6 ? AF_INET6 : AF_INET);
|
||||||
ifaddrs * addrs = nullptr;
|
ifaddrs *addrs, *cur = nullptr;
|
||||||
if(getifaddrs(&addrs) == 0)
|
if(getifaddrs(&addrs) == 0)
|
||||||
{
|
{
|
||||||
// got ifaddrs
|
// got ifaddrs
|
||||||
ifaddrs * cur = addrs;
|
cur = addrs;
|
||||||
while(cur)
|
while(cur)
|
||||||
{
|
{
|
||||||
std::string cur_ifname(cur->ifa_name);
|
std::string cur_ifname(cur->ifa_name);
|
||||||
|
@ -431,10 +435,7 @@ namespace net
|
||||||
|
|
||||||
boost::asio::ip::address_v6 GetYggdrasilAddress ()
|
boost::asio::ip::address_v6 GetYggdrasilAddress ()
|
||||||
{
|
{
|
||||||
#if defined(ANDROID)
|
#if defined(_WIN32)
|
||||||
// TODO: implement
|
|
||||||
return boost::asio::ip::address_v6 ();
|
|
||||||
#elif defined(_WIN32)
|
|
||||||
ULONG outBufLen = 0;
|
ULONG outBufLen = 0;
|
||||||
PIP_ADAPTER_ADDRESSES pAddresses = nullptr;
|
PIP_ADAPTER_ADDRESSES pAddresses = nullptr;
|
||||||
PIP_ADAPTER_ADDRESSES pCurrAddresses = nullptr;
|
PIP_ADAPTER_ADDRESSES pCurrAddresses = nullptr;
|
||||||
|
@ -482,11 +483,11 @@ namespace net
|
||||||
FREE(pAddresses);
|
FREE(pAddresses);
|
||||||
return boost::asio::ip::address_v6 ();
|
return boost::asio::ip::address_v6 ();
|
||||||
#else
|
#else
|
||||||
ifaddrs * addrs = nullptr;
|
ifaddrs *addrs, *cur = nullptr;
|
||||||
auto err = getifaddrs(&addrs);
|
auto err = getifaddrs(&addrs);
|
||||||
if (!err)
|
if (!err)
|
||||||
{
|
{
|
||||||
ifaddrs * cur = addrs;
|
cur = addrs;
|
||||||
while(cur)
|
while(cur)
|
||||||
{
|
{
|
||||||
if (cur->ifa_addr && cur->ifa_addr->sa_family == AF_INET6)
|
if (cur->ifa_addr && cur->ifa_addr->sa_family == AF_INET6)
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
#define MAKE_VERSION_NUMBER(a,b,c) ((a*100+b)*100+c)
|
#define MAKE_VERSION_NUMBER(a,b,c) ((a*100+b)*100+c)
|
||||||
|
|
||||||
#define I2PD_VERSION_MAJOR 2
|
#define I2PD_VERSION_MAJOR 2
|
||||||
#define I2PD_VERSION_MINOR 36
|
#define I2PD_VERSION_MINOR 37
|
||||||
#define I2PD_VERSION_MICRO 0
|
#define I2PD_VERSION_MICRO 0
|
||||||
#define I2PD_VERSION_PATCH 0
|
#define I2PD_VERSION_PATCH 0
|
||||||
#define I2PD_VERSION MAKE_VERSION(I2PD_VERSION_MAJOR, I2PD_VERSION_MINOR, I2PD_VERSION_MICRO)
|
#define I2PD_VERSION MAKE_VERSION(I2PD_VERSION_MAJOR, I2PD_VERSION_MINOR, I2PD_VERSION_MICRO)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -433,13 +433,13 @@ namespace proxy {
|
||||||
if (m_ProxyURL.is_i2p())
|
if (m_ProxyURL.is_i2p())
|
||||||
{
|
{
|
||||||
m_ClientRequest.uri = origURI;
|
m_ClientRequest.uri = origURI;
|
||||||
if (!m_ProxyURL.user.empty () || !m_ProxyURL.pass.empty ())
|
auto auth = i2p::http::CreateBasicAuthorizationString (m_ProxyURL.user, m_ProxyURL.pass);
|
||||||
|
if (!auth.empty ())
|
||||||
{
|
{
|
||||||
// remove existing authorization if any
|
// remove existing authorization if any
|
||||||
m_ClientRequest.RemoveHeader("Proxy-");
|
m_ClientRequest.RemoveHeader("Proxy-");
|
||||||
// add own http proxy authorization
|
// add own http proxy authorization
|
||||||
std::string s = "Basic " + i2p::data::ToBase64Standard (m_ProxyURL.user + ":" + m_ProxyURL.pass);
|
m_ClientRequest.AddHeader("Proxy-Authorization", auth);
|
||||||
m_ClientRequest.AddHeader("Proxy-Authorization", s);
|
|
||||||
}
|
}
|
||||||
m_send_buf = m_ClientRequest.to_string();
|
m_send_buf = m_ClientRequest.to_string();
|
||||||
m_recv_buf.erase(0, m_req_len);
|
m_recv_buf.erase(0, m_req_len);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -72,7 +72,8 @@ namespace client
|
||||||
bool MatchedTunnelDestination::SelectPeers(i2p::tunnel::Path & path, int hops, bool inbound)
|
bool MatchedTunnelDestination::SelectPeers(i2p::tunnel::Path & path, int hops, bool inbound)
|
||||||
{
|
{
|
||||||
auto pool = GetTunnelPool();
|
auto pool = GetTunnelPool();
|
||||||
if(!i2p::tunnel::StandardSelectPeers(path, hops, inbound, std::bind(&i2p::tunnel::TunnelPool::SelectNextHop, pool, std::placeholders::_1)))
|
if(!i2p::tunnel::StandardSelectPeers(path, hops, inbound,
|
||||||
|
std::bind(&i2p::tunnel::TunnelPool::SelectNextHop, pool, std::placeholders::_1, std::placeholders::_2)))
|
||||||
return false;
|
return false;
|
||||||
// more here for outbound tunnels
|
// more here for outbound tunnels
|
||||||
if(!inbound && m_RemoteLeaseSet)
|
if(!inbound && m_RemoteLeaseSet)
|
||||||
|
|
Loading…
Add table
Reference in a new issue