Merge pull request #920 from PurpleI2P/openssl

2.15.0
This commit is contained in:
orignal 2017-08-17 14:20:41 -04:00 committed by GitHub
commit c21c1f5225
48 changed files with 2991 additions and 629 deletions

View File

@ -1,6 +1,20 @@
# 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.15.0] - 2017-08-17
### Added
- QT GUI
- Ability to add and remove I2P tunnels without restart
- Ability to disable SOCKS outproxy option
### Changed
- Strip-out Accept-* hedaers in HTTP proxy
- Don't run peer test if nat=false
- Separate output of NTCP and SSU sessions in Transports tab
### Fixed
- Handle lines with comments in hosts.txt file for address book
- Run router with empty netdb for testnet
- Skip expired introducers by iexp
## [2.14.0] - 2017-06-01 ## [2.14.0] - 2017-06-01
### Added ### Added
- Transit traffic bandwidth limitation - Transit traffic bandwidth limitation

View File

@ -43,6 +43,15 @@ The easiest way to install i2pd is by using
See [documentation](https://i2pd.readthedocs.io/en/latest/) for how to build See [documentation](https://i2pd.readthedocs.io/en/latest/) for how to build
i2pd from source on your OS. i2pd from source on your OS.
Build instructions:
* [unix](https://i2pd.readthedocs.io/en/latest/devs/building/unix/)
* [windows](https://i2pd.readthedocs.io/en/latest/devs/building/windows/)
* [iOS](https://i2pd.readthedocs.io/en/latest/devs/building/ios/)
* [android](https://i2pd.readthedocs.io/en/latest/devs/building/android/)
**Supported systems:** **Supported systems:**
* GNU/Linux x86/x64 - [![Build Status](https://travis-ci.org/PurpleI2P/i2pd.svg?branch=openssl)](https://travis-ci.org/PurpleI2P/i2pd) * GNU/Linux x86/x64 - [![Build Status](https://travis-ci.org/PurpleI2P/i2pd.svg?branch=openssl)](https://travis-ci.org/PurpleI2P/i2pd)

View File

@ -70,7 +70,6 @@ void WINAPI I2PService::ServiceCtrlHandler(DWORD dwCtrl)
} }
} }
I2PService::I2PService(PSTR pszServiceName, I2PService::I2PService(PSTR pszServiceName,
BOOL fCanStop, BOOL fCanStop,
BOOL fCanShutdown, BOOL fCanShutdown,
@ -147,8 +146,7 @@ void I2PService::Start(DWORD dwArgc, PSTR *pszArgv)
void I2PService::OnStart(DWORD dwArgc, PSTR *pszArgv) void I2PService::OnStart(DWORD dwArgc, PSTR *pszArgv)
{ {
LogPrint(eLogInfo, "Win32Service in OnStart", LogPrint(eLogInfo, "Win32Service in OnStart", EVENTLOG_INFORMATION_TYPE);
EVENTLOG_INFORMATION_TYPE);
Daemon.start(); Daemon.start();
@ -165,7 +163,7 @@ void I2PService::WorkerThread()
{ {
while (!m_fStopping) while (!m_fStopping)
{ {
::Sleep(1000); // Simulate some lengthy operations. ::Sleep(1000); // Simulate some lengthy operations.
} }
// Signal the stopped event. // Signal the stopped event.
@ -270,12 +268,10 @@ void I2PService::Continue()
} }
} }
void I2PService::OnContinue() void I2PService::OnContinue()
{ {
} }
void I2PService::Shutdown() void I2PService::Shutdown()
{ {
try try
@ -294,19 +290,16 @@ void I2PService::Shutdown()
} }
} }
void I2PService::OnShutdown() void I2PService::OnShutdown()
{ {
} }
void I2PService::SetServiceStatus(DWORD dwCurrentState, void I2PService::SetServiceStatus(DWORD dwCurrentState,
DWORD dwWin32ExitCode, DWORD dwWin32ExitCode,
DWORD dwWaitHint) DWORD dwWaitHint)
{ {
static DWORD dwCheckPoint = 1; static DWORD dwCheckPoint = 1;
m_status.dwCurrentState = dwCurrentState; m_status.dwCurrentState = dwCurrentState;
m_status.dwWin32ExitCode = dwWin32ExitCode; m_status.dwWin32ExitCode = dwWin32ExitCode;
m_status.dwWaitHint = dwWaitHint; m_status.dwWaitHint = dwWaitHint;
@ -335,12 +328,7 @@ void FreeHandles(SC_HANDLE schSCManager, SC_HANDLE schService)
} }
} }
void InstallService(PSTR pszServiceName, void InstallService(PSTR pszServiceName, PSTR pszDisplayName, DWORD dwStartType, PSTR pszDependencies, PSTR pszAccount, PSTR pszPassword)
PSTR pszDisplayName,
DWORD dwStartType,
PSTR pszDependencies,
PSTR pszAccount,
PSTR pszPassword)
{ {
printf("Try to install Win32Service (%s).\n", pszServiceName); printf("Try to install Win32Service (%s).\n", pszServiceName);
@ -354,10 +342,10 @@ void InstallService(PSTR pszServiceName,
FreeHandles(schSCManager, schService); FreeHandles(schSCManager, schService);
return; return;
} }
strncat(szPath, " --daemon", MAX_PATH);
// Open the local default service control manager database // Open the local default service control manager database
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT | schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE);
SC_MANAGER_CREATE_SERVICE);
if (schSCManager == NULL) if (schSCManager == NULL)
{ {
printf("OpenSCManager failed w/err 0x%08lx\n", GetLastError()); printf("OpenSCManager failed w/err 0x%08lx\n", GetLastError());
@ -381,6 +369,7 @@ void InstallService(PSTR pszServiceName,
pszAccount, // Service running account pszAccount, // Service running account
pszPassword // Password of the account pszPassword // Password of the account
); );
if (schService == NULL) if (schService == NULL)
{ {
printf("CreateService failed w/err 0x%08lx\n", GetLastError()); printf("CreateService failed w/err 0x%08lx\n", GetLastError());
@ -412,8 +401,7 @@ void UninstallService(PSTR pszServiceName)
} }
// Open the service with delete, stop, and query status permissions // Open the service with delete, stop, and query status permissions
schService = OpenService(schSCManager, pszServiceName, SERVICE_STOP | schService = OpenService(schSCManager, pszServiceName, SERVICE_STOP | SERVICE_QUERY_STATUS | DELETE);
SERVICE_QUERY_STATUS | DELETE);
if (schService == NULL) if (schService == NULL)
{ {
printf("OpenService failed w/err 0x%08lx\n", GetLastError()); printf("OpenService failed w/err 0x%08lx\n", GetLastError());

View File

@ -1,5 +1,5 @@
#define I2Pd_AppName "i2pd" #define I2Pd_AppName "i2pd"
#define I2Pd_ver "2.14.0" #define I2Pd_ver "2.15.0"
#define I2Pd_Publisher "PurpleI2P" #define I2Pd_Publisher "PurpleI2P"
[Setup] [Setup]

View File

@ -2,7 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.purplei2p.i2pd" package="org.purplei2p.i2pd"
android:versionCode="1" android:versionCode="1"
android:versionName="2.14.0" android:versionName="2.15.0"
android:installLocation="auto"> android:installLocation="auto">
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="25"/> <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="25"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

View File

@ -1,4 +1,4 @@
version: 2.14.{build} version: 2.15.{build}
pull_requests: pull_requests:
do_not_increment_build_number: true do_not_increment_build_number: true
branches: branches:

View File

@ -0,0 +1,13 @@
-----BEGIN CERTIFICATE-----
MIIB6jCCAY+gAwIBAgIJAPeWi4iUKLBJMAoGCCqGSM49BAMCMHoxCzAJBgNVBAYT
AlhYMQswCQYDVQQIDAJYWDELMAkGA1UEBwwCWFgxHjAcBgNVBAoMFUkyUCBBbm9u
eW1vdXMgTmV0d29yazEPMA0GA1UECwwGZmFtaWx5MSAwHgYDVQQDDBdnb3N0Y29p
bi5mYW1pbHkuaTJwLm5ldDAeFw0xNzA4MDExMzQ4MzdaFw0yNzA3MzAxMzQ4Mzda
MHoxCzAJBgNVBAYTAlhYMQswCQYDVQQIDAJYWDELMAkGA1UEBwwCWFgxHjAcBgNV
BAoMFUkyUCBBbm9ueW1vdXMgTmV0d29yazEPMA0GA1UECwwGZmFtaWx5MSAwHgYD
VQQDDBdnb3N0Y29pbi5mYW1pbHkuaTJwLm5ldDBZMBMGByqGSM49AgEGCCqGSM49
AwEHA0IABC+9iIYumUNnsqKbnTluHimV8OdGvo7yeGxuqhfNNB2b3jvbFJ81scgH
dsZtMQmUxgKM5nH+NQJMoCxHhSlRy2QwCgYIKoZIzj0EAwIDSQAwRgIhANNh7mOp
nBBPRh2a/ipG1VYS0d+mNjSrpz8xWcG3CXPLAiEAjM5MTfv9sOJ74PeZVhFZ02w4
vhgyZCeLJ57f123Lm1A=
-----END CERTIFICATE-----

View File

@ -5,7 +5,9 @@ After=network.target
[Service] [Service]
User=i2pd User=i2pd
Group=i2pd Group=i2pd
Type=forking RuntimeDirectory=i2pd
RuntimeDirectoryMode=0700
Type=simple
ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service
ExecReload=/bin/kill -HUP $MAINPID ExecReload=/bin/kill -HUP $MAINPID
PIDFile=/var/run/i2pd/i2pd.pid PIDFile=/var/run/i2pd/i2pd.pid

View File

@ -12,7 +12,7 @@ ENV REPO_URL=${REPO_URL}
ENV I2PD_HOME="/home/i2pd" ENV I2PD_HOME="/home/i2pd"
ENV DATA_DIR="${I2PD_HOME}/data" ENV DATA_DIR="${I2PD_HOME}/data"
RUN mkdir -p "$I2PD_HOME" \ RUN mkdir -p "$I2PD_HOME" "$DATA_DIR" \
&& adduser -S -h "$I2PD_HOME" i2pd \ && adduser -S -h "$I2PD_HOME" i2pd \
&& chown -R i2pd:nobody "$I2PD_HOME" && chown -R i2pd:nobody "$I2PD_HOME"

View File

@ -7,8 +7,6 @@ DEFAULT_ARGS=" --datadir=$DATA_DIR --reseed.verify=true --upnp.enabled=false --h
if [ "$1" = "--help" ]; then if [ "$1" = "--help" ]; then
set -- $COMMAND --help set -- $COMMAND --help
else else
# Create datadir
mkdir -p "$DATA_DIR"
ln -s /i2pd_certificates "$DATA_DIR"/certificates ln -s /i2pd_certificates "$DATA_DIR"/certificates
set -- $COMMAND $DEFAULT_ARGS $@ set -- $COMMAND $DEFAULT_ARGS $@
fi fi

View File

@ -136,6 +136,8 @@ port = 4447
# keys = socks-proxy-keys.dat # keys = socks-proxy-keys.dat
## Socks outproxy. Example below is set to use Tor for all connections except i2p ## Socks outproxy. Example below is set to use Tor for all connections except i2p
## Uncomment and set to 'true' to enable using of SOCKS outproxy
# outproxy.enabled = false
## Address and port of outproxy ## Address and port of outproxy
# outproxy = 127.0.0.1 # outproxy = 127.0.0.1
# outproxyport = 9050 # outproxyport = 9050

View File

@ -1,7 +1,7 @@
%define build_timestamp %(date +"%Y%m%d") %define build_timestamp %(date +"%Y%m%d")
Name: i2pd Name: i2pd
Version: 2.14.0 Version: 2.15.0
Release: %{build_timestamp}git%{?dist} Release: %{build_timestamp}git%{?dist}
Summary: I2P router written in C++ Summary: I2P router written in C++
@ -103,6 +103,17 @@ getent passwd i2pd >/dev/null || \
%changelog %changelog
* Thu Aug 17 2017 orignal <i2porignal@yandex.ru> - 2.15.0
- Added QT GUI
- Added ability add and remove I2P tunnels without restart
- Added ability to disable SOCKS outproxy option
- Changed strip-out Accept-* hedaers in HTTP proxy
- Changed peer test if nat=false
- Changed separate output of NTCP and SSU sessions in Transports tab
- Fixed handle lines with comments in hosts.txt file for address book
- Fixed run router with empty netdb for testnet
- Fixed skip expired introducers by iexp
* Thu Jun 01 2017 orignal <i2porignal@yandex.ru> - 2.14.0 * Thu Jun 01 2017 orignal <i2porignal@yandex.ru> - 2.14.0
- Added transit traffic bandwidth limitation - Added transit traffic bandwidth limitation
- Added NTCP connections through HTTP and SOCKS proxies - Added NTCP connections through HTTP and SOCKS proxies

View File

@ -496,18 +496,42 @@ namespace http {
if (ntcpServer) if (ntcpServer)
{ {
auto sessions = ntcpServer->GetNTCPSessions (); auto sessions = ntcpServer->GetNTCPSessions ();
s << "<b>NTCP</b> ( " << (int) sessions.size() << " )<br>\r\n"; if (!sessions.empty ())
for (const auto& it: sessions )
{ {
if (it.second && it.second->IsEstablished ()) std::stringstream tmp_s, tmp_s6; uint16_t cnt = 0, cnt6 = 0;
for (const auto& it: sessions )
{ {
// incoming connection doesn't have remote RI if (it.second && it.second->IsEstablished () && !it.second->GetSocket ().remote_endpoint ().address ().is_v6 ())
if (it.second->IsOutgoing ()) s << " &#8658; "; {
s << i2p::data::GetIdentHashAbbreviation (it.second->GetRemoteIdentity ()->GetIdentHash ()) << ": " // incoming connection doesn't have remote RI
<< it.second->GetSocket ().remote_endpoint().address ().to_string (); if (it.second->IsOutgoing ()) tmp_s << " &#8658; ";
if (!it.second->IsOutgoing ()) s << " &#8658; "; tmp_s << i2p::data::GetIdentHashAbbreviation (it.second->GetRemoteIdentity ()->GetIdentHash ()) << ": "
s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]"; << it.second->GetSocket ().remote_endpoint().address ().to_string ();
s << "<br>\r\n" << std::endl; if (!it.second->IsOutgoing ()) tmp_s << " &#8658; ";
tmp_s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
tmp_s << "<br>\r\n" << std::endl;
cnt++;
}
if (it.second && it.second->IsEstablished () && it.second->GetSocket ().remote_endpoint ().address ().is_v6 ())
{
if (it.second->IsOutgoing ()) tmp_s6 << " &#8658; ";
tmp_s6 << i2p::data::GetIdentHashAbbreviation (it.second->GetRemoteIdentity ()->GetIdentHash ()) << ": "
<< "[" << it.second->GetSocket ().remote_endpoint().address ().to_string () << "]";
if (!it.second->IsOutgoing ()) tmp_s6 << " &#8658; ";
tmp_s6 << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
tmp_s6 << "<br>\r\n" << std::endl;
cnt6++;
}
}
if (!tmp_s.str ().empty ())
{
s << "<b>NTCP</b> ( " << cnt << " )<br>\r\n";
s << tmp_s.str () << "<br>\r\n";
}
if (!tmp_s6.str ().empty ())
{
s << "<b>NTCP6</b> ( " << cnt6 << " )<br>\r\n";
s << tmp_s6.str () << "<br>\r\n";
} }
} }
} }
@ -515,27 +539,38 @@ namespace http {
if (ssuServer) if (ssuServer)
{ {
auto sessions = ssuServer->GetSessions (); auto sessions = ssuServer->GetSessions ();
s << "<br>\r\n<b>SSU</b> ( " << (int) sessions.size() << " )<br>\r\n"; if (!sessions.empty ())
for (const auto& it: sessions)
{ {
auto endpoint = it.second->GetRemoteEndpoint (); s << "<b>SSU</b> ( " << (int) sessions.size() << " )<br>\r\n";
if (it.second->IsOutgoing ()) s << " &#8658; "; for (const auto& it: sessions)
s << endpoint.address ().to_string () << ":" << endpoint.port (); {
if (!it.second->IsOutgoing ()) s << " &#8658; "; auto endpoint = it.second->GetRemoteEndpoint ();
s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]"; if (it.second->IsOutgoing ()) s << " &#8658; ";
if (it.second->GetRelayTag ()) s << endpoint.address ().to_string () << ":" << endpoint.port ();
s << " [itag:" << it.second->GetRelayTag () << "]"; if (!it.second->IsOutgoing ()) s << " &#8658; ";
s << "<br>\r\n" << std::endl; s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
if (it.second->GetRelayTag ())
s << " [itag:" << it.second->GetRelayTag () << "]";
s << "<br>\r\n" << std::endl;
}
s << "<br>\r\n";
} }
s << "<br>\r\n<b>SSU6</b><br>\r\n"; auto sessions6 = ssuServer->GetSessionsV6 ();
for (const auto& it: ssuServer->GetSessionsV6 ()) if (!sessions6.empty ())
{ {
auto endpoint = it.second->GetRemoteEndpoint (); s << "<b>SSU6</b> ( " << (int) sessions6.size() << " )<br>\r\n";
if (it.second->IsOutgoing ()) s << " &#8658; "; for (const auto& it: sessions6)
s << endpoint.address ().to_string () << ":" << endpoint.port (); {
if (!it.second->IsOutgoing ()) s << " &#8658; "; auto endpoint = it.second->GetRemoteEndpoint ();
s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]"; if (it.second->IsOutgoing ()) s << " &#8658; ";
s << "<br>\r\n" << std::endl; s << "[" << endpoint.address ().to_string () << "]:" << endpoint.port ();
if (!it.second->IsOutgoing ()) s << " &#8658; ";
s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
if (it.second->GetRelayTag ())
s << " [itag:" << it.second->GetRelayTag () << "]";
s << "<br>\r\n" << std::endl;
}
s << "<br>\r\n";
} }
} }
} }

6
debian/changelog vendored
View File

@ -1,3 +1,9 @@
i2pd (2.15.0-1) unstable; urgency=low
* updated to version 2.15.0/0.9.31
-- orignal <orignal@i2pmail.org> Thu, 17 Aug 2017 18:00:00 +0000
i2pd (2.14.0-1) unstable; urgency=low i2pd (2.14.0-1) unstable; urgency=low
* updated to version 2.14.0/0.9.30 * updated to version 2.14.0/0.9.30

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2016, The PurpleI2P Project * Copyright (c) 2013-2017, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -24,294 +24,301 @@ using namespace boost::program_options;
namespace i2p { namespace i2p {
namespace config { namespace config {
options_description m_OptionsDesc; options_description m_OptionsDesc;
variables_map m_Options; variables_map m_Options;
void Init() { void Init()
{
options_description general("General options"); options_description general("General options");
general.add_options() general.add_options()
("help", "Show this message") ("help", "Show this message")
("conf", value<std::string>()->default_value(""), "Path to main i2pd config file (default: try ~/.i2pd/i2pd.conf or /var/lib/i2pd/i2pd.conf)") ("conf", value<std::string>()->default_value(""), "Path to main i2pd config file (default: try ~/.i2pd/i2pd.conf or /var/lib/i2pd/i2pd.conf)")
("tunconf", value<std::string>()->default_value(""), "Path to config with tunnels list and options (default: try ~/.i2pd/tunnels.conf or /var/lib/i2pd/tunnels.conf)") ("tunconf", value<std::string>()->default_value(""), "Path to config with tunnels list and options (default: try ~/.i2pd/tunnels.conf or /var/lib/i2pd/tunnels.conf)")
("pidfile", value<std::string>()->default_value(""), "Path to pidfile (default: ~/i2pd/i2pd.pid or /var/lib/i2pd/i2pd.pid)") ("pidfile", value<std::string>()->default_value(""), "Path to pidfile (default: ~/i2pd/i2pd.pid or /var/lib/i2pd/i2pd.pid)")
("log", value<std::string>()->default_value(""), "Logs destination: stdout, file, syslog (stdout if not set)") ("log", value<std::string>()->default_value(""), "Logs destination: stdout, file, syslog (stdout if not set)")
("logfile", value<std::string>()->default_value(""), "Path to logfile (stdout if not set, autodetect if daemon)") ("logfile", value<std::string>()->default_value(""), "Path to logfile (stdout if not set, autodetect if daemon)")
("loglevel", value<std::string>()->default_value("info"), "Set the minimal level of log messages (debug, info, warn, error)") ("loglevel", value<std::string>()->default_value("info"), "Set the minimal level of log messages (debug, info, warn, error)")
("family", value<std::string>()->default_value(""), "Specify a family, router belongs to") ("family", value<std::string>()->default_value(""), "Specify a family, router belongs to")
("datadir", value<std::string>()->default_value(""), "Path to storage of i2pd data (RI, keys, peer profiles, ...)") ("datadir", value<std::string>()->default_value(""), "Path to storage of i2pd data (RI, keys, peer profiles, ...)")
("host", value<std::string>()->default_value("0.0.0.0"), "External IP") ("host", value<std::string>()->default_value("0.0.0.0"), "External IP")
("ifname", value<std::string>()->default_value(""), "Network interface to bind to") ("ifname", value<std::string>()->default_value(""), "Network interface to bind to")
("ifname4", value<std::string>()->default_value(""), "Network interface to bind to for ipv4") ("ifname4", value<std::string>()->default_value(""), "Network interface to bind to for ipv4")
("ifname6", value<std::string>()->default_value(""), "Network interface to bind to for ipv6") ("ifname6", value<std::string>()->default_value(""), "Network interface to bind to for ipv6")
("nat", value<bool>()->zero_tokens()->default_value(true), "Should we assume we are behind NAT?") ("nat", value<bool>()->default_value(true), "Should we assume we are behind NAT?")
("port", value<uint16_t>()->default_value(0), "Port to listen for incoming connections (default: auto)") ("port", value<uint16_t>()->default_value(0), "Port to listen for incoming connections (default: auto)")
("ipv4", value<bool>()->zero_tokens()->default_value(true), "Enable communication through ipv4") ("ipv4", value<bool>()->default_value(true), "Enable communication through ipv4")
("ipv6", value<bool>()->zero_tokens()->default_value(false), "Enable communication through ipv6") ("ipv6", value<bool>()->zero_tokens()->default_value(false), "Enable communication through ipv6")
("netid", value<int>()->default_value(I2PD_NET_ID), "Specify NetID. Main I2P is 2") ("netid", value<int>()->default_value(I2PD_NET_ID), "Specify NetID. Main I2P is 2")
("daemon", value<bool>()->zero_tokens()->default_value(false), "Router will go to background after start") ("daemon", value<bool>()->zero_tokens()->default_value(false), "Router will go to background after start")
("service", value<bool>()->zero_tokens()->default_value(false), "Router will use system folders like '/var/lib/i2pd'") ("service", value<bool>()->zero_tokens()->default_value(false), "Router will use system folders like '/var/lib/i2pd'")
("notransit", value<bool>()->zero_tokens()->default_value(false), "Router will not accept transit tunnels at startup") ("notransit", value<bool>()->zero_tokens()->default_value(false), "Router will not accept transit tunnels at startup")
("floodfill", value<bool>()->zero_tokens()->default_value(false), "Router will be floodfill") ("floodfill", value<bool>()->zero_tokens()->default_value(false), "Router will be floodfill")
("bandwidth", value<std::string>()->default_value(""), "Bandwidth limit: integer in KBps or letters: L (32), O (256), P (2048), X (>9000)") ("bandwidth", value<std::string>()->default_value(""), "Bandwidth limit: integer in KBps or letters: L (32), O (256), P (2048), X (>9000)")
("share", value<int>()->default_value(100), "Limit of transit traffic from max bandwidth in percents. (default: 100") ("share", value<int>()->default_value(100), "Limit of transit traffic from max bandwidth in percents. (default: 100")
("ntcp", value<bool>()->zero_tokens()->default_value(true), "Enable NTCP transport") ("ntcp", value<bool>()->default_value(true), "Enable NTCP transport")
("ssu", value<bool>()->zero_tokens()->default_value(true), "Enable SSU transport") ("ssu", value<bool>()->default_value(true), "Enable SSU transport")
("ntcpproxy", value<std::string>()->default_value(""), "proxy url for ntcp transport") ("ntcpproxy", value<std::string>()->default_value(""), "Proxy URL for NTCP transport")
#ifdef _WIN32 #ifdef _WIN32
("svcctl", value<std::string>()->default_value(""), "Windows service management ('install' or 'remove')") ("svcctl", value<std::string>()->default_value(""), "Windows service management ('install' or 'remove')")
("insomnia", value<bool>()->zero_tokens()->default_value(false), "Prevent system from sleeping") ("insomnia", value<bool>()->zero_tokens()->default_value(false), "Prevent system from sleeping")
("close", value<std::string>()->default_value("ask"), "Action on close: minimize, exit, ask") // TODO: add custom validator or something ("close", value<std::string>()->default_value("ask"), "Action on close: minimize, exit, ask") // TODO: add custom validator or something
#endif #endif
; ;
options_description limits("Limits options"); options_description limits("Limits options");
limits.add_options() limits.add_options()
("limits.coresize", value<uint32_t>()->default_value(0), "Maximum size of corefile in Kb (0 - use system limit)") ("limits.coresize", value<uint32_t>()->default_value(0), "Maximum size of corefile in Kb (0 - use system limit)")
("limits.openfiles", value<uint16_t>()->default_value(0), "Maximum number of open files (0 - use system default)") ("limits.openfiles", value<uint16_t>()->default_value(0), "Maximum number of open files (0 - use system default)")
("limits.transittunnels", value<uint16_t>()->default_value(2500), "Maximum active transit sessions (default:2500)") ("limits.transittunnels", value<uint16_t>()->default_value(2500), "Maximum active transit sessions (default:2500)")
; ;
options_description httpserver("HTTP Server options"); options_description httpserver("HTTP Server options");
httpserver.add_options() httpserver.add_options()
("http.enabled", value<bool>()->default_value(true), "Enable or disable webconsole") ("http.enabled", value<bool>()->default_value(true), "Enable or disable webconsole")
("http.address", value<std::string>()->default_value("127.0.0.1"), "Webconsole listen address") ("http.address", value<std::string>()->default_value("127.0.0.1"), "Webconsole listen address")
("http.port", value<uint16_t>()->default_value(7070), "Webconsole listen port") ("http.port", value<uint16_t>()->default_value(7070), "Webconsole listen port")
("http.auth", value<bool>()->default_value(false), "Enable Basic HTTP auth for webconsole") ("http.auth", value<bool>()->default_value(false), "Enable Basic HTTP auth for webconsole")
("http.user", value<std::string>()->default_value("i2pd"), "Username for basic auth") ("http.user", value<std::string>()->default_value("i2pd"), "Username for basic auth")
("http.pass", value<std::string>()->default_value(""), "Password for basic auth (default: random, see logs)") ("http.pass", value<std::string>()->default_value(""), "Password for basic auth (default: random, see logs)")
; ;
options_description httpproxy("HTTP Proxy options"); options_description httpproxy("HTTP Proxy options");
httpproxy.add_options() httpproxy.add_options()
("httpproxy.enabled", value<bool>()->default_value(true), "Enable or disable HTTP Proxy") ("httpproxy.enabled", value<bool>()->default_value(true), "Enable or disable HTTP Proxy")
("httpproxy.address", value<std::string>()->default_value("127.0.0.1"), "HTTP Proxy listen address") ("httpproxy.address", value<std::string>()->default_value("127.0.0.1"), "HTTP Proxy listen address")
("httpproxy.port", value<uint16_t>()->default_value(4444), "HTTP Proxy listen port") ("httpproxy.port", value<uint16_t>()->default_value(4444), "HTTP Proxy listen port")
("httpproxy.keys", value<std::string>()->default_value(""), "File to persist HTTP Proxy keys") ("httpproxy.keys", value<std::string>()->default_value(""), "File to persist HTTP Proxy keys")
("httpproxy.signaturetype", value<i2p::data::SigningKeyType>()->default_value(i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519), "Signature type for new keys. 7 (EdDSA) by default") ("httpproxy.signaturetype", value<i2p::data::SigningKeyType>()->default_value(i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519), "Signature type for new keys. 7 (EdDSA) by default")
("httpproxy.inbound.length", value<std::string>()->default_value("3"), "HTTP proxy inbound tunnel length") ("httpproxy.inbound.length", value<std::string>()->default_value("3"), "HTTP proxy inbound tunnel length")
("httpproxy.outbound.length", value<std::string>()->default_value("3"), "HTTP proxy outbound tunnel length") ("httpproxy.outbound.length", value<std::string>()->default_value("3"), "HTTP proxy outbound tunnel length")
("httpproxy.inbound.quantity", value<std::string>()->default_value("5"), "HTTP proxy inbound tunnels quantity") ("httpproxy.inbound.quantity", value<std::string>()->default_value("5"), "HTTP proxy inbound tunnels quantity")
("httpproxy.outbound.quantity", value<std::string>()->default_value("5"), "HTTP proxy outbound tunnels quantity") ("httpproxy.outbound.quantity", value<std::string>()->default_value("5"), "HTTP proxy outbound tunnels quantity")
("httpproxy.latency.min", value<std::string>()->default_value("0"), "HTTP proxy min latency for tunnels") ("httpproxy.latency.min", value<std::string>()->default_value("0"), "HTTP proxy min latency for tunnels")
("httpproxy.latency.max", value<std::string>()->default_value("0"), "HTTP proxy max latency for tunnels") ("httpproxy.latency.max", value<std::string>()->default_value("0"), "HTTP proxy max latency for tunnels")
("httpproxy.outproxy", value<std::string>()->default_value(""), "HTTP proxy upstream out proxy url") ("httpproxy.outproxy", value<std::string>()->default_value(""), "HTTP proxy upstream out proxy url")
("httpproxy.addresshelper", value<bool>()->default_value(true), "Enable or disable addresshelper") ("httpproxy.addresshelper", value<bool>()->default_value(true), "Enable or disable addresshelper")
; ;
options_description socksproxy("SOCKS Proxy options"); options_description socksproxy("SOCKS Proxy options");
socksproxy.add_options() socksproxy.add_options()
("socksproxy.enabled", value<bool>()->default_value(true), "Enable or disable SOCKS Proxy") ("socksproxy.enabled", value<bool>()->default_value(true), "Enable or disable SOCKS Proxy")
("socksproxy.address", value<std::string>()->default_value("127.0.0.1"), "SOCKS Proxy listen address") ("socksproxy.address", value<std::string>()->default_value("127.0.0.1"), "SOCKS Proxy listen address")
("socksproxy.port", value<uint16_t>()->default_value(4447), "SOCKS Proxy listen port") ("socksproxy.port", value<uint16_t>()->default_value(4447), "SOCKS Proxy listen port")
("socksproxy.keys", value<std::string>()->default_value(""), "File to persist SOCKS Proxy keys") ("socksproxy.keys", value<std::string>()->default_value(""), "File to persist SOCKS Proxy keys")
("socksproxy.signaturetype", value<i2p::data::SigningKeyType>()->default_value(i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519), "Signature type for new keys. 7 (EdDSA) by default") ("socksproxy.signaturetype", value<i2p::data::SigningKeyType>()->default_value(i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519), "Signature type for new keys. 7 (EdDSA) by default")
("socksproxy.inbound.length", value<std::string>()->default_value("3"), "SOCKS proxy inbound tunnel length") ("socksproxy.inbound.length", value<std::string>()->default_value("3"), "SOCKS proxy inbound tunnel length")
("socksproxy.outbound.length", value<std::string>()->default_value("3"), "SOCKS proxy outbound tunnel length") ("socksproxy.outbound.length", value<std::string>()->default_value("3"), "SOCKS proxy outbound tunnel length")
("socksproxy.inbound.quantity", value<std::string>()->default_value("5"), "SOCKS proxy inbound tunnels quantity") ("socksproxy.inbound.quantity", value<std::string>()->default_value("5"), "SOCKS proxy inbound tunnels quantity")
("socksproxy.outbound.quantity", value<std::string>()->default_value("5"), "SOCKS proxy outbound tunnels quantity") ("socksproxy.outbound.quantity", value<std::string>()->default_value("5"), "SOCKS proxy outbound tunnels quantity")
("socksproxy.latency.min", value<std::string>()->default_value("0"), "SOCKS proxy min latency for tunnels") ("socksproxy.latency.min", value<std::string>()->default_value("0"), "SOCKS proxy min latency for tunnels")
("socksproxy.latency.max", value<std::string>()->default_value("0"), "SOCKS proxy max latency for tunnels") ("socksproxy.latency.max", value<std::string>()->default_value("0"), "SOCKS proxy max latency for tunnels")
("socksproxy.outproxy", value<std::string>()->default_value("127.0.0.1"), "Upstream outproxy address for SOCKS Proxy") ("socksproxy.outproxy.enabled", value<bool>()->default_value(false), "Enable or disable SOCKS outproxy")
("socksproxy.outproxyport", value<uint16_t>()->default_value(9050), "Upstream outproxy port for SOCKS Proxy") ("socksproxy.outproxy", value<std::string>()->default_value("127.0.0.1"), "Upstream outproxy address for SOCKS Proxy")
; ("socksproxy.outproxyport", value<uint16_t>()->default_value(9050), "Upstream outproxy port for SOCKS Proxy")
;
options_description sam("SAM bridge options"); options_description sam("SAM bridge options");
sam.add_options() sam.add_options()
("sam.enabled", value<bool>()->default_value(true), "Enable or disable SAM Application bridge") ("sam.enabled", value<bool>()->default_value(true), "Enable or disable SAM Application bridge")
("sam.address", value<std::string>()->default_value("127.0.0.1"), "SAM listen address") ("sam.address", value<std::string>()->default_value("127.0.0.1"), "SAM listen address")
("sam.port", value<uint16_t>()->default_value(7656), "SAM listen port") ("sam.port", value<uint16_t>()->default_value(7656), "SAM listen port")
; ;
options_description bob("BOB options"); options_description bob("BOB options");
bob.add_options() bob.add_options()
("bob.enabled", value<bool>()->default_value(false), "Enable or disable BOB command channel") ("bob.enabled", value<bool>()->default_value(false), "Enable or disable BOB command channel")
("bob.address", value<std::string>()->default_value("127.0.0.1"), "BOB listen address") ("bob.address", value<std::string>()->default_value("127.0.0.1"), "BOB listen address")
("bob.port", value<uint16_t>()->default_value(2827), "BOB listen port") ("bob.port", value<uint16_t>()->default_value(2827), "BOB listen port")
; ;
options_description i2cp("I2CP options"); options_description i2cp("I2CP options");
i2cp.add_options() i2cp.add_options()
("i2cp.enabled", value<bool>()->default_value(false), "Enable or disable I2CP") ("i2cp.enabled", value<bool>()->default_value(false), "Enable or disable I2CP")
("i2cp.address", value<std::string>()->default_value("127.0.0.1"), "I2CP listen address") ("i2cp.address", value<std::string>()->default_value("127.0.0.1"), "I2CP listen address")
("i2cp.port", value<uint16_t>()->default_value(7654), "I2CP listen port") ("i2cp.port", value<uint16_t>()->default_value(7654), "I2CP listen port")
; ;
options_description i2pcontrol("I2PControl options"); options_description i2pcontrol("I2PControl options");
i2pcontrol.add_options() i2pcontrol.add_options()
("i2pcontrol.enabled", value<bool>()->default_value(false), "Enable or disable I2P Control Protocol") ("i2pcontrol.enabled", value<bool>()->default_value(false), "Enable or disable I2P Control Protocol")
("i2pcontrol.address", value<std::string>()->default_value("127.0.0.1"), "I2PCP listen address") ("i2pcontrol.address", value<std::string>()->default_value("127.0.0.1"), "I2PCP listen address")
("i2pcontrol.port", value<uint16_t>()->default_value(7650), "I2PCP listen port") ("i2pcontrol.port", value<uint16_t>()->default_value(7650), "I2PCP listen port")
("i2pcontrol.password", value<std::string>()->default_value("itoopie"), "I2PCP access password") ("i2pcontrol.password", value<std::string>()->default_value("itoopie"), "I2PCP access password")
("i2pcontrol.cert", value<std::string>()->default_value("i2pcontrol.crt.pem"), "I2PCP connection cerificate") ("i2pcontrol.cert", value<std::string>()->default_value("i2pcontrol.crt.pem"), "I2PCP connection cerificate")
("i2pcontrol.key", value<std::string>()->default_value("i2pcontrol.key.pem"), "I2PCP connection cerificate key") ("i2pcontrol.key", value<std::string>()->default_value("i2pcontrol.key.pem"), "I2PCP connection cerificate key")
; ;
bool upnp_default = false; bool upnp_default = false;
#if (defined(USE_UPNP) && (defined(WIN32_APP) || defined(ANDROID))) #if (defined(USE_UPNP) && (defined(WIN32_APP) || defined(ANDROID)))
upnp_default = true; // enable UPNP for windows GUI and android by default upnp_default = true; // enable UPNP for windows GUI and android by default
#endif #endif
options_description upnp("UPnP options"); options_description upnp("UPnP options");
upnp.add_options() upnp.add_options()
("upnp.enabled", value<bool>()->default_value(upnp_default), "Enable or disable UPnP: automatic port forwarding") ("upnp.enabled", value<bool>()->default_value(upnp_default), "Enable or disable UPnP: automatic port forwarding")
("upnp.name", value<std::string>()->default_value("I2Pd"), "Name i2pd appears in UPnP forwardings list") ("upnp.name", value<std::string>()->default_value("I2Pd"), "Name i2pd appears in UPnP forwardings list")
; ;
options_description precomputation("Precomputation options"); options_description precomputation("Precomputation options");
precomputation.add_options() precomputation.add_options()
("precomputation.elgamal", ("precomputation.elgamal",
#if defined(__x86_64__) #if defined(__x86_64__)
value<bool>()->default_value(false), value<bool>()->default_value(false),
#else #else
value<bool>()->default_value(true), value<bool>()->default_value(true),
#endif #endif
"Enable or disable elgamal precomputation table") "Enable or disable elgamal precomputation table")
; ;
options_description reseed("Reseed options"); options_description reseed("Reseed options");
reseed.add_options() reseed.add_options()
("reseed.verify", value<bool>()->default_value(false), "Verify .su3 signature") ("reseed.verify", value<bool>()->default_value(false), "Verify .su3 signature")
("reseed.threshold", value<uint16_t>()->default_value(25), "Minimum number of known routers before requesting reseed") ("reseed.threshold", value<uint16_t>()->default_value(25), "Minimum number of known routers before requesting reseed")
("reseed.floodfill", value<std::string>()->default_value(""), "Path to router info of floodfill to reseed from") ("reseed.floodfill", value<std::string>()->default_value(""), "Path to router info of floodfill to reseed from")
("reseed.file", value<std::string>()->default_value(""), "Path to local .su3 file or HTTPS URL to reseed from") ("reseed.file", value<std::string>()->default_value(""), "Path to local .su3 file or HTTPS URL to reseed from")
("reseed.zipfile", value<std::string>()->default_value(""), "Path to local .zip file to reseed from") ("reseed.zipfile", value<std::string>()->default_value(""), "Path to local .zip file to reseed from")
("reseed.urls", value<std::string>()->default_value( ("reseed.urls", value<std::string>()->default_value(
"https://reseed.i2p-projekt.de/," "https://reseed.i2p-projekt.de/,"
"https://i2p.mooo.com/netDb/," "https://i2p.mooo.com/netDb/,"
"https://netdb.i2p2.no/," "https://netdb.i2p2.no/,"
// "https://us.reseed.i2p2.no:444/," // mamoth's shit // "https://us.reseed.i2p2.no:444/," // mamoth's shit
// "https://uk.reseed.i2p2.no:444/," // mamoth's shit // "https://uk.reseed.i2p2.no:444/," // mamoth's shit
"https://i2p-0.manas.ca:8443/," "https://i2p-0.manas.ca:8443/,"
"https://download.xxlspeed.com/," "https://download.xxlspeed.com/,"
"https://reseed-ru.lngserv.ru/," "https://reseed-ru.lngserv.ru/,"
"https://reseed.atomike.ninja/," "https://reseed.atomike.ninja/,"
"https://reseed.memcpy.io/," "https://reseed.memcpy.io/,"
"https://reseed.onion.im/," "https://reseed.onion.im/,"
"https://itoopie.atomike.ninja/," "https://itoopie.atomike.ninja/,"
"https://i2pseed.creativecowpat.net:8443/" "https://i2pseed.creativecowpat.net:8443/"
), "Reseed URLs, separated by comma") ), "Reseed URLs, separated by comma")
; ;
options_description addressbook("AddressBook options"); options_description addressbook("AddressBook options");
addressbook.add_options() addressbook.add_options()
("addressbook.defaulturl", value<std::string>()->default_value( ("addressbook.defaulturl", value<std::string>()->default_value(
"http://joajgazyztfssty4w2on5oaqksz6tqoxbduy553y34mf4byv6gpq.b32.i2p/export/alive-hosts.txt" "http://joajgazyztfssty4w2on5oaqksz6tqoxbduy553y34mf4byv6gpq.b32.i2p/export/alive-hosts.txt"
), "AddressBook subscription URL for initial setup") ), "AddressBook subscription URL for initial setup")
("addressbook.subscriptions", value<std::string>()->default_value(""), ("addressbook.subscriptions", value<std::string>()->default_value(""), "AddressBook subscriptions URLs, separated by comma");
"AddressBook subscriptions URLs, separated by comma");
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 Familiy 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?")
;
options_description websocket("Websocket Options"); options_description websocket("Websocket Options");
websocket.add_options() websocket.add_options()
("websockets.enabled", value<bool>()->default_value(false), "enable websocket server") ("websockets.enabled", value<bool>()->default_value(false), "Enable websocket server")
("websockets.address", value<std::string>()->default_value("127.0.0.1"), "address to bind websocket server on") ("websockets.address", value<std::string>()->default_value("127.0.0.1"), "Address to bind websocket server on")
("websockets.port", value<uint16_t>()->default_value(7666), "port to bind websocket server on"); ("websockets.port", value<uint16_t>()->default_value(7666), "Port to bind websocket server on")
;
options_description exploratory("Exploratory Options"); options_description exploratory("Exploratory Options");
exploratory.add_options() exploratory.add_options()
("exploratory.inbound.length", value<int>()->default_value(2), "Exploratory inbound tunnel length") ("exploratory.inbound.length", value<int>()->default_value(2), "Exploratory inbound tunnel length")
("exploratory.outbound.length", value<int>()->default_value(2), "Exploratory outbound tunnel length") ("exploratory.outbound.length", value<int>()->default_value(2), "Exploratory outbound tunnel length")
("exploratory.inbound.quantity", value<int>()->default_value(3), "Exploratory inbound tunnels quantity") ("exploratory.inbound.quantity", value<int>()->default_value(3), "Exploratory inbound tunnels quantity")
("exploratory.outbound.quantity", value<int>()->default_value(3), "Exploratory outbound tunnels quantity"); ("exploratory.outbound.quantity", value<int>()->default_value(3), "Exploratory outbound tunnels quantity")
;
m_OptionsDesc m_OptionsDesc
.add(general) .add(general)
.add(limits) .add(limits)
.add(httpserver) .add(httpserver)
.add(httpproxy) .add(httpproxy)
.add(socksproxy) .add(socksproxy)
.add(sam) .add(sam)
.add(bob) .add(bob)
.add(i2cp) .add(i2cp)
.add(i2pcontrol) .add(i2pcontrol)
.add(upnp) .add(upnp)
.add(precomputation) .add(precomputation)
.add(reseed) .add(reseed)
.add(addressbook) .add(addressbook)
.add(trust) .add(trust)
.add(websocket) .add(websocket)
.add(exploratory) .add(exploratory)
; ;
} }
void ParseCmdline(int argc, char* argv[], bool ignoreUnknown) void ParseCmdline(int argc, char* argv[], bool ignoreUnknown)
{
try
{ {
auto style = boost::program_options::command_line_style::unix_style try
| boost::program_options::command_line_style::allow_long_disguise; {
style &= ~ boost::program_options::command_line_style::allow_guessing; auto style = boost::program_options::command_line_style::unix_style
if (ignoreUnknown) | boost::program_options::command_line_style::allow_long_disguise;
store(command_line_parser(argc, argv).options(m_OptionsDesc).style (style).allow_unregistered().run(), m_Options); style &= ~ boost::program_options::command_line_style::allow_guessing;
else if (ignoreUnknown)
store(parse_command_line(argc, argv, m_OptionsDesc, style), m_Options); store(command_line_parser(argc, argv).options(m_OptionsDesc).style (style).allow_unregistered().run(), m_Options);
} else
catch (boost::program_options::error& e) store(parse_command_line(argc, argv, m_OptionsDesc, style), m_Options);
}
catch (boost::program_options::error& e)
{
std::cerr << "args: " << e.what() << std::endl;
exit(EXIT_FAILURE);
}
if (!ignoreUnknown && (m_Options.count("help") || m_Options.count("h")))
{
std::cout << "i2pd version " << I2PD_VERSION << " (" << I2P_VERSION << ")" << std::endl;
std::cout << m_OptionsDesc;
exit(EXIT_SUCCESS);
}
}
void ParseConfig(const std::string& path)
{ {
std::cerr << "args: " << e.what() << std::endl; if (path == "") return;
exit(EXIT_FAILURE);
}
if (!ignoreUnknown && (m_Options.count("help") || m_Options.count("h"))) std::ifstream config(path, std::ios::in);
if (!config.is_open())
{
std::cerr << "missing/unreadable config file: " << path << std::endl;
exit(EXIT_FAILURE);
}
try
{
store(boost::program_options::parse_config_file(config, m_OptionsDesc), m_Options);
}
catch (boost::program_options::error& e)
{
std::cerr << e.what() << std::endl;
exit(EXIT_FAILURE);
};
}
void Finalize()
{ {
std::cout << "i2pd version " << I2PD_VERSION << " (" << I2P_VERSION << ")" << std::endl; notify(m_Options);
std::cout << m_OptionsDesc; }
exit(EXIT_SUCCESS);
}
}
void ParseConfig(const std::string& path) { bool IsDefault(const char *name)
if (path == "") return;
std::ifstream config(path, std::ios::in);
if (!config.is_open())
{ {
std::cerr << "missing/unreadable config file: " << path << std::endl; if (!m_Options.count(name))
exit(EXIT_FAILURE); throw "try to check non-existent option";
}
try if (m_Options[name].defaulted())
return true;
return false;
}
bool GetOptionAsAny(const char *name, boost::any& value)
{ {
store(boost::program_options::parse_config_file(config, m_OptionsDesc), m_Options); if (!m_Options.count(name))
} return false;
catch (boost::program_options::error& e) value = m_Options[name];
return true;
}
bool GetOptionAsAny(const std::string& name, boost::any& value)
{ {
std::cerr << e.what() << std::endl; return GetOptionAsAny (name.c_str (), value);
exit(EXIT_FAILURE); }
};
}
void Finalize() {
notify(m_Options);
}
bool IsDefault(const char *name) {
if (!m_Options.count(name))
throw "try to check non-existent option";
if (m_Options[name].defaulted())
return true;
return false;
}
bool GetOptionAsAny(const char *name, boost::any& value) {
if (!m_Options.count(name))
return false;
value = m_Options[name];
return true;
}
bool GetOptionAsAny(const std::string& name, boost::any& value)
{
return GetOptionAsAny (name.c_str (), value);
}
} // namespace config } // namespace config
} // namespace i2p } // namespace i2p

View File

@ -694,7 +694,7 @@ namespace client
ClientDestination::ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map<std::string, std::string> * params): ClientDestination::ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map<std::string, std::string> * params):
LeaseSetDestination (isPublic, params), LeaseSetDestination (isPublic, params),
m_Keys (keys), m_DatagramDestination (nullptr), m_Keys (keys), m_DatagramDestination (nullptr), m_RefCounter (0),
m_ReadyChecker(GetService()) m_ReadyChecker(GetService())
{ {
if (isPublic) if (isPublic)

View File

@ -181,6 +181,11 @@ namespace client
const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; }; const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; };
void Sign (const uint8_t * buf, int len, uint8_t * signature) const { m_Keys.Sign (buf, len, signature); }; void Sign (const uint8_t * buf, int len, uint8_t * signature) const { m_Keys.Sign (buf, len, signature); };
// ref counter
int Acquire () { return ++m_RefCounter; };
int Release () { return --m_RefCounter; };
int GetRefCounter () const { return m_RefCounter; };
// streaming // streaming
std::shared_ptr<i2p::stream::StreamingDestination> CreateStreamingDestination (int port, bool gzip = true); // additional std::shared_ptr<i2p::stream::StreamingDestination> CreateStreamingDestination (int port, bool gzip = true); // additional
std::shared_ptr<i2p::stream::StreamingDestination> GetStreamingDestination (int port = 0) const; std::shared_ptr<i2p::stream::StreamingDestination> GetStreamingDestination (int port = 0) const;
@ -223,7 +228,8 @@ namespace client
std::shared_ptr<i2p::stream::StreamingDestination> m_StreamingDestination; // default std::shared_ptr<i2p::stream::StreamingDestination> m_StreamingDestination; // default
std::map<uint16_t, std::shared_ptr<i2p::stream::StreamingDestination> > m_StreamingDestinationsByPorts; std::map<uint16_t, std::shared_ptr<i2p::stream::StreamingDestination> > m_StreamingDestinationsByPorts;
i2p::datagram::DatagramDestination * m_DatagramDestination; i2p::datagram::DatagramDestination * m_DatagramDestination;
int m_RefCounter; // how many clients(tunnels) use this destination
boost::asio::deadline_timer m_ReadyChecker; boost::asio::deadline_timer m_ReadyChecker;

View File

@ -293,11 +293,11 @@ namespace http {
} }
} }
void HTTPReq::RemoveHeader (const std::string& name) void HTTPReq::RemoveHeader (const std::string& name, const std::string& exempt)
{ {
for (auto it = headers.begin (); it != headers.end ();) for (auto it = headers.begin (); it != headers.end ();)
{ {
if (!it->first.compare(0, name.length (), name)) if (!it->first.compare(0, name.length (), name) && it->first != exempt)
it = headers.erase (it); it = headers.erase (it);
else else
it++; it++;

View File

@ -16,14 +16,17 @@
#include <string> #include <string>
#include <vector> #include <vector>
namespace i2p { namespace i2p
namespace http { {
namespace http
{
const char CRLF[] = "\r\n"; /**< HTTP line terminator */ const char CRLF[] = "\r\n"; /**< HTTP line terminator */
const char HTTP_EOH[] = "\r\n\r\n"; /**< HTTP end-of-headers mark */ const char HTTP_EOH[] = "\r\n\r\n"; /**< HTTP end-of-headers mark */
extern const std::vector<std::string> HTTP_METHODS; /**< list of valid HTTP methods */ extern const std::vector<std::string> HTTP_METHODS; /**< list of valid HTTP methods */
extern const std::vector<std::string> HTTP_VERSIONS; /**< list of valid HTTP versions */ extern const std::vector<std::string> HTTP_VERSIONS; /**< list of valid HTTP versions */
struct URL { struct URL
{
std::string schema; std::string schema;
std::string user; std::string user;
std::string pass; std::string pass;
@ -90,7 +93,8 @@ namespace http {
void AddHeader (const std::string& name, const std::string& value); void AddHeader (const std::string& name, const std::string& value);
void UpdateHeader (const std::string& name, const std::string& value); void UpdateHeader (const std::string& name, const std::string& value);
void RemoveHeader (const std::string& name); void RemoveHeader (const std::string& name, const std::string& exempt); // remove all headers starting with name, but exempt
void RemoveHeader (const std::string& name) { RemoveHeader (name, ""); };
std::string GetHeader (const std::string& name) const; std::string GetHeader (const std::string& name) const;
}; };

View File

@ -13,7 +13,7 @@ namespace data
{ {
// copy public and signing keys together // copy public and signing keys together
memcpy (publicKey, keys.publicKey, sizeof (publicKey) + sizeof (signingKey)); memcpy (publicKey, keys.publicKey, sizeof (publicKey) + sizeof (signingKey));
memset (certificate, 0, sizeof (certificate)); memset (certificate, 0, sizeof (certificate));
return *this; return *this;
} }
@ -32,8 +32,8 @@ namespace data
IdentHash hash; IdentHash hash;
SHA256(publicKey, DEFAULT_IDENTITY_SIZE, hash); SHA256(publicKey, DEFAULT_IDENTITY_SIZE, hash);
return hash; return hash;
} }
IdentityEx::IdentityEx (): IdentityEx::IdentityEx ():
m_IsVerifierCreated (false), m_ExtendedLen (0), m_ExtendedBuffer (nullptr) m_IsVerifierCreated (false), m_ExtendedLen (0), m_ExtendedBuffer (nullptr)
{ {
@ -41,7 +41,7 @@ namespace data
IdentityEx::IdentityEx(const uint8_t * publicKey, const uint8_t * signingKey, SigningKeyType type): IdentityEx::IdentityEx(const uint8_t * publicKey, const uint8_t * signingKey, SigningKeyType type):
m_IsVerifierCreated (false) m_IsVerifierCreated (false)
{ {
memcpy (m_StandardIdentity.publicKey, publicKey, sizeof (m_StandardIdentity.publicKey)); memcpy (m_StandardIdentity.publicKey, publicKey, sizeof (m_StandardIdentity.publicKey));
if (type != SIGNING_KEY_TYPE_DSA_SHA1) if (type != SIGNING_KEY_TYPE_DSA_SHA1)
{ {
@ -50,19 +50,19 @@ namespace data
switch (type) switch (type)
{ {
case SIGNING_KEY_TYPE_ECDSA_SHA256_P256: case SIGNING_KEY_TYPE_ECDSA_SHA256_P256:
{ {
size_t padding = 128 - i2p::crypto::ECDSAP256_KEY_LENGTH; // 64 = 128 - 64 size_t padding = 128 - i2p::crypto::ECDSAP256_KEY_LENGTH; // 64 = 128 - 64
RAND_bytes (m_StandardIdentity.signingKey, padding); RAND_bytes (m_StandardIdentity.signingKey, padding);
memcpy (m_StandardIdentity.signingKey + padding, signingKey, i2p::crypto::ECDSAP256_KEY_LENGTH); memcpy (m_StandardIdentity.signingKey + padding, signingKey, i2p::crypto::ECDSAP256_KEY_LENGTH);
break; break;
} }
case SIGNING_KEY_TYPE_ECDSA_SHA384_P384: case SIGNING_KEY_TYPE_ECDSA_SHA384_P384:
{ {
size_t padding = 128 - i2p::crypto::ECDSAP384_KEY_LENGTH; // 32 = 128 - 96 size_t padding = 128 - i2p::crypto::ECDSAP384_KEY_LENGTH; // 32 = 128 - 96
RAND_bytes (m_StandardIdentity.signingKey, padding); RAND_bytes (m_StandardIdentity.signingKey, padding);
memcpy (m_StandardIdentity.signingKey + padding, signingKey, i2p::crypto::ECDSAP384_KEY_LENGTH); memcpy (m_StandardIdentity.signingKey + padding, signingKey, i2p::crypto::ECDSAP384_KEY_LENGTH);
break; break;
} }
case SIGNING_KEY_TYPE_ECDSA_SHA512_P521: case SIGNING_KEY_TYPE_ECDSA_SHA512_P521:
{ {
memcpy (m_StandardIdentity.signingKey, signingKey, 128); memcpy (m_StandardIdentity.signingKey, signingKey, 128);
@ -70,7 +70,7 @@ namespace data
excessBuf = new uint8_t[excessLen]; excessBuf = new uint8_t[excessLen];
memcpy (excessBuf, signingKey + 128, excessLen); memcpy (excessBuf, signingKey + 128, excessLen);
break; break;
} }
case SIGNING_KEY_TYPE_RSA_SHA256_2048: case SIGNING_KEY_TYPE_RSA_SHA256_2048:
{ {
memcpy (m_StandardIdentity.signingKey, signingKey, 128); memcpy (m_StandardIdentity.signingKey, signingKey, 128);
@ -78,7 +78,7 @@ namespace data
excessBuf = new uint8_t[excessLen]; excessBuf = new uint8_t[excessLen];
memcpy (excessBuf, signingKey + 128, excessLen); memcpy (excessBuf, signingKey + 128, excessLen);
break; break;
} }
case SIGNING_KEY_TYPE_RSA_SHA384_3072: case SIGNING_KEY_TYPE_RSA_SHA384_3072:
{ {
memcpy (m_StandardIdentity.signingKey, signingKey, 128); memcpy (m_StandardIdentity.signingKey, signingKey, 128);
@ -86,7 +86,7 @@ namespace data
excessBuf = new uint8_t[excessLen]; excessBuf = new uint8_t[excessLen];
memcpy (excessBuf, signingKey + 128, excessLen); memcpy (excessBuf, signingKey + 128, excessLen);
break; break;
} }
case SIGNING_KEY_TYPE_RSA_SHA512_4096: case SIGNING_KEY_TYPE_RSA_SHA512_4096:
{ {
memcpy (m_StandardIdentity.signingKey, signingKey, 128); memcpy (m_StandardIdentity.signingKey, signingKey, 128);
@ -94,17 +94,17 @@ namespace data
excessBuf = new uint8_t[excessLen]; excessBuf = new uint8_t[excessLen];
memcpy (excessBuf, signingKey + 128, excessLen); memcpy (excessBuf, signingKey + 128, excessLen);
break; break;
} }
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519: case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
{ {
size_t padding = 128 - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; // 96 = 128 - 32 size_t padding = 128 - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; // 96 = 128 - 32
RAND_bytes (m_StandardIdentity.signingKey, padding); RAND_bytes (m_StandardIdentity.signingKey, padding);
memcpy (m_StandardIdentity.signingKey + padding, signingKey, i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH); memcpy (m_StandardIdentity.signingKey + padding, signingKey, i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH);
break; break;
} }
case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256: case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256:
case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256_TEST: case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256_TEST:
{ {
// 256 // 256
size_t padding = 128 - i2p::crypto::GOSTR3410_256_PUBLIC_KEY_LENGTH; // 64 = 128 - 64 size_t padding = 128 - i2p::crypto::GOSTR3410_256_PUBLIC_KEY_LENGTH; // 64 = 128 - 64
RAND_bytes (m_StandardIdentity.signingKey, padding); RAND_bytes (m_StandardIdentity.signingKey, padding);
@ -112,20 +112,20 @@ namespace data
break; break;
} }
case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512: case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512:
case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512_TEST: case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512_TEST:
{ {
// 512 // 512
// no padding, key length is 128 // no padding, key length is 128
memcpy (m_StandardIdentity.signingKey, signingKey, i2p::crypto::GOSTR3410_512_PUBLIC_KEY_LENGTH); memcpy (m_StandardIdentity.signingKey, signingKey, i2p::crypto::GOSTR3410_512_PUBLIC_KEY_LENGTH);
break; break;
} }
default: default:
LogPrint (eLogError, "Identity: Signing key type ", (int)type, " is not supported"); LogPrint (eLogError, "Identity: Signing key type ", (int)type, " is not supported");
} }
m_ExtendedLen = 4 + excessLen; // 4 bytes extra + excess length m_ExtendedLen = 4 + excessLen; // 4 bytes extra + excess length
// fill certificate // fill certificate
m_StandardIdentity.certificate[0] = CERTIFICATE_TYPE_KEY; m_StandardIdentity.certificate[0] = CERTIFICATE_TYPE_KEY;
htobe16buf (m_StandardIdentity.certificate + 1, m_ExtendedLen); htobe16buf (m_StandardIdentity.certificate + 1, m_ExtendedLen);
// fill extended buffer // fill extended buffer
m_ExtendedBuffer = new uint8_t[m_ExtendedLen]; m_ExtendedBuffer = new uint8_t[m_ExtendedLen];
htobe16buf (m_ExtendedBuffer, type); htobe16buf (m_ExtendedBuffer, type);
@ -134,12 +134,9 @@ namespace data
{ {
memcpy (m_ExtendedBuffer + 4, excessBuf, excessLen); memcpy (m_ExtendedBuffer + 4, excessBuf, excessLen);
delete[] excessBuf; delete[] excessBuf;
} }
// calculate ident hash // calculate ident hash
uint8_t * buf = new uint8_t[GetFullLen ()]; RecalculateIdentHash();
ToBuffer (buf, GetFullLen ());
SHA256(buf, GetFullLen (), m_IdentHash);
delete[] buf;
} }
else // DSA-SHA1 else // DSA-SHA1
{ {
@ -148,10 +145,22 @@ namespace data
m_IdentHash = m_StandardIdentity.Hash (); m_IdentHash = m_StandardIdentity.Hash ();
m_ExtendedLen = 0; m_ExtendedLen = 0;
m_ExtendedBuffer = nullptr; m_ExtendedBuffer = nullptr;
} }
CreateVerifier (); CreateVerifier ();
} }
void IdentityEx::RecalculateIdentHash(uint8_t * buf)
{
bool dofree = buf == nullptr;
size_t sz = GetFullLen();
if(!buf)
buf = new uint8_t[sz];
ToBuffer (buf, sz);
SHA256(buf, sz, m_IdentHash);
if(dofree)
delete[] buf;
}
IdentityEx::IdentityEx (const uint8_t * buf, size_t len): IdentityEx::IdentityEx (const uint8_t * buf, size_t len):
m_IsVerifierCreated (false), m_ExtendedLen (0), m_ExtendedBuffer (nullptr) m_IsVerifierCreated (false), m_ExtendedLen (0), m_ExtendedBuffer (nullptr)
{ {
@ -162,62 +171,62 @@ namespace data
m_IsVerifierCreated (false), m_ExtendedLen (0), m_ExtendedBuffer (nullptr) m_IsVerifierCreated (false), m_ExtendedLen (0), m_ExtendedBuffer (nullptr)
{ {
*this = other; *this = other;
} }
IdentityEx::IdentityEx (const Identity& standard): IdentityEx::IdentityEx (const Identity& standard):
m_IsVerifierCreated (false), m_ExtendedLen (0), m_ExtendedBuffer (nullptr) m_IsVerifierCreated (false), m_ExtendedLen (0), m_ExtendedBuffer (nullptr)
{ {
*this = standard; *this = standard;
} }
IdentityEx::~IdentityEx () IdentityEx::~IdentityEx ()
{ {
delete[] m_ExtendedBuffer; delete[] m_ExtendedBuffer;
} }
IdentityEx& IdentityEx::operator=(const IdentityEx& other) IdentityEx& IdentityEx::operator=(const IdentityEx& other)
{ {
memcpy (&m_StandardIdentity, &other.m_StandardIdentity, DEFAULT_IDENTITY_SIZE); memcpy (&m_StandardIdentity, &other.m_StandardIdentity, DEFAULT_IDENTITY_SIZE);
m_IdentHash = other.m_IdentHash; m_IdentHash = other.m_IdentHash;
delete[] m_ExtendedBuffer; delete[] m_ExtendedBuffer;
m_ExtendedLen = other.m_ExtendedLen; m_ExtendedLen = other.m_ExtendedLen;
if (m_ExtendedLen > 0) if (m_ExtendedLen > 0)
{ {
m_ExtendedBuffer = new uint8_t[m_ExtendedLen]; m_ExtendedBuffer = new uint8_t[m_ExtendedLen];
memcpy (m_ExtendedBuffer, other.m_ExtendedBuffer, m_ExtendedLen); memcpy (m_ExtendedBuffer, other.m_ExtendedBuffer, m_ExtendedLen);
} }
else else
m_ExtendedBuffer = nullptr; m_ExtendedBuffer = nullptr;
m_Verifier = nullptr; m_Verifier = nullptr;
m_IsVerifierCreated = false; m_IsVerifierCreated = false;
return *this; return *this;
} }
IdentityEx& IdentityEx::operator=(const Identity& standard) IdentityEx& IdentityEx::operator=(const Identity& standard)
{ {
m_StandardIdentity = standard; m_StandardIdentity = standard;
m_IdentHash = m_StandardIdentity.Hash (); m_IdentHash = m_StandardIdentity.Hash ();
delete[] m_ExtendedBuffer; delete[] m_ExtendedBuffer;
m_ExtendedBuffer = nullptr; m_ExtendedBuffer = nullptr;
m_ExtendedLen = 0; m_ExtendedLen = 0;
m_Verifier = nullptr; m_Verifier = nullptr;
m_IsVerifierCreated = false; m_IsVerifierCreated = false;
return *this; return *this;
} }
size_t IdentityEx::FromBuffer (const uint8_t * buf, size_t len) size_t IdentityEx::FromBuffer (const uint8_t * buf, size_t len)
{ {
if (len < DEFAULT_IDENTITY_SIZE) if (len < DEFAULT_IDENTITY_SIZE)
{ {
LogPrint (eLogError, "Identity: buffer length ", len, " is too small"); LogPrint (eLogError, "Identity: buffer length ", len, " is too small");
return 0; return 0;
} }
memcpy (&m_StandardIdentity, buf, DEFAULT_IDENTITY_SIZE); memcpy (&m_StandardIdentity, buf, DEFAULT_IDENTITY_SIZE);
if(m_ExtendedBuffer) delete[] m_ExtendedBuffer; if(m_ExtendedBuffer) delete[] m_ExtendedBuffer;
@ -227,28 +236,28 @@ namespace data
if (m_ExtendedLen) if (m_ExtendedLen)
{ {
if (m_ExtendedLen + DEFAULT_IDENTITY_SIZE <= len) if (m_ExtendedLen + DEFAULT_IDENTITY_SIZE <= len)
{ {
m_ExtendedBuffer = new uint8_t[m_ExtendedLen]; m_ExtendedBuffer = new uint8_t[m_ExtendedLen];
memcpy (m_ExtendedBuffer, buf + DEFAULT_IDENTITY_SIZE, m_ExtendedLen); memcpy (m_ExtendedBuffer, buf + DEFAULT_IDENTITY_SIZE, m_ExtendedLen);
} }
else else
{ {
LogPrint (eLogError, "Identity: Certificate length ", m_ExtendedLen, " exceeds buffer length ", len - DEFAULT_IDENTITY_SIZE); LogPrint (eLogError, "Identity: Certificate length ", m_ExtendedLen, " exceeds buffer length ", len - DEFAULT_IDENTITY_SIZE);
m_ExtendedLen = 0; m_ExtendedLen = 0;
return 0; return 0;
} }
} }
else else
{ {
m_ExtendedLen = 0; m_ExtendedLen = 0;
m_ExtendedBuffer = nullptr; m_ExtendedBuffer = nullptr;
} }
SHA256(buf, GetFullLen (), m_IdentHash); SHA256(buf, GetFullLen (), m_IdentHash);
m_Verifier = nullptr; m_Verifier = nullptr;
return GetFullLen (); return GetFullLen ();
} }
size_t IdentityEx::ToBuffer (uint8_t * buf, size_t len) const size_t IdentityEx::ToBuffer (uint8_t * buf, size_t len) const
{ {
@ -266,8 +275,8 @@ namespace data
std::vector<uint8_t> buf(slen); // binary data can't exceed base64 std::vector<uint8_t> buf(slen); // binary data can't exceed base64
const size_t len = Base64ToByteStream (s.c_str(), slen, buf.data(), slen); const size_t len = Base64ToByteStream (s.c_str(), slen, buf.data(), slen);
return FromBuffer (buf.data(), len); return FromBuffer (buf.data(), len);
} }
std::string IdentityEx::ToBase64 () const std::string IdentityEx::ToBase64 () const
{ {
const size_t bufLen = GetFullLen(); const size_t bufLen = GetFullLen();
@ -278,53 +287,53 @@ namespace data
size_t l1 = i2p::data::ByteStreamToBase64 (buf.data(), l, str.data(), strLen); size_t l1 = i2p::data::ByteStreamToBase64 (buf.data(), l, str.data(), strLen);
return std::string (str.data(), l1); return std::string (str.data(), l1);
} }
size_t IdentityEx::GetSigningPublicKeyLen () const size_t IdentityEx::GetSigningPublicKeyLen () const
{ {
if (!m_Verifier) CreateVerifier (); if (!m_Verifier) CreateVerifier ();
if (m_Verifier) if (m_Verifier)
return m_Verifier->GetPublicKeyLen (); return m_Verifier->GetPublicKeyLen ();
return 128; return 128;
} }
size_t IdentityEx::GetSigningPrivateKeyLen () const size_t IdentityEx::GetSigningPrivateKeyLen () const
{ {
if (!m_Verifier) CreateVerifier (); if (!m_Verifier) CreateVerifier ();
if (m_Verifier) if (m_Verifier)
return m_Verifier->GetPrivateKeyLen (); return m_Verifier->GetPrivateKeyLen ();
return GetSignatureLen ()/2; return GetSignatureLen ()/2;
} }
size_t IdentityEx::GetSignatureLen () const size_t IdentityEx::GetSignatureLen () const
{ {
if (!m_Verifier) CreateVerifier (); if (!m_Verifier) CreateVerifier ();
if (m_Verifier) if (m_Verifier)
return m_Verifier->GetSignatureLen (); return m_Verifier->GetSignatureLen ();
return i2p::crypto::DSA_SIGNATURE_LENGTH; return i2p::crypto::DSA_SIGNATURE_LENGTH;
} }
bool IdentityEx::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const bool IdentityEx::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const
{ {
if (!m_Verifier) CreateVerifier (); if (!m_Verifier) CreateVerifier ();
if (m_Verifier) if (m_Verifier)
return m_Verifier->Verify (buf, len, signature); return m_Verifier->Verify (buf, len, signature);
return false; return false;
} }
SigningKeyType IdentityEx::GetSigningKeyType () const SigningKeyType IdentityEx::GetSigningKeyType () const
{ {
if (m_StandardIdentity.certificate[0] == CERTIFICATE_TYPE_KEY && m_ExtendedLen >= 2) if (m_StandardIdentity.certificate[0] == CERTIFICATE_TYPE_KEY && m_ExtendedLen >= 2)
return bufbe16toh (m_ExtendedBuffer); // signing key return bufbe16toh (m_ExtendedBuffer); // signing key
return SIGNING_KEY_TYPE_DSA_SHA1; return SIGNING_KEY_TYPE_DSA_SHA1;
} }
CryptoKeyType IdentityEx::GetCryptoKeyType () const CryptoKeyType IdentityEx::GetCryptoKeyType () const
{ {
if (m_StandardIdentity.certificate[0] == CERTIFICATE_TYPE_KEY && m_ExtendedLen >= 4) if (m_StandardIdentity.certificate[0] == CERTIFICATE_TYPE_KEY && m_ExtendedLen >= 4)
return bufbe16toh (m_ExtendedBuffer + 2); // crypto key return bufbe16toh (m_ExtendedBuffer + 2); // crypto key
return CRYPTO_KEY_TYPE_ELGAMAL; return CRYPTO_KEY_TYPE_ELGAMAL;
} }
void IdentityEx::CreateVerifier () const void IdentityEx::CreateVerifier () const
{ {
if (m_Verifier) return; // don't create again if (m_Verifier) return; // don't create again
auto keyType = GetSigningKeyType (); auto keyType = GetSigningKeyType ();
@ -334,77 +343,77 @@ namespace data
UpdateVerifier (new i2p::crypto::DSAVerifier (m_StandardIdentity.signingKey)); UpdateVerifier (new i2p::crypto::DSAVerifier (m_StandardIdentity.signingKey));
break; break;
case SIGNING_KEY_TYPE_ECDSA_SHA256_P256: case SIGNING_KEY_TYPE_ECDSA_SHA256_P256:
{ {
size_t padding = 128 - i2p::crypto::ECDSAP256_KEY_LENGTH; // 64 = 128 - 64 size_t padding = 128 - i2p::crypto::ECDSAP256_KEY_LENGTH; // 64 = 128 - 64
UpdateVerifier (new i2p::crypto::ECDSAP256Verifier (m_StandardIdentity.signingKey + padding)); UpdateVerifier (new i2p::crypto::ECDSAP256Verifier (m_StandardIdentity.signingKey + padding));
break; break;
} }
case SIGNING_KEY_TYPE_ECDSA_SHA384_P384: case SIGNING_KEY_TYPE_ECDSA_SHA384_P384:
{ {
size_t padding = 128 - i2p::crypto::ECDSAP384_KEY_LENGTH; // 32 = 128 - 96 size_t padding = 128 - i2p::crypto::ECDSAP384_KEY_LENGTH; // 32 = 128 - 96
UpdateVerifier (new i2p::crypto::ECDSAP384Verifier (m_StandardIdentity.signingKey + padding)); UpdateVerifier (new i2p::crypto::ECDSAP384Verifier (m_StandardIdentity.signingKey + padding));
break; break;
} }
case SIGNING_KEY_TYPE_ECDSA_SHA512_P521: case SIGNING_KEY_TYPE_ECDSA_SHA512_P521:
{ {
uint8_t signingKey[i2p::crypto::ECDSAP521_KEY_LENGTH]; uint8_t signingKey[i2p::crypto::ECDSAP521_KEY_LENGTH];
memcpy (signingKey, m_StandardIdentity.signingKey, 128); memcpy (signingKey, m_StandardIdentity.signingKey, 128);
size_t excessLen = i2p::crypto::ECDSAP521_KEY_LENGTH - 128; // 4 = 132- 128 size_t excessLen = i2p::crypto::ECDSAP521_KEY_LENGTH - 128; // 4 = 132- 128
memcpy (signingKey + 128, m_ExtendedBuffer + 4, excessLen); // right after signing and crypto key types memcpy (signingKey + 128, m_ExtendedBuffer + 4, excessLen); // right after signing and crypto key types
UpdateVerifier (new i2p::crypto::ECDSAP521Verifier (signingKey)); UpdateVerifier (new i2p::crypto::ECDSAP521Verifier (signingKey));
break; break;
} }
case SIGNING_KEY_TYPE_RSA_SHA256_2048: case SIGNING_KEY_TYPE_RSA_SHA256_2048:
{ {
uint8_t signingKey[i2p::crypto::RSASHA2562048_KEY_LENGTH]; uint8_t signingKey[i2p::crypto::RSASHA2562048_KEY_LENGTH];
memcpy (signingKey, m_StandardIdentity.signingKey, 128); memcpy (signingKey, m_StandardIdentity.signingKey, 128);
size_t excessLen = i2p::crypto::RSASHA2562048_KEY_LENGTH - 128; // 128 = 256- 128 size_t excessLen = i2p::crypto::RSASHA2562048_KEY_LENGTH - 128; // 128 = 256- 128
memcpy (signingKey + 128, m_ExtendedBuffer + 4, excessLen); // right after signing and crypto key types memcpy (signingKey + 128, m_ExtendedBuffer + 4, excessLen); // right after signing and crypto key types
UpdateVerifier (new i2p::crypto:: RSASHA2562048Verifier (signingKey)); UpdateVerifier (new i2p::crypto:: RSASHA2562048Verifier (signingKey));
break; break;
} }
case SIGNING_KEY_TYPE_RSA_SHA384_3072: case SIGNING_KEY_TYPE_RSA_SHA384_3072:
{ {
uint8_t signingKey[i2p::crypto::RSASHA3843072_KEY_LENGTH]; uint8_t signingKey[i2p::crypto::RSASHA3843072_KEY_LENGTH];
memcpy (signingKey, m_StandardIdentity.signingKey, 128); memcpy (signingKey, m_StandardIdentity.signingKey, 128);
size_t excessLen = i2p::crypto::RSASHA3843072_KEY_LENGTH - 128; // 256 = 384- 128 size_t excessLen = i2p::crypto::RSASHA3843072_KEY_LENGTH - 128; // 256 = 384- 128
memcpy (signingKey + 128, m_ExtendedBuffer + 4, excessLen); // right after signing and crypto key types memcpy (signingKey + 128, m_ExtendedBuffer + 4, excessLen); // right after signing and crypto key types
UpdateVerifier (new i2p::crypto:: RSASHA3843072Verifier (signingKey)); UpdateVerifier (new i2p::crypto:: RSASHA3843072Verifier (signingKey));
break; break;
} }
case SIGNING_KEY_TYPE_RSA_SHA512_4096: case SIGNING_KEY_TYPE_RSA_SHA512_4096:
{ {
uint8_t signingKey[i2p::crypto::RSASHA5124096_KEY_LENGTH]; uint8_t signingKey[i2p::crypto::RSASHA5124096_KEY_LENGTH];
memcpy (signingKey, m_StandardIdentity.signingKey, 128); memcpy (signingKey, m_StandardIdentity.signingKey, 128);
size_t excessLen = i2p::crypto::RSASHA5124096_KEY_LENGTH - 128; // 384 = 512- 128 size_t excessLen = i2p::crypto::RSASHA5124096_KEY_LENGTH - 128; // 384 = 512- 128
memcpy (signingKey + 128, m_ExtendedBuffer + 4, excessLen); // right after signing and crypto key types memcpy (signingKey + 128, m_ExtendedBuffer + 4, excessLen); // right after signing and crypto key types
UpdateVerifier (new i2p::crypto:: RSASHA5124096Verifier (signingKey)); UpdateVerifier (new i2p::crypto:: RSASHA5124096Verifier (signingKey));
break; break;
} }
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519: case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
{ {
size_t padding = 128 - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; // 96 = 128 - 32 size_t padding = 128 - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; // 96 = 128 - 32
UpdateVerifier (new i2p::crypto::EDDSA25519Verifier (m_StandardIdentity.signingKey + padding)); UpdateVerifier (new i2p::crypto::EDDSA25519Verifier (m_StandardIdentity.signingKey + padding));
break; break;
} }
case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256: case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256:
case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256_TEST: case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256_TEST:
{ {
size_t padding = 128 - i2p::crypto::GOSTR3410_256_PUBLIC_KEY_LENGTH; // 64 = 128 - 64 size_t padding = 128 - i2p::crypto::GOSTR3410_256_PUBLIC_KEY_LENGTH; // 64 = 128 - 64
UpdateVerifier (new i2p::crypto::GOSTR3410_256_Verifier (i2p::crypto::eGOSTR3410CryptoProA, m_StandardIdentity.signingKey + padding)); UpdateVerifier (new i2p::crypto::GOSTR3410_256_Verifier (i2p::crypto::eGOSTR3410CryptoProA, m_StandardIdentity.signingKey + padding));
break; break;
} }
case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512: case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512:
case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512_TEST: case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512_TEST:
{ {
// zero padding // zero padding
UpdateVerifier (new i2p::crypto::GOSTR3410_512_Verifier (i2p::crypto::eGOSTR3410TC26A512, m_StandardIdentity.signingKey)); UpdateVerifier (new i2p::crypto::GOSTR3410_512_Verifier (i2p::crypto::eGOSTR3410TC26A512, m_StandardIdentity.signingKey));
break; break;
} }
default: default:
LogPrint (eLogError, "Identity: Signing key type ", (int)keyType, " is not supported"); LogPrint (eLogError, "Identity: Signing key type ", (int)keyType, " is not supported");
} }
} }
void IdentityEx::UpdateVerifier (i2p::crypto::Verifier * verifier) const void IdentityEx::UpdateVerifier (i2p::crypto::Verifier * verifier) const
{ {
@ -418,29 +427,29 @@ namespace data
delete verifier; delete verifier;
int count = 0; int count = 0;
while (!m_Verifier && count < 500) // 5 seconds while (!m_Verifier && count < 500) // 5 seconds
{ {
std::this_thread::sleep_for (std::chrono::milliseconds(10)); std::this_thread::sleep_for (std::chrono::milliseconds(10));
count++; count++;
} }
if (!m_Verifier) if (!m_Verifier)
LogPrint (eLogError, "Identity: couldn't get verifier in 5 seconds"); LogPrint (eLogError, "Identity: couldn't get verifier in 5 seconds");
} }
} }
else else
delete verifier; delete verifier;
} }
void IdentityEx::DropVerifier () const void IdentityEx::DropVerifier () const
{ {
// TODO: potential race condition with Verify // TODO: potential race condition with Verify
m_IsVerifierCreated = false; m_IsVerifierCreated = false;
m_Verifier = nullptr; m_Verifier = nullptr;
} }
PrivateKeys& PrivateKeys::operator=(const Keys& keys) PrivateKeys& PrivateKeys::operator=(const Keys& keys)
{ {
m_Public = std::make_shared<IdentityEx>(Identity (keys)); m_Public = std::make_shared<IdentityEx>(Identity (keys));
memcpy (m_PrivateKey, keys.privateKey, 256); // 256 memcpy (m_PrivateKey, keys.privateKey, 256); // 256
memcpy (m_SigningPrivateKey, keys.signingPrivateKey, m_Public->GetSigningPrivateKeyLen ()); memcpy (m_SigningPrivateKey, keys.signingPrivateKey, m_Public->GetSigningPrivateKeyLen ());
m_Signer = nullptr; m_Signer = nullptr;
CreateSigner (); CreateSigner ();
@ -448,31 +457,31 @@ namespace data
} }
PrivateKeys& PrivateKeys::operator=(const PrivateKeys& other) PrivateKeys& PrivateKeys::operator=(const PrivateKeys& other)
{ {
m_Public = std::make_shared<IdentityEx>(*other.m_Public); m_Public = std::make_shared<IdentityEx>(*other.m_Public);
memcpy (m_PrivateKey, other.m_PrivateKey, 256); // 256 memcpy (m_PrivateKey, other.m_PrivateKey, 256); // 256
memcpy (m_SigningPrivateKey, other.m_SigningPrivateKey, m_Public->GetSigningPrivateKeyLen ()); memcpy (m_SigningPrivateKey, other.m_SigningPrivateKey, m_Public->GetSigningPrivateKeyLen ());
m_Signer = nullptr; m_Signer = nullptr;
CreateSigner (); CreateSigner ();
return *this; return *this;
} }
size_t PrivateKeys::FromBuffer (const uint8_t * buf, size_t len) size_t PrivateKeys::FromBuffer (const uint8_t * buf, size_t len)
{ {
m_Public = std::make_shared<IdentityEx>(); m_Public = std::make_shared<IdentityEx>();
size_t ret = m_Public->FromBuffer (buf, len); size_t ret = m_Public->FromBuffer (buf, len);
if (!ret || ret + 256 > len) return 0; // overflow if (!ret || ret + 256 > len) return 0; // overflow
memcpy (m_PrivateKey, buf + ret, 256); // private key always 256 memcpy (m_PrivateKey, buf + ret, 256); // private key always 256
ret += 256; ret += 256;
size_t signingPrivateKeySize = m_Public->GetSigningPrivateKeyLen (); size_t signingPrivateKeySize = m_Public->GetSigningPrivateKeyLen ();
if(signingPrivateKeySize + ret > len) return 0; // overflow if(signingPrivateKeySize + ret > len) return 0; // overflow
memcpy (m_SigningPrivateKey, buf + ret, signingPrivateKeySize); memcpy (m_SigningPrivateKey, buf + ret, signingPrivateKeySize);
ret += signingPrivateKeySize; ret += signingPrivateKeySize;
m_Signer = nullptr; m_Signer = nullptr;
CreateSigner (); CreateSigner ();
return ret; return ret;
} }
size_t PrivateKeys::ToBuffer (uint8_t * buf, size_t len) const size_t PrivateKeys::ToBuffer (uint8_t * buf, size_t len) const
{ {
size_t ret = m_Public->ToBuffer (buf, len); size_t ret = m_Public->ToBuffer (buf, len);
@ -480,10 +489,10 @@ namespace data
ret += 256; ret += 256;
size_t signingPrivateKeySize = m_Public->GetSigningPrivateKeyLen (); size_t signingPrivateKeySize = m_Public->GetSigningPrivateKeyLen ();
if(ret + signingPrivateKeySize > len) return 0; // overflow if(ret + signingPrivateKeySize > len) return 0; // overflow
memcpy (buf + ret, m_SigningPrivateKey, signingPrivateKeySize); memcpy (buf + ret, m_SigningPrivateKey, signingPrivateKeySize);
ret += signingPrivateKeySize; ret += signingPrivateKeySize;
return ret; return ret;
} }
size_t PrivateKeys::FromBase64(const std::string& s) size_t PrivateKeys::FromBase64(const std::string& s)
{ {
@ -492,8 +501,8 @@ namespace data
size_t ret = FromBuffer (buf, l); size_t ret = FromBuffer (buf, l);
delete[] buf; delete[] buf;
return ret; return ret;
} }
std::string PrivateKeys::ToBase64 () const std::string PrivateKeys::ToBase64 () const
{ {
uint8_t * buf = new uint8_t[GetFullLen ()]; uint8_t * buf = new uint8_t[GetFullLen ()];
@ -512,25 +521,25 @@ namespace data
if (!m_Signer) if (!m_Signer)
CreateSigner(); CreateSigner();
m_Signer->Sign (buf, len, signature); m_Signer->Sign (buf, len, signature);
} }
void PrivateKeys::CreateSigner () const void PrivateKeys::CreateSigner () const
{ {
if (m_Signer) return; if (m_Signer) return;
switch (m_Public->GetSigningKeyType ()) switch (m_Public->GetSigningKeyType ())
{ {
case SIGNING_KEY_TYPE_DSA_SHA1: case SIGNING_KEY_TYPE_DSA_SHA1:
m_Signer.reset (new i2p::crypto::DSASigner (m_SigningPrivateKey, m_Public->GetStandardIdentity ().signingKey)); m_Signer.reset (new i2p::crypto::DSASigner (m_SigningPrivateKey, m_Public->GetStandardIdentity ().signingKey));
break; break;
case SIGNING_KEY_TYPE_ECDSA_SHA256_P256: case SIGNING_KEY_TYPE_ECDSA_SHA256_P256:
m_Signer.reset (new i2p::crypto::ECDSAP256Signer (m_SigningPrivateKey)); m_Signer.reset (new i2p::crypto::ECDSAP256Signer (m_SigningPrivateKey));
break; break;
case SIGNING_KEY_TYPE_ECDSA_SHA384_P384: case SIGNING_KEY_TYPE_ECDSA_SHA384_P384:
m_Signer.reset (new i2p::crypto::ECDSAP384Signer (m_SigningPrivateKey)); m_Signer.reset (new i2p::crypto::ECDSAP384Signer (m_SigningPrivateKey));
break; break;
case SIGNING_KEY_TYPE_ECDSA_SHA512_P521: case SIGNING_KEY_TYPE_ECDSA_SHA512_P521:
m_Signer.reset (new i2p::crypto::ECDSAP521Signer (m_SigningPrivateKey)); m_Signer.reset (new i2p::crypto::ECDSAP521Signer (m_SigningPrivateKey));
break; break;
case SIGNING_KEY_TYPE_RSA_SHA256_2048: case SIGNING_KEY_TYPE_RSA_SHA256_2048:
m_Signer.reset (new i2p::crypto::RSASHA2562048Signer (m_SigningPrivateKey)); m_Signer.reset (new i2p::crypto::RSASHA2562048Signer (m_SigningPrivateKey));
break; break;
@ -539,65 +548,73 @@ namespace data
break; break;
case SIGNING_KEY_TYPE_RSA_SHA512_4096: case SIGNING_KEY_TYPE_RSA_SHA512_4096:
m_Signer.reset (new i2p::crypto::RSASHA5124096Signer (m_SigningPrivateKey)); m_Signer.reset (new i2p::crypto::RSASHA5124096Signer (m_SigningPrivateKey));
break; break;
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519: case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
m_Signer.reset (new i2p::crypto::EDDSA25519Signer (m_SigningPrivateKey, m_Public->GetStandardIdentity ().certificate - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH)); m_Signer.reset (new i2p::crypto::EDDSA25519Signer (m_SigningPrivateKey, m_Public->GetStandardIdentity ().certificate - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH));
break; break;
case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256: case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256:
case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256_TEST: case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256_TEST:
m_Signer.reset (new i2p::crypto::GOSTR3410_256_Signer (i2p::crypto::eGOSTR3410CryptoProA, m_SigningPrivateKey)); m_Signer.reset (new i2p::crypto::GOSTR3410_256_Signer (i2p::crypto::eGOSTR3410CryptoProA, m_SigningPrivateKey));
break; break;
case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512: case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512:
case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512_TEST: case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512_TEST:
m_Signer.reset (new i2p::crypto::GOSTR3410_512_Signer (i2p::crypto::eGOSTR3410TC26A512, m_SigningPrivateKey)); m_Signer.reset (new i2p::crypto::GOSTR3410_512_Signer (i2p::crypto::eGOSTR3410TC26A512, m_SigningPrivateKey));
break; break;
default: default:
LogPrint (eLogError, "Identity: Signing key type ", (int)m_Public->GetSigningKeyType (), " is not supported"); LogPrint (eLogError, "Identity: Signing key type ", (int)m_Public->GetSigningKeyType (), " is not supported");
} }
} }
uint8_t * PrivateKeys::GetPadding()
{
if(m_Public->GetSigningKeyType () == SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519)
return m_Public->GetEncryptionPublicKeyBuffer() + 256;
else
return nullptr; // TODO: implement me
}
PrivateKeys PrivateKeys::CreateRandomKeys (SigningKeyType type) PrivateKeys PrivateKeys::CreateRandomKeys (SigningKeyType type)
{ {
if (type != SIGNING_KEY_TYPE_DSA_SHA1) if (type != SIGNING_KEY_TYPE_DSA_SHA1)
{ {
PrivateKeys keys; PrivateKeys keys;
// signature // signature
uint8_t signingPublicKey[512]; // signing public key is 512 bytes max uint8_t signingPublicKey[512]; // signing public key is 512 bytes max
switch (type) switch (type)
{ {
case SIGNING_KEY_TYPE_ECDSA_SHA256_P256: case SIGNING_KEY_TYPE_ECDSA_SHA256_P256:
i2p::crypto::CreateECDSAP256RandomKeys (keys.m_SigningPrivateKey, signingPublicKey); i2p::crypto::CreateECDSAP256RandomKeys (keys.m_SigningPrivateKey, signingPublicKey);
break; break;
case SIGNING_KEY_TYPE_ECDSA_SHA384_P384: case SIGNING_KEY_TYPE_ECDSA_SHA384_P384:
i2p::crypto::CreateECDSAP384RandomKeys (keys.m_SigningPrivateKey, signingPublicKey); i2p::crypto::CreateECDSAP384RandomKeys (keys.m_SigningPrivateKey, signingPublicKey);
break; break;
case SIGNING_KEY_TYPE_ECDSA_SHA512_P521: case SIGNING_KEY_TYPE_ECDSA_SHA512_P521:
i2p::crypto::CreateECDSAP521RandomKeys (keys.m_SigningPrivateKey, signingPublicKey); i2p::crypto::CreateECDSAP521RandomKeys (keys.m_SigningPrivateKey, signingPublicKey);
break; break;
case SIGNING_KEY_TYPE_RSA_SHA256_2048: case SIGNING_KEY_TYPE_RSA_SHA256_2048:
i2p::crypto::CreateRSARandomKeys (i2p::crypto::RSASHA2562048_KEY_LENGTH, keys.m_SigningPrivateKey, signingPublicKey); i2p::crypto::CreateRSARandomKeys (i2p::crypto::RSASHA2562048_KEY_LENGTH, keys.m_SigningPrivateKey, signingPublicKey);
break; break;
case SIGNING_KEY_TYPE_RSA_SHA384_3072: case SIGNING_KEY_TYPE_RSA_SHA384_3072:
i2p::crypto::CreateRSARandomKeys (i2p::crypto::RSASHA3843072_KEY_LENGTH, keys.m_SigningPrivateKey, signingPublicKey); i2p::crypto::CreateRSARandomKeys (i2p::crypto::RSASHA3843072_KEY_LENGTH, keys.m_SigningPrivateKey, signingPublicKey);
break; break;
case SIGNING_KEY_TYPE_RSA_SHA512_4096: case SIGNING_KEY_TYPE_RSA_SHA512_4096:
i2p::crypto::CreateRSARandomKeys (i2p::crypto::RSASHA5124096_KEY_LENGTH, keys.m_SigningPrivateKey, signingPublicKey); i2p::crypto::CreateRSARandomKeys (i2p::crypto::RSASHA5124096_KEY_LENGTH, keys.m_SigningPrivateKey, signingPublicKey);
break; break;
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519: case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
i2p::crypto::CreateEDDSA25519RandomKeys (keys.m_SigningPrivateKey, signingPublicKey); i2p::crypto::CreateEDDSA25519RandomKeys (keys.m_SigningPrivateKey, signingPublicKey);
break; break;
case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256: case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256:
case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256_TEST: case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256_TEST:
i2p::crypto::CreateGOSTR3410RandomKeys (i2p::crypto::eGOSTR3410CryptoProA, keys.m_SigningPrivateKey, signingPublicKey); i2p::crypto::CreateGOSTR3410RandomKeys (i2p::crypto::eGOSTR3410CryptoProA, keys.m_SigningPrivateKey, signingPublicKey);
break; break;
case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512: case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512:
case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512_TEST: case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512_TEST:
i2p::crypto::CreateGOSTR3410RandomKeys (i2p::crypto::eGOSTR3410TC26A512, keys.m_SigningPrivateKey, signingPublicKey); i2p::crypto::CreateGOSTR3410RandomKeys (i2p::crypto::eGOSTR3410TC26A512, keys.m_SigningPrivateKey, signingPublicKey);
break; break;
default: default:
LogPrint (eLogError, "Identity: Signing key type ", (int)type, " is not supported. Create DSA-SHA1"); LogPrint (eLogError, "Identity: Signing key type ", (int)type, " is not supported. Create DSA-SHA1");
return PrivateKeys (i2p::data::CreateRandomKeys ()); // DSA-SHA1 return PrivateKeys (i2p::data::CreateRandomKeys ()); // DSA-SHA1
} }
// encryption // encryption
uint8_t publicKey[256]; uint8_t publicKey[256];
i2p::crypto::GenerateElGamalKeyPair (keys.m_PrivateKey, publicKey); i2p::crypto::GenerateElGamalKeyPair (keys.m_PrivateKey, publicKey);
@ -606,19 +623,19 @@ namespace data
keys.CreateSigner (); keys.CreateSigner ();
return keys; return keys;
} }
return PrivateKeys (i2p::data::CreateRandomKeys ()); // DSA-SHA1 return PrivateKeys (i2p::data::CreateRandomKeys ()); // DSA-SHA1
} }
Keys CreateRandomKeys () Keys CreateRandomKeys ()
{ {
Keys keys; Keys keys;
// encryption // encryption
i2p::crypto::GenerateElGamalKeyPair(keys.privateKey, keys.publicKey); i2p::crypto::GenerateElGamalKeyPair(keys.privateKey, keys.publicKey);
// signing // signing
i2p::crypto::CreateDSARandomKeys (keys.signingPrivateKey, keys.signingKey); i2p::crypto::CreateDSARandomKeys (keys.signingPrivateKey, keys.signingKey);
return keys; return keys;
} }
IdentHash CreateRoutingKey (const IdentHash& ident) IdentHash CreateRoutingKey (const IdentHash& ident)
{ {
@ -632,26 +649,26 @@ namespace data
#else #else
gmtime_r(&t, &tm); gmtime_r(&t, &tm);
sprintf((char *)(buf + 32), "%04i%02i%02i", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); sprintf((char *)(buf + 32), "%04i%02i%02i", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
#endif #endif
IdentHash key; IdentHash key;
SHA256(buf, 40, key); SHA256(buf, 40, key);
return key; return key;
} }
XORMetric operator^(const IdentHash& key1, const IdentHash& key2) XORMetric operator^(const IdentHash& key1, const IdentHash& key2)
{ {
XORMetric m; XORMetric m;
#if defined(__AVX__) // for AVX #if defined(__AVX__) // for AVX
__asm__ __asm__
( (
"vmovups %1, %%ymm0 \n" "vmovups %1, %%ymm0 \n"
"vmovups %2, %%ymm1 \n" "vmovups %2, %%ymm1 \n"
"vxorps %%ymm0, %%ymm1, %%ymm1 \n" "vxorps %%ymm0, %%ymm1, %%ymm1 \n"
"vmovups %%ymm1, %0 \n" "vmovups %%ymm1, %0 \n"
: "=m"(*m.metric) : "=m"(*m.metric)
: "m"(*key1), "m"(*key2) : "m"(*key1), "m"(*key2)
: "memory", "%xmm0", "%xmm1" // should be replaced by %ymm0/1 once supported by compiler : "memory", "%xmm0", "%xmm1" // should be replaced by %ymm0/1 once supported by compiler
); );
#else #else
const uint64_t * hash1 = key1.GetLL (), * hash2 = key2.GetLL (); const uint64_t * hash1 = key1.GetLL (), * hash2 = key2.GetLL ();
m.metric_ll[0] = hash1[0] ^ hash2[0]; m.metric_ll[0] = hash1[0] ^ hash2[0];
@ -661,6 +678,6 @@ namespace data
#endif #endif
return m; return m;
} }
} }
} }

View File

@ -14,9 +14,9 @@ namespace i2p
namespace data namespace data
{ {
typedef Tag<32> IdentHash; typedef Tag<32> IdentHash;
inline std::string GetIdentHashAbbreviation (const IdentHash& ident) inline std::string GetIdentHashAbbreviation (const IdentHash& ident)
{ {
return ident.ToBase64 ().substr (0, 4); return ident.ToBase64 ().substr (0, 4);
} }
struct Keys struct Keys
@ -26,12 +26,12 @@ namespace data
uint8_t publicKey[256]; uint8_t publicKey[256];
uint8_t signingKey[128]; uint8_t signingKey[128];
}; };
const uint8_t CERTIFICATE_TYPE_NULL = 0; const uint8_t CERTIFICATE_TYPE_NULL = 0;
const uint8_t CERTIFICATE_TYPE_HASHCASH = 1; const uint8_t CERTIFICATE_TYPE_HASHCASH = 1;
const uint8_t CERTIFICATE_TYPE_HIDDEN = 2; const uint8_t CERTIFICATE_TYPE_HIDDEN = 2;
const uint8_t CERTIFICATE_TYPE_SIGNED = 3; const uint8_t CERTIFICATE_TYPE_SIGNED = 3;
const uint8_t CERTIFICATE_TYPE_MULTIPLE = 4; const uint8_t CERTIFICATE_TYPE_MULTIPLE = 4;
const uint8_t CERTIFICATE_TYPE_KEY = 5; const uint8_t CERTIFICATE_TYPE_KEY = 5;
struct Identity struct Identity
@ -48,9 +48,9 @@ namespace data
}; };
Keys CreateRandomKeys (); Keys CreateRandomKeys ();
const size_t DEFAULT_IDENTITY_SIZE = sizeof (Identity); // 387 bytes const size_t DEFAULT_IDENTITY_SIZE = sizeof (Identity); // 387 bytes
const uint16_t CRYPTO_KEY_TYPE_ELGAMAL = 0; const uint16_t CRYPTO_KEY_TYPE_ELGAMAL = 0;
const uint16_t SIGNING_KEY_TYPE_DSA_SHA1 = 0; const uint16_t SIGNING_KEY_TYPE_DSA_SHA1 = 0;
const uint16_t SIGNING_KEY_TYPE_ECDSA_SHA256_P256 = 1; const uint16_t SIGNING_KEY_TYPE_ECDSA_SHA256_P256 = 1;
@ -64,13 +64,13 @@ namespace data
// following signature type should never appear in netid=2 // following signature type should never appear in netid=2
const uint16_t SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256 = 9; const uint16_t SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256 = 9;
const uint16_t SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512 = 10; // approved by FSB const uint16_t SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512 = 10; // approved by FSB
// TODO: remove later // TODO: remove later
const uint16_t SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256_TEST = 65281; const uint16_t SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256_TEST = 65281;
const uint16_t SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512_TEST = 65282; const uint16_t SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512_TEST = 65282;
typedef uint16_t SigningKeyType; typedef uint16_t SigningKeyType;
typedef uint16_t CryptoKeyType; typedef uint16_t CryptoKeyType;
class IdentityEx class IdentityEx
{ {
public: public:
@ -89,9 +89,11 @@ namespace data
size_t ToBuffer (uint8_t * buf, size_t len) const; size_t ToBuffer (uint8_t * buf, size_t len) const;
size_t FromBase64(const std::string& s); size_t FromBase64(const std::string& s);
std::string ToBase64 () const; std::string ToBase64 () const;
const Identity& GetStandardIdentity () const { return m_StandardIdentity; }; const Identity& GetStandardIdentity () const { return m_StandardIdentity; };
const IdentHash& GetIdentHash () const { return m_IdentHash; }; const IdentHash& GetIdentHash () const { return m_IdentHash; };
const uint8_t * GetEncryptionPublicKey () const { return m_StandardIdentity.publicKey; }; const uint8_t * GetEncryptionPublicKey () const { return m_StandardIdentity.publicKey; };
uint8_t * GetEncryptionPublicKeyBuffer () { return m_StandardIdentity.publicKey; };
size_t GetFullLen () const { return m_ExtendedLen + DEFAULT_IDENTITY_SIZE; }; size_t GetFullLen () const { return m_ExtendedLen + DEFAULT_IDENTITY_SIZE; };
size_t GetSigningPublicKeyLen () const; size_t GetSigningPublicKeyLen () const;
size_t GetSigningPrivateKeyLen () const; size_t GetSigningPrivateKeyLen () const;
@ -99,42 +101,46 @@ namespace data
bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const; bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const;
SigningKeyType GetSigningKeyType () const; SigningKeyType GetSigningKeyType () const;
CryptoKeyType GetCryptoKeyType () const; CryptoKeyType GetCryptoKeyType () const;
void DropVerifier () const; // to save memory void DropVerifier () const; // to save memory
bool operator == (const IdentityEx & other) const { return GetIdentHash() == other.GetIdentHash(); } bool operator == (const IdentityEx & other) const { return GetIdentHash() == other.GetIdentHash(); }
void RecalculateIdentHash(uint8_t * buff=nullptr);
private: private:
void CreateVerifier () const; void CreateVerifier () const;
void UpdateVerifier (i2p::crypto::Verifier * verifier) const; void UpdateVerifier (i2p::crypto::Verifier * verifier) const;
private: private:
Identity m_StandardIdentity; Identity m_StandardIdentity;
IdentHash m_IdentHash; IdentHash m_IdentHash;
mutable std::unique_ptr<i2p::crypto::Verifier> m_Verifier; mutable std::unique_ptr<i2p::crypto::Verifier> m_Verifier;
mutable std::atomic_bool m_IsVerifierCreated; // make sure we don't create twice mutable std::atomic_bool m_IsVerifierCreated; // make sure we don't create twice
size_t m_ExtendedLen; size_t m_ExtendedLen;
uint8_t * m_ExtendedBuffer; uint8_t * m_ExtendedBuffer;
}; };
class PrivateKeys // for eepsites class PrivateKeys // for eepsites
{ {
public: public:
PrivateKeys () = default; PrivateKeys () = default;
PrivateKeys (const PrivateKeys& other) { *this = other; }; PrivateKeys (const PrivateKeys& other) { *this = other; };
PrivateKeys (const Keys& keys) { *this = keys; }; PrivateKeys (const Keys& keys) { *this = keys; };
PrivateKeys& operator=(const Keys& keys); PrivateKeys& operator=(const Keys& keys);
PrivateKeys& operator=(const PrivateKeys& other); PrivateKeys& operator=(const PrivateKeys& other);
~PrivateKeys () = default; ~PrivateKeys () = default;
std::shared_ptr<const IdentityEx> GetPublic () const { return m_Public; }; std::shared_ptr<const IdentityEx> GetPublic () const { return m_Public; };
const uint8_t * GetPrivateKey () const { return m_PrivateKey; }; const uint8_t * GetPrivateKey () const { return m_PrivateKey; };
const uint8_t * GetSigningPrivateKey () const { return m_SigningPrivateKey; }; const uint8_t * GetSigningPrivateKey () const { return m_SigningPrivateKey; };
uint8_t * GetPadding();
void RecalculateIdentHash(uint8_t * buf=nullptr) { m_Public->RecalculateIdentHash(buf); }
void Sign (const uint8_t * buf, int len, uint8_t * signature) const; void Sign (const uint8_t * buf, int len, uint8_t * signature) const;
size_t GetFullLen () const { return m_Public->GetFullLen () + 256 + m_Public->GetSigningPrivateKeyLen (); }; size_t GetFullLen () const { return m_Public->GetFullLen () + 256 + m_Public->GetSigningPrivateKeyLen (); };
size_t FromBuffer (const uint8_t * buf, size_t len); size_t FromBuffer (const uint8_t * buf, size_t len);
size_t ToBuffer (uint8_t * buf, size_t len) const; size_t ToBuffer (uint8_t * buf, size_t len) const;
@ -142,11 +148,11 @@ namespace data
std::string ToBase64 () const; std::string ToBase64 () const;
static PrivateKeys CreateRandomKeys (SigningKeyType type = SIGNING_KEY_TYPE_DSA_SHA1); static PrivateKeys CreateRandomKeys (SigningKeyType type = SIGNING_KEY_TYPE_DSA_SHA1);
private: private:
void CreateSigner () const; void CreateSigner () const;
private: private:
std::shared_ptr<IdentityEx> m_Public; std::shared_ptr<IdentityEx> m_Public;
@ -159,19 +165,19 @@ namespace data
struct XORMetric struct XORMetric
{ {
union union
{ {
uint8_t metric[32]; uint8_t metric[32];
uint64_t metric_ll[4]; uint64_t metric_ll[4];
}; };
void SetMin () { memset (metric, 0, 32); }; void SetMin () { memset (metric, 0, 32); };
void SetMax () { memset (metric, 0xFF, 32); }; void SetMax () { memset (metric, 0xFF, 32); };
bool operator< (const XORMetric& other) const { return memcmp (metric, other.metric, 32) < 0; }; bool operator< (const XORMetric& other) const { return memcmp (metric, other.metric, 32) < 0; };
}; };
IdentHash CreateRoutingKey (const IdentHash& ident); IdentHash CreateRoutingKey (const IdentHash& ident);
XORMetric operator^(const IdentHash& key1, const IdentHash& key2); XORMetric operator^(const IdentHash& key1, const IdentHash& key2);
// destination for delivery instuctions // destination for delivery instuctions
class RoutingDestination class RoutingDestination
{ {
@ -179,22 +185,22 @@ namespace data
RoutingDestination () {}; RoutingDestination () {};
virtual ~RoutingDestination () {}; virtual ~RoutingDestination () {};
virtual const IdentHash& GetIdentHash () const = 0; virtual const IdentHash& GetIdentHash () const = 0;
virtual const uint8_t * GetEncryptionPublicKey () const = 0; virtual const uint8_t * GetEncryptionPublicKey () const = 0;
virtual bool IsDestination () const = 0; // for garlic virtual bool IsDestination () const = 0; // for garlic
}; };
class LocalDestination class LocalDestination
{ {
public: public:
virtual ~LocalDestination() {}; virtual ~LocalDestination() {};
virtual const uint8_t * GetEncryptionPrivateKey () const = 0; virtual const uint8_t * GetEncryptionPrivateKey () const = 0;
virtual std::shared_ptr<const IdentityEx> GetIdentity () const = 0; virtual std::shared_ptr<const IdentityEx> GetIdentity () const = 0;
const IdentHash& GetIdentHash () const { return GetIdentity ()->GetIdentHash (); }; const IdentHash& GetIdentHash () const { return GetIdentity ()->GetIdentHash (); };
}; };
} }
} }

View File

@ -2,6 +2,7 @@
#include <fstream> #include <fstream>
#include <vector> #include <vector>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include <stdexcept>
#include "I2PEndian.h" #include "I2PEndian.h"
#include "Base.h" #include "Base.h"
@ -139,8 +140,7 @@ namespace data
auto numRouters = m_RouterInfos.size (); auto numRouters = m_RouterInfos.size ();
if (numRouters == 0) if (numRouters == 0)
{ {
LogPrint(eLogError, "NetDb: no known routers, reseed seems to be totally failed"); throw std::runtime_error("No known routers, reseed seems to be totally failed");
break;
} }
else // we have peers now else // we have peers now
m_FloodfillBootstrap = nullptr; m_FloodfillBootstrap = nullptr;

View File

@ -433,7 +433,7 @@ namespace transport
{ {
boost::asio::ip::udp::endpoint remoteEndpoint (address->host, address->port); boost::asio::ip::udp::endpoint remoteEndpoint (address->host, address->port);
auto it = m_Sessions.find (remoteEndpoint); auto it = m_Sessions.find (remoteEndpoint);
// check if session if presented alredy // check if session is presented already
if (it != m_Sessions.end ()) if (it != m_Sessions.end ())
{ {
auto session = it->second; auto session = it->second;
@ -480,18 +480,24 @@ namespace transport
introducerSession = std::make_shared<SSUSession> (*this, introducerEndpoint, router); introducerSession = std::make_shared<SSUSession> (*this, introducerEndpoint, router);
m_Sessions[introducerEndpoint] = introducerSession; m_Sessions[introducerEndpoint] = introducerSession;
} }
// create session #if BOOST_VERSION >= 104900
auto session = std::make_shared<SSUSession> (*this, remoteEndpoint, router, peerTest); if (!address->host.is_unspecified () && address->port)
m_Sessions[remoteEndpoint] = session; #endif
// introduce
LogPrint (eLogInfo, "SSU: Introduce new session to [", i2p::data::GetIdentHashAbbreviation (router->GetIdentHash ()),
"] through introducer ", introducer->iHost, ":", introducer->iPort);
session->WaitForIntroduction ();
if (i2p::context.GetRouterInfo ().UsesIntroducer ()) // if we are unreachable
{ {
uint8_t buf[1]; // create session
Send (buf, 0, remoteEndpoint); // send HolePunch auto session = std::make_shared<SSUSession> (*this, remoteEndpoint, router, peerTest);
} m_Sessions[remoteEndpoint] = session;
// introduce
LogPrint (eLogInfo, "SSU: Introduce new session to [", i2p::data::GetIdentHashAbbreviation (router->GetIdentHash ()),
"] through introducer ", introducer->iHost, ":", introducer->iPort);
session->WaitForIntroduction ();
if (i2p::context.GetRouterInfo ().UsesIntroducer ()) // if we are unreachable
{
uint8_t buf[1];
Send (buf, 0, remoteEndpoint); // send HolePunch
}
}
introducerSession->Introduce (*introducer, router); introducerSession->Introduce (*introducer, router);
} }
else else

View File

@ -2,7 +2,7 @@
#define TAG_H__ #define TAG_H__
/* /*
* Copyright (c) 2013-2016, The PurpleI2P Project * Copyright (c) 2013-2017, 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
* *
@ -28,6 +28,7 @@ public:
Tag (const uint8_t * buf) { memcpy (m_Buf, buf, sz); } Tag (const uint8_t * buf) { memcpy (m_Buf, buf, sz); }
bool operator== (const Tag& other) const { return !memcmp (m_Buf, other.m_Buf, sz); } bool operator== (const Tag& other) const { return !memcmp (m_Buf, other.m_Buf, sz); }
bool operator!= (const Tag& other) const { return !(*this == other); }
bool operator< (const Tag& other) const { return memcmp (m_Buf, other.m_Buf, sz) < 0; } bool operator< (const Tag& other) const { return memcmp (m_Buf, other.m_Buf, sz) < 0; }
uint8_t * operator()() { return m_Buf; } uint8_t * operator()() { return m_Buf; }

View File

@ -110,7 +110,7 @@ namespace transport
Transports transports; Transports transports;
Transports::Transports (): Transports::Transports ():
m_IsOnline (true), m_IsRunning (false), m_Thread (nullptr), m_Service (nullptr), m_IsOnline (true), m_IsRunning (false), m_IsNAT (true), m_Thread (nullptr), m_Service (nullptr),
m_Work (nullptr), m_PeerCleanupTimer (nullptr), m_PeerTestTimer (nullptr), m_Work (nullptr), m_PeerCleanupTimer (nullptr), m_PeerTestTimer (nullptr),
m_NTCPServer (nullptr), m_SSUServer (nullptr), m_DHKeysPairSupplier (5), // 5 pre-generated keys m_NTCPServer (nullptr), m_SSUServer (nullptr), m_DHKeysPairSupplier (5), // 5 pre-generated keys
m_TotalSentBytes(0), m_TotalReceivedBytes(0), m_TotalTransitTransmittedBytes (0), m_TotalSentBytes(0), m_TotalReceivedBytes(0), m_TotalTransitTransmittedBytes (0),
@ -142,6 +142,8 @@ namespace transport
m_PeerTestTimer = new boost::asio::deadline_timer (*m_Service); m_PeerTestTimer = new boost::asio::deadline_timer (*m_Service);
} }
i2p::config::GetOption("nat", m_IsNAT);
m_DHKeysPairSupplier.Start (); m_DHKeysPairSupplier.Start ();
m_IsRunning = true; m_IsRunning = true;
m_Thread = new std::thread (std::bind (&Transports::Run, this)); m_Thread = new std::thread (std::bind (&Transports::Run, this));
@ -221,8 +223,12 @@ namespace transport
} }
m_PeerCleanupTimer->expires_from_now (boost::posix_time::seconds(5*SESSION_CREATION_TIMEOUT)); m_PeerCleanupTimer->expires_from_now (boost::posix_time::seconds(5*SESSION_CREATION_TIMEOUT));
m_PeerCleanupTimer->async_wait (std::bind (&Transports::HandlePeerCleanupTimer, this, std::placeholders::_1)); m_PeerCleanupTimer->async_wait (std::bind (&Transports::HandlePeerCleanupTimer, this, std::placeholders::_1));
m_PeerTestTimer->expires_from_now (boost::posix_time::minutes(PEER_TEST_INTERVAL));
m_PeerTestTimer->async_wait (std::bind (&Transports::HandlePeerTestTimer, this, std::placeholders::_1)); if (m_IsNAT)
{
m_PeerTestTimer->expires_from_now (boost::posix_time::minutes(PEER_TEST_INTERVAL));
m_PeerTestTimer->async_wait (std::bind (&Transports::HandlePeerTestTimer, this, std::placeholders::_1));
}
} }
void Transports::Stop () void Transports::Stop ()
@ -605,9 +611,8 @@ namespace transport
} }
if (m_SSUServer) if (m_SSUServer)
{ {
bool nat; i2p::config::GetOption("nat", nat);
bool isv4 = i2p::context.SupportsV4 (); bool isv4 = i2p::context.SupportsV4 ();
if (nat && isv4) if (m_IsNAT && isv4)
i2p::context.SetStatus (eRouterStatusTesting); i2p::context.SetStatus (eRouterStatusTesting);
for (int i = 0; i < 5; i++) for (int i = 0; i < 5; i++)
{ {

View File

@ -146,7 +146,7 @@ namespace transport
private: private:
bool m_IsOnline, m_IsRunning; bool m_IsOnline, m_IsRunning, m_IsNAT;
std::thread * m_Thread; std::thread * m_Thread;
boost::asio::io_service * m_Service; boost::asio::io_service * m_Service;
boost::asio::io_service::work * m_Work; boost::asio::io_service::work * m_Work;

View File

@ -122,7 +122,7 @@ namespace tunnel
void AddLatencySample(const uint64_t ms) { m_Latency = (m_Latency + ms) >> 1; } void AddLatencySample(const uint64_t ms) { m_Latency = (m_Latency + ms) >> 1; }
/** @brief get this tunnel's estimated latency */ /** @brief get this tunnel's estimated latency */
uint64_t GetMeanLatency() const { return m_Latency; } uint64_t GetMeanLatency() const { return m_Latency; }
/** @breif return true if this tunnel's latency fits in range [lowerbound, upperbound] */ /** @brief return true if this tunnel's latency fits in range [lowerbound, upperbound] */
bool LatencyFitsRange(uint64_t lowerbound, uint64_t upperbound) const; bool LatencyFitsRange(uint64_t lowerbound, uint64_t upperbound) const;
bool LatencyIsKnown() const { return m_Latency > 0; } bool LatencyIsKnown() const { return m_Latency > 0; }

View File

@ -7,7 +7,7 @@
#define MAKE_VERSION(a,b,c) STRINGIZE(a) "." STRINGIZE(b) "." STRINGIZE(c) #define MAKE_VERSION(a,b,c) STRINGIZE(a) "." STRINGIZE(b) "." STRINGIZE(c)
#define I2PD_VERSION_MAJOR 2 #define I2PD_VERSION_MAJOR 2
#define I2PD_VERSION_MINOR 14 #define I2PD_VERSION_MINOR 15
#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)
@ -21,7 +21,7 @@
#define I2P_VERSION_MAJOR 0 #define I2P_VERSION_MAJOR 0
#define I2P_VERSION_MINOR 9 #define I2P_VERSION_MINOR 9
#define I2P_VERSION_MICRO 30 #define I2P_VERSION_MICRO 31
#define I2P_VERSION_PATCH 0 #define I2P_VERSION_PATCH 0
#define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO) #define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO)

View File

@ -376,12 +376,23 @@ namespace client
continue; continue;
} }
numAddresses++; numAddresses++;
if (m_Addresses.count(name) > 0) auto it = m_Addresses.find (name);
continue; /* already exists */ if (it != m_Addresses.end ()) // aleady exists ?
m_Addresses[name] = ident->GetIdentHash (); {
m_Storage->AddAddress (ident); if (it->second != ident->GetIdentHash ()) // address changed?
if (is_update) {
LogPrint(eLogInfo, "Addressbook: added new host: ", name); it->second = ident->GetIdentHash ();
m_Storage->AddAddress (ident);
LogPrint (eLogInfo, "Addressbook: updated host: ", name);
}
}
else
{
m_Addresses.insert (std::make_pair (name, ident->GetIdentHash ()));
m_Storage->AddAddress (ident);
if (is_update)
LogPrint (eLogInfo, "Addressbook: added new host: ", name);
}
} }
else else
incomplete = f.eof (); incomplete = f.eof ();

View File

@ -38,6 +38,7 @@ namespace client
if (!m_SharedLocalDestination) if (!m_SharedLocalDestination)
{ {
m_SharedLocalDestination = CreateNewLocalDestination (); // non-public, DSA m_SharedLocalDestination = CreateNewLocalDestination (); // non-public, DSA
m_SharedLocalDestination->Acquire ();
m_Destinations[m_SharedLocalDestination->GetIdentity ()->GetIdentHash ()] = m_SharedLocalDestination; m_Destinations[m_SharedLocalDestination->GetIdentity ()->GetIdentHash ()] = m_SharedLocalDestination;
m_SharedLocalDestination->Start (); m_SharedLocalDestination->Start ();
} }
@ -47,7 +48,8 @@ namespace client
std::shared_ptr<ClientDestination> localDestination; std::shared_ptr<ClientDestination> localDestination;
bool httproxy; i2p::config::GetOption("httpproxy.enabled", httproxy); bool httproxy; i2p::config::GetOption("httpproxy.enabled", httproxy);
if (httproxy) { if (httproxy)
{
std::string httpProxyKeys; i2p::config::GetOption("httpproxy.keys", httpProxyKeys); std::string httpProxyKeys; i2p::config::GetOption("httpproxy.keys", httpProxyKeys);
std::string httpProxyAddr; i2p::config::GetOption("httpproxy.address", httpProxyAddr); std::string httpProxyAddr; i2p::config::GetOption("httpproxy.address", httpProxyAddr);
uint16_t httpProxyPort; i2p::config::GetOption("httpproxy.port", httpProxyPort); uint16_t httpProxyPort; i2p::config::GetOption("httpproxy.port", httpProxyPort);
@ -61,14 +63,18 @@ namespace client
std::map<std::string, std::string> params; std::map<std::string, std::string> params;
ReadI2CPOptionsFromConfig ("httpproxy.", params); ReadI2CPOptionsFromConfig ("httpproxy.", params);
localDestination = CreateNewLocalDestination (keys, false, &params); localDestination = CreateNewLocalDestination (keys, false, &params);
localDestination->Acquire ();
} }
else else
LogPrint(eLogError, "Clients: failed to load HTTP Proxy key"); LogPrint(eLogError, "Clients: failed to load HTTP Proxy key");
} }
try { try
{
m_HttpProxy = new i2p::proxy::HTTPProxy(httpProxyAddr, httpProxyPort, localDestination); m_HttpProxy = new i2p::proxy::HTTPProxy(httpProxyAddr, httpProxyPort, localDestination);
m_HttpProxy->Start(); m_HttpProxy->Start();
} catch (std::exception& e) { }
catch (std::exception& e)
{
LogPrint(eLogError, "Clients: Exception in HTTP Proxy: ", e.what()); LogPrint(eLogError, "Clients: Exception in HTTP Proxy: ", e.what());
} }
} }
@ -77,9 +83,10 @@ namespace client
bool socksproxy; i2p::config::GetOption("socksproxy.enabled", socksproxy); bool socksproxy; i2p::config::GetOption("socksproxy.enabled", socksproxy);
if (socksproxy) if (socksproxy)
{ {
std::string socksProxyKeys; i2p::config::GetOption("socksproxy.keys", socksProxyKeys); std::string socksProxyKeys; i2p::config::GetOption("socksproxy.keys", socksProxyKeys);
std::string socksProxyAddr; i2p::config::GetOption("socksproxy.address", socksProxyAddr); std::string socksProxyAddr; i2p::config::GetOption("socksproxy.address", socksProxyAddr);
uint16_t socksProxyPort; i2p::config::GetOption("socksproxy.port", socksProxyPort); uint16_t socksProxyPort; i2p::config::GetOption("socksproxy.port", socksProxyPort);
bool socksOutProxy; i2p::config::GetOption("socksproxy.outproxy.enabled", socksOutProxy);
std::string socksOutProxyAddr; i2p::config::GetOption("socksproxy.outproxy", socksOutProxyAddr); std::string socksOutProxyAddr; i2p::config::GetOption("socksproxy.outproxy", socksOutProxyAddr);
uint16_t socksOutProxyPort; i2p::config::GetOption("socksproxy.outproxyport", socksOutProxyPort); uint16_t socksOutProxyPort; i2p::config::GetOption("socksproxy.outproxyport", socksOutProxyPort);
i2p::data::SigningKeyType sigType; i2p::config::GetOption("socksproxy.signaturetype", sigType); i2p::data::SigningKeyType sigType; i2p::config::GetOption("socksproxy.signaturetype", sigType);
@ -92,15 +99,19 @@ namespace client
std::map<std::string, std::string> params; std::map<std::string, std::string> params;
ReadI2CPOptionsFromConfig ("socksproxy.", params); ReadI2CPOptionsFromConfig ("socksproxy.", params);
localDestination = CreateNewLocalDestination (keys, false, &params); localDestination = CreateNewLocalDestination (keys, false, &params);
localDestination->Acquire ();
} }
else else
LogPrint(eLogError, "Clients: failed to load SOCKS Proxy key"); LogPrint(eLogError, "Clients: failed to load SOCKS Proxy key");
} }
try { try
m_SocksProxy = new i2p::proxy::SOCKSProxy(socksProxyAddr, socksProxyPort, socksOutProxyAddr, socksOutProxyPort, localDestination); {
m_SocksProxy->Start(); m_SocksProxy = new i2p::proxy::SOCKSProxy(socksProxyAddr, socksProxyPort, socksOutProxy, socksOutProxyAddr, socksOutProxyPort, localDestination);
} catch (std::exception& e) { m_SocksProxy->Start();
LogPrint(eLogError, "Clients: Exception in SOCKS Proxy: ", e.what()); }
catch (std::exception& e)
{
LogPrint(eLogError, "Clients: Exception in SOCKS Proxy: ", e.what());
} }
} }
@ -242,10 +253,30 @@ namespace client
void ClientContext::ReloadConfig () void ClientContext::ReloadConfig ()
{ {
std::string config; i2p::config::GetOption("conf", config); // TODO: handle config changes
i2p::config::ParseConfig(config); /*std::string config; i2p::config::GetOption("conf", config);
Stop(); i2p::config::ParseConfig(config);*/
Start();
// handle tunnels
// reset isUpdated for each tunnel
VisitTunnels ([](I2PService * s)->bool { s->isUpdated = false; return true; });
// reload tunnels
ReadTunnels();
// delete not updated tunnels (not in config anymore)
VisitTunnels ([](I2PService * s)->bool { return s->isUpdated; });
// delete unused destinations
std::unique_lock<std::mutex> l(m_DestinationsMutex);
for (auto it = m_Destinations.begin (); it != m_Destinations.end ();)
{
auto dest = it->second;
if (dest->GetRefCounter () > 0) ++it; // skip
else
{
dest->Stop ();
it = m_Destinations.erase (it);
}
}
} }
bool ClientContext::LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename, i2p::data::SigningKeyType sigType) bool ClientContext::LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename, i2p::data::SigningKeyType sigType)
@ -499,14 +530,14 @@ namespace client
if (type == I2P_TUNNELS_SECTION_TYPE_SOCKS) if (type == I2P_TUNNELS_SECTION_TYPE_SOCKS)
{ {
// socks proxy // socks proxy
clientTunnel = new i2p::proxy::SOCKSProxy(address, port, "", destinationPort, localDestination); clientTunnel = new i2p::proxy::SOCKSProxy(address, port, false, "", destinationPort, localDestination);
clientEndpoint = ((i2p::proxy::SOCKSProxy*)clientTunnel)->GetAcceptor().local_endpoint(); clientEndpoint = ((i2p::proxy::SOCKSProxy*)clientTunnel)->GetLocalEndpoint ();
} }
else if (type == I2P_TUNNELS_SECTION_TYPE_HTTPPROXY) else if (type == I2P_TUNNELS_SECTION_TYPE_HTTPPROXY)
{ {
// http proxy // http proxy
clientTunnel = new i2p::proxy::HTTPProxy(address, port, localDestination); clientTunnel = new i2p::proxy::HTTPProxy(address, port, localDestination);
clientEndpoint = ((i2p::proxy::HTTPProxy*)clientTunnel)->GetAcceptor().local_endpoint(); clientEndpoint = ((i2p::proxy::HTTPProxy*)clientTunnel)->GetLocalEndpoint ();
} }
else if (type == I2P_TUNNELS_SECTION_TYPE_WEBSOCKS) else if (type == I2P_TUNNELS_SECTION_TYPE_WEBSOCKS)
{ {
@ -518,15 +549,20 @@ namespace client
{ {
// tcp client // tcp client
clientTunnel = new I2PClientTunnel (name, dest, address, port, localDestination, destinationPort); clientTunnel = new I2PClientTunnel (name, dest, address, port, localDestination, destinationPort);
clientEndpoint = ((I2PClientTunnel*)clientTunnel)->GetAcceptor().local_endpoint(); clientEndpoint = ((I2PClientTunnel*)clientTunnel)->GetLocalEndpoint ();
} }
if (m_ClientTunnels.insert (std::make_pair (clientEndpoint, std::unique_ptr<I2PService>(clientTunnel))).second) auto ins = m_ClientTunnels.insert (std::make_pair (clientEndpoint, std::unique_ptr<I2PService>(clientTunnel)));
if (ins.second)
{ {
clientTunnel->Start (); clientTunnel->Start ();
numClientTunnels++; numClientTunnels++;
} }
else else
LogPrint (eLogError, "Clients: I2P client tunnel for endpoint ", clientEndpoint, "already exists"); {
// TODO: update
ins.first->second->isUpdated = true;
LogPrint (eLogInfo, "Clients: I2P client tunnel for endpoint ", clientEndpoint, "already exists");
}
} }
} }
else if (type == I2P_TUNNELS_SECTION_TYPE_SERVER else if (type == I2P_TUNNELS_SECTION_TYPE_SERVER
@ -619,15 +655,20 @@ namespace client
while (comma != std::string::npos); while (comma != std::string::npos);
serverTunnel->SetAccessList (idents); serverTunnel->SetAccessList (idents);
} }
if (m_ServerTunnels.insert (std::make_pair ( auto ins = m_ServerTunnels.insert (std::make_pair (
std::make_pair (localDestination->GetIdentHash (), inPort), std::make_pair (localDestination->GetIdentHash (), inPort),
std::unique_ptr<I2PServerTunnel>(serverTunnel))).second) std::unique_ptr<I2PServerTunnel>(serverTunnel)));
if (ins.second)
{ {
serverTunnel->Start (); serverTunnel->Start ();
numServerTunnels++; numServerTunnels++;
} }
else else
LogPrint (eLogError, "Clients: I2P server tunnel for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash ()), "/", inPort, " already exists"); {
// TODO: update
ins.first->second->isUpdated = true;
LogPrint (eLogInfo, "Clients: I2P server tunnel for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash ()), "/", inPort, " already exists");
}
} }
else else
@ -662,5 +703,28 @@ namespace client
ScheduleCleanupUDP(); ScheduleCleanupUDP();
} }
} }
template<typename Container, typename Visitor>
void VisitTunnelsContainer (Container& c, Visitor v)
{
for (auto it = c.begin (); it != c.end ();)
{
if (!v (it->second.get ()))
{
it->second->Stop ();
it = c.erase (it);
}
else
it++;
}
}
template<typename Visitor>
void ClientContext::VisitTunnels (Visitor v)
{
VisitTunnelsContainer (m_ClientTunnels, v);
VisitTunnelsContainer (m_ServerTunnels, v);
// TODO: implement UDP forwards
}
} }
} }

View File

@ -89,6 +89,9 @@ namespace client
void CleanupUDP(const boost::system::error_code & ecode); void CleanupUDP(const boost::system::error_code & ecode);
void ScheduleCleanupUDP(); void ScheduleCleanupUDP();
template<typename Visitor>
void VisitTunnels (Visitor v); // Visitor: (I2PService *) -> bool, true means retain
private: private:
std::mutex m_DestinationsMutex; std::mutex m_DestinationsMutex;

View File

@ -202,10 +202,11 @@ namespace proxy {
/* drop common headers */ /* drop common headers */
req.RemoveHeader ("Referer"); req.RemoveHeader ("Referer");
req.RemoveHeader("Via"); req.RemoveHeader("Via");
req.RemoveHeader("Forwarded"); req.RemoveHeader("Forwarded");
req.RemoveHeader("Accept-", "Accept-Encoding"); // Accept-*, but Accept-Encoding
/* drop proxy-disclosing headers */ /* drop proxy-disclosing headers */
req.RemoveHeader("X-Forwarded"); req.RemoveHeader("X-Forwarded");
req.RemoveHeader("Proxy-"); req.RemoveHeader("Proxy-"); // Proxy-*
/* replace headers */ /* replace headers */
req.UpdateHeader("User-Agent", "MYOB/6.66 (AN/ON)"); req.UpdateHeader("User-Agent", "MYOB/6.66 (AN/ON)");
/* add headers */ /* add headers */

View File

@ -11,15 +11,32 @@ namespace client
I2PService::I2PService (std::shared_ptr<ClientDestination> localDestination): I2PService::I2PService (std::shared_ptr<ClientDestination> localDestination):
m_LocalDestination (localDestination ? localDestination : m_LocalDestination (localDestination ? localDestination :
i2p::client::context.CreateNewLocalDestination (false, I2P_SERVICE_DEFAULT_KEY_TYPE)) i2p::client::context.CreateNewLocalDestination (false, I2P_SERVICE_DEFAULT_KEY_TYPE)), isUpdated (true)
{ {
m_LocalDestination->Acquire ();
} }
I2PService::I2PService (i2p::data::SigningKeyType kt): I2PService::I2PService (i2p::data::SigningKeyType kt):
m_LocalDestination (i2p::client::context.CreateNewLocalDestination (false, kt)) m_LocalDestination (i2p::client::context.CreateNewLocalDestination (false, kt)),
isUpdated (true)
{ {
m_LocalDestination->Acquire ();
} }
I2PService::~I2PService ()
{
ClearHandlers ();
if (m_LocalDestination) m_LocalDestination->Release ();
}
void I2PService::ClearHandlers ()
{
std::unique_lock<std::mutex> l(m_HandlersMutex);
for (auto it: m_Handlers)
it->Terminate ();
m_Handlers.clear();
}
void I2PService::CreateStream (StreamRequestComplete streamRequestComplete, const std::string& dest, int port) { void I2PService::CreateStream (StreamRequestComplete streamRequestComplete, const std::string& dest, int port) {
assert(streamRequestComplete); assert(streamRequestComplete);
i2p::data::IdentHash identHash; i2p::data::IdentHash identHash;
@ -173,13 +190,18 @@ namespace client
void TCPIPAcceptor::Start () void TCPIPAcceptor::Start ()
{ {
m_Acceptor.listen (); m_Acceptor.reset (new boost::asio::ip::tcp::acceptor (GetService (), m_LocalEndpoint));
m_Acceptor->listen ();
Accept (); Accept ();
} }
void TCPIPAcceptor::Stop () void TCPIPAcceptor::Stop ()
{ {
m_Acceptor.close(); if (m_Acceptor)
{
m_Acceptor->close();
m_Acceptor.reset (nullptr);
}
m_Timer.cancel (); m_Timer.cancel ();
ClearHandlers(); ClearHandlers();
} }
@ -187,7 +209,7 @@ namespace client
void TCPIPAcceptor::Accept () void TCPIPAcceptor::Accept ()
{ {
auto newSocket = std::make_shared<boost::asio::ip::tcp::socket> (GetService ()); auto newSocket = std::make_shared<boost::asio::ip::tcp::socket> (GetService ());
m_Acceptor.async_accept (*newSocket, std::bind (&TCPIPAcceptor::HandleAccept, this, m_Acceptor->async_accept (*newSocket, std::bind (&TCPIPAcceptor::HandleAccept, this,
std::placeholders::_1, newSocket)); std::placeholders::_1, newSocket));
} }

View File

@ -19,7 +19,7 @@ namespace client
public: public:
I2PService (std::shared_ptr<ClientDestination> localDestination = nullptr); I2PService (std::shared_ptr<ClientDestination> localDestination = nullptr);
I2PService (i2p::data::SigningKeyType kt); I2PService (i2p::data::SigningKeyType kt);
virtual ~I2PService () { ClearHandlers (); } virtual ~I2PService ();
inline void AddHandler (std::shared_ptr<I2PServiceHandler> conn) inline void AddHandler (std::shared_ptr<I2PServiceHandler> conn)
{ {
@ -31,11 +31,7 @@ namespace client
std::unique_lock<std::mutex> l(m_HandlersMutex); std::unique_lock<std::mutex> l(m_HandlersMutex);
m_Handlers.erase(conn); m_Handlers.erase(conn);
} }
inline void ClearHandlers () void ClearHandlers ();
{
std::unique_lock<std::mutex> l(m_HandlersMutex);
m_Handlers.clear();
}
inline std::shared_ptr<ClientDestination> GetLocalDestination () { return m_LocalDestination; } inline std::shared_ptr<ClientDestination> GetLocalDestination () { return m_LocalDestination; }
inline std::shared_ptr<const ClientDestination> GetLocalDestination () const { return m_LocalDestination; } inline std::shared_ptr<const ClientDestination> GetLocalDestination () const { return m_LocalDestination; }
@ -53,6 +49,9 @@ namespace client
std::shared_ptr<ClientDestination> m_LocalDestination; std::shared_ptr<ClientDestination> m_LocalDestination;
std::unordered_set<std::shared_ptr<I2PServiceHandler> > m_Handlers; std::unordered_set<std::shared_ptr<I2PServiceHandler> > m_Handlers;
std::mutex m_HandlersMutex; std::mutex m_HandlersMutex;
public:
bool isUpdated; // transient, used during reload only
}; };
/*Simple interface for I2PHandlers, allows detection of finalization amongst other things */ /*Simple interface for I2PHandlers, allows detection of finalization amongst other things */
@ -63,6 +62,9 @@ namespace client
virtual ~I2PServiceHandler() { } virtual ~I2PServiceHandler() { }
//If you override this make sure you call it from the children //If you override this make sure you call it from the children
virtual void Handle() {}; //Start handling the socket virtual void Handle() {}; //Start handling the socket
void Terminate () { Kill (); };
protected: protected:
// Call when terminating or handing over to avoid race conditions // Call when terminating or handing over to avoid race conditions
inline bool Kill () { return m_Dead.exchange(true); } inline bool Kill () { return m_Dead.exchange(true); }
@ -108,11 +110,11 @@ namespace client
public: public:
TCPIPAcceptor (const std::string& address, int port, std::shared_ptr<ClientDestination> localDestination = nullptr) : TCPIPAcceptor (const std::string& address, int port, std::shared_ptr<ClientDestination> localDestination = nullptr) :
I2PService(localDestination), I2PService(localDestination),
m_Acceptor (GetService (), boost::asio::ip::tcp::endpoint (boost::asio::ip::address::from_string(address), port)), m_LocalEndpoint (boost::asio::ip::address::from_string(address), port),
m_Timer (GetService ()) {} m_Timer (GetService ()) {}
TCPIPAcceptor (const std::string& address, int port, i2p::data::SigningKeyType kt) : TCPIPAcceptor (const std::string& address, int port, i2p::data::SigningKeyType kt) :
I2PService(kt), I2PService(kt),
m_Acceptor (GetService (), boost::asio::ip::tcp::endpoint (boost::asio::ip::address::from_string(address), port)), m_LocalEndpoint (boost::asio::ip::address::from_string(address), port),
m_Timer (GetService ()) {} m_Timer (GetService ()) {}
virtual ~TCPIPAcceptor () { TCPIPAcceptor::Stop(); } virtual ~TCPIPAcceptor () { TCPIPAcceptor::Stop(); }
//If you override this make sure you call it from the children //If you override this make sure you call it from the children
@ -120,7 +122,7 @@ namespace client
//If you override this make sure you call it from the children //If you override this make sure you call it from the children
void Stop (); void Stop ();
const boost::asio::ip::tcp::acceptor& GetAcceptor () const { return m_Acceptor; }; const boost::asio::ip::tcp::endpoint& GetLocalEndpoint () const { return m_LocalEndpoint; };
virtual const char* GetName() { return "Generic TCP/IP accepting daemon"; } virtual const char* GetName() { return "Generic TCP/IP accepting daemon"; }
@ -129,7 +131,8 @@ namespace client
private: private:
void Accept(); void Accept();
void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr<boost::asio::ip::tcp::socket> socket); void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr<boost::asio::ip::tcp::socket> socket);
boost::asio::ip::tcp::acceptor m_Acceptor; boost::asio::ip::tcp::endpoint m_LocalEndpoint;
std::unique_ptr<boost::asio::ip::tcp::acceptor> m_Acceptor;
boost::asio::deadline_timer m_Timer; boost::asio::deadline_timer m_Timer;
}; };
} }

View File

@ -921,6 +921,7 @@ namespace client
} }
if (localDestination) if (localDestination)
{ {
localDestination->Acquire ();
auto session = std::make_shared<SAMSession>(localDestination); auto session = std::make_shared<SAMSession>(localDestination);
std::unique_lock<std::mutex> l(m_SessionsMutex); std::unique_lock<std::mutex> l(m_SessionsMutex);
auto ret = m_Sessions.insert (std::make_pair(id, session)); auto ret = m_Sessions.insert (std::make_pair(id, session));
@ -945,6 +946,7 @@ namespace client
} }
if (session) if (session)
{ {
session->localDestination->Release ();
session->localDestination->StopAcceptingStreams (); session->localDestination->StopAcceptingStreams ();
session->CloseStreams (); session->CloseStreams ();
} }

View File

@ -765,18 +765,18 @@ namespace proxy
m_upstreamSock = std::make_shared<boost::asio::ip::tcp::socket>(service); m_upstreamSock = std::make_shared<boost::asio::ip::tcp::socket>(service);
boost::asio::async_connect(*m_upstreamSock, itr, boost::asio::async_connect(*m_upstreamSock, itr,
std::bind(&SOCKSHandler::HandleUpstreamConnected, std::bind(&SOCKSHandler::HandleUpstreamConnected,
shared_from_this(), std::placeholders::_1, std::placeholders::_2)); shared_from_this(), std::placeholders::_1, std::placeholders::_2));
} }
SOCKSServer::SOCKSServer(const std::string& address, int port, const std::string& outAddress, uint16_t outPort, SOCKSServer::SOCKSServer(const std::string& address, int port, bool outEnable, const std::string& outAddress, uint16_t outPort,
std::shared_ptr<i2p::client::ClientDestination> localDestination) : std::shared_ptr<i2p::client::ClientDestination> localDestination) :
TCPIPAcceptor (address, port, localDestination ? localDestination : i2p::client::context.GetSharedLocalDestination ()) TCPIPAcceptor (address, port, localDestination ? localDestination : i2p::client::context.GetSharedLocalDestination ())
{ {
m_UseUpstreamProxy = false; m_UseUpstreamProxy = false;
if (outAddress.length() > 0) if (outAddress.length() > 0 && outEnable)
SetUpstreamProxy(outAddress, outPort); SetUpstreamProxy(outAddress, outPort);
} }
std::shared_ptr<i2p::client::I2PServiceHandler> SOCKSServer::CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket) std::shared_ptr<i2p::client::I2PServiceHandler> SOCKSServer::CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket)
{ {
return std::make_shared<SOCKSHandler> (this, socket, m_UpstreamProxyAddress, m_UpstreamProxyPort, m_UseUpstreamProxy); return std::make_shared<SOCKSHandler> (this, socket, m_UpstreamProxyAddress, m_UpstreamProxyPort, m_UseUpstreamProxy);

View File

@ -14,27 +14,24 @@ namespace proxy
class SOCKSServer: public i2p::client::TCPIPAcceptor class SOCKSServer: public i2p::client::TCPIPAcceptor
{ {
public: public:
SOCKSServer(const std::string& address, int port, bool outEnable, const std::string& outAddress, uint16_t outPort,
SOCKSServer(const std::string& address, int port, const std::string& outAddress, uint16_t outPort,
std::shared_ptr<i2p::client::ClientDestination> localDestination = nullptr); std::shared_ptr<i2p::client::ClientDestination> localDestination = nullptr);
~SOCKSServer() {}; ~SOCKSServer() {};
void SetUpstreamProxy(const std::string & addr, const uint16_t port); void SetUpstreamProxy(const std::string & addr, const uint16_t port);
protected: protected:
// Implements TCPIPAcceptor // Implements TCPIPAcceptor
std::shared_ptr<i2p::client::I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket); std::shared_ptr<i2p::client::I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket);
const char* GetName() { return "SOCKS"; } const char* GetName() { return "SOCKS"; }
private: private:
std::string m_UpstreamProxyAddress; std::string m_UpstreamProxyAddress;
uint16_t m_UpstreamProxyPort; uint16_t m_UpstreamProxyPort;
bool m_UseUpstreamProxy; bool m_UseUpstreamProxy;
}; };
typedef SOCKSServer SOCKSProxy; typedef SOCKSServer SOCKSProxy;
} }
} }
#endif #endif

View File

@ -91,6 +91,7 @@ protected:
ctc->setdestinationPort(dportInt); ctc->setdestinationPort(dportInt);
ctc->setsigType(readSigTypeComboboxUI(sigTypeComboBox)); ctc->setsigType(readSigTypeComboboxUI(sigTypeComboBox));
return true;
} }
}; };

View File

@ -161,6 +161,7 @@ namespace qt
{ {
i2p::qt::Controller daemonQtController(daemon); i2p::qt::Controller daemonQtController(daemon);
w.setI2PController(&daemonQtController);
qDebug("Starting the daemon..."); qDebug("Starting the daemon...");
emit daemonQtController.startDaemon(); emit daemonQtController.startDaemon();
//daemon.start (); //daemon.start ();

View File

@ -155,6 +155,7 @@ protected:
stc->setisUniqueLocal(isUniqueLocalCheckBox->isChecked()); stc->setisUniqueLocal(isUniqueLocalCheckBox->isChecked());
stc->setsigType(readSigTypeComboboxUI(sigTypeComboBox)); stc->setsigType(readSigTypeComboboxUI(sigTypeComboBox));
return true;
} }
}; };

View File

@ -18,8 +18,11 @@ class SignatureTypeComboBoxFactory
} }
public: public:
static QComboBox* createSignatureTypeComboBox(QWidget* parent, uint16_t selectedSigType) { static const uint16_t getSigType(const QVariant& var) {
QComboBox* signatureTypeCombobox = new QComboBox(parent); return (uint16_t)var.toInt();
}
static void fillComboBox(QComboBox* signatureTypeCombobox, uint16_t selectedSigType) {
/* /*
<orignal> https://geti2p.net/spec/common-structures#certificate <orignal> https://geti2p.net/spec/common-structures#certificate
<orignal> все коды перечислены <orignal> все коды перечислены
@ -78,7 +81,11 @@ public:
addItem(signatureTypeCombobox, QString::number(selectedSigType), selectedSigType); //unknown sigtype addItem(signatureTypeCombobox, QString::number(selectedSigType), selectedSigType); //unknown sigtype
signatureTypeCombobox->setCurrentIndex(index); signatureTypeCombobox->setCurrentIndex(index);
} }
}
static QComboBox* createSignatureTypeComboBox(QWidget* parent, uint16_t selectedSigType) {
QComboBox* signatureTypeCombobox = new QComboBox(parent);
fillComboBox(signatureTypeCombobox, selectedSigType);
return signatureTypeCombobox; return signatureTypeCombobox;
} }
}; };

View File

@ -196,7 +196,8 @@ public:
gzip(gzip_), gzip(gzip_),
sigType(sigType_), sigType(sigType_),
maxConns(maxConns_), maxConns(maxConns_),
address(address_) {} address(address_),
isUniqueLocal(isUniqueLocal_) {}
std::string& gethost(){return host;} std::string& gethost(){return host;}
int getport(){return port;} int getport(){return port;}
std::string& getkeys(){return keys;} std::string& getkeys(){return keys;}

View File

@ -88,6 +88,7 @@ protected:
i2cpParams.setOutbound_length(outbound_lengthLineEdit->text()); i2cpParams.setOutbound_length(outbound_lengthLineEdit->text());
i2cpParams.setOutbound_quantity(outbound_quantityLineEdit->text()); i2cpParams.setOutbound_quantity(outbound_quantityLineEdit->text());
i2cpParams.setCrypto_tagsToSend(crypto_tagsToSendLineEdit->text()); i2cpParams.setCrypto_tagsToSend(crypto_tagsToSendLineEdit->text());
return true;
} }
void setupTunnelPane( void setupTunnelPane(

View File

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<manifest package="org.purplei2p.i2pd" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="2.14.0" android:versionCode="2" android:installLocation="auto"> <manifest package="org.purplei2p.i2pd" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="2.15.0" android:versionCode="2" android:installLocation="auto">
<uses-sdk android:minSdkVersion="11" android:targetSdkVersion="23"/> <uses-sdk android:minSdkVersion="11" android:targetSdkVersion="23"/>
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/> <supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
<!-- <application android:hardwareAccelerated="true" --> <!-- <application android:hardwareAccelerated="true" -->

View File

@ -17,6 +17,9 @@
#include <fstream> #include <fstream>
#include "DaemonQT.h"
#include "SignatureTypeComboboxFactory.h"
std::string programOptionsWriterCurrentSection; std::string programOptionsWriterCurrentSection;
MainWindow::MainWindow(QWidget *parent) : MainWindow::MainWindow(QWidget *parent) :
@ -25,6 +28,7 @@ MainWindow::MainWindow(QWidget *parent) :
,quitting(false) ,quitting(false)
#endif #endif
,ui(new Ui::MainWindow) ,ui(new Ui::MainWindow)
,i2pController(nullptr)
,configItems() ,configItems()
,datadir() ,datadir()
,confpath() ,confpath()
@ -48,8 +52,6 @@ MainWindow::MainWindow(QWidget *parent) :
int w = 683; int w = 683;
int h = 3060; int h = 3060;
ui->settingsContents->setFixedSize(w, h); ui->settingsContents->setFixedSize(w, h);
//ui->settingsContents->resize(w, h);
//ui->settingsContents->adjustSize();
/* /*
QPalette pal(palette()); QPalette pal(palette());
@ -77,6 +79,8 @@ MainWindow::MainWindow(QWidget *parent) :
QObject::connect(ui->fastQuitPushButton, SIGNAL(released()), this, SLOT(handleQuitButton())); QObject::connect(ui->fastQuitPushButton, SIGNAL(released()), this, SLOT(handleQuitButton()));
QObject::connect(ui->gracefulQuitPushButton, SIGNAL(released()), this, SLOT(handleGracefulQuitButton())); QObject::connect(ui->gracefulQuitPushButton, SIGNAL(released()), this, SLOT(handleGracefulQuitButton()));
QObject::connect(ui->doRestartI2PDPushButton, SIGNAL(released()), this, SLOT(handleDoRestartButton()));
# define OPTION(section,option,defaultValueGetter) ConfigOption(QString(section),QString(option)) # define OPTION(section,option,defaultValueGetter) ConfigOption(QString(section),QString(option))
initFileChooser( OPTION("","conf",[](){return "";}), ui->configFileLineEdit, ui->configFileBrowsePushButton); initFileChooser( OPTION("","conf",[](){return "";}), ui->configFileLineEdit, ui->configFileBrowsePushButton);
@ -120,6 +124,7 @@ MainWindow::MainWindow(QWidget *parent) :
initIPAddressBox( OPTION("httpproxy","address",[]{return "";}), ui->httpProxyAddressLineEdit, tr("HTTP proxy -> IP address")); initIPAddressBox( OPTION("httpproxy","address",[]{return "";}), ui->httpProxyAddressLineEdit, tr("HTTP proxy -> IP address"));
initTCPPortBox( OPTION("httpproxy","port",[]{return "4444";}), ui->httpProxyPortLineEdit, tr("HTTP proxy -> Port")); initTCPPortBox( OPTION("httpproxy","port",[]{return "4444";}), ui->httpProxyPortLineEdit, tr("HTTP proxy -> Port"));
initFileChooser( OPTION("httpproxy","keys",[]{return "";}), ui->httpProxyKeyFileLineEdit, ui->httpProxyKeyFilePushButton); initFileChooser( OPTION("httpproxy","keys",[]{return "";}), ui->httpProxyKeyFileLineEdit, ui->httpProxyKeyFilePushButton);
initSignatureTypeCombobox(OPTION("httpproxy","signaturetype",[]{return "7";}), ui->comboBox_httpPorxySignatureType); initSignatureTypeCombobox(OPTION("httpproxy","signaturetype",[]{return "7";}), ui->comboBox_httpPorxySignatureType);
initStringBox( OPTION("httpproxy","inbound.length",[]{return "3";}), ui->httpProxyInboundTunnelsLenLineEdit); initStringBox( OPTION("httpproxy","inbound.length",[]{return "3";}), ui->httpProxyInboundTunnelsLenLineEdit);
initStringBox( OPTION("httpproxy","inbound.quantity",[]{return "5";}), ui->httpProxyInboundTunnQuantityLineEdit); initStringBox( OPTION("httpproxy","inbound.quantity",[]{return "5";}), ui->httpProxyInboundTunnQuantityLineEdit);
@ -328,6 +333,12 @@ void MainWindow::handleGracefulQuitButton() {
, this, SLOT(handleGracefulQuitTimerEvent())); , this, SLOT(handleGracefulQuitTimerEvent()));
} }
void MainWindow::handleDoRestartButton() {
qDebug()<<"Do Restart pressed.";
emit i2pController->restartDaemon();
}
void MainWindow::handleGracefulQuitTimerEvent() { void MainWindow::handleGracefulQuitTimerEvent() {
qDebug("Hiding the main window"); qDebug("Hiding the main window");
#ifndef ANDROID #ifndef ANDROID
@ -616,3 +627,7 @@ void MainWindow::addServerTunnelPushButtonReleased() {
void MainWindow::addClientTunnelPushButtonReleased() { void MainWindow::addClientTunnelPushButtonReleased() {
CreateDefaultClientTunnel(); CreateDefaultClientTunnel();
} }
void MainWindow::setI2PController(i2p::qt::Controller* controller_) {
this->i2pController = controller_;
}

View File

@ -51,6 +51,9 @@
#include "TunnelsPageUpdateListener.h" #include "TunnelsPageUpdateListener.h"
#include "DaemonQT.h"
#include "SignatureTypeComboboxFactory.h"
template<typename ValueType> template<typename ValueType>
bool isType(boost::any& a) { bool isType(boost::any& a) {
return return
@ -216,16 +219,15 @@ class SignatureTypeComboBoxItem : public ComboBoxItem {
public: public:
SignatureTypeComboBoxItem(ConfigOption option_, QComboBox* comboBox_) : ComboBoxItem(option_, comboBox_) {}; SignatureTypeComboBoxItem(ConfigOption option_, QComboBox* comboBox_) : ComboBoxItem(option_, comboBox_) {};
virtual ~SignatureTypeComboBoxItem(){} virtual ~SignatureTypeComboBoxItem(){}
virtual void loadFromConfigOption(){//TODO virtual void loadFromConfigOption(){
MainWindowItem::loadFromConfigOption(); MainWindowItem::loadFromConfigOption();
comboBox->setCurrentText(QString::number(boost::any_cast<unsigned short>(optionValue))); while(comboBox->count()>0)comboBox->removeItem(0);
uint16_t selected = (uint16_t) boost::any_cast<unsigned short>(optionValue);
SignatureTypeComboBoxFactory::fillComboBox(comboBox, selected);
} }
virtual void saveToStringStream(std::stringstream& out){//TODO virtual void saveToStringStream(std::stringstream& out){
QString txt = comboBox->currentText(); uint16_t selected = SignatureTypeComboBoxFactory::getSigType(comboBox->currentData());
if(txt.isEmpty()) optionValue=(unsigned short)selected;
optionValue=std::string();
else
optionValue=(unsigned short)std::stoi(txt.toStdString());
MainWindowItem::saveToStringStream(out); MainWindowItem::saveToStringStream(out);
} }
virtual bool isValid() { return true; } virtual bool isValid() { return true; }
@ -311,6 +313,10 @@ using namespace i2p::client;
class TunnelPane; class TunnelPane;
using namespace i2p::qt;
class Controller;
class MainWindow : public QMainWindow { class MainWindow : public QMainWindow {
Q_OBJECT Q_OBJECT
@ -318,6 +324,8 @@ public:
explicit MainWindow(QWidget *parent=0); explicit MainWindow(QWidget *parent=0);
~MainWindow(); ~MainWindow();
void setI2PController(i2p::qt::Controller* controller_);
//typedef std::function<QString ()> DefaultValueGetter; //typedef std::function<QString ()> DefaultValueGetter;
//#ifndef ANDROID //#ifndef ANDROID
@ -327,6 +335,7 @@ public:
private slots: private slots:
void handleQuitButton(); void handleQuitButton();
void handleGracefulQuitButton(); void handleGracefulQuitButton();
void handleDoRestartButton();
void handleGracefulQuitTimerEvent(); void handleGracefulQuitTimerEvent();
#ifndef ANDROID #ifndef ANDROID
void setIcon(); void setIcon();
@ -351,6 +360,8 @@ private:
Ui::MainWindow* ui; Ui::MainWindow* ui;
i2p::qt::Controller* i2pController;
protected: protected:
#ifndef ANDROID #ifndef ANDROID
void closeEvent(QCloseEvent *event); void closeEvent(QCloseEvent *event);

View File

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>816</width> <width>816</width>
<height>5000</height> <height>516</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -37,8 +37,8 @@
<rect> <rect>
<x>10</x> <x>10</x>
<y>10</y> <y>10</y>
<width>801</width> <width>796</width>
<height>518</height> <height>496</height>
</rect> </rect>
</property> </property>
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
@ -126,17 +126,17 @@
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>0</width> <width>0</width>
<height>516</height> <height>496</height>
</size> </size>
</property> </property>
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>16777215</width> <width>16777215</width>
<height>516</height> <height>496</height>
</size> </size>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>1</number> <number>4</number>
</property> </property>
<widget class="QWidget" name="statusPage"> <widget class="QWidget" name="statusPage">
<widget class="QWidget" name="verticalLayoutWidget_5"> <widget class="QWidget" name="verticalLayoutWidget_5">
@ -144,8 +144,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>671</width> <width>686</width>
<height>5000</height> <height>496</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_5"> <layout class="QVBoxLayout" name="verticalLayout_5">
@ -192,8 +192,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>701</width> <width>706</width>
<height>400</height> <height>461</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_4"> <layout class="QVBoxLayout" name="verticalLayout_4">
@ -232,7 +232,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>679</width> <width>679</width>
<height>400</height> <height>3000</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -245,14 +245,13 @@
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>10</x> <x>10</x>
<y>11</y> <y>10</y>
<width>679</width> <width>679</width>
<height>2962</height> <height>3000</height>
</rect> </rect>
</property> </property>
<layout class="QGridLayout" name="settingsContentsGridLayout" rowstretch="0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"> <layout class="QGridLayout" name="settingsContentsGridLayout" rowstretch="0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0">
<item row="14" column="0"> <item row="14" column="0">
<widget class="QGroupBox" name="samGroupBox"> <widget class="QGroupBox" name="samGroupBox">
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
@ -360,9 +359,6 @@
</layout> </layout>
</widget> </widget>
</widget> </widget>
</item> </item>
<item row="8" column="0"> <item row="8" column="0">
<widget class="QLabel" name="winOptLabel"> <widget class="QLabel" name="winOptLabel">
@ -2570,13 +2566,13 @@ Comma separated list of base64 identities:</string>
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>0</width> <width>0</width>
<height>370</height> <height>400</height>
</size> </size>
</property> </property>
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>16777215</width> <width>16777215</width>
<height>370</height> <height>400</height>
</size> </size>
</property> </property>
<property name="title"> <property name="title">
@ -2997,8 +2993,8 @@ Comma separated list of base64 identities:</string>
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>681</width> <width>706</width>
<height>460</height> <height>461</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_6"> <layout class="QVBoxLayout" name="verticalLayout_6">
@ -3064,8 +3060,8 @@ Comma separated list of base64 identities:</string>
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>663</width> <width>699</width>
<height>395</height> <height>425</height>
</rect> </rect>
</property> </property>
</widget> </widget>
@ -3080,8 +3076,8 @@ Comma separated list of base64 identities:</string>
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>681</width> <width>686</width>
<height>451</height> <height>496</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_3"> <layout class="QVBoxLayout" name="verticalLayout_3">
@ -3135,8 +3131,8 @@ Comma separated list of base64 identities:</string>
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>671</width> <width>686</width>
<height>480</height> <height>496</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="quitPageVerticalLayout"> <layout class="QVBoxLayout" name="quitPageVerticalLayout">