Browse Source

Merge pull request #920 from PurpleI2P/openssl

2.15.0
pull/1036/head
orignal 7 years ago committed by GitHub
parent
commit
c21c1f5225
  1. 14
      ChangeLog
  2. 9
      README.md
  3. 26
      Win32/Win32Service.cpp
  4. 2
      Win32/installer.iss
  5. 2
      android/AndroidManifest.xml
  6. 2
      appveyor.yml
  7. 13
      contrib/certificates/family/gostcoin.crt
  8. 4
      contrib/debian/i2pd.service
  9. 2
      contrib/docker/Dockerfile
  10. 2
      contrib/docker/entrypoint.sh
  11. 2
      contrib/i2pd.conf
  12. 13
      contrib/rpm/i2pd.spec
  13. 91
      daemon/HTTPServer.cpp
  14. 6
      debian/changelog
  15. 2099
      docs/Doxyfile
  16. 551
      libi2pd/Config.cpp
  17. 2
      libi2pd/Destination.cpp
  18. 8
      libi2pd/Destination.h
  19. 4
      libi2pd/HTTP.cpp
  20. 12
      libi2pd/HTTP.h
  21. 307
      libi2pd/Identity.cpp
  22. 82
      libi2pd/Identity.h
  23. 4
      libi2pd/NetDb.cpp
  24. 30
      libi2pd/SSU.cpp
  25. 3
      libi2pd/Tag.h
  26. 15
      libi2pd/Transports.cpp
  27. 2
      libi2pd/Transports.h
  28. 2
      libi2pd/Tunnel.h
  29. 4
      libi2pd/version.h
  30. 23
      libi2pd_client/AddressBook.cpp
  31. 112
      libi2pd_client/ClientContext.cpp
  32. 3
      libi2pd_client/ClientContext.h
  33. 5
      libi2pd_client/HTTPProxy.cpp
  34. 32
      libi2pd_client/I2PService.cpp
  35. 23
      libi2pd_client/I2PService.h
  36. 2
      libi2pd_client/SAM.cpp
  37. 12
      libi2pd_client/SOCKS.cpp
  38. 15
      libi2pd_client/SOCKS.h
  39. 1
      qt/i2pd_qt/ClientTunnelPane.h
  40. 1
      qt/i2pd_qt/DaemonQT.cpp
  41. 1
      qt/i2pd_qt/ServerTunnelPane.h
  42. 11
      qt/i2pd_qt/SignatureTypeComboboxFactory.h
  43. 3
      qt/i2pd_qt/TunnelConfig.h
  44. 1
      qt/i2pd_qt/TunnelPane.h
  45. 2
      qt/i2pd_qt/android/AndroidManifest.xml
  46. 19
      qt/i2pd_qt/mainwindow.cpp
  47. 27
      qt/i2pd_qt/mainwindow.h
  48. 50
      qt/i2pd_qt/mainwindow.ui

14
ChangeLog

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

9
README.md

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

26
Win32/Win32Service.cpp

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

2
Win32/installer.iss

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

2
android/AndroidManifest.xml

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

2
appveyor.yml

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

13
contrib/certificates/family/gostcoin.crt

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

4
contrib/debian/i2pd.service vendored

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

2
contrib/docker/Dockerfile

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

2
contrib/docker/entrypoint.sh

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

2
contrib/i2pd.conf

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

13
contrib/rpm/i2pd.spec

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

91
daemon/HTTPServer.cpp

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

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

2099
docs/Doxyfile

File diff suppressed because it is too large Load Diff

551
libi2pd/Config.cpp

@ -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");
sam.add_options() options_description sam("SAM bridge options");
("sam.enabled", value<bool>()->default_value(true), "Enable or disable SAM Application bridge") sam.add_options()
("sam.address", value<std::string>()->default_value("127.0.0.1"), "SAM listen address") ("sam.enabled", value<bool>()->default_value(true), "Enable or disable SAM Application bridge")
("sam.port", value<uint16_t>()->default_value(7656), "SAM listen port") ("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")
;
options_description bob("BOB options");
bob.add_options() options_description bob("BOB options");
("bob.enabled", value<bool>()->default_value(false), "Enable or disable BOB command channel") bob.add_options()
("bob.address", value<std::string>()->default_value("127.0.0.1"), "BOB listen address") ("bob.enabled", value<bool>()->default_value(false), "Enable or disable BOB command channel")
("bob.port", value<uint16_t>()->default_value(2827), "BOB listen port") ("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")
;
options_description i2cp("I2CP options");
i2cp.add_options() options_description i2cp("I2CP options");
("i2cp.enabled", value<bool>()->default_value(false), "Enable or disable I2CP") i2cp.add_options()
("i2cp.address", value<std::string>()->default_value("127.0.0.1"), "I2CP listen address") ("i2cp.enabled", value<bool>()->default_value(false), "Enable or disable I2CP")
("i2cp.port", value<uint16_t>()->default_value(7654), "I2CP listen port") ("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")
;
options_description i2pcontrol("I2PControl options");
i2pcontrol.add_options() options_description i2pcontrol("I2PControl options");
("i2pcontrol.enabled", value<bool>()->default_value(false), "Enable or disable I2P Control Protocol") i2pcontrol.add_options()
("i2pcontrol.address", value<std::string>()->default_value("127.0.0.1"), "I2PCP listen address") ("i2pcontrol.enabled", value<bool>()->default_value(false), "Enable or disable I2P Control Protocol")
("i2pcontrol.port", value<uint16_t>()->default_value(7650), "I2PCP listen port") ("i2pcontrol.address", value<std::string>()->default_value("127.0.0.1"), "I2PCP listen address")
("i2pcontrol.password", value<std::string>()->default_value("itoopie"), "I2PCP access password") ("i2pcontrol.port", value<uint16_t>()->default_value(7650), "I2PCP listen port")
("i2pcontrol.cert", value<std::string>()->default_value("i2pcontrol.crt.pem"), "I2PCP connection cerificate") ("i2pcontrol.password", value<std::string>()->default_value("itoopie"), "I2PCP access password")
("i2pcontrol.key", value<std::string>()->default_value("i2pcontrol.key.pem"), "I2PCP connection cerificate key") ("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")
;
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");
websocket.add_options() options_description websocket("Websocket Options");
("websockets.enabled", value<bool>()->default_value(false), "enable websocket server") websocket.add_options()
("websockets.address", value<std::string>()->default_value("127.0.0.1"), "address to bind websocket server on") ("websockets.enabled", value<bool>()->default_value(false), "Enable websocket server")
("websockets.port", value<uint16_t>()->default_value(7666), "port 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")
options_description exploratory("Exploratory Options"); ;
exploratory.add_options()
("exploratory.inbound.length", value<int>()->default_value(2), "Exploratory inbound tunnel length") options_description exploratory("Exploratory Options");
("exploratory.outbound.length", value<int>()->default_value(2), "Exploratory outbound tunnel length") exploratory.add_options()
("exploratory.inbound.quantity", value<int>()->default_value(3), "Exploratory inbound tunnels quantity") ("exploratory.inbound.length", value<int>()->default_value(2), "Exploratory inbound tunnel length")
("exploratory.outbound.quantity", value<int>()->default_value(3), "Exploratory outbound tunnels quantity"); ("exploratory.outbound.length", value<int>()->default_value(2), "Exploratory outbound tunnel length")
("exploratory.inbound.quantity", value<int>()->default_value(3), "Exploratory inbound tunnels quantity")
m_OptionsDesc ("exploratory.outbound.quantity", value<int>()->default_value(3), "Exploratory outbound tunnels quantity")
.add(general) ;
.add(limits)
.add(httpserver) m_OptionsDesc
.add(httpproxy) .add(general)
.add(socksproxy) .add(limits)
.add(sam) .add(httpserver)
.add(bob) .add(httpproxy)
.add(i2cp) .add(socksproxy)
.add(i2pcontrol) .add(sam)
.add(upnp) .add(bob)
.add(precomputation) .add(i2cp)
.add(reseed) .add(i2pcontrol)
.add(addressbook) .add(upnp)
.add(trust) .add(precomputation)
.add(websocket) .add(reseed)
.add(exploratory) .add(addressbook)
; .add(trust)
} .add(websocket)
.add(exploratory)
void ParseCmdline(int argc, char* argv[], bool ignoreUnknown) ;
{ }
try
void ParseCmdline(int argc, char* argv[], bool ignoreUnknown)
{ {
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);
} std::ifstream config(path, std::ios::in);
if (!ignoreUnknown && (m_Options.count("help") || m_Options.count("h"))) 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; {
if (!m_Options.count(name))
throw "try to check non-existent option";
std::ifstream config(path, std::ios::in); if (m_Options[name].defaulted())
return true;
return false;
}
if (!config.is_open()) bool GetOptionAsAny(const char *name, boost::any& value)
{ {
std::cerr << "missing/unreadable config file: " << path << std::endl; if (!m_Options.count(name))
exit(EXIT_FAILURE); return false;
} value = m_Options[name];
return true;
}
try bool GetOptionAsAny(const std::string& name, boost::any& value)
{
store(boost::program_options::parse_config_file(config, m_OptionsDesc), m_Options);
}
catch (boost::program_options::error& e)
{ {
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

2
libi2pd/Destination.cpp

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

8
libi2pd/Destination.h

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

4
libi2pd/HTTP.cpp

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

12
libi2pd/HTTP.h

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

307
libi2pd/Identity.cpp

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

82
libi2pd/Identity.h

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

4
libi2pd/NetDb.cpp

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

30
libi2pd/SSU.cpp

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

3
libi2pd/Tag.h

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

15
libi2pd/Transports.cpp

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

2
libi2pd/Transports.h

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

2
libi2pd/Tunnel.h

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

4
libi2pd/version.h

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

23
libi2pd_client/AddressBook.cpp

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

112
libi2pd_client/ClientContext.cpp

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

3
libi2pd_client/ClientContext.h

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

5
libi2pd_client/HTTPProxy.cpp

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

32
libi2pd_client/I2PService.cpp

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

23
libi2pd_client/I2PService.h

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

2
libi2pd_client/SAM.cpp

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

12
libi2pd_client/SOCKS.cpp

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

15
libi2pd_client/SOCKS.h

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

1
qt/i2pd_qt/ClientTunnelPane.h

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

1
qt/i2pd_qt/DaemonQT.cpp

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

1
qt/i2pd_qt/ServerTunnelPane.h

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

11
qt/i2pd_qt/SignatureTypeComboboxFactory.h

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

3
qt/i2pd_qt/TunnelConfig.h

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

1
qt/i2pd_qt/TunnelPane.h

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

2
qt/i2pd_qt/android/AndroidManifest.xml

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

19
qt/i2pd_qt/mainwindow.cpp

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

27
qt/i2pd_qt/mainwindow.h

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

50
qt/i2pd_qt/mainwindow.ui

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

Loading…
Cancel
Save