diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml new file mode 100644 index 00000000..9763f75b --- /dev/null +++ b/.github/workflows/build-windows.yml @@ -0,0 +1,29 @@ +name: Build on Windows + +on: [push, pull_request] + +defaults: + run: + shell: msys2 {0} + +jobs: + build: + name: Building for ${{ matrix.arch }} + runs-on: windows-latest + strategy: + fail-fast: true + matrix: + include: [ + { msystem: MINGW64, arch: x86_64 }, + { msystem: MINGW32, arch: i686 } + ] + steps: + - uses: actions/checkout@v2 + - name: Setup MSYS2 + uses: msys2/setup-msys2@v2 + with: + msystem: ${{ matrix.msystem }} + install: base-devel mingw-w64-${{ matrix.arch }}-gcc mingw-w64-${{ matrix.arch }}-boost mingw-w64-${{ matrix.arch }}-openssl mingw-w64-${{ matrix.arch }}-miniupnpc + update: true + - name: build application + run: make USE_UPNP=yes DEBUG=no -j3 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..ba6acbf8 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,21 @@ +name: Build on Ubuntu with make + +on: [push, pull_request] + +jobs: + build: + name: Building with USE_UPNP=${{ matrix.with_upnp }} flag + runs-on: ubuntu-16.04 + strategy: + fail-fast: true + matrix: + with_upnp: ['yes', 'no'] + steps: + - uses: actions/checkout@v2 + - name: install packages + run: | + sudo add-apt-repository ppa:mhier/libboost-latest + sudo apt-get update + sudo apt-get install build-essential libboost1.74-dev libminiupnpc-dev libssl-dev zlib1g-dev + - name: build application + run: make USE_AVX=no USE_AESNI=no USE_UPNP=${{ matrix.with_upnp }} -j3 diff --git a/android/src/org/purplei2p/i2pd/I2PDActivity.java b/android/src/org/purplei2p/i2pd/I2PDActivity.java index 8295e9f1..777ca748 100755 --- a/android/src/org/purplei2p/i2pd/I2PDActivity.java +++ b/android/src/org/purplei2p/i2pd/I2PDActivity.java @@ -15,6 +15,7 @@ import java.util.TimerTask; import android.Manifest; import android.annotation.SuppressLint; +import android.annotation.TargetApi; import android.app.Activity; import android.app.AlertDialog; import android.content.ActivityNotFoundException; @@ -25,6 +26,10 @@ import android.content.ServiceConnection; import android.content.SharedPreferences; import android.content.res.AssetManager; import android.content.pm.PackageManager; +import android.net.ConnectivityManager; +import android.net.Network; +import android.net.NetworkCapabilities; +import android.net.NetworkRequest; import android.net.Uri; import android.os.Bundle; import android.os.Build; @@ -41,6 +46,7 @@ import android.widget.Toast; import androidx.annotation.NonNull; +import androidx.annotation.RequiresApi; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; @@ -63,6 +69,7 @@ public class I2PDActivity extends Activity { private TextView textView; private boolean assetsCopied; + private NetworkStateCallback networkCallback; private String i2pdpath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/i2pd/"; //private ConfigParser parser = new ConfigParser(i2pdpath); // TODO: @@ -116,7 +123,7 @@ public class I2PDActivity extends Activity { daemonStateUpdatedListener.daemonStateUpdate(); // request permissions - if (Build.VERSION.SDK_INT >= 23) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, @@ -137,6 +144,10 @@ public class I2PDActivity extends Activity { } openBatteryOptimizationDialogIfNeeded(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + registerNetworkCallback(); + } } @Override @@ -244,7 +255,7 @@ public class I2PDActivity extends Activity { } private boolean isBatteryOptimizationsOpenOsDialogApiAvailable() { - return android.os.Build.VERSION.SDK_INT >= 23; + return android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M; } @Override @@ -631,6 +642,33 @@ public class I2PDActivity extends Activity { return "show_battery_optimization" + (device == null ? "" : device); } + @TargetApi(Build.VERSION_CODES.M) + private void registerNetworkCallback() { + ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkRequest request = new NetworkRequest.Builder() + .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) + .build(); + networkCallback = new NetworkStateCallback(); + connectivityManager.registerNetworkCallback(request, networkCallback); + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + private final class NetworkStateCallback extends ConnectivityManager.NetworkCallback { + @Override + public void onAvailable(Network network) { + super.onAvailable(network); + I2PD_JNI.onNetworkStateChanged(true); + Log.i(TAG, "NetworkCallback.onAvailable"); + } + + @Override + public void onLost(Network network) { + super.onLost(network); + I2PD_JNI.onNetworkStateChanged(false); + Log.i(TAG, " NetworkCallback.onLost"); + } + } + private void quit() { try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { diff --git a/appveyor.yml b/appveyor.yml index 10165e5f..3cf51c2b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -9,46 +9,49 @@ os: Visual Studio 2015 shallow_clone: true clone_depth: 1 +# avoid building 32-bit if 64-bit failed already +matrix: + fast_finish: true + environment: + APPVEYOR_SAVE_CACHE_ON_ERROR: true MSYS2_PATH_TYPE: inherit CHERE_INVOKING: enabled_from_arguments matrix: - MSYSTEM: MINGW64 - MSYS_PACKAGES: mingw-w64-x86_64-boost mingw-w64-x86_64-miniupnpc - MSYS_BITNESS: 64 - MSYSTEM: MINGW32 - MSYS_PACKAGES: mingw-w64-i686-boost mingw-w64-i686-miniupnpc - MSYS_BITNESS: 32 + +cache: + - c:\msys64\var\cache\pacman\pkg\ install: -# install new signing keyring -- c:\msys64\usr\bin\bash -lc "curl -O https://mirror.selfnet.de/msys2/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz" -- c:\msys64\usr\bin\bash -lc "curl -O https://mirror.selfnet.de/msys2/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig" -- c:\msys64\usr\bin\bash -lc "pacman-key --verify msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig" +# install new signing keyring +- c:\msys64\usr\bin\bash -lc "curl -O https://mirror.selfnet.de/msys2/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz" +- c:\msys64\usr\bin\bash -lc "curl -O https://mirror.selfnet.de/msys2/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig" +- c:\msys64\usr\bin\bash -lc "pacman-key --verify msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig" - c:\msys64\usr\bin\bash -lc "pacman --noconfirm -U msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz" -# disable inaccessible miror (something block sed from changing files, so rewrite them) - https://github.com/msys2/MINGW-packages/issues/7084 -- c:\msys64\usr\bin\bash -lc "echo 'Server = https://mirror.yandex.ru/mirrors/msys2/mingw/x86_64/' > /etc/pacman.d/mirrorlist.mingw64" -- c:\msys64\usr\bin\bash -lc "echo 'Server = https://mirror.yandex.ru/mirrors/msys2/mingw/i686/' > /etc/pacman.d/mirrorlist.mingw32" -- c:\msys64\usr\bin\bash -lc "echo 'Server = https://mirror.yandex.ru/mirrors/msys2/msys/$arch/' > /etc/pacman.d/mirrorlist.msys" # remove packages which can break build - c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Rns gcc-fortran gcc mingw-w64-{i686,x86_64}-gcc-ada mingw-w64-{i686,x86_64}-gcc-objc" # update runtime - c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu" # Kill bash before next try - taskkill /T /F /IM bash.exe /IM gpg.exe /IM gpg-agent.exe | exit /B 0 -# rewrite mirrorlist again because pacman update can rewrite it -- c:\msys64\usr\bin\bash -lc "echo 'Server = https://mirror.yandex.ru/mirrors/msys2/mingw/x86_64/' > /etc/pacman.d/mirrorlist.mingw64" -- c:\msys64\usr\bin\bash -lc "echo 'Server = https://mirror.yandex.ru/mirrors/msys2/mingw/i686/' > /etc/pacman.d/mirrorlist.mingw32" -- c:\msys64\usr\bin\bash -lc "echo 'Server = https://mirror.yandex.ru/mirrors/msys2/msys/$arch/' > /etc/pacman.d/mirrorlist.msys" # update packages and install required -- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu ${MSYS_PACKAGES}" +- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu $MINGW_PACKAGE_PREFIX-boost $MINGW_PACKAGE_PREFIX-miniupnpc" build_script: -- echo MSYSTEM = %MSYSTEM%, bitness = %MSYS_BITNESS% -- c:\msys64\usr\bin\bash -lc "make USE_UPNP=yes -j3" -- 7z a -tzip -mx9 -mmt i2pd-mingw-win%MSYS_BITNESS%.zip i2pd.exe +- c:\msys64\usr\bin\bash -lc "make USE_UPNP=yes DEBUG=no -j3" +# prepare archive for uploading +- set "FILELIST=i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates contrib/tunnels.d" +- echo This is development build, use it carefully! For running in portable mode, move all files from contrib directory here. > README.txt +- 7z a -tzip -mx9 -mmt i2pd-%APPVEYOR_BUILD_VERSION%-%APPVEYOR_REPO_COMMIT:~0,7%-mingw-win%MSYSTEM:~-2%.zip %FILELIST% + +after_build: +- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Sc" test: off +deploy: off + artifacts: -- path: i2pd-mingw-win*.zip +- path: i2pd-*.zip diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 4825855b..827e20d3 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -85,6 +85,7 @@ set(LIBI2PD_SRC "${LIBI2PD_SRC_DIR}/TunnelEndpoint.cpp" "${LIBI2PD_SRC_DIR}/TunnelGateway.cpp" "${LIBI2PD_SRC_DIR}/TunnelPool.cpp" + "${LIBI2PD_SRC_DIR}/TunnelConfig.cpp" "${LIBI2PD_SRC_DIR}/util.cpp" ) diff --git a/build/appveyor-msys2-upgrade.bash b/build/appveyor-msys2-upgrade.bash deleted file mode 100644 index 20c6af69..00000000 --- a/build/appveyor-msys2-upgrade.bash +++ /dev/null @@ -1,10 +0,0 @@ -set -e -x - -base_url='http://repo.msys2.org/msys/x86_64/' -packages="libzstd-1.4.4-2-x86_64.pkg.tar.xz pacman-5.2.1-6-x86_64.pkg.tar.xz zstd-1.4.4-2-x86_64.pkg.tar.xz" -for p in $packages -do - curl "${base_url}$p" -o "$p" -done -pacman -U --noconfirm $packages -rm -f $packages diff --git a/daemon/Daemon.cpp b/daemon/Daemon.cpp index 1b9c0a2c..0317704a 100644 --- a/daemon/Daemon.cpp +++ b/daemon/Daemon.cpp @@ -299,14 +299,16 @@ namespace i2p bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); bool ssu; i2p::config::GetOption("ssu", ssu); + bool checkInReserved; i2p::config::GetOption("reservedrange", checkInReserved); LogPrint(eLogInfo, "Daemon: starting Transports"); if(!ssu) LogPrint(eLogInfo, "Daemon: ssu disabled"); if(!ntcp2) LogPrint(eLogInfo, "Daemon: ntcp2 disabled"); + i2p::transport::transports.SetCheckReserved(checkInReserved); i2p::transport::transports.Start(ntcp2, ssu); - if (i2p::transport::transports.IsBoundSSU() || i2p::transport::transports.IsBoundNTCP2()) + if (i2p::transport::transports.IsBoundSSU() || i2p::transport::transports.IsBoundNTCP2()) LogPrint(eLogInfo, "Daemon: Transports started"); - else + else { LogPrint(eLogError, "Daemon: failed to start Transports"); /** shut down netdb right away */ diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 19734038..3b9f6eaa 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -257,7 +257,10 @@ namespace http { switch (i2p::context.GetError ()) { case eRouterErrorClockSkew: - s << "
Clock skew"; + s << " - Clock skew"; + break; + case eRouterErrorOffline: + s << " - Offline"; break; default: ; } diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 1c565083..fc479532 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -51,6 +51,7 @@ namespace config { ("port", value()->default_value(0), "Port to listen for incoming connections (default: auto)") ("ipv4", value()->default_value(true), "Enable communication through ipv4 (default: enabled)") ("ipv6", bool_switch()->default_value(false), "Enable communication through ipv6 (default: disabled)") + ("reservedrange", value()->default_value(true), "Check remote RI for being in blacklist of reserved IP ranges (default: enabled)") ("netid", value()->default_value(I2PD_NET_ID), "Specify NetID. Main I2P is 2") ("daemon", bool_switch()->default_value(false), "Router will go to background after start (default: disabled)") ("service", bool_switch()->default_value(false), "Router will use system folders like '/var/lib/i2pd' (default: disabled)") @@ -107,8 +108,8 @@ namespace config { ("httpproxy.latency.max", value()->default_value("0"), "HTTP proxy max latency for tunnels") ("httpproxy.outproxy", value()->default_value(""), "HTTP proxy upstream out proxy url") ("httpproxy.addresshelper", value()->default_value(true), "Enable or disable addresshelper") - ("httpproxy.i2cp.leaseSetType", value()->default_value("1"), "Local destination's LeaseSet type") - ("httpproxy.i2cp.leaseSetEncType", value()->default_value("0"), "Local destination's LeaseSet encryption type") + ("httpproxy.i2cp.leaseSetType", value()->default_value("3"), "Local destination's LeaseSet type") + ("httpproxy.i2cp.leaseSetEncType", value()->default_value("0,4"), "Local destination's LeaseSet encryption type") ; options_description socksproxy("SOCKS Proxy options"); @@ -128,8 +129,8 @@ namespace config { ("socksproxy.outproxy.enabled", value()->default_value(false), "Enable or disable SOCKS outproxy") ("socksproxy.outproxy", value()->default_value("127.0.0.1"), "Upstream outproxy address for SOCKS Proxy") ("socksproxy.outproxyport", value()->default_value(9050), "Upstream outproxy port for SOCKS Proxy") - ("socksproxy.i2cp.leaseSetType", value()->default_value("1"), "Local destination's LeaseSet type") - ("socksproxy.i2cp.leaseSetEncType", value()->default_value("0"), "Local destination's LeaseSet encryption type") + ("socksproxy.i2cp.leaseSetType", value()->default_value("3"), "Local destination's LeaseSet type") + ("socksproxy.i2cp.leaseSetEncType", value()->default_value("0,4"), "Local destination's LeaseSet encryption type") ; options_description sam("SAM bridge options"); diff --git a/libi2pd/CryptoWorker.h b/libi2pd/CryptoWorker.h deleted file mode 100644 index 27b012e7..00000000 --- a/libi2pd/CryptoWorker.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -* Copyright (c) 2013-2020, The PurpleI2P Project -* -* This file is part of Purple i2pd project and licensed under BSD3 -* -* See full license text in LICENSE file at top of project tree -*/ - -#ifndef CRYPTO_WORKER_H_ -#define CRYPTO_WORKER_H_ - -#include -#include -#include -#include -#include -#include - -namespace i2p -{ -namespace worker -{ - template - struct ThreadPool - { - typedef std::function ResultFunc; - typedef std::function WorkFunc; - typedef std::pair, WorkFunc> Job; - typedef std::mutex mtx_t; - typedef std::unique_lock lock_t; - typedef std::condition_variable cond_t; - ThreadPool(int workers) - { - stop = false; - if(workers > 0) - { - while(workers--) - { - threads.emplace_back([this] { - for (;;) - { - Job job; - { - lock_t lock(this->queue_mutex); - this->condition.wait( - lock, [this] { return this->stop || !this->jobs.empty(); }); - if (this->stop && this->jobs.empty()) return; - job = std::move(this->jobs.front()); - this->jobs.pop_front(); - } - ResultFunc result = job.second(); - job.first->GetService().post(result); - } - }); - } - } - }; - - void Offer(const Job & job) - { - { - lock_t lock(queue_mutex); - if (stop) return; - jobs.emplace_back(job); - } - condition.notify_one(); - } - - ~ThreadPool() - { - { - lock_t lock(queue_mutex); - stop = true; - } - condition.notify_all(); - for(auto &t: threads) t.join(); - } - - std::vector threads; - std::deque jobs; - mtx_t queue_mutex; - cond_t condition; - bool stop; - }; -} -} - -#endif diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 669fd791..927e98a0 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -559,7 +559,9 @@ namespace client m_ExcludedFloodfills.insert (floodfill->GetIdentHash ()); LogPrint (eLogDebug, "Destination: Publish LeaseSet of ", GetIdentHash ().ToBase32 ()); RAND_bytes ((uint8_t *)&m_PublishReplyToken, 4); - auto msg = WrapMessage (floodfill, i2p::CreateDatabaseStoreMsg (leaseSet, m_PublishReplyToken, inbound)); + auto msg = i2p::CreateDatabaseStoreMsg (leaseSet, m_PublishReplyToken, inbound); + if (floodfill->GetIdentity ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL) // TODO: remove when implemented + msg = WrapMessage (floodfill, msg); m_PublishConfirmationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT)); m_PublishConfirmationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishConfirmationTimer, shared_from_this (), std::placeholders::_1)); @@ -754,9 +756,10 @@ namespace client else AddSessionKey (replyKey, replyTag); - auto msg = WrapMessage (nextFloodfill, - CreateLeaseSetDatabaseLookupMsg (dest, request->excluded, - request->replyTunnel, replyKey, replyTag, isECIES)); + auto msg = CreateLeaseSetDatabaseLookupMsg (dest, request->excluded, + request->replyTunnel, replyKey, replyTag, isECIES); + if (nextFloodfill->GetIdentity ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL) // TODO: remove when implemented + msg = WrapMessage (nextFloodfill, msg); request->outboundTunnel->SendTunnelDataMsg ( { i2p::tunnel::TunnelMessageBlock diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 429a2092..5f76bca1 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -740,7 +740,8 @@ namespace garlic session = std::make_shared (this, true); session->SetRemoteStaticKey (staticKey); } - session->SetDestination (destination->GetIdentHash ()); // TODO: remove + if (destination->IsDestination ()) + session->SetDestination (destination->GetIdentHash ()); // TODO: remove return session; } else diff --git a/libi2pd/HTTP.cpp b/libi2pd/HTTP.cpp index 4f7b03a1..484f4c0c 100644 --- a/libi2pd/HTTP.cpp +++ b/libi2pd/HTTP.cpp @@ -16,8 +16,8 @@ namespace i2p { namespace http { const std::vector HTTP_METHODS = { - "GET", "HEAD", "POST", "PUT", "PATCH", - "DELETE", "OPTIONS", "CONNECT", "PROPFIND" + "GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "CONNECT", // HTTP basic methods + "COPY", "LOCK", "MKCOL", "MOVE", "PROPFIND", "PROPPATCH", "UNLOCK", "SEARCH" // WebDAV methods, for SEARCH see rfc5323 }; const std::vector HTTP_VERSIONS = { "HTTP/1.0", "HTTP/1.1" diff --git a/libi2pd/I2NPProtocol.h b/libi2pd/I2NPProtocol.h index fe5ca968..03f0f439 100644 --- a/libi2pd/I2NPProtocol.h +++ b/libi2pd/I2NPProtocol.h @@ -81,6 +81,25 @@ namespace i2p const size_t BUILD_RESPONSE_RECORD_PADDING_SIZE = 495; const size_t BUILD_RESPONSE_RECORD_RET_OFFSET = BUILD_RESPONSE_RECORD_PADDING_OFFSET + BUILD_RESPONSE_RECORD_PADDING_SIZE; + // ECIES BuildRequestRecordClearText + const size_t ECIES_BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET = 0; + const size_t ECIES_BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET = ECIES_BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET + 4; + const size_t ECIES_BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET = ECIES_BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET + 4; + const size_t ECIES_BUILD_REQUEST_RECORD_LAYER_KEY_OFFSET = ECIES_BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET + 32; + const size_t ECIES_BUILD_REQUEST_RECORD_IV_KEY_OFFSET = ECIES_BUILD_REQUEST_RECORD_LAYER_KEY_OFFSET + 32; + const size_t ECIES_BUILD_REQUEST_RECORD_REPLY_KEY_OFFSET = ECIES_BUILD_REQUEST_RECORD_IV_KEY_OFFSET + 32; + const size_t ECIES_BUILD_REQUEST_RECORD_REPLY_IV_OFFSET = ECIES_BUILD_REQUEST_RECORD_REPLY_KEY_OFFSET + 32; + const size_t ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET = ECIES_BUILD_REQUEST_RECORD_REPLY_IV_OFFSET + 16; + const size_t ECIES_BUILD_REQUEST_RECORD_MORE_FLAGS_OFFSET = ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET + 1; + const size_t ECIES_BUILD_REQUEST_RECORD_REQUEST_TIME_OFFSET = ECIES_BUILD_REQUEST_RECORD_MORE_FLAGS_OFFSET + 3; + const size_t ECIES_BUILD_REQUEST_RECORD_REQUEST_EXPIRATION_OFFSET = ECIES_BUILD_REQUEST_RECORD_REQUEST_TIME_OFFSET + 4; + const size_t ECIES_BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET = ECIES_BUILD_REQUEST_RECORD_REQUEST_EXPIRATION_OFFSET + 4; + const size_t ECIES_BUILD_REQUEST_RECORD_PADDING_OFFSET = ECIES_BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET + 4; + const size_t ECIES_BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE = 464; + + // ECIES BuildResponseRecord + const size_t ECIES_BUILD_RESPONSE_RECORD_RET_OFFSET = 511; + enum I2NPMessageType { eI2NPDummyMsg = 0, diff --git a/libi2pd/Identity.cpp b/libi2pd/Identity.cpp index b2b5f2b4..490b8692 100644 --- a/libi2pd/Identity.cpp +++ b/libi2pd/Identity.cpp @@ -48,7 +48,13 @@ namespace data IdentityEx::IdentityEx(const uint8_t * publicKey, const uint8_t * signingKey, SigningKeyType type, CryptoKeyType cryptoType) { - memcpy (m_StandardIdentity.publicKey, publicKey, 256); // publicKey in awlays assumed 256 regardless actual size, padding must be taken care of + if (cryptoType == CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET) + { + memcpy (m_StandardIdentity.publicKey, publicKey, 32); + RAND_bytes (m_StandardIdentity.publicKey, 224); + } + else + memcpy (m_StandardIdentity.publicKey, publicKey, 256); if (type != SIGNING_KEY_TYPE_DSA_SHA1) { size_t excessLen = 0; diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 4ce839ee..318db953 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -125,7 +125,8 @@ namespace data } } if (!m_IsRunning) break; - + if (!i2p::transport::transports.IsOnline ()) continue; // don't manage netdb when offline + uint64_t ts = i2p::util::GetSecondsSinceEpoch (); if (ts - lastManageRequest >= 15) // manage requests every 15 seconds { diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index a576d6b6..37e1791d 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -37,7 +37,8 @@ namespace i2p enum RouterError { eRouterErrorNone = 0, - eRouterErrorClockSkew = 1 + eRouterErrorClockSkew = 1, + eRouterErrorOffline = 2 }; class RouterContext: public i2p::garlic::GarlicDestination diff --git a/libi2pd/SSU.cpp b/libi2pd/SSU.cpp index 0f4526bd..07c95a7a 100644 --- a/libi2pd/SSU.cpp +++ b/libi2pd/SSU.cpp @@ -19,27 +19,25 @@ namespace transport { SSUServer::SSUServer (const boost::asio::ip::address & addr, int port): - m_OnlyV6(true), m_IsRunning(false), - m_Thread (nullptr), m_ThreadV6 (nullptr), m_ReceiversThread (nullptr), - m_ReceiversThreadV6 (nullptr), m_Work (m_Service), m_WorkV6 (m_ServiceV6), + m_OnlyV6(true), m_IsRunning(false), m_Thread (nullptr), + m_ReceiversThread (nullptr), m_ReceiversThreadV6 (nullptr), m_Work (m_Service), m_ReceiversWork (m_ReceiversService), m_ReceiversWorkV6 (m_ReceiversServiceV6), m_EndpointV6 (addr, port), m_Socket (m_ReceiversService, m_Endpoint), m_SocketV6 (m_ReceiversServiceV6), m_IntroducersUpdateTimer (m_Service), m_PeerTestsCleanupTimer (m_Service), m_TerminationTimer (m_Service), - m_TerminationTimerV6 (m_ServiceV6) + m_TerminationTimerV6 (m_Service) { OpenSocketV6 (); } SSUServer::SSUServer (int port): - m_OnlyV6(false), m_IsRunning(false), - m_Thread (nullptr), m_ThreadV6 (nullptr), m_ReceiversThread (nullptr), - m_ReceiversThreadV6 (nullptr), m_Work (m_Service), m_WorkV6 (m_ServiceV6), + m_OnlyV6(false), m_IsRunning(false), m_Thread (nullptr), + m_ReceiversThread (nullptr), m_ReceiversThreadV6 (nullptr), m_Work (m_Service), m_ReceiversWork (m_ReceiversService), m_ReceiversWorkV6 (m_ReceiversServiceV6), m_Endpoint (boost::asio::ip::udp::v4 (), port), m_EndpointV6 (boost::asio::ip::udp::v6 (), port), m_Socket (m_ReceiversService), m_SocketV6 (m_ReceiversServiceV6), m_IntroducersUpdateTimer (m_Service), m_PeerTestsCleanupTimer (m_Service), - m_TerminationTimer (m_Service), m_TerminationTimerV6 (m_ServiceV6) + m_TerminationTimer (m_Service), m_TerminationTimerV6 (m_Service) { OpenSocket (); if (context.SupportsV6 ()) @@ -98,7 +96,8 @@ namespace transport if (context.SupportsV6 ()) { m_ReceiversThreadV6 = new std::thread (std::bind (&SSUServer::RunReceiversV6, this)); - m_ThreadV6 = new std::thread (std::bind (&SSUServer::RunV6, this)); + if (!m_Thread) + m_Thread = new std::thread (std::bind (&SSUServer::Run, this)); m_ReceiversServiceV6.post (std::bind (&SSUServer::ReceiveV6, this)); ScheduleTerminationV6 (); } @@ -114,7 +113,6 @@ namespace transport m_TerminationTimerV6.cancel (); m_Service.stop (); m_Socket.close (); - m_ServiceV6.stop (); m_SocketV6.close (); m_ReceiversService.stop (); m_ReceiversServiceV6.stop (); @@ -136,12 +134,6 @@ namespace transport delete m_ReceiversThreadV6; m_ReceiversThreadV6 = nullptr; } - if (m_ThreadV6) - { - m_ThreadV6->join (); - delete m_ThreadV6; - m_ThreadV6 = nullptr; - } } void SSUServer::Run () @@ -159,21 +151,6 @@ namespace transport } } - void SSUServer::RunV6 () - { - while (m_IsRunning) - { - try - { - m_ServiceV6.run (); - } - catch (std::exception& ex) - { - LogPrint (eLogError, "SSU: v6 server runtime exception: ", ex.what ()); - } - } - } - void SSUServer::RunReceivers () { while (m_IsRunning) @@ -242,10 +219,16 @@ namespace transport void SSUServer::Send (const uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& to) { + boost::system::error_code ec; if (to.protocol () == boost::asio::ip::udp::v4()) - m_Socket.send_to (boost::asio::buffer (buf, len), to); + m_Socket.send_to (boost::asio::buffer (buf, len), to, 0, ec); else - m_SocketV6.send_to (boost::asio::buffer (buf, len), to); + m_SocketV6.send_to (boost::asio::buffer (buf, len), to, 0, ec); + + if (ec) + { + LogPrint (eLogError, "SSU: send exception: ", ec.message (), " while trying to send data to ", to.address (), ":", to.port (), " (length: ", len, ")"); + } } void SSUServer::Receive () @@ -264,7 +247,13 @@ namespace transport void SSUServer::HandleReceivedFrom (const boost::system::error_code& ecode, std::size_t bytes_transferred, SSUPacket * packet) { - if (!ecode) + if (!ecode || + ecode == boost::asio::error::connection_refused || + ecode == boost::asio::error::connection_reset || + ecode == boost::asio::error::network_unreachable || + ecode == boost::asio::error::host_unreachable) + // just try continue reading when received ICMP response otherwise socket can crash, + // but better to find out which host were sent it and mark that router as unreachable { packet->len = bytes_transferred; std::vector packets; @@ -286,7 +275,7 @@ namespace transport } else { - LogPrint (eLogError, "SSU: receive_from error: ", ec.message ()); + LogPrint (eLogError, "SSU: receive_from error: code ", ec.value(), ": ", ec.message ()); delete packet; break; } @@ -301,7 +290,7 @@ namespace transport delete packet; if (ecode != boost::asio::error::operation_aborted) { - LogPrint (eLogError, "SSU: receive error: ", ecode.message ()); + LogPrint (eLogError, "SSU: receive error: code ", ecode.value(), ": ", ecode.message ()); m_Socket.close (); OpenSocket (); Receive (); @@ -311,7 +300,13 @@ namespace transport void SSUServer::HandleReceivedFromV6 (const boost::system::error_code& ecode, std::size_t bytes_transferred, SSUPacket * packet) { - if (!ecode) + if (!ecode || + ecode == boost::asio::error::connection_refused || + ecode == boost::asio::error::connection_reset || + ecode == boost::asio::error::network_unreachable || + ecode == boost::asio::error::host_unreachable) + // just try continue reading when received ICMP response otherwise socket can crash, + // but better to find out which host were sent it and mark that router as unreachable { packet->len = bytes_transferred; std::vector packets; @@ -333,14 +328,14 @@ namespace transport } else { - LogPrint (eLogError, "SSU: v6 receive_from error: ", ec.message ()); + LogPrint (eLogError, "SSU: v6 receive_from error: code ", ec.value(), ": ", ec.message ()); delete packet; break; } } } - m_ServiceV6.post (std::bind (&SSUServer::HandleReceivedPackets, this, packets, &m_SessionsV6)); + m_Service.post (std::bind (&SSUServer::HandleReceivedPackets, this, packets, &m_SessionsV6)); ReceiveV6 (); } else @@ -348,7 +343,7 @@ namespace transport delete packet; if (ecode != boost::asio::error::operation_aborted) { - LogPrint (eLogError, "SSU: v6 receive error: ", ecode.message ()); + LogPrint (eLogError, "SSU: v6 receive error: code ", ecode.value(), ": ", ecode.message ()); m_SocketV6.close (); OpenSocketV6 (); ReceiveV6 (); @@ -438,8 +433,7 @@ namespace transport else { boost::asio::ip::udp::endpoint remoteEndpoint (addr, port); - auto& s = addr.is_v6 () ? m_ServiceV6 : m_Service; - s.post (std::bind (&SSUServer::CreateDirectSession, this, router, remoteEndpoint, peerTest)); + m_Service.post (std::bind (&SSUServer::CreateDirectSession, this, router, remoteEndpoint, peerTest)); } } } @@ -459,6 +453,7 @@ namespace transport // otherwise create new session auto session = std::make_shared (*this, remoteEndpoint, router, peerTest); sessions[remoteEndpoint] = session; + // connect LogPrint (eLogDebug, "SSU: Creating new session to [", i2p::data::GetIdentHashAbbreviation (router->GetIdentHash ()), "] ", remoteEndpoint.address ().to_string (), ":", remoteEndpoint.port ()); @@ -822,7 +817,7 @@ namespace transport auto session = it.second; if (it.first != session->GetRemoteEndpoint ()) LogPrint (eLogWarning, "SSU: remote endpoint ", session->GetRemoteEndpoint (), " doesn't match key ", it.first); - m_ServiceV6.post ([session] + m_Service.post ([session] { LogPrint (eLogWarning, "SSU: no activity with ", session->GetRemoteEndpoint (), " for ", session->GetTerminationTimeout (), " seconds"); session->Failed (); diff --git a/libi2pd/SSU.h b/libi2pd/SSU.h index 6a79f754..213f379f 100644 --- a/libi2pd/SSU.h +++ b/libi2pd/SSU.h @@ -64,7 +64,6 @@ namespace transport void DeleteAllSessions (); boost::asio::io_service& GetService () { return m_Service; }; - boost::asio::io_service& GetServiceV6 () { return m_ServiceV6; }; const boost::asio::ip::udp::endpoint& GetEndpoint () const { return m_Endpoint; }; void Send (const uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& to); void AddRelay (uint32_t tag, std::shared_ptr relay); @@ -82,7 +81,6 @@ namespace transport void OpenSocket (); void OpenSocketV6 (); void Run (); - void RunV6 (); void RunReceivers (); void RunReceiversV6 (); void Receive (); @@ -122,9 +120,9 @@ namespace transport bool m_OnlyV6; bool m_IsRunning; - std::thread * m_Thread, * m_ThreadV6, * m_ReceiversThread, * m_ReceiversThreadV6; - boost::asio::io_service m_Service, m_ServiceV6, m_ReceiversService, m_ReceiversServiceV6; - boost::asio::io_service::work m_Work, m_WorkV6, m_ReceiversWork, m_ReceiversWorkV6; + std::thread * m_Thread, * m_ReceiversThread, * m_ReceiversThreadV6; + boost::asio::io_service m_Service, m_ReceiversService, m_ReceiversServiceV6; + boost::asio::io_service::work m_Work, m_ReceiversWork, m_ReceiversWorkV6; boost::asio::ip::udp::endpoint m_Endpoint, m_EndpointV6; boost::asio::ip::udp::socket m_Socket, m_SocketV6; boost::asio::deadline_timer m_IntroducersUpdateTimer, m_PeerTestsCleanupTimer, diff --git a/libi2pd/SSUSession.cpp b/libi2pd/SSUSession.cpp index 399b2fc7..860c2be3 100644 --- a/libi2pd/SSUSession.cpp +++ b/libi2pd/SSUSession.cpp @@ -49,7 +49,7 @@ namespace transport boost::asio::io_service& SSUSession::GetService () { - return IsV6 () ? m_Server.GetServiceV6 () : m_Server.GetService (); + return m_Server.GetService (); } void SSUSession::CreateAESandMacKey (const uint8_t * pubKey) @@ -224,7 +224,11 @@ namespace transport return; } if (!m_DHKeysPair) - m_DHKeysPair = transports.GetNextDHKeysPair (); + { + auto pair = std::make_shared (); + pair->GenerateKeys (); + m_DHKeysPair = pair; + } CreateAESandMacKey (buf + headerSize); SendSessionCreated (buf + headerSize, sendRelayTag); } @@ -826,9 +830,9 @@ namespace transport { if (m_State == eSessionStateUnknown) { - // set connect timer - ScheduleConnectTimer (); - m_DHKeysPair = transports.GetNextDHKeysPair (); + ScheduleConnectTimer (); // set connect timer + m_DHKeysPair = std::make_shared (); + m_DHKeysPair->GenerateKeys (); SendSessionRequest (); } } diff --git a/libi2pd/SSUSession.h b/libi2pd/SSUSession.h index ea820517..3aa04638 100644 --- a/libi2pd/SSUSession.h +++ b/libi2pd/SSUSession.h @@ -166,6 +166,7 @@ namespace transport bool m_IsDataReceived; std::unique_ptr m_SignedData; // we need it for SessionConfirmed only std::map > m_RelayRequests; // nonce->Charlie + std::shared_ptr m_DHKeysPair; // X - for client and Y - for server }; } } diff --git a/libi2pd/Timestamp.cpp b/libi2pd/Timestamp.cpp index 4362a878..45684333 100644 --- a/libi2pd/Timestamp.cpp +++ b/libi2pd/Timestamp.cpp @@ -35,18 +35,24 @@ namespace util 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 uint32_t GetLocalMinutesSinceEpoch () + { + 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 int64_t g_TimeOffset = 0; // in seconds static void SyncTimeWithNTP (const std::string& address) @@ -178,14 +184,19 @@ namespace util return GetLocalMillisecondsSinceEpoch () + g_TimeOffset*1000; } - uint32_t GetHoursSinceEpoch () - { - return GetLocalHoursSinceEpoch () + g_TimeOffset/3600; - } - uint64_t GetSecondsSinceEpoch () { return GetLocalSecondsSinceEpoch () + g_TimeOffset; + } + + uint32_t GetMinutesSinceEpoch () + { + return GetLocalMinutesSinceEpoch () + g_TimeOffset/60; + } + + uint32_t GetHoursSinceEpoch () + { + return GetLocalHoursSinceEpoch () + g_TimeOffset/3600; } void GetCurrentDate (char * date) diff --git a/libi2pd/Timestamp.h b/libi2pd/Timestamp.h index 91175a49..b46f423d 100644 --- a/libi2pd/Timestamp.h +++ b/libi2pd/Timestamp.h @@ -20,8 +20,9 @@ namespace i2p namespace util { uint64_t GetMillisecondsSinceEpoch (); - uint32_t GetHoursSinceEpoch (); uint64_t GetSecondsSinceEpoch (); + uint32_t GetMinutesSinceEpoch (); + uint32_t GetHoursSinceEpoch (); void GetCurrentDate (char * date); // returns date as YYYYMMDD string, 9 bytes void GetDateString (uint64_t timestamp, char * date); // timestap is seconds since epoch, returns date as YYYYMMDD string, 9 bytes diff --git a/libi2pd/TransportSession.h b/libi2pd/TransportSession.h index a97f246f..12d4894b 100644 --- a/libi2pd/TransportSession.h +++ b/libi2pd/TransportSession.h @@ -64,7 +64,7 @@ namespace transport public: TransportSession (std::shared_ptr router, int terminationTimeout): - m_DHKeysPair (nullptr), m_NumSentBytes (0), m_NumReceivedBytes (0), m_IsOutgoing (router), m_TerminationTimeout (terminationTimeout), + m_NumSentBytes (0), m_NumReceivedBytes (0), m_IsOutgoing (router), m_TerminationTimeout (terminationTimeout), m_LastActivityTimestamp (i2p::util::GetSecondsSinceEpoch ()) { if (router) @@ -103,7 +103,6 @@ namespace transport std::shared_ptr m_RemoteIdentity; mutable std::mutex m_RemoteIdentityMutex; - std::shared_ptr m_DHKeysPair; // X - for client and Y - for server size_t m_NumSentBytes, m_NumReceivedBytes; bool m_IsOutgoing; int m_TerminationTimeout; diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 19e17f52..c6e90ad2 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -27,20 +27,20 @@ namespace transport { } - template + template EphemeralKeysSupplier::~EphemeralKeysSupplier () { Stop (); } - template + template void EphemeralKeysSupplier::Start () { m_IsRunning = true; m_Thread = new std::thread (std::bind (&EphemeralKeysSupplier::Run, this)); } - template + template void EphemeralKeysSupplier::Stop () { { @@ -56,7 +56,7 @@ namespace transport } } - template + template void EphemeralKeysSupplier::Run () { while (m_IsRunning) @@ -81,7 +81,7 @@ namespace transport } } - template + template void EphemeralKeysSupplier::CreateEphemeralKeys (int num) { if (num > 0) @@ -96,7 +96,7 @@ namespace transport } } - template + template std::shared_ptr EphemeralKeysSupplier::Acquire () { { @@ -115,7 +115,7 @@ namespace transport return pair; } - template + template void EphemeralKeysSupplier::Return (std::shared_ptr pair) { if (pair) @@ -131,10 +131,10 @@ namespace transport Transports transports; Transports::Transports (): - 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_IsOnline (true), m_IsRunning (false), m_IsNAT (true), m_CheckReserved(true), m_Thread (nullptr), + m_Service (nullptr), m_Work (nullptr), m_PeerCleanupTimer (nullptr), m_PeerTestTimer (nullptr), m_SSUServer (nullptr), m_NTCP2Server (nullptr), - m_DHKeysPairSupplier (5), m_X25519KeysPairSupplier (5), // 5 pre-generated keys + m_X25519KeysPairSupplier (5), // 5 pre-generated keys m_TotalSentBytes(0), m_TotalReceivedBytes(0), m_TotalTransitTransmittedBytes (0), m_InBandwidth (0), m_OutBandwidth (0), m_TransitBandwidth(0), m_LastInBandwidthUpdateBytes (0), m_LastOutBandwidthUpdateBytes (0), @@ -165,12 +165,11 @@ namespace transport } i2p::config::GetOption("nat", m_IsNAT); - m_DHKeysPairSupplier.Start (); m_X25519KeysPairSupplier.Start (); m_IsRunning = true; m_Thread = new std::thread (std::bind (&Transports::Run, this)); std::string ntcp2proxy; i2p::config::GetOption("ntcp2.proxy", ntcp2proxy); - i2p::http::URL proxyurl; + i2p::http::URL proxyurl; // create NTCP2. TODO: move to acceptor if (enableNTCP2) { @@ -252,7 +251,7 @@ namespace transport delete m_SSUServer; m_SSUServer = nullptr; } - + if (m_NTCP2Server) { m_NTCP2Server->Stop (); @@ -260,7 +259,6 @@ namespace transport m_NTCP2Server = nullptr; } - m_DHKeysPairSupplier.Stop (); m_X25519KeysPairSupplier.Stop (); m_IsRunning = false; if (m_Service) m_Service->stop (); @@ -321,7 +319,8 @@ namespace transport void Transports::SendMessage (const i2p::data::IdentHash& ident, std::shared_ptr msg) { - SendMessages (ident, std::vector > {msg }); + if (m_IsOnline) + SendMessages (ident, std::vector > {msg }); } void Transports::SendMessages (const i2p::data::IdentHash& ident, const std::vector >& msgs) @@ -371,7 +370,7 @@ namespace transport } else { - LogPrint (eLogWarning, "Transports: delayed messages queue size to ", + LogPrint (eLogWarning, "Transports: delayed messages queue size to ", ident.ToBase64 (), " exceeds ", MAX_NUM_DELAYED_MESSAGES); std::unique_lock l(m_PeersMutex); m_Peers.erase (it); @@ -392,7 +391,7 @@ namespace transport { // NTCP2 have priority over NTCP auto address = peer.router->GetNTCP2Address (true, !context.SupportsV6 ()); // published only - if (address && !peer.router->IsUnreachable ()) + if (address && !peer.router->IsUnreachable () && (!m_CheckReserved || !i2p::util::net::IsInReservedRange(address->host))) { auto s = std::make_shared (*m_NTCP2Server, peer.router); @@ -418,8 +417,11 @@ namespace transport if (m_SSUServer && peer.router->IsSSU (!context.SupportsV6 ())) { auto address = peer.router->GetSSUAddress (!context.SupportsV6 ()); - m_SSUServer->CreateSession (peer.router, address->host, address->port); - return true; + if (!m_CheckReserved || !i2p::util::net::IsInReservedRange(address->host)) + { + m_SSUServer->CreateSession (peer.router, address->host, address->port); + return true; + } } } LogPrint (eLogInfo, "Transports: No NTCP or SSU addresses available"); @@ -499,7 +501,7 @@ namespace transport { auto addr = router->GetSSUV6Address (); if (addr) - m_SSUServer->GetServiceV6 ().post ([this, router, addr] + m_SSUServer->GetService ().post ([this, router, addr] { m_SSUServer->CreateDirectSession (router, { addr->host, (uint16_t)addr->port }, false); }); @@ -536,16 +538,6 @@ namespace transport } } - std::shared_ptr Transports::GetNextDHKeysPair () - { - return m_DHKeysPairSupplier.Acquire (); - } - - void Transports::ReuseDHKeysPair (std::shared_ptr pair) - { - m_DHKeysPairSupplier.Return (pair); - } - std::shared_ptr Transports::GetNextX25519KeysPair () { return m_X25519KeysPairSupplier.Acquire (); @@ -555,7 +547,7 @@ namespace transport { m_X25519KeysPairSupplier.Return (pair); } - + void Transports::PeerConnected (std::shared_ptr session) { m_Service->post([session, this]() @@ -756,5 +748,17 @@ namespace transport } return false; } + + void Transports::SetOnline (bool online) + { + if (m_IsOnline != online) + { + m_IsOnline = online; + if (online) + PeerTest (); + else + i2p::context.SetError (eRouterErrorOffline); + } + } } } diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index c3008b09..d480840a 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -59,7 +59,6 @@ namespace transport std::condition_variable m_Acquired; std::mutex m_AcquiredMutex; }; - typedef EphemeralKeysSupplier DHKeysPairSupplier; typedef EphemeralKeysSupplier X25519KeysPairSupplier; struct Peer @@ -94,11 +93,9 @@ namespace transport bool IsBoundNTCP2() const { return m_NTCP2Server != nullptr; } bool IsOnline() const { return m_IsOnline; }; - void SetOnline (bool online) { m_IsOnline = online; }; + void SetOnline (bool online); boost::asio::io_service& GetService () { return *m_Service; }; - std::shared_ptr GetNextDHKeysPair (); - void ReuseDHKeysPair (std::shared_ptr pair); std::shared_ptr GetNextX25519KeysPair (); void ReuseX25519KeysPair (std::shared_ptr pair); @@ -136,6 +133,9 @@ namespace transport void PeerTest (); + void SetCheckReserved (bool check) { m_CheckReserved = check; }; + bool IsCheckReserved () { return m_CheckReserved; }; + private: void Run (); @@ -151,7 +151,8 @@ namespace transport private: - bool m_IsOnline, m_IsRunning, m_IsNAT; + volatile bool m_IsOnline; + bool m_IsRunning, m_IsNAT, m_CheckReserved; std::thread * m_Thread; boost::asio::io_service * m_Service; boost::asio::io_service::work * m_Work; @@ -162,7 +163,6 @@ namespace transport mutable std::mutex m_PeersMutex; std::unordered_map m_Peers; - DHKeysPairSupplier m_DHKeysPairSupplier; X25519KeysPairSupplier m_X25519KeysPairSupplier; std::atomic m_TotalSentBytes, m_TotalReceivedBytes, m_TotalTransitTransmittedBytes; diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index fe7e36af..bfe466e3 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -111,7 +111,7 @@ namespace tunnel while (hop) { decryption.SetKey (hop->replyKey); - // decrypt records before and including current hop + // decrypt records before and current hop TunnelHopConfig * hop1 = hop; while (hop1) { @@ -119,8 +119,22 @@ namespace tunnel if (idx >= 0 && idx < msg[0]) { uint8_t * record = msg + 1 + idx*TUNNEL_BUILD_RECORD_SIZE; - decryption.SetIV (hop->replyIV); - decryption.Decrypt(record, TUNNEL_BUILD_RECORD_SIZE, record); + if (hop1 == hop && hop1->IsECIES ()) + { + uint8_t nonce[12]; + memset (nonce, 0, 12); + if (!i2p::crypto::AEADChaCha20Poly1305 (record, TUNNEL_BUILD_RECORD_SIZE - 16, + hop->h, 32, hop->ck, nonce, record, TUNNEL_BUILD_RECORD_SIZE - 16, false)) // decrypt + { + LogPrint (eLogWarning, "Tunnel: Response AEAD decryption failed"); + return false; + } + } + else + { + decryption.SetIV (hop->replyIV); + decryption.Decrypt(record, TUNNEL_BUILD_RECORD_SIZE, record); + } } else LogPrint (eLogWarning, "Tunnel: hop index ", idx, " is out of range"); @@ -134,7 +148,7 @@ namespace tunnel while (hop) { const uint8_t * record = msg + 1 + hop->recordIndex*TUNNEL_BUILD_RECORD_SIZE; - uint8_t ret = record[BUILD_RESPONSE_RECORD_RET_OFFSET]; + uint8_t ret = record[hop->IsECIES () ? ECIES_BUILD_RESPONSE_RECORD_RET_OFFSET : BUILD_RESPONSE_RECORD_RET_OFFSET]; LogPrint (eLogDebug, "Tunnel: Build response ret code=", (int)ret); auto profile = i2p::data::netdb.FindRouterProfile (hop->ident->GetIdentHash ()); if (profile) @@ -303,6 +317,7 @@ namespace tunnel { for (auto& msg : msgs) { + if (!msg.data) continue; switch (msg.deliveryType) { case eDeliveryTypeLocal: @@ -521,7 +536,7 @@ namespace tunnel } uint64_t ts = i2p::util::GetSecondsSinceEpoch (); - if (ts - lastTs >= 15) // manage tunnels every 15 seconds + if (ts - lastTs >= 15 && i2p::transport::transports.IsOnline()) // manage tunnels every 15 seconds { ManageTunnels (); lastTs = ts; diff --git a/libi2pd/TunnelConfig.cpp b/libi2pd/TunnelConfig.cpp new file mode 100644 index 00000000..5c2cbd53 --- /dev/null +++ b/libi2pd/TunnelConfig.cpp @@ -0,0 +1,166 @@ +/* +* Copyright (c) 2013-2020, The PurpleI2P Project +* +* This file is part of Purple i2pd project and licensed under BSD3 +* +* See full license text in LICENSE file at top of project tree +* +*/ + +#include +#include +#include +#include "Crypto.h" +#include "Log.h" +#include "Transports.h" +#include "Timestamp.h" +#include "I2PEndian.h" +#include "I2NPProtocol.h" +#include "TunnelConfig.h" + +namespace i2p +{ +namespace tunnel +{ + TunnelHopConfig::TunnelHopConfig (std::shared_ptr r) + { + RAND_bytes (layerKey, 32); + RAND_bytes (ivKey, 32); + RAND_bytes (replyKey, 32); + RAND_bytes (replyIV, 16); + RAND_bytes ((uint8_t *)&tunnelID, 4); + if (!tunnelID) tunnelID = 1; // tunnelID can't be zero + isGateway = true; + isEndpoint = true; + ident = r; + //nextRouter = nullptr; + nextTunnelID = 0; + + next = nullptr; + prev = nullptr; + } + + void TunnelHopConfig::SetNextIdent (const i2p::data::IdentHash& ident) + { + nextIdent = ident; + isEndpoint = false; + RAND_bytes ((uint8_t *)&nextTunnelID, 4); + if (!nextTunnelID) nextTunnelID = 1; // tunnelID can't be zero + } + + void TunnelHopConfig::SetReplyHop (uint32_t replyTunnelID, const i2p::data::IdentHash& replyIdent) + { + nextIdent = replyIdent; + nextTunnelID = replyTunnelID; + isEndpoint = true; + } + + void TunnelHopConfig::SetNext (TunnelHopConfig * n) + { + next = n; + if (next) + { + next->prev = this; + next->isGateway = false; + isEndpoint = false; + nextIdent = next->ident->GetIdentHash (); + nextTunnelID = next->tunnelID; + } + } + + void TunnelHopConfig::SetPrev (TunnelHopConfig * p) + { + prev = p; + if (prev) + { + prev->next = this; + prev->isEndpoint = false; + isGateway = false; + } + } + + void TunnelHopConfig::CreateBuildRequestRecord (uint8_t * record, uint32_t replyMsgID, BN_CTX * ctx) + { + uint8_t flag = 0; + if (isGateway) flag |= 0x80; + if (isEndpoint) flag |= 0x40; + auto encryptor = ident->CreateEncryptor (nullptr); + if (IsECIES ()) + { + uint8_t clearText[ECIES_BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE]; + htobe32buf (clearText + ECIES_BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET, tunnelID); + htobe32buf (clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET, nextTunnelID); + memcpy (clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, nextIdent, 32); + memcpy (clearText + ECIES_BUILD_REQUEST_RECORD_LAYER_KEY_OFFSET, layerKey, 32); + memcpy (clearText + ECIES_BUILD_REQUEST_RECORD_IV_KEY_OFFSET, ivKey, 32); + memcpy (clearText + ECIES_BUILD_REQUEST_RECORD_REPLY_KEY_OFFSET, replyKey, 32); + memcpy (clearText + ECIES_BUILD_REQUEST_RECORD_REPLY_IV_OFFSET, replyIV, 16); + clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] = flag; + memset (clearText + ECIES_BUILD_REQUEST_RECORD_MORE_FLAGS_OFFSET, 0, 3); // set to 0 for compatibility + htobe32buf (clearText + ECIES_BUILD_REQUEST_RECORD_REQUEST_TIME_OFFSET, i2p::util::GetMinutesSinceEpoch ()); + htobe32buf (clearText + ECIES_BUILD_REQUEST_RECORD_REQUEST_EXPIRATION_OFFSET, 600); // +10 minutes + htobe32buf (clearText + ECIES_BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET, replyMsgID); + memset (clearText + ECIES_BUILD_REQUEST_RECORD_PADDING_OFFSET, 0, ECIES_BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE - ECIES_BUILD_REQUEST_RECORD_PADDING_OFFSET); + if (encryptor) + EncryptECIES (encryptor, clearText, record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, ctx); + } + else + { + uint8_t clearText[BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE]; + htobe32buf (clearText + BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET, tunnelID); + memcpy (clearText + BUILD_REQUEST_RECORD_OUR_IDENT_OFFSET, ident->GetIdentHash (), 32); + htobe32buf (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET, nextTunnelID); + memcpy (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, nextIdent, 32); + memcpy (clearText + BUILD_REQUEST_RECORD_LAYER_KEY_OFFSET, layerKey, 32); + memcpy (clearText + BUILD_REQUEST_RECORD_IV_KEY_OFFSET, ivKey, 32); + memcpy (clearText + BUILD_REQUEST_RECORD_REPLY_KEY_OFFSET, replyKey, 32); + memcpy (clearText + BUILD_REQUEST_RECORD_REPLY_IV_OFFSET, replyIV, 16); + clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET] = flag; + htobe32buf (clearText + BUILD_REQUEST_RECORD_REQUEST_TIME_OFFSET, i2p::util::GetHoursSinceEpoch ()); + htobe32buf (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET, replyMsgID); + RAND_bytes (clearText + BUILD_REQUEST_RECORD_PADDING_OFFSET, BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE - BUILD_REQUEST_RECORD_PADDING_OFFSET); + if (encryptor) + encryptor->Encrypt (clearText, record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, ctx, false); + } + memcpy (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)ident->GetIdentHash (), 16); + } + + void TunnelHopConfig::EncryptECIES (std::shared_ptr& encryptor, + const uint8_t * plainText, uint8_t * encrypted, BN_CTX * ctx) + { + static const char protocolName[] = "Noise_N_25519_ChaChaPoly_SHA256"; // 31 chars + memcpy (ck, protocolName, 32); // ck = h = protocol_name || 0 + SHA256 (ck, 32, h); // h = SHA256(h); + uint8_t hepk[32]; + encryptor->Encrypt (nullptr, hepk, nullptr, false); + MixHash (hepk, 32); // h = SHA256(h || hepk) + auto ephemeralKeys = i2p::transport::transports.GetNextX25519KeysPair (); + memcpy (encrypted, ephemeralKeys->GetPublicKey (), 32); + MixHash (encrypted, 32); // h = SHA256(h || sepk) + encrypted += 32; + uint8_t sharedSecret[32]; + ephemeralKeys->Agree (hepk, sharedSecret); // x25519(sesk, hepk) + uint8_t keydata[64]; + i2p::crypto::HKDF (ck, sharedSecret, 32, "", keydata); + memcpy (ck, keydata, 32); + uint8_t nonce[12]; + memset (nonce, 0, 12); + if (!i2p::crypto::AEADChaCha20Poly1305 (plainText, ECIES_BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE, h, 32, + keydata + 32, nonce, encrypted, ECIES_BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE + 16, true)) // encrypt + { + LogPrint (eLogWarning, "Tunnel: Plaintext AEAD encryption failed"); + return; + } + MixHash (encrypted, ECIES_BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE + 16); // h = SHA256(h || ciphertext) + } + + void TunnelHopConfig::MixHash (const uint8_t * buf, size_t len) + { + SHA256_CTX ctx; + SHA256_Init (&ctx); + SHA256_Update (&ctx, h, 32); + SHA256_Update (&ctx, buf, len); + SHA256_Final (h, &ctx); + } +} +} \ No newline at end of file diff --git a/libi2pd/TunnelConfig.h b/libi2pd/TunnelConfig.h index 0bd8a842..0e757071 100644 --- a/libi2pd/TunnelConfig.h +++ b/libi2pd/TunnelConfig.h @@ -9,13 +9,9 @@ #ifndef TUNNEL_CONFIG_H__ #define TUNNEL_CONFIG_H__ -#include -#include #include -#include #include "Identity.h" #include "RouterContext.h" -#include "Timestamp.h" namespace i2p { @@ -34,87 +30,20 @@ namespace tunnel TunnelHopConfig * next, * prev; int recordIndex; // record # in tunnel build message + uint8_t ck[32], h[32]; // for ECIES + + TunnelHopConfig (std::shared_ptr r); + + void SetNextIdent (const i2p::data::IdentHash& ident); + void SetReplyHop (uint32_t replyTunnelID, const i2p::data::IdentHash& replyIdent); + void SetNext (TunnelHopConfig * n); + void SetPrev (TunnelHopConfig * p); - TunnelHopConfig (std::shared_ptr r) - { - RAND_bytes (layerKey, 32); - RAND_bytes (ivKey, 32); - RAND_bytes (replyKey, 32); - RAND_bytes (replyIV, 16); - RAND_bytes ((uint8_t *)&tunnelID, 4); - if (!tunnelID) tunnelID = 1; // tunnelID can't be zero - isGateway = true; - isEndpoint = true; - ident = r; - //nextRouter = nullptr; - nextTunnelID = 0; - - next = nullptr; - prev = nullptr; - } - - void SetNextIdent (const i2p::data::IdentHash& ident) - { - nextIdent = ident; - isEndpoint = false; - RAND_bytes ((uint8_t *)&nextTunnelID, 4); - if (!nextTunnelID) nextTunnelID = 1; // tunnelID can't be zero - } - - void SetReplyHop (uint32_t replyTunnelID, const i2p::data::IdentHash& replyIdent) - { - nextIdent = replyIdent; - nextTunnelID = replyTunnelID; - isEndpoint = true; - } - - void SetNext (TunnelHopConfig * n) - { - next = n; - if (next) - { - next->prev = this; - next->isGateway = false; - isEndpoint = false; - nextIdent = next->ident->GetIdentHash (); - nextTunnelID = next->tunnelID; - } - } - - void SetPrev (TunnelHopConfig * p) - { - prev = p; - if (prev) - { - prev->next = this; - prev->isEndpoint = false; - isGateway = false; - } - } - - void CreateBuildRequestRecord (uint8_t * record, uint32_t replyMsgID, BN_CTX * ctx) const - { - uint8_t clearText[BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE]; - htobe32buf (clearText + BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET, tunnelID); - memcpy (clearText + BUILD_REQUEST_RECORD_OUR_IDENT_OFFSET, ident->GetIdentHash (), 32); - htobe32buf (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET, nextTunnelID); - memcpy (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, nextIdent, 32); - memcpy (clearText + BUILD_REQUEST_RECORD_LAYER_KEY_OFFSET, layerKey, 32); - memcpy (clearText + BUILD_REQUEST_RECORD_IV_KEY_OFFSET, ivKey, 32); - memcpy (clearText + BUILD_REQUEST_RECORD_REPLY_KEY_OFFSET, replyKey, 32); - memcpy (clearText + BUILD_REQUEST_RECORD_REPLY_IV_OFFSET, replyIV, 16); - uint8_t flag = 0; - if (isGateway) flag |= 0x80; - if (isEndpoint) flag |= 0x40; - clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET] = flag; - htobe32buf (clearText + BUILD_REQUEST_RECORD_REQUEST_TIME_OFFSET, i2p::util::GetHoursSinceEpoch ()); - htobe32buf (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET, replyMsgID); - RAND_bytes (clearText + BUILD_REQUEST_RECORD_PADDING_OFFSET, BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE - BUILD_REQUEST_RECORD_PADDING_OFFSET); - auto encryptor = ident->CreateEncryptor (nullptr); - if (encryptor) - encryptor->Encrypt (clearText, record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, ctx, false); - memcpy (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)ident->GetIdentHash (), 16); - } + bool IsECIES () const { return ident->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET; }; + void CreateBuildRequestRecord (uint8_t * record, uint32_t replyMsgID, BN_CTX * ctx); + void EncryptECIES (std::shared_ptr& encryptor, + const uint8_t * clearText, uint8_t * encrypted, BN_CTX * ctx); + void MixHash (const uint8_t * buf, size_t len); }; class TunnelConfig diff --git a/libi2pd/util.cpp b/libi2pd/util.cpp index f5204a50..2cc101c7 100644 --- a/libi2pd/util.cpp +++ b/libi2pd/util.cpp @@ -61,6 +61,9 @@ int inet_pton_xp(int af, const char *src, void *dst) #include #endif +#define address_pair_v4(a,b) { boost::asio::ip::address_v4::from_string (a).to_ulong (), boost::asio::ip::address_v4::from_string (b).to_ulong () } +#define address_pair_v6(a,b) { boost::asio::ip::address_v6::from_string (a).to_bytes (), boost::asio::ip::address_v6::from_string (b).to_bytes () } + namespace i2p { namespace util @@ -391,6 +394,50 @@ namespace net return boost::asio::ip::address::from_string(fallback); #endif } -} + + bool IsInReservedRange(const boost::asio::ip::address& host) { + // https://en.wikipedia.org/wiki/Reserved_IP_addresses + if(host.is_v4()) + { + static const std::vector< std::pair > reservedIPv4Ranges { + address_pair_v4("0.0.0.0", "0.255.255.255"), + address_pair_v4("10.0.0.0", "10.255.255.255"), + address_pair_v4("100.64.0.0", "100.127.255.255"), + address_pair_v4("127.0.0.0", "127.255.255.255"), + address_pair_v4("169.254.0.0", "169.254.255.255"), + address_pair_v4("172.16.0.0", "172.31.255.255"), + address_pair_v4("192.0.0.0", "192.0.0.255"), + address_pair_v4("192.0.2.0", "192.0.2.255"), + address_pair_v4("192.88.99.0", "192.88.99.255"), + address_pair_v4("192.168.0.0", "192.168.255.255"), + address_pair_v4("198.18.0.0", "192.19.255.255"), + address_pair_v4("198.51.100.0", "198.51.100.255"), + address_pair_v4("203.0.113.0", "203.0.113.255"), + address_pair_v4("224.0.0.0", "255.255.255.255") + }; + + uint32_t ipv4_address = host.to_v4 ().to_ulong (); + for(const auto& it : reservedIPv4Ranges) { + if (ipv4_address >= it.first && ipv4_address <= it.second) + return true; + } + } + if(host.is_v6()) + { + static const std::vector< std::pair > reservedIPv6Ranges { + address_pair_v6("2001:db8::", "2001:db8:ffff:ffff:ffff:ffff:ffff:ffff"), + address_pair_v6("fc00::", "fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"), + address_pair_v6("fe80::", "febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff") + }; + + boost::asio::ip::address_v6::bytes_type ipv6_address = host.to_v6 ().to_bytes (); + for(const auto& it : reservedIPv6Ranges) { + if (ipv6_address >= it.first && ipv6_address <= it.second) + return true; + } + } + return false; + } +} // net } // util } // i2p diff --git a/libi2pd/util.h b/libi2pd/util.h index cb8fd8f1..56ce1e08 100644 --- a/libi2pd/util.h +++ b/libi2pd/util.h @@ -172,6 +172,7 @@ namespace util { int GetMTU (const boost::asio::ip::address& localAddress); const boost::asio::ip::address GetInterfaceAddress(const std::string & ifname, bool ipv6=false); + bool IsInReservedRange(const boost::asio::ip::address& host); } } } diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index 04f50e6f..ab868916 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -456,7 +456,7 @@ namespace client options[I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY] = GetI2CPOption(section, I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY, DEFAULT_INITIAL_ACK_DELAY); options[I2CP_PARAM_STREAMING_ANSWER_PINGS] = GetI2CPOption(section, I2CP_PARAM_STREAMING_ANSWER_PINGS, isServer ? DEFAULT_ANSWER_PINGS : false); options[I2CP_PARAM_LEASESET_TYPE] = GetI2CPOption(section, I2CP_PARAM_LEASESET_TYPE, DEFAULT_LEASESET_TYPE); - std::string encType = GetI2CPStringOption(section, I2CP_PARAM_LEASESET_ENCRYPTION_TYPE, ""); + std::string encType = GetI2CPStringOption(section, I2CP_PARAM_LEASESET_ENCRYPTION_TYPE, isServer ? "" : "0,4"); if (encType.length () > 0) options[I2CP_PARAM_LEASESET_ENCRYPTION_TYPE] = encType; std::string privKey = GetI2CPStringOption(section, I2CP_PARAM_LEASESET_PRIV_KEY, ""); if (privKey.length () > 0) options[I2CP_PARAM_LEASESET_PRIV_KEY] = privKey; diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index 24c2496b..80274d86 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -226,14 +226,13 @@ namespace client } I2CPSession::I2CPSession (I2CPServer& owner, std::shared_ptr socket): - m_Owner (owner), m_Socket (socket), m_Payload (nullptr), - m_SessionID (0xFFFF), m_MessageID (0), m_IsSendAccepted (true) + m_Owner (owner), m_Socket (socket), m_SessionID (0xFFFF), + m_MessageID (0), m_IsSendAccepted (true) { } I2CPSession::~I2CPSession () { - delete[] m_Payload; } void I2CPSession::Start () @@ -264,6 +263,11 @@ namespace client void I2CPSession::ReceiveHeader () { + if (!m_Socket) + { + LogPrint (eLogError, "I2CP: Can't receive header"); + return; + } boost::asio::async_read (*m_Socket, boost::asio::buffer (m_Header, I2CP_HEADER_SIZE), boost::asio::transfer_all (), std::bind (&I2CPSession::HandleReceivedHeader, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); @@ -279,10 +283,7 @@ namespace client if (m_PayloadLen > 0) { if (m_PayloadLen <= I2CP_MAX_MESSAGE_LENGTH) - { - m_Payload = new uint8_t[m_PayloadLen]; ReceivePayload (); - } else { LogPrint (eLogError, "I2CP: Unexpected payload length ", m_PayloadLen); @@ -299,6 +300,11 @@ namespace client void I2CPSession::ReceivePayload () { + if (!m_Socket) + { + LogPrint (eLogError, "I2CP: Can't receive payload"); + return; + } boost::asio::async_read (*m_Socket, boost::asio::buffer (m_Payload, m_PayloadLen), boost::asio::transfer_all (), std::bind (&I2CPSession::HandleReceivedPayload, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); @@ -311,8 +317,6 @@ namespace client else { HandleMessage (); - delete[] m_Payload; - m_Payload = nullptr; m_PayloadLen = 0; ReceiveHeader (); // next message } @@ -345,6 +349,11 @@ namespace client void I2CPSession::SendI2CPMessage (uint8_t type, const uint8_t * payload, size_t len) { + if (len > I2CP_MAX_MESSAGE_LENGTH) + { + LogPrint (eLogError, "I2CP: Message to send is too long ", len); + return; + } auto socket = m_Socket; if (socket) { diff --git a/libi2pd_client/I2CP.h b/libi2pd_client/I2CP.h index 4c6b7531..c5dc80e7 100644 --- a/libi2pd_client/I2CP.h +++ b/libi2pd_client/I2CP.h @@ -179,7 +179,7 @@ namespace client I2CPServer& m_Owner; std::shared_ptr m_Socket; - uint8_t m_Header[I2CP_HEADER_SIZE], * m_Payload; + uint8_t m_Header[I2CP_HEADER_SIZE], m_Payload[I2CP_MAX_MESSAGE_LENGTH]; size_t m_PayloadLen; std::shared_ptr m_Destination; diff --git a/qt/i2pd_qt/.gitignore b/qt/i2pd_qt/.gitignore index f1d57c58..1f9d6012 100644 --- a/qt/i2pd_qt/.gitignore +++ b/qt/i2pd_qt/.gitignore @@ -8,4 +8,6 @@ Makefile* object_script.* i2pd_qt_plugin_import.cpp i2pd_qt.pro.autosave* +build* +nohup.out diff --git a/qt/i2pd_qt/ClientTunnelPane.cpp b/qt/i2pd_qt/ClientTunnelPane.cpp index 256d0510..fbfa74cb 100644 --- a/qt/i2pd_qt/ClientTunnelPane.cpp +++ b/qt/i2pd_qt/ClientTunnelPane.cpp @@ -168,6 +168,23 @@ int ClientTunnelPane::appendClientTunnelForm( horizontalLayout_2->addItem(horizontalSpacer); tunnelGridLayout->addLayout(horizontalLayout_2); } + { + int cryptoType = tunnelConfig->getcryptoType(); + QHBoxLayout *horizontalLayout_2 = new QHBoxLayout(); + ui.cryptoTypeLabel = new QLabel(gridLayoutWidget_2); + cryptoTypeLabel->setObjectName(QStringLiteral("cryptoTypeLabel")); + horizontalLayout_2->addWidget(cryptoTypeLabel); + ui.cryptoTypeLineEdit = new QLineEdit(gridLayoutWidget_2); + cryptoTypeLineEdit->setObjectName(QStringLiteral("cryptoTypeLineEdit")); + cryptoTypeLineEdit->setText(QString::number(cryptoType)); + cryptoTypeLineEdit->setMaximumWidth(80); + QObject::connect(cryptoTypeLineEdit, SIGNAL(textChanged(const QString &)), + this, SLOT(updated())); + horizontalLayout_2->addWidget(cryptoTypeLineEdit); + QSpacerItem * horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + horizontalLayout_2->addItem(horizontalSpacer); + tunnelGridLayout->addLayout(horizontalLayout_2); + } { i2p::data::SigningKeyType sigType = tunnelConfig->getsigType(); QHBoxLayout *horizontalLayout_2 = new QHBoxLayout(); diff --git a/qt/i2pd_qt/ClientTunnelPane.h b/qt/i2pd_qt/ClientTunnelPane.h index c2e076b7..80d331de 100644 --- a/qt/i2pd_qt/ClientTunnelPane.h +++ b/qt/i2pd_qt/ClientTunnelPane.h @@ -53,6 +53,10 @@ private: QLabel * sigTypeLabel; QComboBox * sigTypeComboBox; + //cryptoType + QLabel * cryptoTypeLabel; + QLineEdit * cryptoTypeLineEdit; + protected slots: virtual void setGroupBoxTitle(const QString & title); @@ -61,6 +65,7 @@ private: typeLabel->setText(QApplication::translate("cltTunForm", "Client tunnel type:", 0)); destinationLabel->setText(QApplication::translate("cltTunForm", "Destination:", 0)); portLabel->setText(QApplication::translate("cltTunForm", "Port:", 0)); + cryptoTypeLabel->setText(QApplication::translate("cltTunForm", "Crypto type:", 0)); keysLabel->setText(QApplication::translate("cltTunForm", "Keys:", 0)); destinationPortLabel->setText(QApplication::translate("cltTunForm", "Destination port:", 0)); addressLabel->setText(QApplication::translate("cltTunForm", "Address:", 0)); @@ -86,6 +91,14 @@ protected: } ctc->setport(portInt); + auto cryptoTypeStr=cryptoTypeLineEdit->text(); + int cryptoTypeInt=cryptoTypeStr.toInt(&ok); + if(!ok){ + highlightWrongInput(QApplication::tr("Bad crypto type, must be int.")+" "+cannotSaveSettings,cryptoTypeLineEdit); + return false; + } + ctc->setcryptoType(cryptoTypeInt); + ctc->setkeys(keysLineEdit->text().toStdString()); ctc->setaddress(addressLineEdit->text().toStdString()); diff --git a/qt/i2pd_qt/ServerTunnelPane.cpp b/qt/i2pd_qt/ServerTunnelPane.cpp index bc6389a9..cd751f5d 100644 --- a/qt/i2pd_qt/ServerTunnelPane.cpp +++ b/qt/i2pd_qt/ServerTunnelPane.cpp @@ -235,6 +235,23 @@ int ServerTunnelPane::appendServerTunnelForm( horizontalLayout_2->addItem(horizontalSpacer); tunnelGridLayout->addLayout(horizontalLayout_2); } + { + int cryptoType = tunnelConfig->getcryptoType(); + QHBoxLayout *horizontalLayout_2 = new QHBoxLayout(); + ui.cryptoTypeLabel = new QLabel(gridLayoutWidget_2); + cryptoTypeLabel->setObjectName(QStringLiteral("cryptoTypeLabel")); + horizontalLayout_2->addWidget(cryptoTypeLabel); + ui.cryptoTypeLineEdit = new QLineEdit(gridLayoutWidget_2); + cryptoTypeLineEdit->setObjectName(QStringLiteral("cryptoTypeLineEdit")); + cryptoTypeLineEdit->setText(QString::number(cryptoType)); + cryptoTypeLineEdit->setMaximumWidth(80); + QObject::connect(cryptoTypeLineEdit, SIGNAL(textChanged(const QString &)), + this, SLOT(updated())); + horizontalLayout_2->addWidget(cryptoTypeLineEdit); + QSpacerItem * horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + horizontalLayout_2->addItem(horizontalSpacer); + tunnelGridLayout->addLayout(horizontalLayout_2); + } { I2CPParameters& i2cpParameters = tunnelConfig->getI2cpParameters(); appendControlsForI2CPParameters(i2cpParameters, gridIndex); diff --git a/qt/i2pd_qt/ServerTunnelPane.h b/qt/i2pd_qt/ServerTunnelPane.h index 0a07267b..92ee4da5 100644 --- a/qt/i2pd_qt/ServerTunnelPane.h +++ b/qt/i2pd_qt/ServerTunnelPane.h @@ -65,6 +65,10 @@ private: QLabel * inPortLabel; QLineEdit * inPortLineEdit; + //cryptoType + QLabel * cryptoTypeLabel; + QLineEdit * cryptoTypeLineEdit; + //accessList QLabel * accessListLabel; QLineEdit * accessListLineEdit; @@ -101,6 +105,7 @@ private: portLabel->setText(QApplication::translate("srvTunForm", "Port:", 0)); keysLabel->setText(QApplication::translate("srvTunForm", "Keys:", 0)); inPortLabel->setText(QApplication::translate("srvTunForm", "InPort:", 0)); + cryptoTypeLabel->setText(QApplication::translate("srvTunForm", "Crypto type:", 0)); accessListLabel->setText(QApplication::translate("srvTunForm", "Access list:", 0)); hostOverrideLabel->setText(QApplication::translate("srvTunForm", "Host override:", 0)); webIRCPassLabel->setText(QApplication::translate("srvTunForm", "WebIRC password:", 0)); @@ -129,6 +134,14 @@ protected: } stc->setport(portInt); + auto cryptoTypeStr=cryptoTypeLineEdit->text(); + int cryptoTypeInt=cryptoTypeStr.toInt(&ok); + if(!ok){ + highlightWrongInput(QApplication::tr("Bad crypto type, must be int.")+" "+cannotSaveSettings,cryptoTypeLineEdit); + return false; + } + stc->setcryptoType(cryptoTypeInt); + stc->setkeys(keysLineEdit->text().toStdString()); auto str=inPortLineEdit->text(); diff --git a/qt/i2pd_qt/TunnelConfig.cpp b/qt/i2pd_qt/TunnelConfig.cpp index 8ed72930..a2cdf92b 100644 --- a/qt/i2pd_qt/TunnelConfig.cpp +++ b/qt/i2pd_qt/TunnelConfig.cpp @@ -24,6 +24,18 @@ void TunnelConfig::saveI2CPParametersToStringStream(std::stringstream& out) { if (!i2cpParameters.getExplicitPeers().isEmpty()) //todo #947 out << i2p::client::I2CP_PARAM_EXPLICIT_PEERS << "=" << i2cpParameters.getExplicitPeers().toStdString() << "\n"; + out << i2p::client::I2CP_PARAM_LEASESET_AUTH_TYPE << "=" + << i2cpParameters.get_i2cp_leaseSetAuthType().toStdString() << "\n"; + out << i2p::client::I2CP_PARAM_LEASESET_ENCRYPTION_TYPE << "=" + << i2cpParameters.get_i2cp_leaseSetEncType().toStdString() << "\n"; + out << i2p::client::I2CP_PARAM_LEASESET_PRIV_KEY << "=" + << i2cpParameters.get_i2cp_leaseSetPrivKey().toStdString() << "\n"; + out << i2p::client::I2CP_PARAM_LEASESET_TYPE << "=" + << i2cpParameters.get_i2cp_leaseSetType().toStdString() << "\n"; + out << i2p::client::I2CP_PARAM_STREAMING_ANSWER_PINGS << "=" + << (i2cpParameters.get_i2p_streaming_answerPings() ? "true" : "false") << "\n"; + out << i2p::client::I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY << "=" + << i2cpParameters.get_i2p_streaming_initialAckDelay().toStdString() << "\n"; out << "\n"; } @@ -32,6 +44,7 @@ void ClientTunnelConfig::saveToStringStream(std::stringstream& out) { << "port=" << port << "\n" << "destination=" << dest << "\n" << "destinationport=" << destinationPort << "\n" + << "cryptoType=" << getcryptoType() << "\n" << "signaturetype=" << sigType << "\n"; if(!keys.empty()) out << "keys=" << keys << "\n"; } @@ -41,9 +54,10 @@ void ServerTunnelConfig::saveToStringStream(std::stringstream& out) { out << "host=" << host << "\n" << "port=" << port << "\n" << "signaturetype=" << sigType << "\n" - << "inport=" << inPort << "\n" - << "accesslist=" << accessList << "\n" - << "gzip=" << (gzip?"true":"false") << "\n" + << "inport=" << inPort << "\n"; + if(accessList.size()>0) { out << "accesslist=" << accessList << "\n"; } + out << "gzip=" << (gzip?"true":"false") << "\n" + << "cryptoType=" << getcryptoType() << "\n" << "enableuniquelocal=" << (isUniqueLocal?"true":"false") << "\n" << "address=" << address << "\n" << "hostoverride=" << hostOverride << "\n" diff --git a/qt/i2pd_qt/TunnelConfig.h b/qt/i2pd_qt/TunnelConfig.h index 059d48b5..530a525c 100644 --- a/qt/i2pd_qt/TunnelConfig.h +++ b/qt/i2pd_qt/TunnelConfig.h @@ -16,25 +16,49 @@ class I2CPParameters{ QString outbound_quantity; //number of outbound tunnels. 5 by default QString crypto_tagsToSend; //number of ElGamal/AES tags to send. 40 by default; too low value may cause problems with tunnel building QString explicitPeers; //list of comma-separated b64 addresses of peers to use, default: unset + QString i2p_streaming_initialAckDelay; //i2p.streaming.initialAckDelay -- milliseconds to wait before sending Ack. 200 by default + bool i2p_streaming_answerPings; //i2p.streaming.answerPings -- enable sending pongs. true by default + QString i2cp_leaseSetType; //i2cp.leaseSetType -- type of LeaseSet to be sent. 1, 3 or 5. 1 by default + QString i2cp_leaseSetEncType; //i2cp.leaseSetEncType -- comma separated encryption types to be used in LeaseSet type 3 or 5. Identity's type by default + QString i2cp_leaseSetPrivKey; //i2cp.leaseSetPrivKey -- decryption key for encrypted LeaseSet in base64. PSK or private DH + QString i2cp_leaseSetAuthType; //i2cp.leaseSetAuthType -- authentication type for encrypted LeaseSet. 0 - no authentication(default), 1 - DH, 2 - PSK public: I2CPParameters(): inbound_length(), outbound_length(), inbound_quantity(), outbound_quantity(), crypto_tagsToSend(), - explicitPeers() {} + explicitPeers(), + i2p_streaming_initialAckDelay(), + i2p_streaming_answerPings(true), + i2cp_leaseSetType(), + i2cp_leaseSetEncType(), + i2cp_leaseSetPrivKey(), + i2cp_leaseSetAuthType() {} const QString& getInbound_length(){return inbound_length;} const QString& getOutbound_length(){return outbound_length;} const QString& getInbound_quantity(){return inbound_quantity;} const QString& getOutbound_quantity(){return outbound_quantity;} const QString& getCrypto_tagsToSend(){return crypto_tagsToSend;} const QString& getExplicitPeers(){return explicitPeers;} + const QString& get_i2p_streaming_initialAckDelay(){return i2p_streaming_initialAckDelay;} + bool get_i2p_streaming_answerPings(){return i2p_streaming_answerPings;} + const QString& get_i2cp_leaseSetType(){return i2cp_leaseSetType;} + const QString& get_i2cp_leaseSetEncType(){return i2cp_leaseSetEncType;} + const QString& get_i2cp_leaseSetPrivKey(){return i2cp_leaseSetPrivKey;} + const QString& get_i2cp_leaseSetAuthType(){return i2cp_leaseSetAuthType;} void setInbound_length(QString inbound_length_){inbound_length=inbound_length_;} void setOutbound_length(QString outbound_length_){outbound_length=outbound_length_;} void setInbound_quantity(QString inbound_quantity_){inbound_quantity=inbound_quantity_;} void setOutbound_quantity(QString outbound_quantity_){outbound_quantity=outbound_quantity_;} void setCrypto_tagsToSend(QString crypto_tagsToSend_){crypto_tagsToSend=crypto_tagsToSend_;} void setExplicitPeers(QString explicitPeers_){explicitPeers=explicitPeers_;} + void set_i2p_streaming_initialAckDelay(QString i2p_streaming_initialAckDelay_){i2p_streaming_initialAckDelay=i2p_streaming_initialAckDelay_;} + void set_i2p_streaming_answerPings(bool i2p_streaming_answerPings_){i2p_streaming_answerPings=i2p_streaming_answerPings_;} + void set_i2cp_leaseSetType(QString i2cp_leaseSetType_){i2cp_leaseSetType=i2cp_leaseSetType_;} + void set_i2cp_leaseSetEncType(QString i2cp_leaseSetEncType_){i2cp_leaseSetEncType=i2cp_leaseSetEncType_;} + void set_i2cp_leaseSetPrivKey(QString i2cp_leaseSetPrivKey_){i2cp_leaseSetPrivKey=i2cp_leaseSetPrivKey_;} + void set_i2cp_leaseSetAuthType(QString i2cp_leaseSetAuthType_){i2cp_leaseSetAuthType=i2cp_leaseSetAuthType_;} }; @@ -58,12 +82,14 @@ class TunnelConfig { QString type; std::string name; TunnelPane* tunnelPane; + int cryptoType; public: - TunnelConfig(std::string name_, QString& type_, I2CPParameters& i2cpParameters_): - type(type_), name(name_), i2cpParameters(i2cpParameters_) {} + TunnelConfig(std::string name_, QString& type_, I2CPParameters& i2cpParameters_, int cryptoType_): + type(type_), name(name_), cryptoType(cryptoType_), i2cpParameters(i2cpParameters_) {} virtual ~TunnelConfig(){} const QString& getType(){return type;} const std::string& getName(){return name;} + int getcryptoType(){return cryptoType;} void setType(const QString& type_){type=type_;} void setName(const std::string& name_){name=name_;} I2CPParameters& getI2cpParameters(){return i2cpParameters;} @@ -74,6 +100,7 @@ public: virtual ServerTunnelConfig* asServerTunnelConfig()=0; void setTunnelPane(TunnelPane* tp){this->tunnelPane = tp;} TunnelPane* getTunnelPane() {return tunnelPane;} + void setcryptoType(int cryptoType_){cryptoType=cryptoType_;} private: I2CPParameters i2cpParameters; }; @@ -114,13 +141,14 @@ public: std::string keys_, std::string address_, int destinationPort_, - i2p::data::SigningKeyType sigType_): TunnelConfig(name_, type_, i2cpParameters_), + i2p::data::SigningKeyType sigType_, + int cryptoType_): TunnelConfig(name_, type_, i2cpParameters_, cryptoType_), dest(dest_), port(port_), keys(keys_), address(address_), destinationPort(destinationPort_), - sigType(sigType_){} + sigType(sigType_) {} std::string& getdest(){return dest;} int getport(){return port;} std::string & getkeys(){return keys;} @@ -188,7 +216,8 @@ public: bool gzip_, i2p::data::SigningKeyType sigType_, std::string address_, - bool isUniqueLocal_): TunnelConfig(name_, type_, i2cpParameters_), + bool isUniqueLocal_, + int cryptoType_): TunnelConfig(name_, type_, i2cpParameters_, cryptoType_), host(host_), port(port_), keys(keys_), diff --git a/qt/i2pd_qt/TunnelPane.cpp b/qt/i2pd_qt/TunnelPane.cpp index c64b37ab..4b873ac1 100644 --- a/qt/i2pd_qt/TunnelPane.cpp +++ b/qt/i2pd_qt/TunnelPane.cpp @@ -31,7 +31,7 @@ void TunnelPane::setupTunnelPane( this->gridLayoutWidget_2=gridLayoutWidget_2; tunnelGridLayout = new QVBoxLayout(gridLayoutWidget_2); tunnelGridLayout->setObjectName(QStringLiteral("tunnelGridLayout")); - tunnelGridLayout->setContentsMargins(5, 5, 5, 5); + tunnelGridLayout->setContentsMargins(10, 25, 10, 10); tunnelGridLayout->setSpacing(5); //header @@ -185,6 +185,153 @@ void TunnelPane::appendControlsForI2CPParameters(I2CPParameters& i2cpParameters, tunnelGridLayout->addLayout(horizontalLayout_2); } + { + //explicitPeers -- list of comma-separated b64 addresses of peers to use, default: unset + const QString& value=i2cpParameters.getExplicitPeers(); + QHBoxLayout *horizontalLayout_2 = new QHBoxLayout(); + horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2")); + QLabel *_Label; + explicitPeersLabel = _Label = new QLabel(gridLayoutWidget_2); + _Label->setObjectName(QStringLiteral("_Label")); + horizontalLayout_2->addWidget(_Label); + QLineEdit *_LineEdit; + explicitPeersLineEdit = _LineEdit = new QLineEdit(gridLayoutWidget_2); + _LineEdit->setObjectName(QStringLiteral("_LineEdit")); + _LineEdit->setText(value); + _LineEdit->setMaximumWidth(80); + QObject::connect(_LineEdit, SIGNAL(textChanged(const QString &)), + this, SLOT(updated())); + horizontalLayout_2->addWidget(_LineEdit); + QSpacerItem * horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + horizontalLayout_2->addItem(horizontalSpacer); + tunnelGridLayout->addLayout(horizontalLayout_2); + } + + { + //i2p.streaming.initialAckDelay -- milliseconds to wait before sending Ack. 200 by default + const QString& value=i2cpParameters.get_i2p_streaming_initialAckDelay(); + QHBoxLayout *horizontalLayout_2 = new QHBoxLayout(); + horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2")); + QLabel *_Label; + i2p_streaming_initialAckDelayLabel = _Label = new QLabel(gridLayoutWidget_2); + _Label->setObjectName(QStringLiteral("_Label")); + horizontalLayout_2->addWidget(_Label); + QLineEdit *_LineEdit; + i2p_streaming_initialAckDelayLineEdit = _LineEdit = new QLineEdit(gridLayoutWidget_2); + _LineEdit->setObjectName(QStringLiteral("_LineEdit")); + _LineEdit->setText(value); + _LineEdit->setMaximumWidth(80); + QObject::connect(_LineEdit, SIGNAL(textChanged(const QString &)), + this, SLOT(updated())); + horizontalLayout_2->addWidget(_LineEdit); + QSpacerItem * horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + horizontalLayout_2->addItem(horizontalSpacer); + tunnelGridLayout->addLayout(horizontalLayout_2); + } + + { + //i2p.streaming.answerPings -- enable sending pongs. true by default + const bool value=i2cpParameters.get_i2p_streaming_answerPings(); + QHBoxLayout *horizontalLayout_2 = new QHBoxLayout(); + horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2")); + QCheckBox *_CheckBox; + i2p_streaming_answerPingsCheckBox = _CheckBox = new QCheckBox(gridLayoutWidget_2); + _CheckBox->setObjectName(QStringLiteral("_CheckBox")); + horizontalLayout_2->addWidget(_CheckBox); + _CheckBox->setChecked(value); + QObject::connect(_CheckBox, SIGNAL(toggled(bool)), + this, SLOT(updated())); + tunnelGridLayout->addLayout(horizontalLayout_2); + } + + { + //i2cp.leaseSetType -- type of LeaseSet to be sent. 1, 3 or 5. 1 by default + const QString& value=i2cpParameters.get_i2cp_leaseSetType(); + QHBoxLayout *horizontalLayout_2 = new QHBoxLayout(); + horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2")); + QLabel *_Label; + i2cp_leaseSetTypeLabel = _Label = new QLabel(gridLayoutWidget_2); + _Label->setObjectName(QStringLiteral("_Label")); + horizontalLayout_2->addWidget(_Label); + QLineEdit *_LineEdit; + i2cp_leaseSetTypeLineEdit = _LineEdit = new QLineEdit(gridLayoutWidget_2); + _LineEdit->setObjectName(QStringLiteral("_LineEdit")); + _LineEdit->setText(value); + _LineEdit->setMaximumWidth(80); + QObject::connect(_LineEdit, SIGNAL(textChanged(const QString &)), + this, SLOT(updated())); + horizontalLayout_2->addWidget(_LineEdit); + QSpacerItem * horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + horizontalLayout_2->addItem(horizontalSpacer); + tunnelGridLayout->addLayout(horizontalLayout_2); + } + + { + //i2cp.leaseSetEncType -- comma separated encryption types to be used in LeaseSet type 3 or 5. Identity's type by default + const QString& value=i2cpParameters.get_i2cp_leaseSetEncType(); + QHBoxLayout *horizontalLayout_2 = new QHBoxLayout(); + horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2")); + QLabel *_Label; + i2cp_leaseSetEncTypeLabel = _Label = new QLabel(gridLayoutWidget_2); + _Label->setObjectName(QStringLiteral("_Label")); + horizontalLayout_2->addWidget(_Label); + QLineEdit *_LineEdit; + i2cp_leaseSetEncTypeLineEdit = _LineEdit = new QLineEdit(gridLayoutWidget_2); + _LineEdit->setObjectName(QStringLiteral("_LineEdit")); + _LineEdit->setText(value); + _LineEdit->setMaximumWidth(80); + QObject::connect(_LineEdit, SIGNAL(textChanged(const QString &)), + this, SLOT(updated())); + horizontalLayout_2->addWidget(_LineEdit); + QSpacerItem * horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + horizontalLayout_2->addItem(horizontalSpacer); + tunnelGridLayout->addLayout(horizontalLayout_2); + } + + { + //i2cp.leaseSetPrivKey -- decryption key for encrypted LeaseSet in base64. PSK or private DH + const QString& value=i2cpParameters.get_i2cp_leaseSetPrivKey(); + QHBoxLayout *horizontalLayout_2 = new QHBoxLayout(); + horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2")); + QLabel *_Label; + i2cp_leaseSetPrivKeyLabel = _Label = new QLabel(gridLayoutWidget_2); + _Label->setObjectName(QStringLiteral("_Label")); + horizontalLayout_2->addWidget(_Label); + QLineEdit *_LineEdit; + i2cp_leaseSetPrivKeyLineEdit = _LineEdit = new QLineEdit(gridLayoutWidget_2); + _LineEdit->setObjectName(QStringLiteral("_LineEdit")); + _LineEdit->setText(value); + _LineEdit->setMaximumWidth(80); + QObject::connect(_LineEdit, SIGNAL(textChanged(const QString &)), + this, SLOT(updated())); + horizontalLayout_2->addWidget(_LineEdit); + QSpacerItem * horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + horizontalLayout_2->addItem(horizontalSpacer); + tunnelGridLayout->addLayout(horizontalLayout_2); + } + + { + //i2cp.leaseSetAuthType -- authentication type for encrypted LeaseSet. 0 - no authentication(default), 1 - DH, 2 - PSK + const QString& value=i2cpParameters.get_i2cp_leaseSetAuthType(); + QHBoxLayout *horizontalLayout_2 = new QHBoxLayout(); + horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2")); + QLabel *_Label; + i2cp_leaseSetAuthTypeLabel = _Label = new QLabel(gridLayoutWidget_2); + _Label->setObjectName(QStringLiteral("_Label")); + horizontalLayout_2->addWidget(_Label); + QLineEdit *_LineEdit; + i2cp_leaseSetAuthTypeLineEdit = _LineEdit = new QLineEdit(gridLayoutWidget_2); + _LineEdit->setObjectName(QStringLiteral("_LineEdit")); + _LineEdit->setText(value); + _LineEdit->setMaximumWidth(80); + QObject::connect(_LineEdit, SIGNAL(textChanged(const QString &)), + this, SLOT(updated())); + horizontalLayout_2->addWidget(_LineEdit); + QSpacerItem * horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + horizontalLayout_2->addItem(horizontalSpacer); + tunnelGridLayout->addLayout(horizontalLayout_2); + } + retranslateI2CPParameters(); } diff --git a/qt/i2pd_qt/TunnelPane.h b/qt/i2pd_qt/TunnelPane.h index 71331b4e..59303afd 100644 --- a/qt/i2pd_qt/TunnelPane.h +++ b/qt/i2pd_qt/TunnelPane.h @@ -11,6 +11,7 @@ #include "QLineEdit" #include "QGroupBox" #include "QVBoxLayout" +#include "QCheckBox" #include "TunnelConfig.h" @@ -89,6 +90,27 @@ protected: QLabel * crypto_tagsToSendLabel; QLineEdit * crypto_tagsToSendLineEdit; + QLabel * explicitPeersLabel; + QLineEdit * explicitPeersLineEdit; + + QLabel * i2p_streaming_initialAckDelayLabel; + QLineEdit * i2p_streaming_initialAckDelayLineEdit; + + QCheckBox * i2p_streaming_answerPingsCheckBox; + + QLabel * i2cp_leaseSetTypeLabel; + QLineEdit * i2cp_leaseSetTypeLineEdit; + + QLabel * i2cp_leaseSetEncTypeLabel; + QLineEdit * i2cp_leaseSetEncTypeLineEdit; + + QLabel * i2cp_leaseSetPrivKeyLabel; + QLineEdit * i2cp_leaseSetPrivKeyLineEdit; + + QLabel * i2cp_leaseSetAuthTypeLabel; + QLineEdit * i2cp_leaseSetAuthTypeLineEdit; + + QString readTunnelTypeComboboxData(); //should be created by factory @@ -105,6 +127,12 @@ public: i2cpParams.setOutbound_length(outbound_lengthLineEdit->text()); i2cpParams.setOutbound_quantity(outbound_quantityLineEdit->text()); i2cpParams.setCrypto_tagsToSend(crypto_tagsToSendLineEdit->text()); + i2cpParams.set_i2cp_leaseSetAuthType(i2cp_leaseSetAuthTypeLineEdit->text()); + i2cpParams.set_i2cp_leaseSetEncType(i2cp_leaseSetEncTypeLineEdit->text()); + i2cpParams.set_i2cp_leaseSetPrivKey(i2cp_leaseSetPrivKeyLineEdit->text()); + i2cpParams.set_i2cp_leaseSetType(i2cp_leaseSetTypeLineEdit->text()); + i2cpParams.set_i2p_streaming_answerPings(i2p_streaming_answerPingsCheckBox->isChecked()); + i2cpParams.set_i2p_streaming_initialAckDelay(i2p_streaming_initialAckDelayLineEdit->text()); return true; } protected: @@ -133,6 +161,13 @@ private: inbound_quantityLabel->setText(QApplication::translate("tunForm", "Number of inbound tunnels:", 0));; outbound_quantityLabel->setText(QApplication::translate("tunForm", "Number of outbound tunnels:", 0));; crypto_tagsToSendLabel->setText(QApplication::translate("tunForm", "Number of ElGamal/AES tags to send:", 0));; + explicitPeersLabel->setText(QApplication::translate("tunForm", "List of comma-separated b64 addresses of peers to use:", 0));; + i2p_streaming_initialAckDelayLabel->setText(QApplication::translate("tunForm", "Milliseconds to wait before sending Ack:", 0)); + i2p_streaming_answerPingsCheckBox->setText(QApplication::translate("tunForm", "Enable sending pongs", 0)); + i2cp_leaseSetTypeLabel->setText(QApplication::translate("tunForm", "Type of LeaseSet to be sent. 1, 3 or 5:", 0)); + i2cp_leaseSetEncTypeLabel->setText(QApplication::translate("tunForm", "Comma-separ. encr. types to be used in LeaseSet type 3 or 5:", 0)); + i2cp_leaseSetPrivKeyLabel->setText(QApplication::translate("tunForm", "Decryption key for encrypted LeaseSet in base64. PSK or private DH:", 0)); + i2cp_leaseSetAuthTypeLabel->setText(QApplication::translate("tunForm", "Auth type for encrypted LeaseSet. 0 - no auth, 1 - DH, 2 - PSK:", 0)); } }; diff --git a/qt/i2pd_qt/generalsettingswidget.ui b/qt/i2pd_qt/generalsettingswidget.ui index 9e59132f..7a35c0a5 100644 --- a/qt/i2pd_qt/generalsettingswidget.ui +++ b/qt/i2pd_qt/generalsettingswidget.ui @@ -7,7 +7,7 @@ 0 0 679 - 3033 + 4152 @@ -19,334 +19,36 @@ GeneralSettingsContentsForm + + QGroupBox { + font: bold; + border: 1px solid silver; + border-radius: 6px; + margin-top: 6px; +} + +QGroupBox::title { + subcontrol-origin: margin; + left: 7px; + padding: 0px 5px 0px 5px; +} + + 0 0 679 - 3052 + 4434 - + - QLayout::SetMinAndMaxSize + QLayout::SetDefaultConstraint - - - - - 0 - 0 - - - - - 0 - 51 - - - - - 16777215 - 51 - - - - Configuration file: - - - - - 0 - 18 - 661 - 31 - - - - - QLayout::SetMaximumSize - - - - - - - - - 0 - 0 - - - - - 0 - 27 - - - - - 16777215 - 27 - - - - Browse… - - - - - - - - - - - - 0 - 0 - - - - - 0 - 51 - - - - - 16777215 - 51 - - - - Tunnels configuration file: - - - - - 0 - 18 - 661 - 31 - - - - - QLayout::SetMaximumSize - - - - - - - - - 0 - 0 - - - - - 0 - 27 - - - - - 16777215 - 27 - - - - Browse… - - - - - - - - - - - - 0 - 0 - - - - - 0 - 51 - - - - - 16777215 - 51 - - - - Pid file: - - - - - 0 - 18 - 661 - 31 - - - - - QLayout::SetMaximumSize - - - - - - - - - 0 - 0 - - - - - 0 - 27 - - - - - 16777215 - 27 - - - - Browse… - - - - - - - - - - - - 0 - 98 - - - - - 16777215 - 98 - - - - SAM interface - - - - - 0 - 20 - 97 - 22 - - - - Enabled - - - - - - 0 - 40 - 661 - 31 - - - - - - - IP address to listen on: - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 70 - 661 - 31 - - - - - - - Port to listen on: - - - - - - - - 80 - 16777215 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - + + 0 @@ -365,54 +67,352 @@ - Windows-specific options + General options - - + + + + + 0 + 0 + + 0 - 44 + 80 16777215 - 44 + 80 - - Cryptography + + QGroupBox { + font: bold; + border: 1px solid silver; + border-radius: 6px; + margin-top: 6px; +} + +QGroupBox::title { + subcontrol-origin: margin; + left: 7px; + padding: 0px 5px 0px 5px; +} + - + + Configuration file: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + - 0 - 20 - 661 - 22 + 12 + 19 + 651 + 51 - - Use ElGamal precomputed tables - + + + + + QLayout::SetMinAndMaxSize + + + 10 + + + 10 + + + 10 + + + 10 + + + + + + + + + 0 + 27 + + + + + 0 + 0 + + + + + 16777215 + 27 + + + + Browse… + + + + + + - + + + + + 0 + 80 + + + + + 16777215 + 80 + + + + Data folder (for storage of i2pd data — RI, keys, peer profiles, …): + + + + + 12 + 19 + 651 + 51 + + + + + 10 + + + 10 + + + 10 + + + 10 + + + + + QLayout::SetMaximumSize + + + + + + + + Browse… + + + + + + + + + + + + + + 0 + 0 + + + + + 0 + 80 + + + + + 16777215 + 80 + + + + Pid file: + + + + + 12 + 19 + 651 + 51 + + + + + 10 + + + 10 + + + 10 + + + 10 + + + + + QLayout::SetMaximumSize + + + + + + + + + 0 + 0 + + + + + 0 + 27 + + + + + 16777215 + 27 + + + + Browse… + + + + + + + + + + + + + + 0 + 0 + + + + + 0 + 80 + + + + + 16777215 + 80 + + + + Tunnels configuration file: + + + + + 12 + 19 + 651 + 51 + + + + + 10 + + + 10 + + + 10 + + + 10 + + + + + QLayout::SetMaximumSize + + + + + + + + + 0 + 0 + + + + + 0 + 27 + + + + + 16777215 + 27 + + + + Browse… + + + + + + + + + + 0 - 107 + 130 16777215 - 107 + 130 @@ -432,7 +432,7 @@ - QLayout::SetMinimumSize + QLayout::SetMinAndMaxSize @@ -539,11 +539,722 @@ + + + + Write full CLF-formatted date and time to log + + + - + + + + + 0 + 0 + + + + + 0 + 417 + + + + + 16777215 + 417 + + + + Router options + + + + + 0 + 20 + 661 + 397 + + + + + + + Enable communication through ipv4 + + + + + + + Enable communication through ipv6 + + + + + + + Router will not accept transit tunnels at startup + + + + + + + Router will be floodfill + + + + + + + Enable SSU transport protocol (use UDP) + + + + + + + Assume we are behind NAT + + + + + + + Check remote RI for being in blacklist of reserved IP ranges + + + + + + + + + Bandwidth limit (integer or a letter): + + + + + + + + + + KBps + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Family (name of a family router belongs to): + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + QLayout::SetMaximumSize + + + + + NetID (network ID router belongs to. The main I2P ID is 2): + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Network interface to bind to for IPv4: + + + + + + + + + + + + + + Network interface to bind to for IPv6: + + + + + + + + + + + + + + Max % of bandwidth limit for transit. 0-100: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + 0 + 230 + + + + + 16777215 + 230 + + + + HTTP webconsole + + + + + 0 + 20 + 97 + 22 + + + + Enabled + + + + + + 0 + 40 + 661 + 31 + + + + + + + IP address to listen on: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + 70 + 661 + 31 + + + + + + + Port to listen on: + + + + + + + + 80 + 16777215 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + 100 + 321 + 22 + + + + Enable basic HTTP auth + + + + + + 60 + 120 + 601 + 31 + + + + + + + Username: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 60 + 150 + 601 + 31 + + + + + + + Password: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 1 + 182 + 661 + 21 + + + + Enable strict host checking on web UI + + + + + + -1 + 200 + 661 + 27 + + + + + + + Expected hostname for web UI: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 0 + 78 + + + + + 16777215 + 78 + + + + Addressbook settings + + + + + 0 + 20 + 661 + 31 + + + + + + + Addressbook default subscription URL for initial setup: + + + + + + + + + + + + 0 + 50 + 661 + 31 + + + + + + + Addressbook subscriptions URLs, separated by comma: + + + + + + + + + + + + + + + 0 + 190 + + + + + 16777215 + 190 + + + + Reseeding + + + + + 0 + 20 + 661 + 22 + + + + Request SU3 signature verification + + + + + + 0 + 40 + 661 + 31 + + + + + + + SU3 file to reseed from: + + + + + + + + + + Browse… + + + + + + + + + 0 + 100 + 661 + 31 + + + + + + + Reseed URLs, separated by comma: + + + + + + + + + + + + 0 + 70 + 661 + 31 + + + + + + + Path to local .zip file to reseed from: + + + + + + + + + + Browse... + + + + + + + + + 0 + 130 + 661 + 31 + + + + + + + Minimum number of known routers before requesting reseed: + + + + + + + + + + Qt::Horizontal + + + + 50 + 20 + + + + + + + + + + 0 + 160 + 661 + 31 + + + + + + + URL for https/socks reseed proxy: + + + + + + + + + + + @@ -610,116 +1321,7 @@ - - - - - 0 - 98 - - - - - 16777215 - 98 - - - - I2CP interface - - - - - 0 - 20 - 97 - 22 - - - - Enabled - - - - - - 0 - 40 - 661 - 31 - - - - - - - IP address to listen on: - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 70 - 661 - 31 - - - - - - - Port to listen on: - - - - - - - - 80 - 16777215 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - + @@ -828,215 +1430,111 @@ - - + + 0 - 60 + 170 16777215 - 60 - - - - - 13 - - - - General options - - - - - - - - 0 - 0 - - - - - 0 - 98 - - - - - 16777215 - 98 + 170 - Router external address (for incoming connections) + Trust options - - Qt::AlignJustify|Qt::AlignTop - - + 0 20 661 - 81 + 21 - - - QLayout::SetMinAndMaxSize - - - - - QLayout::SetMinAndMaxSize - - - - - Host: - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - QLayout::SetMinAndMaxSize - - - - - Port (leave 0 to auto-assign): - - - - - - - - 80 - 16777215 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - + + Enable explicit trust options + - - - - - - - 0 - 78 - - - - - 16777215 - 78 - - - - Addressbook settings - - + + + + 390 + 40 + 271 + 23 + + + + 0 - 20 - 661 - 31 + 40 + 391 + 42 - - - - - Addressbook default subscription URL for initial setup: - - - - - - - + + Make direct I2P connections only to +routers in specified Family: + - + 0 - 50 + 82 661 - 31 + 42 - - - - - Addressbook subscriptions URLs, separated by comma: - - - - - - - + + Make direct I2P connections only to routers specified here. +Comma separated list of base64 identities: + + + + + + 0 + 124 + 661 + 23 + + + + + + + 0 + 147 + 661 + 21 + + + + Should we hide our router from other routers? + - + 0 - 280 + 400 16777215 - 280 + 400 @@ -1371,78 +1869,225 @@ - - - - - - - 0 - 60 - - - - - 16777215 - 60 - - - - - 13 - - - - Various options - - - - - - - - 0 - 51 - - - - - 16777215 - 51 - - - - Data folder (for storage of i2pd data — RI, keys, peer profiles, …): - - + 0 - 20 + 280 661 - 31 + 23 - - - QLayout::SetMaximumSize - + + Enable address helper (jump) + + + + + + 0 + 300 + 661 + 95 + + + - + + + + + HTTP proxy upstream out proxy URL (like http://false.i2p): + + + + + + + - - - Browse… - - + + + + + Type of LeaseSet to be sent. 1, 3 or 5: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Comma-separated encryption types to be used in LeaseSet type 3 or 5: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + - - + + + + + 0 + 121 + + + + + 16777215 + 121 + + + + SAM interface + + + + + 0 + 20 + 97 + 22 + + + + Enabled + + + + + + 0 + 40 + 661 + 31 + + + + + + + IP address to listen on: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + 70 + 661 + 31 + + + + + + + Port to listen on: + + + + + + + + 80 + 16777215 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + 100 + 621 + 23 + + + + Single thread for all SAM sessions + + + + + + 0 @@ -1452,127 +2097,88 @@ 0 - 215 + 98 16777215 - 215 + 98 - Router options + Router external address (for incoming connections) - + + Qt::AlignJustify|Qt::AlignTop + + 0 20 661 - 188 + 81 - + + + QLayout::SetMinAndMaxSize + - - - Enable communication through ipv6 - - - - - - - Router will not accept transit tunnels at startup - - - - - - - Router will be floodfill - - - - - - - - - Bandwidth limit (integer or a letter): - - - - - - - - - - KBps - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - Family (name of a family router belongs to): - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - + - QLayout::SetMaximumSize + QLayout::SetMinAndMaxSize - + - NetID (network ID router belongs to. The main I2P ID is 2): + Host: - + - + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + QLayout::SetMinAndMaxSize + + + + + Port (leave 0 to auto-assign): + + + + + + + + 80 + 16777215 + + + + + + Qt::Horizontal @@ -1590,8 +2196,8 @@ - - + + 0 @@ -1714,226 +2320,251 @@ - - + + + + + 0 + 0 + + 0 - 98 + 128 16777215 - 98 + 128 - Reseeding + Nettime options - + 0 20 - 661 - 22 + 671 + 101 - - Request SU3 signature verification - - - - - - 0 - 40 - 661 - 31 - - - + + + QLayout::SetMinAndMaxSize + - + - SU3 file to reseed from: + Enable NTP sync - + + + + + Comma-separated list of NTP servers: + + + + + + + - - - Browse… - - - - - - - - - 0 - 70 - 661 - 31 - - - - - - - Reseed URLs, separated by comma: - - - - - + + + + + NTP time sync interval in hours: + + + + + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + - - + + + + + 0 + 0 + + 0 - 170 + 225 16777215 - 170 + 225 - Trust options + NTCP2 options - + - 0 - 20 - 661 - 21 + -1 + 19 + 671 + 191 - - Enable explicit trust options - - - - - - 390 - 40 - 271 - 23 - - - - - - - 0 - 40 - 391 - 42 - - - - Make direct I2P connections only to -routers in specified Family: - - - - - - 0 - 82 - 661 - 42 - - - - Make direct I2P connections only to routers specified here. -Comma separated list of base64 identities: - - - - - - 0 - 124 - 661 - 23 - - - - - - - 0 - 147 - 661 - 21 - - - - Should we hide our router from other routers? - + + + QLayout::SetMinAndMaxSize + + + + + Enable NTCP2 + + + + + + + Enable incoming NTCP2 connections + + + + + + + + + Port to listen for incoming NTCP2 connections: + + + + + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + External IPv6 address for incoming connections: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Specify proxy server for NTCP2: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Proxy server should be http://address:port or socks://address:port + + + + - - - - - 0 - 60 - - - - - 16777215 - 60 - - - - - 13 - - - - Ports - - - - - - - - 0 - 22 - - - - - 16777215 - 22 - - - - Insomnia (prevent system from sleeping) - - - - + @@ -2135,24 +2766,56 @@ Comma separated list of base64 identities: - - + + 0 - 179 + 44 16777215 - 179 + 44 - HTTP webconsole + Cryptography - + + + + 0 + 20 + 661 + 22 + + + + Use ElGamal precomputed tables + + + + + + + + + 0 + 121 + + + + + 16777215 + 121 + + + + I2CP interface + + 0 @@ -2165,7 +2828,7 @@ Comma separated list of base64 identities: Enabled - + 0 @@ -2174,19 +2837,19 @@ Comma separated list of base64 identities: 31 - + - + IP address to listen on: - + - + Qt::Horizontal @@ -2200,7 +2863,7 @@ Comma separated list of base64 identities: - + 0 @@ -2209,16 +2872,16 @@ Comma separated list of base64 identities: 31 - + - + Port to listen on: - + 80 @@ -2228,7 +2891,7 @@ Comma separated list of base64 identities: - + Qt::Horizontal @@ -2242,514 +2905,896 @@ Comma separated list of base64 identities: - + 0 100 - 321 - 22 + 651 + 23 - Enable basic HTTP auth + Single thread for all I2CP sessions - - - - 60 - 120 - 601 - 31 - - - - - - - Username: - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 60 - 150 - 601 - 31 - - - - - - - Password: - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - + + 0 - 335 + 60 16777215 - 335 + 60 + + + + + 13 + + + + Ports + + + + + + + + 0 + 500 + + + + + 16777215 + 500 Socks proxy - + + + + 9 + 20 + 661 + 470 + + + + + 10 + + + 10 + + + 10 + + + 10 + + + + + Enabled + + + + + + + + + IP address to listen on: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Port to listen on: + + + + + + + + 80 + 16777215 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Keys file: + + + + + + + + + + Browse… + + + + + + + + + + + Signature type: + + + + + + + + + + Edit + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Inbound tunnels length: + + + + + + + + 80 + 16777215 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Inbound tunnels quantity: + + + + + + + + 80 + 16777215 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Outbound tunnels length: + + + + + + + + 80 + 16777215 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Outbound tunnels quantity: + + + + + + + + 80 + 16777215 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + + + 0 + + + + + Outproxy enabled + + + + + + + + + + + Outproxy address: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Outproxy port: + + + + + + + + 80 + 16777215 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Type of LeaseSet to be sent. 1, 3 or 5: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Comma-separated encryption types to be used in LeaseSet type 3 or 5: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + 0 + 0 + + + + + 0 + 145 + + + + + 16777215 + 300 + + + + Websocket Server + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + -1 + 19 + 681 + 124 + + + + + QLayout::SetDefaultConstraint + + + 10 + + + 10 + + + 10 + + + 10 + + + + + Enable websocket server + + + + + + + + + Address to bind websocket server on: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Port to bind websocket server on: + + + + + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + 0 + 60 + + + + + 16777215 + 60 + + + + + 13 + + + + Various options + + + + + + + + 0 + 0 + + + + + 0 + 160 + + + + + 16777215 + 160 + + + + Exploratory Tunnels + + + + + -1 + 19 + 671 + 131 + + + + + QLayout::SetMinAndMaxSize + + + + + + + Exploratory inbound tunnels length: + + + + + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Exploratory inbound tunnels quantity: + + + + + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Exploratory outbound tunnels length: + + + + + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Exploratory outbound tunnels quantity: + + + + + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + 0 + 0 + + + + + 0 + 56 + + + + + 16777215 + 56 + + + + Persist profiles + + 0 20 - 97 - 22 - - - - Enabled - - - - - - 0 - 40 - 661 + 681 31 - + + + QLayout::SetMinAndMaxSize + - + - IP address to listen on: - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 70 - 661 - 31 - - - - - - - Port to listen on: - - - - - - - - 80 - 16777215 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 100 - 661 - 31 - - - - - - - Keys file: - - - - - - - - - - Browse… + Enable peer profile persisting to disk - - - - 0 - 160 - 661 - 31 - - - - - - - Inbound tunnels length: - - - - - - - - 80 - 16777215 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 190 - 661 - 31 - - - - - - - Inbound tunnels quantity: - - - - - - - - 80 - 16777215 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 220 - 661 - 31 - - - - - - - Outbound tunnels length: - - - - - - - - 80 - 16777215 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 250 - 661 - 31 - - - - - - - Outbound tunnels quantity: - - - - - - - - 80 - 16777215 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 280 - 661 - 31 - - - - - - - Outproxy address: - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 310 - 661 - 31 - - - - - - - Outproxy port: - - - - - - - - 80 - 16777215 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 130 - 661 - 31 - - - - - - - Signature type: - - - - - - - - - - Edit - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - + + + + + + + 0 + 60 + + + + + 16777215 + 60 + + + + + 13 + + + + Windows-specific options + + + + + + + + 0 + 0 + + + + + 0 + 22 + + + + + 16777215 + 22 + + + + Insomnia (prevent system from sleeping) + diff --git a/qt/i2pd_qt/i2pd_qt.pro b/qt/i2pd_qt/i2pd_qt.pro index 468d2d00..534d5f5a 100644 --- a/qt/i2pd_qt/i2pd_qt.pro +++ b/qt/i2pd_qt/i2pd_qt.pro @@ -4,7 +4,8 @@ greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = i2pd_qt TEMPLATE = app -QMAKE_CXXFLAGS *= -std=c++11 -Wno-unused-parameter -Wno-maybe-uninitialized +QMAKE_CXXFLAGS *= -Wno-unused-parameter -Wno-maybe-uninitialized +CONFIG += strict_c++ c++11 DEFINES += USE_UPNP @@ -59,6 +60,7 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \ ../../libi2pd/TunnelEndpoint.cpp \ ../../libi2pd/TunnelGateway.cpp \ ../../libi2pd/TunnelPool.cpp \ + ../../libi2pd/TunnelConfig.cpp \ ../../libi2pd/util.cpp \ ../../libi2pd/Elligator.cpp \ ../../libi2pd/ECIESX25519AEADRatchetSession.cpp \ @@ -103,7 +105,6 @@ HEADERS += DaemonQT.h mainwindow.h \ ../../libi2pd/CPU.h \ ../../libi2pd/Crypto.h \ ../../libi2pd/CryptoKey.h \ - ../../libi2pd/CryptoWorker.h \ ../../libi2pd/Datagram.h \ ../../libi2pd/Destination.h \ ../../libi2pd/Ed25519.h \ diff --git a/qt/i2pd_qt/mainwindow.cpp b/qt/i2pd_qt/mainwindow.cpp index 0ce0e2f8..89178ee0 100644 --- a/qt/i2pd_qt/mainwindow.cpp +++ b/qt/i2pd_qt/mainwindow.cpp @@ -81,10 +81,10 @@ MainWindow::MainWindow(std::shared_ptr logStream_, QWidget *paren onResize(); ui->stackedWidget->setCurrentIndex(0); - ui->settingsScrollArea->resize(uiSettings->settingsContentsGridLayout->sizeHint().width()+10,380); + ui->settingsScrollArea->resize(uiSettings->settingsContentsQVBoxLayout->sizeHint().width()+10,380); //QScrollBar* const barSett = ui->settingsScrollArea->verticalScrollBar(); int w = 683; - int h = 3060; + int h = 4550; ui->settingsContents->setFixedSize(w, h); ui->settingsContents->setGeometry(QRect(0,0,w,h)); @@ -159,12 +159,8 @@ MainWindow::MainWindow(std::shared_ptr logStream_, QWidget *paren # define OPTION(section,option,defaultValueGetter) ConfigOption(QString(section),QString(option)) initFileChooser( OPTION("","conf",[](){return "";}), uiSettings->configFileLineEdit, uiSettings->configFileBrowsePushButton); - initFolderChooser( OPTION("","datadir",[]{return "";}), uiSettings->dataFolderLineEdit, uiSettings->dataFolderBrowsePushButton); initFileChooser( OPTION("","tunconf",[](){return "";}), uiSettings->tunnelsConfigFileLineEdit, uiSettings->tunnelsConfigFileBrowsePushButton); - initFileChooser( OPTION("","pidfile",[]{return "";}), uiSettings->pidFileLineEdit, uiSettings->pidFileBrowsePushButton); - daemonOption=initNonGUIOption( OPTION("","daemon",[]{return "";})); - serviceOption=initNonGUIOption( OPTION("","service",[]{return "";})); uiSettings->logDestinationComboBox->clear(); uiSettings->logDestinationComboBox->insertItems(0, QStringList() @@ -176,20 +172,29 @@ MainWindow::MainWindow(std::shared_ptr logStream_, QWidget *paren logFileNameOption=initFileChooser( OPTION("","logfile",[]{return "";}), uiSettings->logFileLineEdit, uiSettings->logFileBrowsePushButton); initLogLevelCombobox(OPTION("","loglevel",[]{return "";}), uiSettings->logLevelComboBox); - + initCheckBox( OPTION("","logclftime",[]{return "false";}), uiSettings->logclftimeCheckBox);//"Write full CLF-formatted date and time to log (default: write only time)" + initFolderChooser( OPTION("","datadir",[]{return "";}), uiSettings->dataFolderLineEdit, uiSettings->dataFolderBrowsePushButton); initIPAddressBox( OPTION("","host",[]{return "";}), uiSettings->routerExternalHostLineEdit, tr("Router external address -> Host")); initTCPPortBox( OPTION("","port",[]{return "";}), uiSettings->routerExternalPortLineEdit, tr("Router external address -> Port")); - + daemonOption=initNonGUIOption( OPTION("","daemon",[]{return "";})); + serviceOption=initNonGUIOption( OPTION("","service",[]{return "";})); + initStringBox( OPTION("","ifname4",[]{return "";}), uiSettings->ifname4LineEdit);//Network interface to bind to for IPv4 + initStringBox( OPTION("","ifname6",[]{return "";}), uiSettings->ifname6LineEdit);//Network interface to bind to for IPv6 + initCheckBox( OPTION("","nat",[]{return "true";}), uiSettings->natCheckBox);//If true, assume we are behind NAT. true by default + initCheckBox( OPTION("","ipv4",[]{return "true";}), uiSettings->ipv4CheckBox);//Enable communication through IPv4. true by default initCheckBox( OPTION("","ipv6",[]{return "false";}), uiSettings->ipv6CheckBox); initCheckBox( OPTION("","notransit",[]{return "false";}), uiSettings->notransitCheckBox); initCheckBox( OPTION("","floodfill",[]{return "false";}), uiSettings->floodfillCheckBox); initStringBox( OPTION("","bandwidth",[]{return "";}), uiSettings->bandwidthLineEdit); + initIntegerBox( OPTION("","share",[]{return "100";}), uiSettings->shareLineEdit, tr("Share"));//Max % of bandwidth limit for transit. 0-100. 100 by default initStringBox( OPTION("","family",[]{return "";}), uiSettings->familyLineEdit); initIntegerBox( OPTION("","netid",[]{return "2";}), uiSettings->netIdLineEdit, tr("NetID")); + initCheckBox( OPTION("","ssu",[]{return "true";}), uiSettings->ssuCheckBox);//Enable SSU transport protocol (use UDP). true by default + initCheckBox( OPTION("","reservedrange",[]{return "true";}), uiSettings->reservedrange_checkbox); #ifdef Q_OS_WIN - initCheckBox( OPTION("","insomnia",[]{return "";}), uiSettings->insomniaCheckBox); initNonGUIOption( OPTION("","svcctl",[]{return "";})); + initCheckBox( OPTION("","insomnia",[]{return "";}), uiSettings->insomniaCheckBox); initNonGUIOption( OPTION("","close",[]{return "";})); #else uiSettings->insomniaCheckBox->setEnabled(false); @@ -201,17 +206,22 @@ MainWindow::MainWindow(std::shared_ptr logStream_, QWidget *paren initCheckBox( OPTION("http","auth",[]{return "";}), uiSettings->webconsoleBasicAuthCheckBox); initStringBox( OPTION("http","user",[]{return "i2pd";}), uiSettings->webconsoleUserNameLineEditBasicAuth); initStringBox( OPTION("http","pass",[]{return "";}), uiSettings->webconsolePasswordLineEditBasicAuth); + initCheckBox( OPTION("http","strictheaders",[]{return "true";}), uiSettings->httpStrictHeadersCheckBox);//Enable strict host checking on WebUI. true by default + initStringBox( OPTION("http","hostname",[]{return "localhost";}), uiSettings->httpHostnameLineEdit);//Expected hostname for WebUI (default: localhost) initCheckBox( OPTION("httpproxy","enabled",[]{return "";}), uiSettings->httpProxyEnabledCheckBox); initIPAddressBox( OPTION("httpproxy","address",[]{return "";}), uiSettings->httpProxyAddressLineEdit, tr("HTTP proxy -> IP address")); initTCPPortBox( OPTION("httpproxy","port",[]{return "4444";}), uiSettings->httpProxyPortLineEdit, tr("HTTP proxy -> Port")); + initCheckBox( OPTION("httpproxy","addresshelper",[]{return "true";}), uiSettings->httpProxyAddressHelperCheckBox);//Enable address helper (jump). true by default initFileChooser( OPTION("httpproxy","keys",[]{return "";}), uiSettings->httpProxyKeyFileLineEdit, uiSettings->httpProxyKeyFilePushButton); - initSignatureTypeCombobox(OPTION("httpproxy","signaturetype",[]{return "7";}), uiSettings->comboBox_httpPorxySignatureType); initStringBox( OPTION("httpproxy","inbound.length",[]{return "3";}), uiSettings->httpProxyInboundTunnelsLenLineEdit); initStringBox( OPTION("httpproxy","inbound.quantity",[]{return "5";}), uiSettings->httpProxyInboundTunnQuantityLineEdit); initStringBox( OPTION("httpproxy","outbound.length",[]{return "3";}), uiSettings->httpProxyOutBoundTunnLenLineEdit); initStringBox( OPTION("httpproxy","outbound.quantity",[]{return "5";}), uiSettings->httpProxyOutboundTunnQuantityLineEdit); + initStringBox( OPTION("httpproxy","outproxy",[]{return "";}), uiSettings->httpProxyOutproxyLineEdit);//HTTP proxy upstream out proxy url (like http://false.i2p) + initStringBox( OPTION("httpproxy","i2cp.leaseSetType",[]{return "1";}), uiSettings->httpProxyI2cpLeaseSetTypeLineEdit);//Type of LeaseSet to be sent. 1, 3 or 5. 1 by default + initStringBox( OPTION("httpproxy","i2cp.leaseSetEncType",[]{return "";}), uiSettings->httpProxyI2cpLeaseSetEncTypeLineEdit);//Comma separated encryption types to be used in LeaseSet type 3 or 5 initCheckBox( OPTION("socksproxy","enabled",[]{return "";}), uiSettings->socksProxyEnabledCheckBox); initIPAddressBox( OPTION("socksproxy","address",[]{return "";}), uiSettings->socksProxyAddressLineEdit, tr("Socks proxy -> IP address")); @@ -222,12 +232,16 @@ MainWindow::MainWindow(std::shared_ptr logStream_, QWidget *paren initStringBox( OPTION("socksproxy","inbound.quantity",[]{return "";}), uiSettings->socksProxyInboundTunnQuantityLineEdit); initStringBox( OPTION("socksproxy","outbound.length",[]{return "";}), uiSettings->socksProxyOutBoundTunnLenLineEdit); initStringBox( OPTION("socksproxy","outbound.quantity",[]{return "";}), uiSettings->socksProxyOutboundTunnQuantityLineEdit); - initIPAddressBox( OPTION("socksproxy","outproxy",[]{return "";}), uiSettings->outproxyAddressLineEdit, tr("Socks proxy -> Outproxy address")); - initTCPPortBox( OPTION("socksproxy","outproxyport",[]{return "";}), uiSettings->outproxyPortLineEdit, tr("Socks proxy -> Outproxy port")); + initCheckBox( OPTION("socksproxy","outproxy.enabled",[]{return "false";}), uiSettings->socksOutproxyEnabledCheckBox); + initIPAddressBox( OPTION("socksproxy","outproxy",[]{return "127.0.0.1";}), uiSettings->outproxyAddressLineEdit, tr("Socks proxy -> Outproxy address")); + initTCPPortBox( OPTION("socksproxy","outproxyport",[]{return "9050";}), uiSettings->outproxyPortLineEdit, tr("Socks proxy -> Outproxy port")); + initStringBox( OPTION("socksproxy","i2cp.leaseSetType",[]{return "1";}), uiSettings->socksProxyI2cpLeaseSetTypeLineEdit);//Type of LeaseSet to be sent. 1, 3 or 5. 1 by default + initStringBox( OPTION("socksproxy","i2cp.leaseSetEncType",[]{return "";}), uiSettings->socksProxyI2cpLeaseSetEncTypeLineEdit);//Comma separated encryption types to be used in LeaseSet type 3 or 5 initCheckBox( OPTION("sam","enabled",[]{return "false";}), uiSettings->samEnabledCheckBox); initIPAddressBox( OPTION("sam","address",[]{return "";}), uiSettings->samAddressLineEdit, tr("SAM -> IP address")); initTCPPortBox( OPTION("sam","port",[]{return "7656";}), uiSettings->samPortLineEdit, tr("SAM -> Port")); + initCheckBox( OPTION("sam","singlethread",[]{return "true";}), uiSettings->samSingleThreadCheckBox);//If false every SAM session runs in own thread. true by default initCheckBox( OPTION("bob","enabled",[]{return "false";}), uiSettings->bobEnabledCheckBox); initIPAddressBox( OPTION("bob","address",[]{return "";}), uiSettings->bobAddressLineEdit, tr("BOB -> IP address")); @@ -236,6 +250,7 @@ MainWindow::MainWindow(std::shared_ptr logStream_, QWidget *paren initCheckBox( OPTION("i2cp","enabled",[]{return "false";}), uiSettings->i2cpEnabledCheckBox); initIPAddressBox( OPTION("i2cp","address",[]{return "";}), uiSettings->i2cpAddressLineEdit, tr("I2CP -> IP address")); initTCPPortBox( OPTION("i2cp","port",[]{return "7654";}), uiSettings->i2cpPortLineEdit, tr("I2CP -> Port")); + //initCheckBox( OPTION("i2cp","singlethread",[]{return "true";}), uiSettings->i2cpSingleThreadCheckBox);//If false every I2CP session runs in own thread. true by default initCheckBox( OPTION("i2pcontrol","enabled",[]{return "false";}), uiSettings->i2pControlEnabledCheckBox); initIPAddressBox( OPTION("i2pcontrol","address",[]{return "";}), uiSettings->i2pControlAddressLineEdit, tr("I2PControl -> IP address")); @@ -252,6 +267,9 @@ MainWindow::MainWindow(std::shared_ptr logStream_, QWidget *paren initCheckBox( OPTION("reseed","verify",[]{return "";}), uiSettings->reseedVerifyCheckBox); initFileChooser( OPTION("reseed","file",[]{return "";}), uiSettings->reseedFileLineEdit, uiSettings->reseedFileBrowsePushButton); initStringBox( OPTION("reseed","urls",[]{return "";}), uiSettings->reseedURLsLineEdit); + initFileChooser( OPTION("reseed","zipfile",[]{return "";}), uiSettings->reseedZipFileLineEdit, uiSettings->reseedZipFileBrowsePushButton); //Path to local .zip file to reseed from + initUInt16Box( OPTION("reseed","threshold",[]{return "25";}), uiSettings->reseedThresholdNumberLineEdit, tr("reseedThreshold")); //Minimum number of known routers before requesting reseed. 25 by default + initStringBox( OPTION("reseed","proxy",[]{return "";}), uiSettings->reseedProxyLineEdit);//URL for https/socks reseed proxy initStringBox( OPTION("addressbook","defaulturl",[]{return "";}), uiSettings->addressbookDefaultURLLineEdit); initStringBox( OPTION("addressbook","subscriptions",[]{return "";}), uiSettings->addressbookSubscriptionsURLslineEdit); @@ -265,6 +283,26 @@ MainWindow::MainWindow(std::shared_ptr logStream_, QWidget *paren initStringBox( OPTION("trust","routers",[]{return "";}), uiSettings->lineEditTrustRouters); initCheckBox( OPTION("trust","hidden",[]{return "false";}), uiSettings->checkBoxTrustHidden); + initCheckBox( OPTION("websockets","enabled",[]{return "false";}), uiSettings->checkBoxWebsocketsEnable); //Enable websocket server. Disabled by default + initIPAddressBox( OPTION("websockets","address",[]{return "127.0.0.1";}), uiSettings->websocketsAddressLineEdit, tr("Websockets -> IP address")); //Address to bind websocket server on. 127.0.0.1 by default + initTCPPortBox( OPTION("websockets","port",[]{return "7666";}), uiSettings->websocketsPortLineEdit, tr("Websockets -> Port")); //Port to bind websocket server on. 7666 by default + + initIntegerBox( OPTION("exploratory","inbound.length",[]{return "2";}), uiSettings->exploratoryInboundTunnelsLengthNumberLineEdit, tr("exploratoryInboundTunnelsLength"));//Exploratory inbound tunnels length. 2 by default + initIntegerBox( OPTION("exploratory","inbound.quantity",[]{return "3";}), uiSettings->exploratoryInboundTunnelsQuantityNumberLineEdit, tr("exploratoryInboundTunnelsQuantity"));//Exploratory inbound tunnels quantity. 3 by default + initIntegerBox( OPTION("exploratory","outbound.length",[]{return "2";}), uiSettings->exploratoryOutboundTunnelsLengthNumberLineEdit, tr("exploratoryOutboundTunnelsLength"));//Exploratory outbound tunnels length. 2 by default + initIntegerBox( OPTION("exploratory","outbound.quantity",[]{return "3";}), uiSettings->exploratoryOutboundTunnelsQuantityNumberLineEdit, tr("exploratoryOutboundTunnelsQuantity"));//Exploratory outbound tunnels length. 3 by default + + initCheckBox( OPTION("ntcp2","enabled",[]{return "true";}), uiSettings->checkBoxNtcp2Enable); //Enable NTCP2. Enabled by default + initCheckBox( OPTION("ntcp2","published",[]{return "false";}), uiSettings->checkBoxNtcp2Published); //Enable incoming NTCP2 connections. Disabled by default + initTCPPortBox( OPTION("ntcp2","port",[]{return "0";}), uiSettings->ntcp2PortLineEdit, tr("NTCP2 -> Port")); //Port to listen for incoming NTCP2 connections (default: auto) + initIPAddressBox( OPTION("ntcp2","addressv6",[]{return "::";}), uiSettings->ntcp2AddressV6LineEdit, tr("NTCP2 -> IPv6 address")); //External IPv6 for incoming connections + initStringBox( OPTION("ntcp2","proxy",[]{return "";}), uiSettings->lineEditNtcp2Proxy); //Specify proxy server for NTCP2. Should be http://address:port or socks://address:port + + initCheckBox( OPTION("nettime","enabled",[]{return "false";}), uiSettings->checkBoxNettimeEnable); //Enable NTP sync. Disabled by default + initStringBox( OPTION("nettime","ntpservers",[]{return "pool.ntp.org";}), uiSettings->lineEditNetTimeNtpServers); //Comma-separated list of NTP servers. pool.ntp.org by default + initIntegerBox( OPTION("nettime","ntpsyncinterval",[]{return "72";}), uiSettings->nettimeNtpSyncIntervalNumberLineEdit, tr("nettimeNtpSyncInterval")); //NTP time sync interval in hours. 72 by default + + initCheckBox( OPTION("persist","profiles",[]{return "true";}), uiSettings->checkBoxPersistProfiles);//Enable peer profile persisting to disk. Enabled by default # undef OPTION //widgetlocks.add(new widgetlock(widget,lockbtn)); @@ -287,6 +325,18 @@ MainWindow::MainWindow(std::shared_ptr logStream_, QWidget *paren ui->tunnelsScrollAreaWidgetContents->setGeometry(QRect(0, 0, 621, 451)); + ui->tunnelsScrollAreaWidgetContents->setStyleSheet("QGroupBox { " \ + " font: bold;" \ + " border: 1px solid silver;" \ + " border-radius: 6px;" \ + " margin-top: 6px;" \ + "}" \ + "QGroupBox::title {" \ + " subcontrol-origin: margin;" \ + " left: 7px;" \ + " padding: 0px 5px 0px 5px;" \ + "}"); + appendTunnelForms(""); uiSettings->configFileLineEdit->setEnabled(false); @@ -666,7 +716,7 @@ void MainWindow::layoutTunnels() { int height=0; ui->tunnelsScrollAreaWidgetContents->setGeometry(0,0,0,0); for(std::map::iterator it = tunnelConfigs.begin(); it != tunnelConfigs.end(); ++it) { - const std::string& name=it->first; + //const std::string& name=it->first; TunnelConfig* tunconf = it->second; TunnelPane * tunnelPane=tunconf->getTunnelPane(); if(!tunnelPane)continue; diff --git a/qt/i2pd_qt/mainwindow.h b/qt/i2pd_qt/mainwindow.h index 91c99122..77c8826b 100644 --- a/qt/i2pd_qt/mainwindow.h +++ b/qt/i2pd_qt/mainwindow.h @@ -104,7 +104,8 @@ class MainWindowItem : public QObject { QWidget* widgetToFocus; QString requirementToBeValid; public: - MainWindowItem(ConfigOption option_, QWidget* widgetToFocus_, QString requirementToBeValid_) : option(option_), widgetToFocus(widgetToFocus_), requirementToBeValid(requirementToBeValid_) {} + MainWindowItem(ConfigOption option_, QWidget* widgetToFocus_, QString requirementToBeValid_) : + option(option_), widgetToFocus(widgetToFocus_), requirementToBeValid(requirementToBeValid_) {} QWidget* getWidgetToFocus(){return widgetToFocus;} QString& getRequirementToBeValid() { return requirementToBeValid; } ConfigOption& getConfigOption() { return option; } @@ -115,7 +116,7 @@ public: std::string optName=""; if(!option.section.isEmpty())optName=option.section.toStdString()+std::string("."); optName+=option.option.toStdString(); - //qDebug() << "loadFromConfigOption[" << optName.c_str() << "]"; + qDebug() << "loadFromConfigOption[" << optName.c_str() << "]"; boost::any programOption; i2p::config::GetOptionAsAny(optName, programOption); optionValue=programOption.empty()?boost::any(std::string("")) @@ -280,6 +281,7 @@ public: virtual void installListeners(MainWindow *mainWindow); virtual void loadFromConfigOption(){ MainWindowItem::loadFromConfigOption(); + qDebug() << "setting value for checkbox " << checkBox->text(); checkBox->setChecked(boost::any_cast(optionValue)); } virtual void saveToStringStream(std::stringstream& out){ @@ -543,6 +545,18 @@ private: void deleteTunnelForms(); void deleteTunnelFromUI(std::string tunnelName, TunnelConfig* cnf); + template + std::string GetI2CPOption (const Section& section, const std::string& name, const std::string& value) const + { + return section.second.get (boost::property_tree::ptree::path_type (name, '/'), value); + } + + template + std::string GetI2CPOption (const Section& section, const std::string& name, const char* value) const + { + return section.second.get (boost::property_tree::ptree::path_type (name, '/'), std::string (value)); + } + template std::string GetI2CPOption (const Section& section, const std::string& name, const Type& value) const { @@ -563,6 +577,19 @@ private: param.setOutbound_quantity(QString(_OUTBOUND_TUNNELS_QUANTITY.c_str())); std::string _TAGS_TO_SEND = options[I2CP_PARAM_TAGS_TO_SEND] = GetI2CPOption (section, I2CP_PARAM_TAGS_TO_SEND, DEFAULT_TAGS_TO_SEND); param.setCrypto_tagsToSend(QString(_TAGS_TO_SEND.c_str())); + std::string _i2cp_leaseSetAuthType = options[I2CP_PARAM_LEASESET_AUTH_TYPE] = GetI2CPOption (section, I2CP_PARAM_LEASESET_AUTH_TYPE, 0); + param.set_i2cp_leaseSetAuthType(QString(_i2cp_leaseSetAuthType.c_str())); + const char DEFAULT_LEASESET_ENCRYPTION_TYPE[] = ""; + std::string _i2cp_leaseSetEncType = options[I2CP_PARAM_LEASESET_ENCRYPTION_TYPE] = GetI2CPOption (section, I2CP_PARAM_LEASESET_ENCRYPTION_TYPE, DEFAULT_LEASESET_ENCRYPTION_TYPE);//todo Identity's type by default + param.set_i2cp_leaseSetEncType(QString(_i2cp_leaseSetEncType.c_str())); + std::string _i2cp_leaseSetPrivKey = options[I2CP_PARAM_LEASESET_PRIV_KEY] = GetI2CPOption (section, I2CP_PARAM_LEASESET_PRIV_KEY, ""); + param.set_i2cp_leaseSetPrivKey(QString(_i2cp_leaseSetPrivKey.c_str())); + std::string _i2cp_leaseSetType = options[I2CP_PARAM_LEASESET_TYPE] = GetI2CPOption (section, I2CP_PARAM_LEASESET_TYPE, DEFAULT_LEASESET_TYPE); + param.set_i2cp_leaseSetType(QString(_i2cp_leaseSetType.c_str())); + std::string _i2p_streaming_answerPings= options[I2CP_PARAM_STREAMING_ANSWER_PINGS] = GetI2CPOption (section, I2CP_PARAM_STREAMING_ANSWER_PINGS, DEFAULT_ANSWER_PINGS); + param.set_i2p_streaming_answerPings((_i2p_streaming_answerPings.compare("true")==0)||(_i2p_streaming_answerPings.compare("yes")==0)); + std::string _i2p_streaming_initialAckDelay = options[I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY] = GetI2CPOption (section, I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY, DEFAULT_INITIAL_ACK_DELAY); + param.set_i2p_streaming_initialAckDelay(QString(_i2p_streaming_initialAckDelay.c_str())); options[I2CP_PARAM_MIN_TUNNEL_LATENCY] = GetI2CPOption(section, I2CP_PARAM_MIN_TUNNEL_LATENCY, DEFAULT_MIN_TUNNEL_LATENCY);//TODO include into param options[I2CP_PARAM_MAX_TUNNEL_LATENCY] = GetI2CPOption(section, I2CP_PARAM_MAX_TUNNEL_LATENCY, DEFAULT_MAX_TUNNEL_LATENCY);//TODO include into param } @@ -580,6 +607,17 @@ private: param.setOutbound_quantity(QString::number(_OUTBOUND_TUNNELS_QUANTITY)); const int _TAGS_TO_SEND = DEFAULT_TAGS_TO_SEND; param.setCrypto_tagsToSend(QString::number(_TAGS_TO_SEND)); + const int _i2cp_leaseSetAuthType = 0; + param.set_i2cp_leaseSetAuthType(QString::number(_i2cp_leaseSetAuthType)); + const QString _i2cp_leaseSetEncType = "0,4"; //todo Identity's type by default + param.set_i2cp_leaseSetEncType(_i2cp_leaseSetEncType); + param.set_i2cp_leaseSetPrivKey(""); + const int _i2cp_leaseSetType = DEFAULT_LEASESET_TYPE; + param.set_i2cp_leaseSetType(QString::number(_i2cp_leaseSetType)); + bool _i2p_streaming_answerPings= DEFAULT_ANSWER_PINGS; + param.set_i2p_streaming_answerPings(_i2p_streaming_answerPings); + const int _i2p_streaming_initialAckDelay = DEFAULT_INITIAL_ACK_DELAY; + param.set_i2p_streaming_initialAckDelay(QString::number(_i2p_streaming_initialAckDelay)); } @@ -613,6 +651,7 @@ private: std::string keys = ""; std::string address = "127.0.0.1"; int destinationPort = 0; + int cryptoType = 0; i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256; // I2CP I2CPParameters i2cpParameters; @@ -624,7 +663,8 @@ private: keys, address, destinationPort, - sigType); + sigType, + cryptoType); saveAllConfigs(true, name); } @@ -643,6 +683,7 @@ private: i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256; std::string address = "127.0.0.1"; bool isUniqueLocal = true; + int cryptoType = 0; // I2CP I2CPParameters i2cpParameters; @@ -659,7 +700,8 @@ private: gzip, sigType, address, - isUniqueLocal); + isUniqueLocal, + cryptoType); saveAllConfigs(true, name); @@ -712,6 +754,7 @@ private: // optional params std::string keys = section.second.get (I2P_CLIENT_TUNNEL_KEYS, ""); std::string address = section.second.get (I2P_CLIENT_TUNNEL_ADDRESS, "127.0.0.1"); + int cryptoType = section.second.get(I2P_CLIENT_TUNNEL_CRYPTO_TYPE, 0); int destinationPort = section.second.get(I2P_CLIENT_TUNNEL_DESTINATION_PORT, 0); std::cout << "had read tunnel destinationPort: " << destinationPort << std::endl; i2p::data::SigningKeyType sigType = section.second.get (I2P_CLIENT_TUNNEL_SIGNATURE_TYPE, i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256); @@ -726,7 +769,8 @@ private: keys, address, destinationPort, - sigType); + sigType, + cryptoType); } else if (type == I2P_TUNNELS_SECTION_TYPE_SERVER || type == I2P_TUNNELS_SECTION_TYPE_HTTP @@ -746,6 +790,7 @@ private: i2p::data::SigningKeyType sigType = section.second.get (I2P_SERVER_TUNNEL_SIGNATURE_TYPE, i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256); std::string address = section.second.get (I2P_SERVER_TUNNEL_ADDRESS, "127.0.0.1"); bool isUniqueLocal = section.second.get(I2P_SERVER_TUNNEL_ENABLE_UNIQUE_LOCAL, true); + int cryptoType = section.second.get(I2P_CLIENT_TUNNEL_CRYPTO_TYPE, 0); // I2CP std::map options; @@ -779,7 +824,8 @@ private: gzip, sigType, address, - isUniqueLocal); + isUniqueLocal, + cryptoType); } else LogPrint (eLogWarning, "Clients: Unknown section type=", type, " of ", name, " in ", tunConf);//TODO show err box and disable the tunn gui