diff --git a/ChangeLog b/ChangeLog index ca30a1ac..9013ede8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,21 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog +## [2.22.0] - 2018-11-09 +### Added +- Multiple tunnel config files from tunnels.d folder +### Changed +- Fetch own RouterInfo upon SessionRequest for NTCP2 +- Faster XOR between AES blocks for non AVX capable CPUs +### Fixed +- Fixed NTCP2 termination send + +## [2.21.1] - 2018-10-22 +### Changed +- cost=13 for unpublished NTCP2 address +### Fixed +- Handle I2NP messages longer than 32K + ## [2.21.0] - 2018-10-04 ### Added - EdDSA, x25519 and SipHash from openssl 1.1.1 diff --git a/Win32/installer.iss b/Win32/installer.iss index 8372a444..787eebeb 100644 --- a/Win32/installer.iss +++ b/Win32/installer.iss @@ -1,5 +1,5 @@ #define I2Pd_AppName "i2pd" -#define I2Pd_ver "2.21.0" +#define I2Pd_ver "2.22.0" #define I2Pd_Publisher "PurpleI2P" [Setup] @@ -32,6 +32,7 @@ Source: ..\contrib\i2pd.conf; DestDir: {userappdata}\i2pd; Flags: onlyifdoesntex Source: ..\contrib\subscriptions.txt; DestDir: {userappdata}\i2pd; Flags: onlyifdoesntexist Source: ..\contrib\tunnels.conf; DestDir: {userappdata}\i2pd; Flags: onlyifdoesntexist Source: ..\contrib\certificates\*; DestDir: {userappdata}\i2pd\certificates; Flags: onlyifdoesntexist recursesubdirs createallsubdirs +Source: ..\contrib\tunnels.d\*; DestDir: {userappdata}\i2pd\tunnels.d; Flags: onlyifdoesntexist recursesubdirs createallsubdirs [Icons] Name: {group}\I2Pd; Filename: {app}\i2pd.exe diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index e5a711aa..5ad3834e 100755 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -3,7 +3,7 @@ package="org.purplei2p.i2pd" android:installLocation="auto" android:versionCode="1" - android:versionName="2.21.0"> + android:versionName="2.22.0"> i2pd Stop Graceful Stop + Cancel Graceful Stop Graceful stop is already in progress Graceful stop is in progress Already stopped diff --git a/android/src/org/purplei2p/i2pd/DaemonSingleton.java b/android/src/org/purplei2p/i2pd/DaemonSingleton.java index 4f3e62f7..4c3d5f44 100644 --- a/android/src/org/purplei2p/i2pd/DaemonSingleton.java +++ b/android/src/org/purplei2p/i2pd/DaemonSingleton.java @@ -33,6 +33,13 @@ public class DaemonSingleton { } } + public synchronized void startAcceptingTunnels() { + if(isStartedOkay()){ + setState(State.startedOkay); + I2PD_JNI.startAcceptingTunnels(); + } + } + private volatile boolean startedOkay; public enum State { diff --git a/android/src/org/purplei2p/i2pd/I2PDActivity.java b/android/src/org/purplei2p/i2pd/I2PDActivity.java index bc6f7209..3c95a832 100755 --- a/android/src/org/purplei2p/i2pd/I2PDActivity.java +++ b/android/src/org/purplei2p/i2pd/I2PDActivity.java @@ -13,13 +13,16 @@ import java.io.StringWriter; import java.util.Timer; import java.util.TimerTask; +import android.Manifest; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.res.AssetManager; +import android.content.pm.PackageManager; import android.os.Bundle; +import android.os.Build; import android.os.Environment; import android.os.IBinder; import android.util.Log; @@ -27,12 +30,15 @@ import android.view.Menu; import android.view.MenuItem; import android.widget.TextView; import android.widget.Toast; +import android.support.v4.app.ActivityCompat; +import android.support.v4.content.ContextCompat; // For future package update checking import org.purplei2p.i2pd.BuildConfig; public class I2PDActivity extends Activity { private static final String TAG = "i2pdActvt"; + private static final int MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE = 1; public static final int GRACEFUL_DELAY_MILLIS = 10 * 60 * 1000; private TextView textView; @@ -93,6 +99,17 @@ public class I2PDActivity extends Activity { daemon.addStateChangeListener(daemonStateUpdatedListener); daemonStateUpdatedListener.daemonStateUpdate(); + // request permissions + if (Build.VERSION.SDK_INT >= 23) + { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) + { + ActivityCompat.requestPermissions(this, + new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE); + } + } + // set the app be foreground doBindService(); @@ -119,6 +136,24 @@ public class I2PDActivity extends Activity { } } + @Override + public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) + { + switch (requestCode) + { + case MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE: + { + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) + Log.e(TAG, "Memory permission granted"); + else + Log.e(TAG, "Memory permission declined"); + // TODO: terminate + return; + } + default: ; + } + } + private static void cancelGracefulStop() { Timer gracefulQuitTimer = getGracefulQuitTimer(); if(gracefulQuitTimer!=null) { @@ -205,7 +240,16 @@ public class I2PDActivity extends Activity { i2pdStop(); return true; case R.id.action_graceful_stop: - i2pdGracefulStop(); + if (getGracefulQuitTimer()!= null) + { + item.setTitle(R.string.action_graceful_stop); + i2pdCancelGracefulStop (); + } + else + { + item.setTitle(R.string.action_cancel_graceful_stop); + i2pdGracefulStop(); + } return true; } @@ -268,6 +312,32 @@ public class I2PDActivity extends Activity { },"gracInit").start(); } + + private void i2pdCancelGracefulStop() + { + cancelGracefulStop(); + Toast.makeText(this, R.string.startedOkay, Toast.LENGTH_SHORT).show(); + new Thread(new Runnable() + { + @Override + public void run() + { + try + { + Log.d(TAG, "grac stopping cancel"); + if(daemon.isStartedOkay()) + daemon.startAcceptingTunnels(); + else + i2pdStop(); + } + catch(Throwable tr) + { + Log.e(TAG,"",tr); + } + } + + },"gracCancel").start(); + } private void rescheduleGraceStop(Timer gracefulQuitTimerOld, long gracefulStopAtMillis) { if(gracefulQuitTimerOld!=null)gracefulQuitTimerOld.cancel(); diff --git a/android/src/org/purplei2p/i2pd/I2PD_JNI.java b/android/src/org/purplei2p/i2pd/I2PD_JNI.java index f965d471..63867273 100644 --- a/android/src/org/purplei2p/i2pd/I2PD_JNI.java +++ b/android/src/org/purplei2p/i2pd/I2PD_JNI.java @@ -12,6 +12,8 @@ public class I2PD_JNI { public static native void stopAcceptingTunnels(); + public static native void startAcceptingTunnels(); + public static native void onNetworkStateChanged(boolean isConnected); public static void loadLibraries() { diff --git a/appveyor.yml b/appveyor.yml index bcaad455..bb9be2ec 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 2.21.{build} +version: 2.22.0.{build} pull_requests: do_not_increment_build_number: true branches: diff --git a/build/build_mingw.cmd b/build/build_mingw.cmd index 7f163878..d7fe363d 100644 --- a/build/build_mingw.cmd +++ b/build/build_mingw.cmd @@ -21,6 +21,8 @@ set MSYSTEM=MINGW32 set "xSH=%WD%bash -lc" +set "FILELIST=i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates contrib/tunnels.d" + REM detecting number of processors and subtract 1. set /a threads=%NUMBER_OF_PROCESSORS%-1 @@ -62,12 +64,12 @@ exit /b 0 %xSH% "make clean" >> nul echo Building i2pd %tag% for win%bitness%: echo Build AVX+AESNI... -%xSH% "make DEBUG=no USE_UPNP=yes USE_AVX=1 USE_AESNI=1 -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw_avx_aesni.zip i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates && make clean" > build/build_win%bitness%_avx_aesni.log 2>&1 +%xSH% "make DEBUG=no USE_UPNP=yes USE_AVX=1 USE_AESNI=1 -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw_avx_aesni.zip %FILELIST% && make clean" > build/build_win%bitness%_avx_aesni_%tag%.log 2>&1 echo Build AVX... -%xSH% "make DEBUG=no USE_UPNP=yes USE_AVX=1 -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw_avx.zip i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates && make clean" > build/build_win%bitness%_avx.log 2>&1 +%xSH% "make DEBUG=no USE_UPNP=yes USE_AVX=1 -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw_avx.zip %FILELIST% && make clean" > build/build_win%bitness%_avx_%tag%.log 2>&1 echo Build AESNI... -%xSH% "make DEBUG=no USE_UPNP=yes USE_AESNI=1 -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw_aesni.zip i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates && make clean" > build/build_win%bitness%_aesni.log 2>&1 +%xSH% "make DEBUG=no USE_UPNP=yes USE_AESNI=1 -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw_aesni.zip %FILELIST% && make clean" > build/build_win%bitness%_aesni_%tag%.log 2>&1 echo Build without extensions... -%xSH% "make DEBUG=no USE_UPNP=yes -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw.zip i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates && make clean" > build/build_win%bitness%.log 2>&1 +%xSH% "make DEBUG=no USE_UPNP=yes -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw.zip %FILELIST% && make clean" > build/build_win%bitness%_%tag%.log 2>&1 :EOF \ No newline at end of file diff --git a/contrib/i2pd.conf b/contrib/i2pd.conf index 92abf496..1ef725bb 100644 --- a/contrib/i2pd.conf +++ b/contrib/i2pd.conf @@ -10,6 +10,11 @@ ## Default: ~/.i2pd/tunnels.conf or /var/lib/i2pd/tunnels.conf # tunconf = /var/lib/i2pd/tunnels.conf +## Tunnels config files path +## Use that path to store separated tunnels in different config files. +## Default: ~/.i2pd/tunnels.d or /var/lib/i2pd/tunnels.d +# tunnelsdir = /var/lib/i2pd/tunnels.conf.d + ## Where to write pidfile (don't write by default) # pidfile = /var/run/i2pd.pid @@ -88,6 +93,8 @@ ipv6 = false ## Address and port service will listen on address = 127.0.0.1 port = 7070 +## Path to web console, default "/" +# webroot = / ## Uncomment following lines to enable Web Console authentication # auth = true # user = i2pd @@ -218,3 +225,7 @@ verify = true # inbound.quantity = 3 # outbound.length = 2 # outbound.quantity = 3 + +[persist] +## Save peer profiles on disk (default: true) +# profiles = true diff --git a/contrib/i2pd.service b/contrib/i2pd.service index debd49b0..a8eeb8d3 100644 --- a/contrib/i2pd.service +++ b/contrib/i2pd.service @@ -11,7 +11,7 @@ RuntimeDirectoryMode=0700 LogsDirectory=i2pd LogsDirectoryMode=0700 Type=forking -ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service +ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --tunnelsdir=/etc/i2pd/tunnels.conf.d --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service ExecReload=/bin/kill -HUP $MAINPID PIDFile=/var/run/i2pd/i2pd.pid ### Uncomment, if auto restart needed @@ -23,8 +23,10 @@ KillSignal=SIGQUIT #KillSignal=SIGINT #TimeoutStopSec=10m -# If you have problems with hanging i2pd, you can try enable this +# If you have problems with hanging i2pd, you can try increase this LimitNOFILE=4096 +# To enable write of coredump uncomment this +#LimitCORE=infinity PrivateDevices=yes [Install] diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index 627b81ae..7888878d 100644 --- a/contrib/rpm/i2pd-git.spec +++ b/contrib/rpm/i2pd-git.spec @@ -1,7 +1,7 @@ %define git_hash %(git rev-parse HEAD | cut -c -7) Name: i2pd-git -Version: 2.21.0 +Version: 2.22.0 Release: git%{git_hash}%{?dist} Summary: I2P router written in C++ Conflicts: i2pd @@ -55,15 +55,21 @@ make %{?_smp_mflags} %install cd build +%if 0%{?mageia} +cd build +%endif chrpath -d i2pd -install -D -m 755 i2pd %{buildroot}%{_sbindir}/i2pd -install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf -install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/tunnels.conf %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf -install -d -m 755 %{buildroot}%{_datadir}/i2pd -%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/certificates/ %{buildroot}%{_datadir}/i2pd/certificates -install -D -m 644 %{_builddir}/%{name}-%{version}/contrib/rpm/i2pd.service %{buildroot}%{_unitdir}/i2pd.service -install -d -m 700 %{buildroot}%{_sharedstatedir}/i2pd -install -d -m 700 %{buildroot}%{_localstatedir}/log/i2pd +%{__install} -D -m 755 i2pd %{buildroot}%{_sbindir}/i2pd +%{__install} -D -m 755 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf +%{__install} -D -m 755 %{_builddir}/%{name}-%{version}/contrib/subscriptions.txt %{buildroot}%{_sysconfdir}/i2pd/subscriptions.txt +%{__install} -D -m 755 %{_builddir}/%{name}-%{version}/contrib/tunnels.conf %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf +%{__install} -D -m 755 %{_builddir}/%{name}-%{version}/contrib/tunnels.d/README %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf.d/README +%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/contrib/rpm/i2pd.service %{buildroot}%{_unitdir}/i2pd.service +%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/debian/i2pd.1 %{buildroot}%{_mandir}/man1/i2pd.1 +%{__install} -d -m 700 %{buildroot}%{_sharedstatedir}/i2pd +%{__install} -d -m 700 %{buildroot}%{_localstatedir}/log/i2pd +%{__install} -d -m 755 %{buildroot}%{_datadir}/%{name} +%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/certificates/ %{buildroot}%{_datadir}/%{name}/certificates ln -s %{_datadir}/%{name}/certificates %{buildroot}%{_sharedstatedir}/i2pd/certificates @@ -87,16 +93,20 @@ getent passwd i2pd >/dev/null || \ %files -%doc LICENSE README.md +%doc LICENSE README.md contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf contrib/tunnels.d %{_sbindir}/i2pd -%{_datadir}/i2pd/certificates %config(noreplace) %{_sysconfdir}/i2pd/* -/%{_unitdir}/i2pd.service -%dir %attr(0700,i2pd,i2pd) %{_localstatedir}/log/i2pd +%{_unitdir}/i2pd.service +%{_mandir}/man1/i2pd.1* %dir %attr(0700,i2pd,i2pd) %{_sharedstatedir}/i2pd +%dir %attr(0700,i2pd,i2pd) %{_localstatedir}/log/i2pd +%{_datadir}/%{name}/certificates %{_sharedstatedir}/i2pd/certificates %changelog +* Fri Nov 09 2018 r4sas - 2.22.0 +- add support of tunnelsdir option + * Thu Feb 01 2018 r4sas - 2.18.0 - Initial i2pd-git based on i2pd 2.18.0-1 spec diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 2deeecab..f7577f0e 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,5 +1,5 @@ Name: i2pd -Version: 2.21.0 +Version: 2.22.0 Release: 1%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git @@ -53,16 +53,22 @@ make %{?_smp_mflags} %install cd build +%if 0%{?mageia} +cd build +%endif chrpath -d i2pd install -D -m 755 i2pd %{buildroot}%{_sbindir}/i2pd install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/tunnels.conf %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf install -d -m 755 %{buildroot}%{_datadir}/i2pd +install -d -m 755 %{buildroot}%{_datadir}/i2pd/tunnels.conf.d %{__cp} -r %{_builddir}/%{name}-%{version}/contrib/certificates/ %{buildroot}%{_datadir}/i2pd/certificates +%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/tunnels.d/ %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf.d install -D -m 644 %{_builddir}/%{name}-%{version}/contrib/rpm/i2pd.service %{buildroot}%{_unitdir}/i2pd.service install -d -m 700 %{buildroot}%{_sharedstatedir}/i2pd install -d -m 700 %{buildroot}%{_localstatedir}/log/i2pd ln -s %{_datadir}/%{name}/certificates %{buildroot}%{_sharedstatedir}/i2pd/certificates +ln -s %{_datadir}/i2pd/tunnels.conf.d %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf.d %pre @@ -89,6 +95,7 @@ getent passwd i2pd >/dev/null || \ %{_sbindir}/i2pd %{_datadir}/i2pd/certificates %config(noreplace) %{_sysconfdir}/i2pd/* +%config(noreplace) %{_sysconfdir}/i2pd/tunnels.conf.d/* /%{_unitdir}/i2pd.service %dir %attr(0700,i2pd,i2pd) %{_localstatedir}/log/i2pd %dir %attr(0700,i2pd,i2pd) %{_sharedstatedir}/i2pd @@ -96,6 +103,13 @@ getent passwd i2pd >/dev/null || \ %changelog +* Fri Nov 09 2018 r4sas - 2.22.0 +- update to 2.22.0 +- add support of tunnelsdir option + +* Thu Oct 22 2018 orignal - 2.21.1 +- update to 2.21.1 + * Thu Oct 4 2018 orignal - 2.21.0 - update to 2.21.0 diff --git a/contrib/tunnels.d/IRC-Ilita.conf b/contrib/tunnels.d/IRC-Ilita.conf new file mode 100644 index 00000000..74d836aa --- /dev/null +++ b/contrib/tunnels.d/IRC-Ilita.conf @@ -0,0 +1,7 @@ +#[IRC-ILITA] +#type = client +#address = 127.0.0.1 +#port = 6669 +#destination = irc.ilita.i2p +#destinationport = 6667 +#keys = irc-keys.dat diff --git a/contrib/tunnels.d/IRC-Irc2P.conf b/contrib/tunnels.d/IRC-Irc2P.conf new file mode 100644 index 00000000..97da71dc --- /dev/null +++ b/contrib/tunnels.d/IRC-Irc2P.conf @@ -0,0 +1,7 @@ +#[IRC-IRC2P] +#type = client +#address = 127.0.0.1 +#port = 6668 +#destination = irc.postman.i2p +#destinationport = 6667 +#keys = irc-keys.dat diff --git a/contrib/tunnels.d/README b/contrib/tunnels.d/README new file mode 100644 index 00000000..7b07c4be --- /dev/null +++ b/contrib/tunnels.d/README @@ -0,0 +1,4 @@ +# In that directory you can store separated config files for every tunnel. +# Please read documentation for more info. +# +# You can find examples in /usr/share/doc/i2pd/tunnels.d directory diff --git a/daemon/Daemon.cpp b/daemon/Daemon.cpp index 0b88e983..8e0804d1 100644 --- a/daemon/Daemon.cpp +++ b/daemon/Daemon.cpp @@ -23,6 +23,7 @@ #include "ClientContext.h" #include "Crypto.h" #include "UPnP.h" +#include "Timestamp.h" #include "util.h" #include "Event.h" @@ -41,6 +42,7 @@ namespace i2p std::unique_ptr httpServer; std::unique_ptr m_I2PControlService; std::unique_ptr UPnP; + std::unique_ptr m_NTPSync; #ifdef WITH_EVENTS std::unique_ptr m_WebsocketServer; #endif @@ -282,6 +284,13 @@ namespace i2p d.UPnP->Start (); } + bool nettime; i2p::config::GetOption("nettime.enabled", nettime); + if (nettime) + { + d.m_NTPSync = std::unique_ptr(new i2p::util::NTPTimeSync); + d.m_NTPSync->Start (); + } + bool ntcp; i2p::config::GetOption("ntcp", ntcp); bool ssu; i2p::config::GetOption("ssu", ssu); LogPrint(eLogInfo, "Daemon: starting Transports"); @@ -351,11 +360,18 @@ namespace i2p LogPrint(eLogInfo, "Daemon: stopping Tunnels"); i2p::tunnel::tunnels.Stop(); - if (d.UPnP) { + if (d.UPnP) + { d.UPnP->Stop (); d.UPnP = nullptr; } + if (d.m_NTPSync) + { + d.m_NTPSync->Stop (); + d.m_NTPSync = nullptr; + } + LogPrint(eLogInfo, "Daemon: stopping Transports"); i2p::transport::transports.Stop(); LogPrint(eLogInfo, "Daemon: stopping NetDB"); diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index b4c3f79b..ccf2640c 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -155,6 +155,8 @@ namespace http { static void ShowPageHead (std::stringstream& s) { + std::string webroot; + i2p::config::GetOption("http.webroot", webroot); s << "\r\n" "\r\n" /* TODO: Add support for locale */ @@ -173,16 +175,16 @@ namespace http { "
i2pd webconsole
\r\n" "
\r\n" "
\r\n" - " Main page
\r\n
\r\n" - " Router commands
\r\n" - " Local destinations
\r\n" - " LeaseSets
\r\n" - " Tunnels
\r\n" - " Transit tunnels
\r\n" - " Transports
\r\n" - " I2P tunnels
\r\n"; + " Main page
\r\n
\r\n" + " Router commands
\r\n" + " Local destinations
\r\n" + " LeaseSets
\r\n" + " Tunnels
\r\n" + " Transit tunnels
\r\n" + " Transports
\r\n" + " I2P tunnels
\r\n"; if (i2p::client::context.GetSAMBridge ()) - s << " SAM sessions
\r\n"; + s << " SAM sessions
\r\n"; s << "
\r\n" "
"; @@ -321,11 +323,12 @@ namespace http { void ShowLocalDestinations (std::stringstream& s) { + std::string webroot; i2p::config::GetOption("http.webroot", webroot); s << "Local Destinations:
\r\n
\r\n"; for (auto& it: i2p::client::context.GetDestinations ()) { auto ident = it.second->GetIdentHash (); - s << ""; + s << ""; s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "
\r\n" << std::endl; } @@ -340,7 +343,7 @@ namespace http { { auto ident = dest->GetIdentHash (); auto& name = dest->GetNickname (); - s << "[ "; + s << "[ "; s << name << " ] ⇔ " << i2p::client::context.GetAddressBook ().ToAddress(ident) <<"
\r\n" << std::endl; } } @@ -510,33 +513,34 @@ namespace http { static void ShowCommands (std::stringstream& s, uint32_t token) { + std::string webroot; i2p::config::GetOption("http.webroot", webroot); /* commands */ s << "Router Commands
\r\n
\r\n"; - s << " Run peer test
\r\n"; + s << " Run peer test
\r\n"; //s << " Reload config
\r\n"; if (i2p::context.AcceptsTunnels ()) - s << " Decline transit tunnels
\r\n"; + s << " Decline transit tunnels
\r\n"; else - s << " Accept transit tunnels
\r\n"; + s << " Accept transit tunnels
\r\n"; #if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY)) if (Daemon.gracefulShutdownInterval) - s << " Cancel graceful shutdown
"; + s << " Cancel graceful shutdown
"; else - s << " Start graceful shutdown
\r\n"; + s << " Start graceful shutdown
\r\n"; #elif defined(WIN32_APP) if (i2p::util::DaemonWin32::Instance().isGraceful) - s << " Cancel graceful shutdown
"; + s << " Cancel graceful shutdown
"; else - s << " Graceful shutdown
\r\n"; + s << " Graceful shutdown
\r\n"; #endif - s << " Force shutdown
\r\n"; + s << " Force shutdown
\r\n"; s << "
\r\nLogging level
\r\n"; - s << " [none] "; - s << " [error] "; - s << " [warn] "; - s << " [info] "; - s << " [debug]
\r\n"; + s << " [none] "; + s << " [error] "; + s << " [warn] "; + s << " [info] "; + s << " [debug]
\r\n"; } void ShowTransitTunnels (std::stringstream& s) @@ -653,6 +657,7 @@ namespace http { void ShowSAMSessions (std::stringstream& s) { + std::string webroot; i2p::config::GetOption("http.webroot", webroot); auto sam = i2p::client::context.GetSAMBridge (); if (!sam) { ShowError(s, "SAM disabled"); @@ -662,13 +667,14 @@ namespace http { for (auto& it: sam->GetSessions ()) { auto& name = it.second->localDestination->GetNickname (); - s << ""; + s << ""; s << name << " (" << it.first << ")
\r\n" << std::endl; } } static void ShowSAMSession (std::stringstream& s, const std::string& id) { + std::string webroot; i2p::config::GetOption("http.webroot", webroot); s << "SAM Session:
\r\n
\r\n"; auto sam = i2p::client::context.GetSAMBridge (); if (!sam) { @@ -681,7 +687,7 @@ namespace http { return; } auto& ident = session->localDestination->GetIdentHash(); - s << ""; + s << ""; s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "
\r\n"; s << "
\r\n"; s << "Streams:
\r\n"; @@ -701,11 +707,12 @@ namespace http { void ShowI2PTunnels (std::stringstream& s) { + std::string webroot; i2p::config::GetOption("http.webroot", webroot); s << "Client Tunnels:
\r\n
\r\n"; for (auto& it: i2p::client::context.GetClientTunnels ()) { auto& ident = it.second->GetLocalDestination ()->GetIdentHash(); - s << ""; + s << ""; s << it.second->GetName () << " ⇐ "; s << i2p::client::context.GetAddressBook ().ToAddress(ident); s << "
\r\n"<< std::endl; @@ -714,7 +721,7 @@ namespace http { if (httpProxy) { auto& ident = httpProxy->GetLocalDestination ()->GetIdentHash(); - s << ""; + s << ""; s << "HTTP Proxy" << " ⇐ "; s << i2p::client::context.GetAddressBook ().ToAddress(ident); s << "
\r\n"<< std::endl; @@ -723,7 +730,7 @@ namespace http { if (socksProxy) { auto& ident = socksProxy->GetLocalDestination ()->GetIdentHash(); - s << ""; + s << ""; s << "SOCKS Proxy" << " ⇐ "; s << i2p::client::context.GetAddressBook ().ToAddress(ident); s << "
\r\n"<< std::endl; @@ -734,7 +741,7 @@ namespace http { for (auto& it: serverTunnels) { auto& ident = it.second->GetLocalDestination ()->GetIdentHash(); - s << ""; + s << ""; s << it.second->GetName () << " ⇒ "; s << i2p::client::context.GetAddressBook ().ToAddress(ident); s << ":" << it.second->GetLocalPort (); @@ -748,7 +755,7 @@ namespace http { for (auto& it: clientForwards) { auto& ident = it.second->GetLocalDestination ()->GetIdentHash(); - s << ""; + s << ""; s << it.second->GetName () << " ⇐ "; s << i2p::client::context.GetAddressBook ().ToAddress(ident); s << "
\r\n"<< std::endl; @@ -761,7 +768,7 @@ namespace http { for (auto& it: serverForwards) { auto& ident = it.second->GetLocalDestination ()->GetIdentHash(); - s << ""; + s << ""; s << it.second->GetName () << " ⇐ "; s << i2p::client::context.GetAddressBook ().ToAddress(ident); s << "
\r\n"<< std::endl; @@ -1025,10 +1032,12 @@ namespace http { ShowError(s, "Unknown command: " + cmd); return; } + std::string webroot; i2p::config::GetOption("http.webroot", webroot); + std::string redirect = "5; url=" + webroot + "?page=commands"; s << "SUCCESS: Command accepted

\r\n"; - s << "Back to commands list
\r\n"; + s << "Back to commands list
\r\n"; s << "

You will be redirected in 5 seconds"; - res.add_header("Refresh", "5; url=/?page=commands"); + res.add_header("Refresh", redirect.c_str()); } void HTTPConnection::SendReply (HTTPRes& reply, std::string& content) diff --git a/debian/.gitignore b/debian/.gitignore index 6bc6bcf2..b03f9e24 100644 --- a/debian/.gitignore +++ b/debian/.gitignore @@ -1,9 +1,9 @@ +debhelper-build-stamp files i2pd-dbg.substvars -i2pd-dbg/ i2pd.postinst.debhelper i2pd.postrm.debhelper i2pd.prerm.debhelper i2pd.substvars i2pd/ - +i2pd-dbg/ diff --git a/debian/changelog b/debian/changelog index f16fb10d..eb48dbdf 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,18 @@ +i2pd (2.22.0-1) unstable; urgency=medium + + * updated to version 2.22.0/0.9.37 + * update manpage (1) + * update links, install files to support tunnelsdir option + * renamed and updated patch (#1210) + + -- r4sas Fri, 09 Nov 2018 02:00:00 +0000 + +i2pd (2.21.1-1) unstable; urgency=medium + + * updated to version 2.21.1 + + -- orignal Thu, 22 Oct 2018 16:00:00 +0000 + i2pd (2.21.0-1) unstable; urgency=medium * updated to version 2.21.0/0.9.37 diff --git a/debian/docs b/debian/docs index b67deb18..dfa6f572 100644 --- a/debian/docs +++ b/debian/docs @@ -2,3 +2,4 @@ README.md contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf +contrib/tunnels.d diff --git a/debian/i2pd.1 b/debian/i2pd.1 index 9dd44093..5145321f 100644 --- a/debian/i2pd.1 +++ b/debian/i2pd.1 @@ -45,6 +45,9 @@ Log messages with full CLF-formatted date and time (\fIdisabled\fR by default) \fB\-\-datadir=\fR Path to storage of i2pd data (RI, keys, peer profiles, ...) .TP +\fB\-\-tunnelsdir=\fR +Path to tunnels configuration files (default: \fI~/.i2pd/tunnels.d\fR or \fI/var/lib/i2pd/tunnels.d\fR) +.TP \fB\-\-host=\fR The external IP address .TP diff --git a/debian/i2pd.init b/debian/i2pd.init index e4ed01e1..33fd80a5 100644 --- a/debian/i2pd.init +++ b/debian/i2pd.init @@ -18,6 +18,7 @@ DAEMON_OPTS="" # Arguments to run the daemon with PIDFILE=/var/run/$NAME/$NAME.pid I2PCONF=/etc/$NAME/i2pd.conf TUNCONF=/etc/$NAME/tunnels.conf +TUNDIR=/etc/$NAME/tunnels.conf.d LOGFILE=/var/log/$NAME/$NAME.log USER="i2pd" @@ -53,7 +54,7 @@ do_start() || return 1 start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --chuid "$USER" -- \ --service --daemon --log=file --logfile=$LOGFILE --conf=$I2PCONF --tunconf=$TUNCONF \ - --pidfile=$PIDFILE $DAEMON_OPTS > /dev/null 2>&1 \ + --tunnelsdir=$TUNDIR --pidfile=$PIDFILE $DAEMON_OPTS > /dev/null 2>&1 \ || return 2 return $? } diff --git a/debian/i2pd.install b/debian/i2pd.install index d81101fc..d20b2c17 100644 --- a/debian/i2pd.install +++ b/debian/i2pd.install @@ -3,4 +3,5 @@ contrib/i2pd.conf etc/i2pd/ contrib/tunnels.conf etc/i2pd/ contrib/subscriptions.txt etc/i2pd/ contrib/certificates/ usr/share/i2pd/ +contrib/tunnels.d/README etc/i2pd/tunnels.conf.d/ contrib/apparmor/usr.sbin.i2pd etc/apparmor.d diff --git a/debian/i2pd.links b/debian/i2pd.links index e8e2473b..a149967f 100644 --- a/debian/i2pd.links +++ b/debian/i2pd.links @@ -1,4 +1,5 @@ etc/i2pd/i2pd.conf var/lib/i2pd/i2pd.conf etc/i2pd/tunnels.conf var/lib/i2pd/tunnels.conf etc/i2pd/subscriptions.txt var/lib/i2pd/subscriptions.txt +etc/i2pd/tunnels.conf.d var/lib/i2pd/tunnels.d usr/share/i2pd/certificates var/lib/i2pd/certificates diff --git a/debian/i2pd.openrc b/debian/i2pd.openrc index 2ad10bc5..deca4625 100644 --- a/debian/i2pd.openrc +++ b/debian/i2pd.openrc @@ -4,10 +4,11 @@ pidfile="/var/run/i2pd/i2pd.pid" logfile="/var/log/i2pd/i2pd.log" mainconf="/etc/i2pd/i2pd.conf" tunconf="/etc/i2pd/tunnels.conf" +tundir="/etc/i2pd/tunnels.conf.d" name="i2pd" command="/usr/sbin/i2pd" -command_args="--service --daemon --log=file --logfile=$logfile --conf=$mainconf --tunconf=$tunconf --pidfile=$pidfile" +command_args="--service --daemon --log=file --logfile=$logfile --conf=$mainconf --tunconf=$tunconf --tunnelsdir=$tundir --pidfile=$pidfile" description="i2p router written in C++" required_dirs="/var/lib/i2pd" required_files="$mainconf" diff --git a/debian/patches/fix-#1210 b/debian/patches/02-fix-1210.patch similarity index 75% rename from debian/patches/fix-#1210 rename to debian/patches/02-fix-1210.patch index 7e68135c..6a4caf94 100644 --- a/debian/patches/fix-#1210 +++ b/debian/patches/02-fix-1210.patch @@ -6,8 +6,8 @@ Bug: https://github.com/PurpleI2P/i2pd/issues/1210 Reviewed-By: r4sas Last-Update: 2018-08-25 ---- i2pd-2.20.0.orig/contrib/i2pd.service -+++ i2pd-2.20.0/contrib/i2pd.service +--- a/contrib/i2pd.service ++++ b/contrib/i2pd.service @@ -6,10 +6,10 @@ After=network.target [Service] User=i2pd @@ -21,5 +21,5 @@ Last-Update: 2018-08-25 +#LogsDirectory=i2pd +#LogsDirectoryMode=0700 Type=forking - ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service + ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --tunnelsdir=/etc/i2pd/tunnels.conf.d --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service ExecReload=/bin/kill -HUP $MAINPID diff --git a/debian/patches/series b/debian/patches/series index 5a9712bd..002802b5 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1,2 +1,2 @@ 01-tune-build-opts.patch -fix-#1210 +02-fix-1210.patch diff --git a/libi2pd/ChaCha20.cpp b/libi2pd/ChaCha20.cpp index e43f1514..0ab98fb2 100644 --- a/libi2pd/ChaCha20.cpp +++ b/libi2pd/ChaCha20.cpp @@ -7,6 +7,8 @@ Kovri go write your own code */ + +#if LEGACY_OPENSSL namespace i2p { namespace crypto @@ -144,4 +146,6 @@ void chacha20(uint8_t * buf, size_t sz, const uint8_t * nonce, const uint8_t * k } } -} \ No newline at end of file +} +#endif + diff --git a/libi2pd/ChaCha20.h b/libi2pd/ChaCha20.h index c88325d5..5a8ce145 100644 --- a/libi2pd/ChaCha20.h +++ b/libi2pd/ChaCha20.h @@ -9,7 +9,9 @@ #define LIBI2PD_CHACHA20_H #include #include +#include "Crypto.h" +#if LEGACY_OPENSSL namespace i2p { namespace crypto @@ -22,5 +24,6 @@ namespace crypto } } +#endif #endif diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 3a3d6c09..0403275f 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -32,6 +32,7 @@ namespace config { options_description general("General options"); general.add_options() ("help", "Show this message") + ("version", "Show i2pd version") ("conf", value()->default_value(""), "Path to main i2pd config file (default: try ~/.i2pd/i2pd.conf or /var/lib/i2pd/i2pd.conf)") ("tunconf", value()->default_value(""), "Path to config with tunnels list and options (default: try ~/.i2pd/tunnels.conf or /var/lib/i2pd/tunnels.conf)") ("tunnelsdir", value()->default_value(""), "Path to extra tunnels' configs folder (default: ~/.i2pd/tunnels.d or /var/lib/i2pd/tunnels.d") @@ -87,6 +88,7 @@ namespace config { ("http.pass", value()->default_value(""), "Password for basic auth (default: random, see logs)") ("http.strictheaders", value()->default_value(true), "Enable strict host checking on WebUI") ("http.hostname", value()->default_value("localhost"), "Expected hostname for WebUI") + ("http.webroot", value()->default_value("/"), "WebUI root path (default: / )") ; options_description httpproxy("HTTP Proxy options"); @@ -235,10 +237,27 @@ namespace config { options_description ntcp2("NTCP2 Options"); ntcp2.add_options() ("ntcp2.enabled", value()->default_value(true), "Enable NTCP2 (default: enabled)") - ("ntcp2.published", value()->default_value(false), "Publish NTCP2 (default: disabled)") + ("ntcp2.published", value()->default_value(false), "Publish NTCP2 (default: disabled)") ("ntcp2.port", value()->default_value(0), "Port to listen for incoming NTCP2 connections (default: auto)") ; + options_description nettime("Time sync options"); + nettime.add_options() + ("nettime.enabled", value()->default_value(false), "Disable time sync (default: disabled)") + ("nettime.ntpservers", value()->default_value( + "0.pool.ntp.org," + "1.pool.ntp.org," + "2.pool.ntp.org," + "3.pool.ntp.org" + ), "Comma separated list of NTCP servers") + ("nettime.ntpsyncinterval", value()->default_value(72), "NTP sync interval in hours (default: 72)") + ; + + options_description persist("Network information persisting options"); + persist.add_options() + ("persist.profiles", value()->default_value(true), "Persist peer profiles (default: true)") + ; + m_OptionsDesc .add(general) .add(limits) @@ -257,6 +276,8 @@ namespace config { .add(websocket) .add(exploratory) .add(ntcp2) + .add(nettime) + .add(persist) ; } @@ -282,6 +303,23 @@ namespace config { { std::cout << "i2pd version " << I2PD_VERSION << " (" << I2P_VERSION << ")" << std::endl; std::cout << m_OptionsDesc; + exit(EXIT_SUCCESS); + } + else if (m_Options.count("version")) + { + std::cout << "i2pd version " << I2PD_VERSION << " (" << I2P_VERSION << ")" << std::endl; + std::cout << "Boost version " + << BOOST_VERSION / 100000 << "." // maj. version + << BOOST_VERSION / 100 % 1000 << "." // min. version + << BOOST_VERSION % 100 // patch version + << std::endl; +#if defined(OPENSSL_VERSION_TEXT) + std::cout << OPENSSL_VERSION_TEXT << std::endl; +#endif +#if defined(LIBRESSL_VERSION_TEXT) + std::cout << LIBRESSL_VERSION_TEXT << std::endl; +#endif + exit(EXIT_SUCCESS); } } diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index e36b3071..2448264f 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -341,6 +341,16 @@ namespace crypto #endif } + void X25519Keys::GetPrivateKey (uint8_t * priv) const + { +#if OPENSSL_X25519 + size_t len = 32; + EVP_PKEY_get_raw_private_key (m_Pkey, priv, &len); +#else + memcpy (priv, m_PrivateKey, 32); +#endif + } + // ElGamal void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding) { diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index c2da1f4d..cbfeb0e9 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -72,6 +72,7 @@ namespace crypto void GenerateKeys (); const uint8_t * GetPublicKey () const { return m_PublicKey; }; + void GetPrivateKey (uint8_t * priv) const; void Agree (const uint8_t * pub, uint8_t * shared); private: @@ -122,11 +123,32 @@ namespace crypto ); } else -#endif +#endif { - // TODO: implement it better - for (int i = 0; i < 16; i++) - buf[i] ^= other.buf[i]; +#if defined(__SSE__) // SSE + __asm__ + ( + "movups (%[buf]), %%xmm0 \n" + "movups (%[other]), %%xmm1 \n" + "pxor %%xmm1, %%xmm0 \n" + "movups %%xmm0, (%[buf]) \n" + : + : [buf]"r"(buf), [other]"r"(other.buf) + : "%xmm0", "%xmm1", "memory" + ); +#else + if (!(((size_t)buf | (size_t)other.buf) & 0x03)) // multiple of 4 ? + { + // we are good to cast to uint32_t * + for (int i = 0; i < 4; i++) + ((uint32_t *)buf)[i] ^= ((uint32_t *)other.buf)[i]; + } + else + { + for (int i = 0; i < 16; i++) + buf[i] ^= other.buf[i]; + } +#endif } } }; diff --git a/libi2pd/Ed25519.cpp b/libi2pd/Ed25519.cpp index 17264926..2c64c475 100644 --- a/libi2pd/Ed25519.cpp +++ b/libi2pd/Ed25519.cpp @@ -411,6 +411,7 @@ namespace crypto } } +#if !OPENSSL_X25519 BIGNUM * Ed25519::ScalarMul (const BIGNUM * u, const BIGNUM * k, BN_CTX * ctx) const { BN_CTX_start (ctx); @@ -488,6 +489,7 @@ namespace crypto EncodeBN (q1, buf, 32); BN_free (p1); BN_free (n); BN_free (q1); } +#endif void Ed25519::ExpandPrivateKey (const uint8_t * key, uint8_t * expandedKey) { diff --git a/libi2pd/Ed25519.h b/libi2pd/Ed25519.h index fc23a457..48b3a665 100644 --- a/libi2pd/Ed25519.h +++ b/libi2pd/Ed25519.h @@ -3,6 +3,7 @@ #include #include +#include "Crypto.h" namespace i2p { @@ -75,8 +76,10 @@ namespace crypto EDDSAPoint GeneratePublicKey (const uint8_t * expandedPrivateKey, BN_CTX * ctx) const; EDDSAPoint DecodePublicKey (const uint8_t * buf, BN_CTX * ctx) const; void EncodePublicKey (const EDDSAPoint& publicKey, uint8_t * buf, BN_CTX * ctx) const; +#if !OPENSSL_X25519 void ScalarMul (const uint8_t * p, const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const; // p is point, e is number for x25519 void ScalarMulB (const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const; +#endif bool Verify (const EDDSAPoint& publicKey, const uint8_t * digest, const uint8_t * signature) const; void Sign (const uint8_t * expandedPrivateKey, const uint8_t * publicKeyEncoded, const uint8_t * buf, size_t len, uint8_t * signature) const; @@ -100,8 +103,10 @@ namespace crypto BIGNUM * DecodeBN (const uint8_t * buf) const; void EncodeBN (const BIGNUM * bn, uint8_t * buf, size_t len) const; +#if !OPENSSL_X25519 // for x25519 BIGNUM * ScalarMul (const BIGNUM * p, const BIGNUM * e, BN_CTX * ctx) const; +#endif private: diff --git a/libi2pd/I2NPProtocol.h b/libi2pd/I2NPProtocol.h index 15e3a32c..5160acec 100644 --- a/libi2pd/I2NPProtocol.h +++ b/libi2pd/I2NPProtocol.h @@ -75,6 +75,7 @@ namespace i2p enum I2NPMessageType { + eI2NPDummyMsg = 0, eI2NPDatabaseStore = 1, eI2NPDatabaseLookup = 2, eI2NPDatabaseSearchReply = 3, diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 1d60fef5..a88d2a3a 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -40,7 +40,7 @@ namespace transport delete[] m_SessionConfirmedBuffer; } - void NTCP2Establisher::MixKey (const uint8_t * inputKeyMaterial, uint8_t * derived) + void NTCP2Establisher::MixKey (const uint8_t * inputKeyMaterial) { // temp_key = HMAC-SHA256(ck, input_key_material) uint8_t tempKey[32]; unsigned int len; @@ -50,7 +50,16 @@ namespace transport HMAC(EVP_sha256(), tempKey, 32, one, 1, m_CK, &len); // derived = HMAC-SHA256(temp_key, ck || byte(0x02)) m_CK[32] = 2; - HMAC(EVP_sha256(), tempKey, 32, m_CK, 33, derived, &len); + HMAC(EVP_sha256(), tempKey, 32, m_CK, 33, m_K, &len); + } + + void NTCP2Establisher::MixHash (const uint8_t * buf, size_t len) + { + SHA256_CTX ctx; + SHA256_Init (&ctx); + SHA256_Update (&ctx, m_H, 32); + SHA256_Update (&ctx, buf, len); + SHA256_Final (m_H, &ctx); } void NTCP2Establisher::KeyDerivationFunction1 (const uint8_t * pub, i2p::crypto::X25519Keys& priv, const uint8_t * rs, const uint8_t * epub) @@ -73,14 +82,11 @@ namespace transport SHA256_Update (&ctx, rs, 32); SHA256_Final (m_H, &ctx); // h = SHA256(h || epub) - SHA256_Init (&ctx); - SHA256_Update (&ctx, m_H, 32); - SHA256_Update (&ctx, epub, 32); - SHA256_Final (m_H, &ctx); + MixHash (epub, 32); // x25519 between pub and priv uint8_t inputKeyMaterial[32]; priv.Agree (pub, inputKeyMaterial); - MixKey (inputKeyMaterial, m_K); + MixKey (inputKeyMaterial); } void NTCP2Establisher::KDF1Alice () @@ -95,30 +101,18 @@ namespace transport void NTCP2Establisher::KeyDerivationFunction2 (const uint8_t * sessionRequest, size_t sessionRequestLen, const uint8_t * epub) { - SHA256_CTX ctx; - SHA256_Init (&ctx); - SHA256_Update (&ctx, m_H, 32); - SHA256_Update (&ctx, sessionRequest + 32, 32); // encrypted payload - SHA256_Final (m_H, &ctx); + MixHash (sessionRequest + 32, 32); // encrypted payload int paddingLength = sessionRequestLen - 64; if (paddingLength > 0) - { - SHA256_Init (&ctx); - SHA256_Update (&ctx, m_H, 32); - SHA256_Update (&ctx, sessionRequest + 64, paddingLength); - SHA256_Final (m_H, &ctx); - } - SHA256_Init (&ctx); - SHA256_Update (&ctx, m_H, 32); - SHA256_Update (&ctx, epub, 32); - SHA256_Final (m_H, &ctx); + MixHash (sessionRequest + 64, paddingLength); + MixHash (epub, 32); // x25519 between remote pub and ephemaral priv uint8_t inputKeyMaterial[32]; m_EphemeralKeys.Agree (GetRemotePub (), inputKeyMaterial); - MixKey (inputKeyMaterial, m_K); + MixKey (inputKeyMaterial); } void NTCP2Establisher::KDF2Alice () @@ -135,14 +129,14 @@ namespace transport { uint8_t inputKeyMaterial[32]; i2p::context.GetStaticKeys ().Agree (GetRemotePub (), inputKeyMaterial); - MixKey (inputKeyMaterial, m_K); + MixKey (inputKeyMaterial); } void NTCP2Establisher::KDF3Bob () { uint8_t inputKeyMaterial[32]; m_EphemeralKeys.Agree (m_RemoteStaticKey, inputKeyMaterial); - MixKey (inputKeyMaterial, m_K); + MixKey (inputKeyMaterial); } void NTCP2Establisher::CreateEphemeralKey () @@ -170,8 +164,17 @@ namespace transport memset (options, 0, 16); options[1] = 2; // ver htobe16buf (options + 2, paddingLength); // padLen - m3p2Len = i2p::context.GetRouterInfo ().GetBufferLen () + 20; // (RI header + RI + MAC for now) TODO: implement options + // m3p2Len + auto bufLen = i2p::context.GetRouterInfo ().GetBufferLen (); + m3p2Len = bufLen + 4 + 16; // (RI header + RI + MAC for now) TODO: implement options htobe16buf (options + 4, m3p2Len); + // fill m3p2 payload (RouterInfo block) + m_SessionConfirmedBuffer = new uint8_t[m3p2Len + 48]; // m3p1 is 48 bytes + uint8_t * m3p2 = m_SessionConfirmedBuffer + 48; + m3p2[0] = eNTCP2BlkRouterInfo; // block + htobe16buf (m3p2 + 1, bufLen + 1); // flag + RI + m3p2[3] = 0; // flag + memcpy (m3p2 + 4, i2p::context.GetRouterInfo ().GetBuffer (), bufLen); // TODO: own RI should be protected by mutex // 2 bytes reserved htobe32buf (options + 8, i2p::util::GetSecondsSinceEpoch ()); // tsA // 4 bytes reserved @@ -208,23 +211,12 @@ namespace transport void NTCP2Establisher::CreateSessionConfirmedMessagePart1 (const uint8_t * nonce) { // update AD - SHA256_CTX ctx; - SHA256_Init (&ctx); - SHA256_Update (&ctx, m_H, 32); - SHA256_Update (&ctx, m_SessionCreatedBuffer + 32, 32); // encrypted payload - SHA256_Final (m_H, &ctx); - + MixHash (m_SessionCreatedBuffer + 32, 32); // encrypted payload int paddingLength = m_SessionCreatedBufferLen - 64; if (paddingLength > 0) - { - SHA256_CTX ctx1; - SHA256_Init (&ctx1); - SHA256_Update (&ctx1, m_H, 32); - SHA256_Update (&ctx1, m_SessionCreatedBuffer + 64, paddingLength); - SHA256_Final (m_H, &ctx1); - } - // part1 48 bytes - m_SessionConfirmedBuffer = new uint8_t[m3p2Len + 48]; + MixHash (m_SessionCreatedBuffer + 64, paddingLength); + + // part1 48 bytes i2p::crypto::AEADChaCha20Poly1305 (i2p::context.GetNTCP2StaticPublicKey (), 32, m_H, 32, m_K, nonce, m_SessionConfirmedBuffer, 48, true); // encrypt } @@ -232,24 +224,13 @@ namespace transport { // part 2 // update AD again - SHA256_CTX ctx; - SHA256_Init (&ctx); - SHA256_Update (&ctx, m_H, 32); - SHA256_Update (&ctx, m_SessionConfirmedBuffer, 48); - SHA256_Final (m_H, &ctx); - // fill and encrypt - uint8_t * buf = m_SessionConfirmedBuffer + 48; - buf[0] = eNTCP2BlkRouterInfo; // block - htobe16buf (buf + 1, i2p::context.GetRouterInfo ().GetBufferLen () + 1); // flag + RI - buf[3] = 0; // flag - memcpy (buf + 4, i2p::context.GetRouterInfo ().GetBuffer (), i2p::context.GetRouterInfo ().GetBufferLen ()); + MixHash (m_SessionConfirmedBuffer, 48); + // encrypt m3p2, it must be filled in SessionRequest KDF3Alice (); - i2p::crypto::AEADChaCha20Poly1305 (buf, m3p2Len - 16, m_H, 32, m_K, nonce, buf, m3p2Len, true); // encrypt + uint8_t * m3p2 = m_SessionConfirmedBuffer + 48; + i2p::crypto::AEADChaCha20Poly1305 (m3p2, m3p2Len - 16, m_H, 32, m_K, nonce, m3p2, m3p2Len, true); // encrypt // update h again - SHA256_Init (&ctx); - SHA256_Update (&ctx, m_H, 32); - SHA256_Update (&ctx, buf, m3p2Len); - SHA256_Final (m_H, &ctx); //h = SHA256(h || ciphertext) + MixHash (m3p2, m3p2Len); //h = SHA256(h || ciphertext) } bool NTCP2Establisher::ProcessSessionRequestMessage (uint16_t& paddingLen) @@ -339,21 +320,11 @@ namespace transport bool NTCP2Establisher::ProcessSessionConfirmedMessagePart1 (const uint8_t * nonce) { // update AD - SHA256_CTX ctx; - SHA256_Init (&ctx); - SHA256_Update (&ctx, m_H, 32); - SHA256_Update (&ctx, m_SessionCreatedBuffer + 32, 32); // encrypted payload - SHA256_Final (m_H, &ctx); - + MixHash (m_SessionCreatedBuffer + 32, 32); // encrypted payload int paddingLength = m_SessionCreatedBufferLen - 64; if (paddingLength > 0) - { - SHA256_CTX ctx1; - SHA256_Init (&ctx1); - SHA256_Update (&ctx1, m_H, 32); - SHA256_Update (&ctx1, m_SessionCreatedBuffer + 64, paddingLength); - SHA256_Final (m_H, &ctx1); - } + MixHash (m_SessionCreatedBuffer + 64, paddingLength); + if (!i2p::crypto::AEADChaCha20Poly1305 (m_SessionConfirmedBuffer, 32, m_H, 32, m_K, nonce, m_RemoteStaticKey, 32, false)) // decrypt S { LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part1 AEAD verification failed "); @@ -365,11 +336,7 @@ namespace transport bool NTCP2Establisher::ProcessSessionConfirmedMessagePart2 (const uint8_t * nonce, uint8_t * m3p2Buf) { // update AD again - SHA256_CTX ctx; - SHA256_Init (&ctx); - SHA256_Update (&ctx, m_H, 32); - SHA256_Update (&ctx, m_SessionConfirmedBuffer, 48); - SHA256_Final (m_H, &ctx); + MixHash (m_SessionConfirmedBuffer, 48); KDF3Bob (); if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionConfirmedBuffer + 48, m3p2Len - 16, m_H, 32, m_K, nonce, m3p2Buf, m3p2Len - 16, false)) // decrypt @@ -728,8 +695,7 @@ namespace transport SendTerminationAndTerminate (eNTCP2IncorrectSParameter); return; } - - i2p::data::netdb.AddRouterInfo (buf.data () + 4, size - 1); // TODO: should insert ri and not parse it twice + i2p::data::netdb.PostI2NPMsg (CreateI2NPMessage (eI2NPDummyMsg, buf.data () + 3, size)); // TODO: should insert ri and not parse it twice // TODO: process options // ready to communicate @@ -894,7 +860,7 @@ namespace transport case eNTCP2BlkRouterInfo: { LogPrint (eLogDebug, "NTCP2: RouterInfo flag=", (int)frame[offset]); - i2p::data::netdb.AddRouterInfo (frame + offset + 1, size - 1); + i2p::data::netdb.PostI2NPMsg (CreateI2NPMessage (eI2NPDummyMsg, frame + offset, size)); break; } case eNTCP2BlkI2NPMessage: @@ -1041,7 +1007,7 @@ namespace transport void NTCP2Session::SendTermination (NTCP2TerminationReason reason) { - if (!IsEstablished ()) return; + if (!m_SendKey || !m_SendSipKey) return; uint8_t payload[12] = { eNTCP2BlkTermination, 0, 9 }; htobe64buf (payload + 3, m_ReceiveSequenceNumber); payload[11] = (uint8_t)reason; diff --git a/libi2pd/NTCP2.h b/libi2pd/NTCP2.h index 7db6e8bf..eb46b2f8 100644 --- a/libi2pd/NTCP2.h +++ b/libi2pd/NTCP2.h @@ -73,6 +73,8 @@ namespace transport eNTCP2Banned, // 17 }; + // RouterInfo flags + const uint8_t NTCP2_ROUTER_INFO_FLAG_REQUEST_FLOOD = 0x01; typedef std::array NTCP2FrameBuffer; struct NTCP2Establisher @@ -95,7 +97,8 @@ namespace transport void KDF3Alice (); // for SessionConfirmed part 2 void KDF3Bob (); - void MixKey (const uint8_t * inputKeyMaterial, uint8_t * derived); + void MixKey (const uint8_t * inputKeyMaterial); + void MixHash (const uint8_t * buf, size_t len); void KeyDerivationFunction1 (const uint8_t * pub, i2p::crypto::X25519Keys& priv, const uint8_t * rs, const uint8_t * epub); // for SessionRequest, (pub, priv) for DH void KeyDerivationFunction2 (const uint8_t * sessionRequest, size_t sessionRequestLen, const uint8_t * epub); // for SessionCreate void CreateEphemeralKey (); diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 0add6f91..2e5c3a23 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -12,6 +12,7 @@ #include "I2NPProtocol.h" #include "Tunnel.h" #include "Transports.h" +#include "NTCP2.h" #include "RouterContext.h" #include "Garlic.h" #include "NetDb.hpp" @@ -25,7 +26,7 @@ namespace data { NetDb netdb; - NetDb::NetDb (): m_IsRunning (false), m_Thread (nullptr), m_Reseeder (nullptr), m_Storage("netDb", "r", "routerInfo-", "dat"), m_FloodfillBootstrap(nullptr), m_HiddenMode(false) + NetDb::NetDb (): m_IsRunning (false), m_Thread (nullptr), m_Reseeder (nullptr), m_Storage("netDb", "r", "routerInfo-", "dat"), m_PersistProfiles (true), m_HiddenMode(false) { } @@ -43,10 +44,12 @@ namespace data m_Families.LoadCertificates (); Load (); - uint16_t threshold; i2p::config::GetOption("reseed.threshold", threshold); + uint16_t threshold; i2p::config::GetOption("reseed.threshold", threshold); if (m_RouterInfos.size () < threshold) // reseed if # of router less than threshold Reseed (); + i2p::config::GetOption("persist.profiles", m_PersistProfiles); + m_IsRunning = true; m_Thread = new std::thread (std::bind (&NetDb::Run, this)); } @@ -55,8 +58,9 @@ namespace data { if (m_IsRunning) { - for (auto& it: m_RouterInfos) - it.second->SaveProfile (); + if (m_PersistProfiles) + for (auto& it: m_RouterInfos) + it.second->SaveProfile (); DeleteObsoleteProfiles (); m_RouterInfos.clear (); m_Floodfills.clear (); @@ -98,6 +102,10 @@ namespace data case eI2NPDatabaseLookup: HandleDatabaseLookupMsg (msg); break; + case eI2NPDummyMsg: + // plain RouterInfo from NTCP2 with flags for now + HandleNTCP2RouterInfoMsg (msg); + break; default: // WTF? LogPrint (eLogError, "NetDb: unexpected message type ", (int) msg->GetTypeID ()); //i2p::HandleI2NPMessage (msg); @@ -162,22 +170,38 @@ namespace data } } + void NetDb::SetHidden(bool hide) + { + // TODO: remove reachable addresses from router info + m_HiddenMode = hide; + } + bool NetDb::AddRouterInfo (const uint8_t * buf, int len) + { + bool updated; + AddRouterInfo (buf, len, updated); + return updated; + } + + std::shared_ptr NetDb::AddRouterInfo (const uint8_t * buf, int len, bool& updated) { IdentityEx identity; if (identity.FromBuffer (buf, len)) - return AddRouterInfo (identity.GetIdentHash (), buf, len); - return false; + return AddRouterInfo (identity.GetIdentHash (), buf, len, updated); + updated = false; + return nullptr; } - void NetDb::SetHidden(bool hide) { - // TODO: remove reachable addresses from router info - m_HiddenMode = hide; - } - bool NetDb::AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len) { - bool updated = true; + bool updated; + AddRouterInfo (ident, buf, len, updated); + return updated; + } + + std::shared_ptr NetDb::AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len, bool& updated) + { + updated = true; auto r = FindRouter (ident); if (r) { @@ -223,7 +247,7 @@ namespace data } // take care about requested destination m_Requests.RequestComplete (ident, r); - return updated; + return r; } bool NetDb::AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len, @@ -518,7 +542,7 @@ namespace data { if (it->second->IsUnreachable ()) { - it->second->SaveProfile (); + if (m_PersistProfiles) it->second->SaveProfile (); it = m_RouterInfos.erase (it); continue; } @@ -570,6 +594,17 @@ namespace data transports.SendMessage (from, dest->CreateRequestMessage (nullptr, nullptr)); } + void NetDb::HandleNTCP2RouterInfoMsg (std::shared_ptr m) + { + uint8_t flood = m->GetPayload ()[0] & NTCP2_ROUTER_INFO_FLAG_REQUEST_FLOOD; + bool updated; + auto ri = AddRouterInfo (m->GetPayload () + 1, m->GetPayloadLength () - 1, updated); // without flags + if (flood && updated && context.IsFloodfill () && ri) + { + auto floodMsg = CreateDatabaseStoreMsg (ri, 0); // replyToken = 0 + Flood (ri->GetIdentHash (), floodMsg); + } + } void NetDb::HandleDatabaseStoreMsg (std::shared_ptr m) { @@ -649,22 +684,7 @@ namespace data { memcpy (payload + DATABASE_STORE_HEADER_SIZE, buf + payloadOffset, msgLen); floodMsg->FillI2NPMessageHeader (eI2NPDatabaseStore); - std::set excluded; - excluded.insert (i2p::context.GetIdentHash ()); // don't flood to itself - excluded.insert (ident); // don't flood back - for (int i = 0; i < 3; i++) - { - auto floodfill = GetClosestFloodfill (ident, excluded); - if (floodfill) - { - auto h = floodfill->GetIdentHash(); - LogPrint(eLogDebug, "NetDb: Flood lease set for ", ident.ToBase32(), " to ", h.ToBase64()); - transports.SendMessage (h, CopyI2NPMessage(floodMsg)); - excluded.insert (h); - } - else - break; - } + Flood (ident, floodMsg); } else LogPrint (eLogError, "NetDb: Database store message is too long ", floodMsg->len); @@ -965,6 +985,26 @@ namespace data } } + void NetDb::Flood (const IdentHash& ident, std::shared_ptr floodMsg) + { + std::set excluded; + excluded.insert (i2p::context.GetIdentHash ()); // don't flood to itself + excluded.insert (ident); // don't flood back + for (int i = 0; i < 3; i++) + { + auto floodfill = GetClosestFloodfill (ident, excluded); + if (floodfill) + { + auto h = floodfill->GetIdentHash(); + LogPrint(eLogDebug, "NetDb: Flood lease set for ", ident.ToBase32(), " to ", h.ToBase64()); + transports.SendMessage (h, CopyI2NPMessage(floodMsg)); + excluded.insert (h); + } + else + break; + } + } + std::shared_ptr NetDb::GetRandomRouter () const { return GetRandomRouter ( diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index 18377b4f..b34458fb 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -65,7 +65,8 @@ namespace data void HandleDatabaseStoreMsg (std::shared_ptr msg); void HandleDatabaseSearchReplyMsg (std::shared_ptr msg); void HandleDatabaseLookupMsg (std::shared_ptr msg); - + void HandleNTCP2RouterInfoMsg (std::shared_ptr m); + std::shared_ptr GetRandomRouter () const; std::shared_ptr GetRandomRouter (std::shared_ptr compatibleWith) const; std::shared_ptr GetHighBandwidthRandomRouter (std::shared_ptr compatibleWith) const; @@ -110,13 +111,16 @@ namespace data void Run (); // exploratory thread void Explore (int numDestinations); void Publish (); + void Flood (const IdentHash& ident, std::shared_ptr floodMsg); void ManageLeaseSets (); void ManageRequests (); - void ReseedFromFloodfill(const RouterInfo & ri, int numRouters=40, int numFloodfills=20); + void ReseedFromFloodfill(const RouterInfo & ri, int numRouters=40, int numFloodfills=20); - template - std::shared_ptr GetRandomRouter (Filter filter) const; + std::shared_ptr AddRouterInfo (const uint8_t * buf, int len, bool& updated); + std::shared_ptr AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len, bool& updated); + template + std::shared_ptr GetRandomRouter (Filter filter) const; private: @@ -140,6 +144,8 @@ namespace data friend class NetDbRequests; NetDbRequests m_Requests; + bool m_PersistProfiles; + /** router info we are bootstrapping from or nullptr if we are not currently doing that*/ std::shared_ptr m_FloodfillBootstrap; diff --git a/libi2pd/Poly1305.cpp b/libi2pd/Poly1305.cpp index 0f953b8a..4ce67d39 100644 --- a/libi2pd/Poly1305.cpp +++ b/libi2pd/Poly1305.cpp @@ -6,6 +6,8 @@ Kovri go write your own code */ + +#if LEGACY_OPENSSL namespace i2p { namespace crypto @@ -19,3 +21,5 @@ namespace crypto } } } +#endif + diff --git a/libi2pd/Poly1305.h b/libi2pd/Poly1305.h index b2d64bb0..d9529c81 100644 --- a/libi2pd/Poly1305.h +++ b/libi2pd/Poly1305.h @@ -9,7 +9,9 @@ #define LIBI2PD_POLY1305_H #include #include +#include "Crypto.h" +#if LEGACY_OPENSSL namespace i2p { namespace crypto @@ -254,5 +256,6 @@ namespace crypto } } +#endif #endif diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 9c1acfcc..6b5053a8 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -116,12 +116,12 @@ namespace i2p void RouterContext::NewNTCP2Keys () { + m_StaticKeys.reset (new i2p::crypto::X25519Keys ()); + m_StaticKeys->GenerateKeys (); m_NTCP2Keys.reset (new NTCP2PrivateKeys ()); - RAND_bytes (m_NTCP2Keys->staticPrivateKey, 32); + m_StaticKeys->GetPrivateKey (m_NTCP2Keys->staticPrivateKey); + memcpy (m_NTCP2Keys->staticPublicKey, m_StaticKeys->GetPublicKey (), 32); RAND_bytes (m_NTCP2Keys->iv, 16); - BN_CTX * ctx = BN_CTX_new (); - i2p::crypto::GetEd25519 ()->ScalarMulB (m_NTCP2Keys->staticPrivateKey, m_NTCP2Keys->staticPublicKey, ctx); - BN_CTX_free (ctx); // save std::ofstream fk (i2p::fs::DataDirPath (NTCP2_KEYS), std::ofstream::binary | std::ofstream::out); fk.write ((char *)m_NTCP2Keys.get (), sizeof (NTCP2PrivateKeys)); diff --git a/libi2pd/Siphash.h b/libi2pd/Siphash.h index aa8b8631..70822466 100644 --- a/libi2pd/Siphash.h +++ b/libi2pd/Siphash.h @@ -9,7 +9,9 @@ #define SIPHASH_H #include +#include "Crypto.h" +#if !OPENSSL_SIPHASH namespace i2p { namespace crypto @@ -148,5 +150,6 @@ namespace crypto } } } +#endif #endif diff --git a/libi2pd/Timestamp.cpp b/libi2pd/Timestamp.cpp index 9e9b4e63..492e4559 100644 --- a/libi2pd/Timestamp.cpp +++ b/libi2pd/Timestamp.cpp @@ -1,6 +1,10 @@ #include #include +#include +#include #include +#include +#include "Config.h" #include "Log.h" #include "I2PEndian.h" #include "Timestamp.h" @@ -15,10 +19,30 @@ namespace i2p { namespace util { + static uint64_t GetLocalMillisecondsSinceEpoch () + { + return std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()).count (); + } + + static uint32_t GetLocalHoursSinceEpoch () + { + return std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()).count (); + } + + static uint64_t GetLocalSecondsSinceEpoch () + { + return std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()).count (); + } + + static int64_t g_TimeOffset = 0; // in seconds - void SyncTimeWithNTP (const std::string& address) + static void SyncTimeWithNTP (const std::string& address) { + LogPrint (eLogInfo, "Timestamp: NTP request to ", address); boost::asio::io_service service; boost::asio::ip::udp::resolver::query query (boost::asio::ip::udp::v4 (), address, "ntp"); boost::system::error_code ec; @@ -48,19 +72,112 @@ namespace util } catch (std::exception& e) { - LogPrint (eLogError, "NTP error: ", e.what ()); + LogPrint (eLogError, "Timestamp: NTP error: ", e.what ()); } if (len >= 8) { - auto ourTs = GetSecondsSinceEpoch (); + auto ourTs = GetLocalSecondsSinceEpoch (); uint32_t ts = bufbe32toh (buf + 32); if (ts > 2208988800U) ts -= 2208988800U; // 1/1/1970 from 1/1/1900 g_TimeOffset = ts - ourTs; - LogPrint (eLogInfo, address, " time offset from system time is ", g_TimeOffset, " seconds"); + LogPrint (eLogInfo, "Timestamp: ", address, " time offset from system time is ", g_TimeOffset, " seconds"); } } + else + LogPrint (eLogError, "Timestamp: Couldn't open UDP socket"); + } + else + LogPrint (eLogError, "Timestamp: Couldn't resove address ", address); + } + + NTPTimeSync::NTPTimeSync (): m_IsRunning (false), m_Timer (m_Service) + { + i2p::config::GetOption("nettime.ntpsyncinterval", m_SyncInterval); + std::string ntpservers; i2p::config::GetOption("nettime.ntpservers", ntpservers); + boost::split (m_NTPServersList, ntpservers, boost::is_any_of(","), boost::token_compress_on); + } + + NTPTimeSync::~NTPTimeSync () + { + Stop (); + } + + void NTPTimeSync::Start() + { + if (m_NTPServersList.size () > 0) + { + m_IsRunning = true; + LogPrint(eLogInfo, "Timestamp: NTP time sync starting"); + m_Service.post (std::bind (&NTPTimeSync::Sync, this)); + m_Thread.reset (new std::thread (std::bind (&NTPTimeSync::Run, this))); + } + else + LogPrint (eLogWarning, "Timestamp: No NTP server found"); + } + + void NTPTimeSync::Stop () + { + if (m_IsRunning) + { + LogPrint(eLogInfo, "Timestamp: NTP time sync stopping"); + m_IsRunning = false; + m_Timer.cancel (); + m_Service.stop (); + if (m_Thread) + { + m_Thread->join (); + m_Thread.reset (nullptr); + } + } + } + + void NTPTimeSync::Run () + { + while (m_IsRunning) + { + try + { + m_Service.run (); + } + catch (std::exception& ex) + { + LogPrint (eLogError, "Timestamp: NTP time sync exception: ", ex.what ()); + } + } + } + + void NTPTimeSync::Sync () + { + if (m_NTPServersList.size () > 0) + SyncTimeWithNTP (m_NTPServersList[rand () % m_NTPServersList.size ()]); + else + m_IsRunning = false; + + if (m_IsRunning) + { + m_Timer.expires_from_now (boost::posix_time::hours (m_SyncInterval)); + m_Timer.async_wait ([this](const boost::system::error_code& ecode) + { + if (ecode != boost::asio::error::operation_aborted) + Sync (); + }); } } + + uint64_t GetMillisecondsSinceEpoch () + { + return GetLocalMillisecondsSinceEpoch () + g_TimeOffset*1000; + } + + uint32_t GetHoursSinceEpoch () + { + return GetLocalHoursSinceEpoch () + g_TimeOffset/3600; + } + + uint64_t GetSecondsSinceEpoch () + { + return GetLocalSecondsSinceEpoch () + g_TimeOffset; + } } } diff --git a/libi2pd/Timestamp.h b/libi2pd/Timestamp.h index cddc6518..e859f7f6 100644 --- a/libi2pd/Timestamp.h +++ b/libi2pd/Timestamp.h @@ -2,29 +2,43 @@ #define TIMESTAMP_H__ #include -#include +#include +#include +#include +#include namespace i2p { namespace util { - inline uint64_t GetMillisecondsSinceEpoch () - { - return std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()).count (); - } + uint64_t GetMillisecondsSinceEpoch (); + uint32_t GetHoursSinceEpoch (); + uint64_t GetSecondsSinceEpoch (); - inline uint32_t GetHoursSinceEpoch () + class NTPTimeSync { - return std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()).count (); - } + public: - inline uint64_t GetSecondsSinceEpoch () - { - return std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()).count (); - } + NTPTimeSync (); + ~NTPTimeSync (); + + void Start (); + void Stop (); + + private: + + void Run (); + void Sync (); + + private: + + bool m_IsRunning; + std::unique_ptr m_Thread; + boost::asio::io_service m_Service; + boost::asio::deadline_timer m_Timer; + int m_SyncInterval; + std::vector m_NTPServersList; + }; } } diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 6a833ae0..64f41afd 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -35,8 +35,11 @@ namespace transport void DHKeysPairSupplier::Stop () { - m_IsRunning = false; - m_Acquired.notify_one (); + { + std::unique_lock l(m_AcquiredMutex); + m_IsRunning = false; + m_Acquired.notify_one (); + } if (m_Thread) { m_Thread->join (); @@ -50,19 +53,20 @@ namespace transport while (m_IsRunning) { int num, total = 0; - while ((num = m_QueueSize - (int)m_Queue.size ()) > 0 && total < 20) + while ((num = m_QueueSize - (int)m_Queue.size ()) > 0 && total < 10) { CreateDHKeysPairs (num); total += num; } - if (total >= 20) + if (total >= 10) { LogPrint (eLogWarning, "Transports: ", total, " DH keys generated at the time"); std::this_thread::sleep_for (std::chrono::seconds(1)); // take a break } else { - std::unique_lock l(m_AcquiredMutex); + std::unique_lock l(m_AcquiredMutex); + if (!m_IsRunning) break; m_Acquired.wait (l); // wait for element gets acquired } } @@ -813,7 +817,6 @@ namespace transport if (profile) { profile->TunnelNonReplied(); - profile->Save(it->first); } std::unique_lock l(m_PeersMutex); it = m_Peers.erase (it); diff --git a/libi2pd/util.cpp b/libi2pd/util.cpp index 1395c2e6..b558fca4 100644 --- a/libi2pd/util.cpp +++ b/libi2pd/util.cpp @@ -21,9 +21,9 @@ #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) #define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) +/* // No more needed. Exists in MinGW. int inet_pton(int af, const char *src, void *dst) -{ /* This function was written by Petar Korponai?. See -http://stackoverflow.com/questions/15660203/inet-pton-identifier-not-found */ +{ // This function was written by Petar Korponai?. See http://stackoverflow.com/questions/15660203/inet-pton-identifier-not-found struct sockaddr_storage ss; int size = sizeof (ss); char src_copy[INET6_ADDRSTRLEN + 1]; @@ -45,7 +45,7 @@ http://stackoverflow.com/questions/15660203/inet-pton-identifier-not-found */ } } return 0; -} +}*/ #else /* !WIN32 => UNIX */ #include #include diff --git a/libi2pd/version.h b/libi2pd/version.h index 3f09928c..22990219 100644 --- a/libi2pd/version.h +++ b/libi2pd/version.h @@ -7,7 +7,7 @@ #define MAKE_VERSION(a,b,c) STRINGIZE(a) "." STRINGIZE(b) "." STRINGIZE(c) #define I2PD_VERSION_MAJOR 2 -#define I2PD_VERSION_MINOR 21 +#define I2PD_VERSION_MINOR 22 #define I2PD_VERSION_MICRO 0 #define I2PD_VERSION_PATCH 0 #define I2PD_VERSION MAKE_VERSION(I2PD_VERSION_MAJOR, I2PD_VERSION_MINOR, I2PD_VERSION_MICRO) diff --git a/qt/i2pd_qt/android/AndroidManifest.xml b/qt/i2pd_qt/android/AndroidManifest.xml index ddb6aeb1..8eb723e7 100644 --- a/qt/i2pd_qt/android/AndroidManifest.xml +++ b/qt/i2pd_qt/android/AndroidManifest.xml @@ -1,5 +1,5 @@ - + diff --git a/qt/i2pd_qt/data/icons/128x128/website.i2pd.i2pd.png b/qt/i2pd_qt/data/icons/128x128/website.i2pd.i2pd.png new file mode 100644 index 00000000..ee5400c4 Binary files /dev/null and b/qt/i2pd_qt/data/icons/128x128/website.i2pd.i2pd.png differ diff --git a/qt/i2pd_qt/data/icons/16x16/website.i2pd.i2pd.png b/qt/i2pd_qt/data/icons/16x16/website.i2pd.i2pd.png new file mode 100644 index 00000000..bc020282 Binary files /dev/null and b/qt/i2pd_qt/data/icons/16x16/website.i2pd.i2pd.png differ diff --git a/qt/i2pd_qt/data/icons/22x22/website.i2pd.i2pd.png b/qt/i2pd_qt/data/icons/22x22/website.i2pd.i2pd.png new file mode 100644 index 00000000..5aed761e Binary files /dev/null and b/qt/i2pd_qt/data/icons/22x22/website.i2pd.i2pd.png differ diff --git a/qt/i2pd_qt/data/icons/24x24/website.i2pd.i2pd.png b/qt/i2pd_qt/data/icons/24x24/website.i2pd.i2pd.png new file mode 100644 index 00000000..996e1296 Binary files /dev/null and b/qt/i2pd_qt/data/icons/24x24/website.i2pd.i2pd.png differ diff --git a/qt/i2pd_qt/data/icons/256x256/website.i2pd.i2pd.png b/qt/i2pd_qt/data/icons/256x256/website.i2pd.i2pd.png new file mode 100644 index 00000000..3ed9b518 Binary files /dev/null and b/qt/i2pd_qt/data/icons/256x256/website.i2pd.i2pd.png differ diff --git a/qt/i2pd_qt/data/icons/32x32/website.i2pd.i2pd.png b/qt/i2pd_qt/data/icons/32x32/website.i2pd.i2pd.png new file mode 100644 index 00000000..922846c6 Binary files /dev/null and b/qt/i2pd_qt/data/icons/32x32/website.i2pd.i2pd.png differ diff --git a/qt/i2pd_qt/data/icons/48x48/website.i2pd.i2pd.png b/qt/i2pd_qt/data/icons/48x48/website.i2pd.i2pd.png new file mode 100644 index 00000000..4b7c81ea Binary files /dev/null and b/qt/i2pd_qt/data/icons/48x48/website.i2pd.i2pd.png differ diff --git a/qt/i2pd_qt/data/icons/512x512/website.i2pd.i2pd.png b/qt/i2pd_qt/data/icons/512x512/website.i2pd.i2pd.png new file mode 100644 index 00000000..6336627c Binary files /dev/null and b/qt/i2pd_qt/data/icons/512x512/website.i2pd.i2pd.png differ diff --git a/qt/i2pd_qt/data/icons/64x64/website.i2pd.i2pd.png b/qt/i2pd_qt/data/icons/64x64/website.i2pd.i2pd.png new file mode 100644 index 00000000..a291cab5 Binary files /dev/null and b/qt/i2pd_qt/data/icons/64x64/website.i2pd.i2pd.png differ diff --git a/qt/i2pd_qt/data/website.i2pd.i2pd.appdata.xml b/qt/i2pd_qt/data/website.i2pd.i2pd.appdata.xml new file mode 100644 index 00000000..f6b98ed7 --- /dev/null +++ b/qt/i2pd_qt/data/website.i2pd.i2pd.appdata.xml @@ -0,0 +1,43 @@ + + + + website.i2pd.i2pd + website.i2pd.i2pd.desktop + CC0-1.0 + BSD-3-Clause + i2pd +

Invisible Internet + +

i2pd (I2P Daemon) is a full-featured C++ implementation of I2P client.

+

I2P (Invisible Internet Protocol) is a universal anonymous network layer. + All communications over I2P are anonymous and end-to-end encrypted, participants + don't reveal their real IP addresses.

+

I2P allows people from all around the world to communicate and share information + without restrictions.

+

Features:

+
    +
  • Distributed anonymous networking framework
  • +
  • End-to-end encrypted communications
  • +
  • Small footprint, simple dependencies, fast performance
  • +
  • Rich set of APIs for developers of secure applications
  • +
+
+ + + https://i2pd.website/images/i2pd_qt.png + + + https://i2pd.website/ + https://github.com/PurpleI2P/i2pd/issues + https://i2pd.readthedocs.io/en/latest/ + supervillain@riseup.net + PurpleI2P Team + + + + + + + + + diff --git a/qt/i2pd_qt/data/website.i2pd.i2pd.desktop b/qt/i2pd_qt/data/website.i2pd.i2pd.desktop new file mode 100644 index 00000000..33cb3214 --- /dev/null +++ b/qt/i2pd_qt/data/website.i2pd.i2pd.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Categories=Network;P2P;Qt; +Exec=i2pd_qt +GenericName=Invisible Internet +Comment=A universal anonymous network layer +Icon=website.i2pd.i2pd +Name=i2pd +Terminal=false +Type=Application +StartupNotify=false +Keywords=i2p;i2pd;vpn;p2p;