From 35d62686754a2d959964cf4c52f6fe3689eb6bbb Mon Sep 17 00:00:00 2001 From: Alexandre ZANNI <16578570+noraj@users.noreply.github.com> Date: Sat, 23 Nov 2019 22:52:31 +0100 Subject: [PATCH 01/44] README: explicit linux distro supported close #1440 --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b5fb8f7e..25e6c3e5 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ [![GitHub release](https://img.shields.io/github/release/PurpleI2P/i2pd.svg?label=latest%20release)](https://github.com/PurpleI2P/i2pd/releases/latest) [![Snapcraft release](https://snapcraft.io/i2pd/badge.svg)](https://snapcraft.io/i2pd) [![License](https://img.shields.io/github/license/PurpleI2P/i2pd.svg)](https://github.com/PurpleI2P/i2pd/blob/openssl/LICENSE) +[![Packaging status](https://repology.org/badge/tiny-repos/i2pd.svg)](https://repology.org/project/i2pd/versions) i2pd ==== @@ -63,9 +64,10 @@ Build instructions: **Supported systems:** * GNU/Linux - [![Build Status](https://travis-ci.org/PurpleI2P/i2pd.svg?branch=openssl)](https://travis-ci.org/PurpleI2P/i2pd) + * CentOS / Fedora / Mageia - [![Build Status](https://copr.fedorainfracloud.org/coprs/supervillain/i2pd/package/i2pd-git/status_image/last_build.png)](https://copr.fedorainfracloud.org/coprs/supervillain/i2pd/package/i2pd-git/) + * Alpine, ArchLinux, openSUSE, Gentoo, Debian, Ubuntu, etc. * Windows - [![Build status](https://ci.appveyor.com/api/projects/status/1908qe4p48ff1x23?svg=true)](https://ci.appveyor.com/project/PurpleI2P/i2pd) * Mac OS X - [![Build Status](https://travis-ci.org/PurpleI2P/i2pd.svg?branch=openssl)](https://travis-ci.org/PurpleI2P/i2pd) -* CentOS / Fedora / Mageia - [![Build Status](https://copr.fedorainfracloud.org/coprs/supervillain/i2pd/package/i2pd-git/status_image/last_build.png)](https://copr.fedorainfracloud.org/coprs/supervillain/i2pd/package/i2pd-git/) * Docker image - [![Build Status](https://dockerbuildbadges.quelltext.eu/status.svg?organization=meeh&repository=i2pd)](https://hub.docker.com/r/meeh/i2pd/builds/) * Snap - [![Snap Status](https://build.snapcraft.io/badge/PurpleI2P/i2pd-snap.svg)](https://build.snapcraft.io/user/PurpleI2P/i2pd-snap) * FreeBSD From 2c6e041ae2f1f930fd953013506151c829ee61ce Mon Sep 17 00:00:00 2001 From: R4SAS Date: Wed, 26 Feb 2020 13:41:35 +0000 Subject: [PATCH 02/44] rpm: make package buildable on mageia cauldron (#1476) --- contrib/rpm/i2pd-git.spec | 12 ++++++++++-- contrib/rpm/i2pd.spec | 12 ++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index 89e3cee9..f9571ca0 100644 --- a/contrib/rpm/i2pd-git.spec +++ b/contrib/rpm/i2pd-git.spec @@ -55,14 +55,22 @@ cd build %endif %endif +%if 0%{?mageia} > 7 +pushd build make %{?_smp_mflags} +popd +%else +make %{?_smp_mflags} +%endif %install -cd build +pushd build + %if 0%{?mageia} -cd build +pushd build %endif + chrpath -d i2pd %{__install} -D -m 755 i2pd %{buildroot}%{_sbindir}/i2pd %{__install} -D -m 755 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 0f91c03b..b3cca8ab 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -53,14 +53,22 @@ cd build %endif %endif +%if 0%{?mageia} > 7 +pushd build make %{?_smp_mflags} +popd +%else +make %{?_smp_mflags} +%endif %install -cd build +pushd build + %if 0%{?mageia} -cd build +pushd build %endif + chrpath -d i2pd install -D -m 755 i2pd %{buildroot}%{_sbindir}/i2pd install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf From 00db527377cfbbee1767766828daf46b81593ae0 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Thu, 27 Feb 2020 14:58:06 +0300 Subject: [PATCH 03/44] drop websockets support Signed-off-by: R4SAS --- Makefile | 4 - build/CMakeLists.txt | 11 - daemon/Daemon.cpp | 87 ++--- libi2pd/Config.cpp | 8 - libi2pd/Event.cpp | 19 -- libi2pd/Event.h | 33 +- libi2pd/NTCPSession.cpp | 6 - libi2pd/SSUData.cpp | 6 - libi2pd/Transports.cpp | 16 - libi2pd/Tunnel.cpp | 21 -- libi2pd/Tunnel.h | 38 +-- libi2pd/TunnelPool.cpp | 15 - libi2pd_client/ClientContext.h | 2 +- libi2pd_client/WebSocks.cpp | 488 +--------------------------- libi2pd_client/Websocket.cpp | 195 ----------- libi2pd_client/Websocket.h | 28 -- qt/i2pd_qt/generalsettingswidget.ui | 115 ------- qt/i2pd_qt/i2pd_qt.pro | 2 - qt/i2pd_qt/mainwindow.cpp | 4 - 19 files changed, 57 insertions(+), 1041 deletions(-) delete mode 100644 libi2pd_client/Websocket.cpp delete mode 100644 libi2pd_client/Websocket.h diff --git a/Makefile b/Makefile index 3dfaaade..a814aecf 100644 --- a/Makefile +++ b/Makefile @@ -27,10 +27,6 @@ else LD_DEBUG = -s endif -ifeq ($(WEBSOCKETS),1) - NEEDED_CXXFLAGS += -DWITH_EVENTS -endif - ifneq (, $(findstring darwin, $(SYS))) DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp ifeq ($(HOMEBREW),1) diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 2577fb1b..324ac468 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -20,7 +20,6 @@ option(WITH_MESHNET "Build for cjdns test network" OFF) option(WITH_ADDRSANITIZER "Build with address sanitizer unix only" OFF) option(WITH_THREADSANITIZER "Build with thread sanitizer unix only" OFF) option(WITH_I2LUA "Build for i2lua" OFF) -option(WITH_WEBSOCKETS "Build with websocket ui" OFF) # paths set ( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules" ) @@ -86,11 +85,6 @@ set (LIBI2PD_SRC "${LIBI2PD_SRC_DIR}/ECIESX25519AEADRatchetSession.cpp" ) -if (WITH_WEBSOCKETS) - add_definitions(-DWITH_EVENTS) - find_package(websocketpp REQUIRED) -endif () - if (WIN32 OR MSYS) list (APPEND LIBI2PD_SRC "${CMAKE_SOURCE_DIR}/I2PEndian.cpp") endif () @@ -127,10 +121,6 @@ set (CLIENT_SRC "${LIBI2PD_CLIENT_SRC_DIR}/WebSocks.cpp" ) -if(WITH_WEBSOCKETS) - list (APPEND CLIENT_SRC "${LIBI2PD_CLIENT_SRC_DIR}/Websocket.cpp") -endif () - add_library(libi2pdclient ${CLIENT_SRC}) set_target_properties(libi2pdclient PROPERTIES PREFIX "") @@ -427,7 +417,6 @@ message(STATUS " MESHNET : ${WITH_MESHNET}") message(STATUS " ADDRSANITIZER : ${WITH_ADDRSANITIZER}") message(STATUS " THREADSANITIZER : ${WITH_THREADSANITIZER}") message(STATUS " I2LUA : ${WITH_I2LUA}") -message(STATUS " WEBSOCKETS : ${WITH_WEBSOCKETS}") message(STATUS "---------------------------------------") #Handle paths nicely diff --git a/daemon/Daemon.cpp b/daemon/Daemon.cpp index 0ea45bb7..2c6b34d7 100644 --- a/daemon/Daemon.cpp +++ b/daemon/Daemon.cpp @@ -26,9 +26,6 @@ #include "Timestamp.h" #include "util.h" -#include "Event.h" -#include "Websocket.h" - namespace i2p { namespace util @@ -43,9 +40,6 @@ namespace i2p std::unique_ptr m_I2PControlService; std::unique_ptr UPnP; std::unique_ptr m_NTPSync; -#ifdef WITH_EVENTS - std::unique_ptr m_WebsocketServer; -#endif }; Daemon_Singleton::Daemon_Singleton() : isDaemon(false), running(true), d(*new Daemon_Singleton_Private()) {} @@ -62,12 +56,12 @@ namespace i2p return service; } - bool Daemon_Singleton::init(int argc, char* argv[]) { - return init(argc, argv, nullptr); - } + bool Daemon_Singleton::init(int argc, char* argv[]) { + return init(argc, argv, nullptr); + } - bool Daemon_Singleton::init(int argc, char* argv[], std::shared_ptr logstream) - { + bool Daemon_Singleton::init(int argc, char* argv[], std::shared_ptr logstream) + { i2p::config::Init(); i2p::config::ParseCmdline(argc, argv); @@ -110,10 +104,10 @@ namespace i2p logs = "file"; i2p::log::Logger().SetLogLevel(loglevel); - if (logstream) { - LogPrint(eLogInfo, "Log: will send messages to std::ostream"); - i2p::log::Logger().SendTo (logstream); - } else if (logs == "file") { + if (logstream) { + LogPrint(eLogInfo, "Log: will send messages to std::ostream"); + i2p::log::Logger().SendTo (logstream); + } else if (logs == "file") { if (logfile == "") logfile = i2p::fs::DataDirPath("i2pd.log"); LogPrint(eLogInfo, "Log: will send messages to ", logfile); @@ -127,7 +121,7 @@ namespace i2p // use stdout -- default } - LogPrint(eLogInfo, "i2pd v", VERSION, " starting"); + LogPrint(eLogInfo, "i2pd v", VERSION, " starting"); LogPrint(eLogDebug, "FS: main config file: ", config); LogPrint(eLogDebug, "FS: data directory: ", datadir); @@ -151,8 +145,8 @@ namespace i2p LogPrint(eLogInfo, "Daemon: accepting incoming connections at port ", port); i2p::context.UpdatePort (port); } - i2p::context.SetSupportsV6 (ipv6); - i2p::context.SetSupportsV4 (ipv4); + i2p::context.SetSupportsV6 (ipv6); + i2p::context.SetSupportsV4 (ipv4); bool ntcp; i2p::config::GetOption("ntcp", ntcp); i2p::context.PublishNTCPAddress (ntcp, !ipv6); @@ -233,15 +227,15 @@ namespace i2p if (family.length () > 0) LogPrint(eLogInfo, "Daemon: family set to ", family); - bool trust; i2p::config::GetOption("trust.enabled", trust); - if (trust) - { - LogPrint(eLogInfo, "Daemon: explicit trust enabled"); - std::string fam; i2p::config::GetOption("trust.family", fam); + bool trust; i2p::config::GetOption("trust.enabled", trust); + if (trust) + { + LogPrint(eLogInfo, "Daemon: explicit trust enabled"); + std::string fam; i2p::config::GetOption("trust.family", fam); std::string routers; i2p::config::GetOption("trust.routers", routers); bool restricted = false; - if (fam.length() > 0) - { + if (fam.length() > 0) + { std::set fams; size_t pos = 0, comma; do @@ -253,7 +247,7 @@ namespace i2p while (comma != std::string::npos); i2p::transport::transports.RestrictRoutesToFamilies(fams); restricted = fams.size() > 0; - } + } if (routers.length() > 0) { std::set idents; size_t pos = 0, comma; @@ -272,14 +266,15 @@ namespace i2p } if(!restricted) LogPrint(eLogError, "Daemon: no trusted routers of families specififed"); - } - bool hidden; i2p::config::GetOption("trust.hidden", hidden); - if (hidden) - { - LogPrint(eLogInfo, "Daemon: using hidden mode"); - i2p::data::netdb.SetHidden(true); - } - return true; + } + + bool hidden; i2p::config::GetOption("trust.hidden", hidden); + if (hidden) + { + LogPrint(eLogInfo, "Daemon: using hidden mode"); + i2p::data::netdb.SetHidden(true); + } + return true; } bool Daemon_Singleton::start() @@ -322,7 +317,7 @@ namespace i2p bool http; i2p::config::GetOption("http.enabled", http); if (http) { std::string httpAddr; i2p::config::GetOption("http.address", httpAddr); - uint16_t httpPort; i2p::config::GetOption("http.port", httpPort); + uint16_t httpPort; i2p::config::GetOption("http.port", httpPort); LogPrint(eLogInfo, "Daemon: starting HTTP Server at ", httpAddr, ":", httpPort); d.httpServer = std::unique_ptr(new i2p::http::HTTPServer(httpAddr, httpPort)); d.httpServer->Start(); @@ -344,26 +339,11 @@ namespace i2p d.m_I2PControlService = std::unique_ptr(new i2p::client::I2PControlService (i2pcpAddr, i2pcpPort)); d.m_I2PControlService->Start (); } -#ifdef WITH_EVENTS - - bool websocket; i2p::config::GetOption("websockets.enabled", websocket); - if(websocket) { - std::string websocketAddr; i2p::config::GetOption("websockets.address", websocketAddr); - uint16_t websocketPort; i2p::config::GetOption("websockets.port", websocketPort); - LogPrint(eLogInfo, "Daemon: starting Websocket server at ", websocketAddr, ":", websocketPort); - d.m_WebsocketServer = std::unique_ptr(new i2p::event::WebsocketServer (websocketAddr, websocketPort)); - d.m_WebsocketServer->Start(); - i2p::event::core.SetListener(d.m_WebsocketServer->ToListener()); - } -#endif return true; } bool Daemon_Singleton::stop() { -#ifdef WITH_EVENTS - i2p::event::core.SetListener(nullptr); -#endif LogPrint(eLogInfo, "Daemon: shutting down"); LogPrint(eLogInfo, "Daemon: stopping Client"); i2p::client::context.Stop(); @@ -397,13 +377,6 @@ namespace i2p d.m_I2PControlService->Stop (); d.m_I2PControlService = nullptr; } -#ifdef WITH_EVENTS - if (d.m_WebsocketServer) { - LogPrint(eLogInfo, "Daemon: stopping Websocket server"); - d.m_WebsocketServer->Stop(); - d.m_WebsocketServer = nullptr; - } -#endif i2p::crypto::TerminateCrypto (); i2p::log::Logger().Stop(); diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index b0f7572d..13cd772d 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -218,13 +218,6 @@ namespace config { ("trust.hidden", value()->default_value(false), "Should we hide our router from other routers?") ; - options_description websocket("Websocket Options"); - websocket.add_options() - ("websockets.enabled", value()->default_value(false), "Enable websocket server") - ("websockets.address", value()->default_value("127.0.0.1"), "Address to bind websocket server on") - ("websockets.port", value()->default_value(7666), "Port to bind websocket server on") - ; - options_description exploratory("Exploratory Options"); exploratory.add_options() ("exploratory.inbound.length", value()->default_value(2), "Exploratory inbound tunnel length") @@ -274,7 +267,6 @@ namespace config { .add(reseed) .add(addressbook) .add(trust) - .add(websocket) .add(exploratory) .add(ntcp2) .add(nettime) diff --git a/libi2pd/Event.cpp b/libi2pd/Event.cpp index 9c75f95b..90c5ed97 100644 --- a/libi2pd/Event.cpp +++ b/libi2pd/Event.cpp @@ -5,10 +5,6 @@ namespace i2p { namespace event { -#ifdef WITH_EVENTS - EventCore core; -#endif - void EventCore::SetListener(EventListener * l) { m_listener = l; @@ -44,18 +40,3 @@ namespace i2p } } } - -void QueueIntEvent(const std::string & type, const std::string & ident, uint64_t val) -{ -#ifdef WITH_EVENTS - i2p::event::core.CollectEvent(type, ident, val); -#endif -} - -void EmitEvent(const EventType & e) -{ -#if WITH_EVENTS - i2p::event::core.QueueEvent(e); -#endif -} - diff --git a/libi2pd/Event.h b/libi2pd/Event.h index a8b46a4b..74eed1db 100644 --- a/libi2pd/Event.h +++ b/libi2pd/Event.h @@ -14,40 +14,33 @@ namespace i2p { namespace event { - class EventListener { + class EventListener { public: virtual ~EventListener() {}; virtual void HandleEvent(const EventType & ev) = 0; - /** @brief handle collected event when pumped */ - virtual void HandlePumpEvent(const EventType & ev, const uint64_t & val) = 0; + /** @brief handle collected event when pumped */ + virtual void HandlePumpEvent(const EventType & ev, const uint64_t & val) = 0; }; class EventCore { public: void QueueEvent(const EventType & ev); - void CollectEvent(const std::string & type, const std::string & ident, uint64_t val); + void CollectEvent(const std::string & type, const std::string & ident, uint64_t val); void SetListener(EventListener * l); - void PumpCollected(EventListener * l); + void PumpCollected(EventListener * l); private: - std::mutex m_collect_mutex; - struct CollectedEvent - { - std::string Key; - std::string Ident; - uint64_t Val; - }; - std::map m_collected; + std::mutex m_collect_mutex; + struct CollectedEvent + { + std::string Key; + std::string Ident; + uint64_t Val; + }; + std::map m_collected; EventListener * m_listener = nullptr; }; -#ifdef WITH_EVENTS - extern EventCore core; -#endif } } - -void QueueIntEvent(const std::string & type, const std::string & ident, uint64_t val); -void EmitEvent(const EventType & ev); - #endif diff --git a/libi2pd/NTCPSession.cpp b/libi2pd/NTCPSession.cpp index 7e8ecd15..9711ffb0 100644 --- a/libi2pd/NTCPSession.cpp +++ b/libi2pd/NTCPSession.cpp @@ -14,9 +14,6 @@ #include "NTCPSession.h" #include "HTTP.h" #include "util.h" -#ifdef WITH_EVENTS -#include "Event.h" -#endif using namespace i2p::crypto; @@ -649,9 +646,6 @@ namespace transport { if (!m_NextMessage->IsExpired ()) { -#ifdef WITH_EVENTS - QueueIntEvent("transport.recvmsg", GetIdentHashBase64(), 1); -#endif m_Handler.PutNextMessage (m_NextMessage); } else diff --git a/libi2pd/SSUData.cpp b/libi2pd/SSUData.cpp index 3ad5e769..add58739 100644 --- a/libi2pd/SSUData.cpp +++ b/libi2pd/SSUData.cpp @@ -5,9 +5,6 @@ #include "NetDb.hpp" #include "SSU.h" #include "SSUData.h" -#ifdef WITH_EVENTS -#include "Event.h" -#endif namespace i2p { @@ -241,9 +238,6 @@ namespace transport m_LastMessageReceivedTime = i2p::util::GetSecondsSinceEpoch (); if (!msg->IsExpired ()) { -#ifdef WITH_EVENTS - QueueIntEvent("transport.recvmsg", m_Session.GetIdentHashBase64(), 1); -#endif m_Handler.PutNextMessage (msg); } else diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 42a605a4..ee99acf7 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -6,10 +6,6 @@ #include "Transports.h" #include "Config.h" #include "HTTP.h" -#ifdef WITH_EVENTS -#include "Event.h" -#include "util.h" -#endif using namespace i2p::data; @@ -346,9 +342,6 @@ namespace transport void Transports::SendMessages (const i2p::data::IdentHash& ident, const std::vector >& msgs) { -#ifdef WITH_EVENTS - QueueIntEvent("transport.send", ident.ToBase64(), msgs.size()); -#endif m_Service->post (std::bind (&Transports::PostMessages, this, ident, msgs)); } @@ -597,9 +590,6 @@ namespace transport auto it = m_Peers.find (ident); if (it != m_Peers.end ()) { -#ifdef WITH_EVENTS - EmitEvent({{"type" , "transport.connected"}, {"ident", ident.ToBase64()}, {"inbound", "false"}}); -#endif bool sendDatabaseStore = true; if (it->second.delayedMessages.size () > 0) { @@ -625,9 +615,6 @@ namespace transport session->Done(); return; } -#ifdef WITH_EVENTS - EmitEvent({{"type" , "transport.connected"}, {"ident", ident.ToBase64()}, {"inbound", "true"}}); -#endif session->SendI2NPMessages ({ CreateDatabaseStoreMsg () }); // send DatabaseStore std::unique_lock l(m_PeersMutex); m_Peers.insert (std::make_pair (ident, Peer{ 0, nullptr, { session }, i2p::util::GetSecondsSinceEpoch (), {} })); @@ -642,9 +629,6 @@ namespace transport auto remoteIdentity = session->GetRemoteIdentity (); if (!remoteIdentity) return; auto ident = remoteIdentity->GetIdentHash (); -#ifdef WITH_EVENTS - EmitEvent({{"type" , "transport.disconnected"}, {"ident", ident.ToBase64()}}); -#endif auto it = m_Peers.find (ident); if (it != m_Peers.end ()) { diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 00b0a12c..9dacddac 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -14,9 +14,6 @@ #include "Config.h" #include "Tunnel.h" #include "TunnelPool.h" -#ifdef WITH_EVENTS -#include "Event.h" -#endif namespace i2p { @@ -35,9 +32,6 @@ namespace tunnel void Tunnel::Build (uint32_t replyMsgID, std::shared_ptr outboundTunnel) { -#ifdef WITH_EVENTS - std::string peers = i2p::context.GetIdentity()->GetIdentHash().ToBase64(); -#endif auto numHops = m_Config->GetNumHops (); int numRecords = numHops <= STANDARD_NUM_RECORDS ? STANDARD_NUM_RECORDS : numHops; auto msg = NewI2NPShortMessage (); @@ -64,15 +58,9 @@ namespace tunnel hop->CreateBuildRequestRecord (records + idx*TUNNEL_BUILD_RECORD_SIZE, msgID, ctx); hop->recordIndex = idx; i++; -#ifdef WITH_EVENTS - peers += ":" + hop->ident->GetIdentHash().ToBase64(); -#endif hop = hop->next; } BN_CTX_free (ctx); -#ifdef WITH_EVENTS - EmitTunnelEvent("tunnel.build", this, peers); -#endif // fill up fake records with random data for (int i = numHops; i < numRecords; i++) { @@ -207,9 +195,6 @@ namespace tunnel void Tunnel::SetState(TunnelState state) { m_State = state; -#ifdef WITH_EVENTS - EmitTunnelEvent("tunnel.state", this, state); -#endif } @@ -614,9 +599,6 @@ namespace tunnel hop = hop->next; } } -#ifdef WITH_EVENTS - EmitTunnelEvent("tunnel.state", tunnel.get(), eTunnelStateBuildFailed); -#endif // for i2lua if(pool) pool->OnTunnelBuildResult(tunnel, eBuildResultTimeout); // delete @@ -628,9 +610,6 @@ namespace tunnel break; case eTunnelStateBuildFailed: LogPrint (eLogDebug, "Tunnel: pending build request ", it->first, " failed, deleted"); -#ifdef WITH_EVENTS - EmitTunnelEvent("tunnel.state", tunnel.get(), eTunnelStateBuildFailed); -#endif // for i2lua if(pool) pool->OnTunnelBuildResult(tunnel, eBuildResultRejected); diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index 3244faad..66b620b8 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -25,42 +25,28 @@ namespace i2p { namespace tunnel { - - template - static void EmitTunnelEvent(const std::string & ev, const TunnelT & t) - { -#ifdef WITH_EVENTS - EmitEvent({{"type", ev}, {"tid", std::to_string(t->GetTunnelID())}}); -#else + template + static void EmitTunnelEvent(const std::string & ev, const TunnelT & t) + { (void) ev; (void) t; -#endif - } + } - template - static void EmitTunnelEvent(const std::string & ev, TunnelT * t, const T & val) - { -#ifdef WITH_EVENTS - EmitEvent({{"type", ev}, {"tid", std::to_string(t->GetTunnelID())}, {"value", std::to_string(val)}, {"inbound", std::to_string(t->IsInbound())}}); -#else + template + static void EmitTunnelEvent(const std::string & ev, TunnelT * t, const T & val) + { (void) ev; (void) t; (void) val; -#endif - } + } - template - static void EmitTunnelEvent(const std::string & ev, TunnelT * t, const std::string & val) - { -#ifdef WITH_EVENTS - EmitEvent({{"type", ev}, {"tid", std::to_string(t->GetTunnelID())}, {"value", val}, {"inbound", std::to_string(t->IsInbound())}}); -#else + template + static void EmitTunnelEvent(const std::string & ev, TunnelT * t, const std::string & val) + { (void) ev; (void) t; (void) val; -#endif - } - + } const int TUNNEL_EXPIRATION_TIMEOUT = 660; // 11 minutes const int TUNNEL_EXPIRATION_THRESHOLD = 60; // 1 minute diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index 7a1325fe..b3e3c7d2 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -11,9 +11,6 @@ #include "Tunnel.h" #include "TunnelPool.h" #include "Destination.h" -#ifdef WITH_EVENTS -#include "Event.h" -#endif namespace i2p { @@ -86,9 +83,6 @@ namespace tunnel { if (!m_IsActive) return; { -#ifdef WITH_EVENTS - EmitTunnelEvent("tunnels.created", createdTunnel); -#endif std::unique_lock l(m_InboundTunnelsMutex); m_InboundTunnels.insert (createdTunnel); } @@ -102,9 +96,6 @@ namespace tunnel { if (expiredTunnel) { -#ifdef WITH_EVENTS - EmitTunnelEvent("tunnels.expired", expiredTunnel); -#endif expiredTunnel->SetTunnelPool (nullptr); for (auto& it: m_Tests) if (it.second.second == expiredTunnel) it.second.second = nullptr; @@ -118,9 +109,6 @@ namespace tunnel { if (!m_IsActive) return; { -#ifdef WITH_EVENTS - EmitTunnelEvent("tunnels.created", createdTunnel); -#endif std::unique_lock l(m_OutboundTunnelsMutex); m_OutboundTunnels.insert (createdTunnel); } @@ -133,9 +121,6 @@ namespace tunnel { if (expiredTunnel) { -#ifdef WITH_EVENTS - EmitTunnelEvent("tunnels.expired", expiredTunnel); -#endif expiredTunnel->SetTunnelPool (nullptr); for (auto& it: m_Tests) if (it.second.first == expiredTunnel) it.second.first = nullptr; diff --git a/libi2pd_client/ClientContext.h b/libi2pd_client/ClientContext.h index a239035f..610914bf 100644 --- a/libi2pd_client/ClientContext.h +++ b/libi2pd_client/ClientContext.h @@ -37,7 +37,7 @@ namespace client const char I2P_CLIENT_TUNNEL_CRYPTO_TYPE[] = "cryptotype"; const char I2P_CLIENT_TUNNEL_DESTINATION_PORT[] = "destinationport"; const char I2P_CLIENT_TUNNEL_MATCH_TUNNELS[] = "matchtunnels"; - const char I2P_CLIENT_TUNNEL_CONNECT_TIMEOUT[] = "connecttimeout"; + const char I2P_CLIENT_TUNNEL_CONNECT_TIMEOUT[] = "connecttimeout"; const char I2P_SERVER_TUNNEL_HOST[] = "host"; const char I2P_SERVER_TUNNEL_HOST_OVERRIDE[] = "hostoverride"; const char I2P_SERVER_TUNNEL_PORT[] = "port"; diff --git a/libi2pd_client/WebSocks.cpp b/libi2pd_client/WebSocks.cpp index c80feac8..95abf455 100644 --- a/libi2pd_client/WebSocks.cpp +++ b/libi2pd_client/WebSocks.cpp @@ -2,491 +2,6 @@ #include "Log.h" #include -#ifdef WITH_EVENTS -#include "ClientContext.h" -#include "Identity.h" -#include "Destination.h" -#include "Streaming.h" -#include - -#include -#include - -#include -#define GCC47_BOOST149 ((BOOST_VERSION == 104900) && (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) -#if !GCC47_BOOST149 -#include -#endif - -namespace i2p -{ -namespace client -{ - typedef websocketpp::server WebSocksServerImpl; - - typedef std::function)> StreamConnectFunc; - - - struct IWebSocksConn : public I2PServiceHandler - { - IWebSocksConn(I2PService * parent) : I2PServiceHandler(parent) {} - virtual void Close() = 0; - virtual void GotMessage(const websocketpp::connection_hdl & conn, WebSocksServerImpl::message_ptr msg) = 0; - }; - - typedef std::shared_ptr WebSocksConn_ptr; - - WebSocksConn_ptr CreateWebSocksConn(const websocketpp::connection_hdl & conn, WebSocksImpl * parent); - - class WebSocksImpl - { - - typedef std::mutex mutex_t; - typedef std::unique_lock lock_t; - - typedef std::shared_ptr Destination_t; - public: - - typedef WebSocksServerImpl ServerImpl; - typedef ServerImpl::message_ptr MessagePtr; - - WebSocksImpl(const std::string & addr, int port) : - Parent(nullptr), - m_Run(false), - m_Addr(addr), - m_Port(port), - m_Thread(nullptr) - { - m_Server.init_asio(); - m_Server.set_open_handler(std::bind(&WebSocksImpl::ConnOpened, this, std::placeholders::_1)); - } - - void InitializeDestination(WebSocks * parent) - { - Parent = parent; - m_Dest = Parent->GetLocalDestination(); - } - - ServerImpl::connection_ptr GetConn(const websocketpp::connection_hdl & conn) - { - return m_Server.get_con_from_hdl(conn); - } - - void CloseConn(const websocketpp::connection_hdl & conn) - { - auto c = GetConn(conn); - if(c) c->close(websocketpp::close::status::normal, "closed"); - } - - void CreateStreamTo(const std::string & addr, int port, StreamConnectFunc complete) - { - auto & addressbook = i2p::client::context.GetAddressBook(); - auto a = addressbook.GetAddress (addr); - if (a && a->IsIdentHash ()) - { - // address found - m_Dest->CreateStream(complete, a->identHash, port); - } - else - { - // not found - complete(nullptr); - } - } - - void ConnOpened(websocketpp::connection_hdl conn) - { - auto ptr = CreateWebSocksConn(conn, this); - Parent->AddHandler(ptr); - m_Conns.push_back(ptr); - } - - void Start() - { - if(m_Run) return; // already started - m_Server.listen(boost::asio::ip::address::from_string(m_Addr), m_Port); - m_Server.start_accept(); - m_Run = true; - m_Thread = new std::thread([&] (){ - while(m_Run) { - try { - m_Server.run(); - } catch( std::exception & ex) { - LogPrint(eLogError, "Websocks runtime exception: ", ex.what()); - } - } - }); - m_Dest->Start(); - } - - void Stop() - { - for(const auto & conn : m_Conns) - conn->Close(); - - m_Dest->Stop(); - m_Run = false; - m_Server.stop(); - if(m_Thread) { - m_Thread->join(); - delete m_Thread; - } - m_Thread = nullptr; - } - - boost::asio::ip::tcp::endpoint GetLocalEndpoint() - { - return boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(m_Addr), m_Port); - } - - i2p::datagram::DatagramDestination * GetDatagramDest() const - { - auto dgram = m_Dest->GetDatagramDestination(); - if(!dgram) dgram = m_Dest->CreateDatagramDestination(); - return dgram; - } - - WebSocks * Parent; - - private: - std::vector m_Conns; - bool m_Run; - ServerImpl m_Server; - std::string m_Addr; - int m_Port; - std::thread * m_Thread; - Destination_t m_Dest; - }; - - struct WebSocksConn : public IWebSocksConn , public std::enable_shared_from_this - { - enum ConnState - { - eWSCInitial, - eWSCTryConnect, - eWSCFailConnect, - eWSCOkayConnect, - eWSCDatagram, - eWSCClose, - eWSCEnd - }; - - typedef WebSocksServerImpl ServerImpl; - typedef ServerImpl::message_ptr Message_t; - typedef websocketpp::connection_hdl ServerConn; - typedef std::shared_ptr Destination_t; - typedef std::shared_ptr StreamDest_t; - typedef std::shared_ptr Stream_t; - - ServerConn m_Conn; - Stream_t m_Stream; - ConnState m_State; - WebSocksImpl * m_Parent; - std::string m_RemoteAddr; - int m_RemotePort; - uint8_t m_RecvBuf[2048]; - bool m_IsDatagram; - i2p::datagram::DatagramDestination * m_Datagram; - - WebSocksConn(const ServerConn & conn, WebSocksImpl * parent) : - IWebSocksConn(parent->Parent), - m_Conn(conn), - m_Stream(nullptr), - m_State(eWSCInitial), - m_Parent(parent), - m_IsDatagram(false), - m_Datagram(nullptr) - { - - } - - ~WebSocksConn() - { - Close(); - } - - void HandleDatagram(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) - { - auto conn = m_Parent->GetConn(m_Conn); - if(conn) - { - std::stringstream ss; - ss << from.GetIdentHash().ToBase32(); - ss << ".b32.i2p:"; - ss << std::to_string(fromPort); - ss << "\n"; - ss.write((char *)buf, len); - conn->send(ss.str()); - } - } - - void BeginDatagram() - { - m_Datagram = m_Parent->GetDatagramDest(); - m_Datagram->SetReceiver( - std::bind( - &WebSocksConn::HandleDatagram, - this, - std::placeholders::_1, - std::placeholders::_2, - std::placeholders::_3, - std::placeholders::_4, - std::placeholders::_5), m_RemotePort); - } - - void EnterState(ConnState state) - { - LogPrint(eLogDebug, "websocks: state ", m_State, " -> ", state); - switch(m_State) - { - case eWSCInitial: - if (state == eWSCClose) { - m_State = eWSCClose; - // connection was opened but never used - LogPrint(eLogInfo, "websocks: connection closed but never used"); - Close(); - return; - } else if (state == eWSCTryConnect) { - // we will try to connect - m_State = eWSCTryConnect; - m_Parent->CreateStreamTo(m_RemoteAddr, m_RemotePort, std::bind(&WebSocksConn::ConnectResult, this, std::placeholders::_1)); - } else if (state == eWSCDatagram) { - if (m_RemotePort >= 0 && m_RemotePort <= 65535) - { - LogPrint(eLogDebug, "websocks: datagram mode initiated"); - m_State = eWSCDatagram; - BeginDatagram(); - SendResponse(""); - } - else - SendResponse("invalid port"); - } else { - LogPrint(eLogWarning, "websocks: invalid state change ", m_State, " -> ", state); - } - return; - case eWSCTryConnect: - if(state == eWSCOkayConnect) { - // we connected okay - LogPrint(eLogDebug, "websocks: connected to ", m_RemoteAddr, ":", m_RemotePort); - SendResponse(""); - m_State = eWSCOkayConnect; - } else if(state == eWSCFailConnect) { - // we did not connect okay - LogPrint(eLogDebug, "websocks: failed to connect to ", m_RemoteAddr, ":", m_RemotePort); - SendResponse("failed to connect"); - m_State = eWSCFailConnect; - EnterState(eWSCInitial); - } else if(state == eWSCClose) { - // premature close - LogPrint(eLogWarning, "websocks: websocket connection closed prematurely"); - m_State = eWSCClose; - } else { - LogPrint(eLogWarning, "websocks: invalid state change ", m_State, " -> ", state); - } - return; - case eWSCFailConnect: - if (state == eWSCInitial) { - // reset to initial state so we can try connecting again - m_RemoteAddr = ""; - m_RemotePort = 0; - LogPrint(eLogDebug, "websocks: reset websocket conn to initial state"); - m_State = eWSCInitial; - } else if (state == eWSCClose) { - // we are going to close the connection - m_State = eWSCClose; - Close(); - } else { - LogPrint(eLogWarning, "websocks: invalid state change ", m_State, " -> ", state); - } - return; - case eWSCDatagram: - if(state != eWSCClose) { - LogPrint(eLogWarning, "websocks: invalid state change ", m_State, " -> ", state); - } - m_State = eWSCClose; - Close(); - return; - case eWSCOkayConnect: - if(state == eWSCClose) { - // graceful close - m_State = eWSCClose; - Close(); - } else { - LogPrint(eLogWarning, "websocks: invalid state change ", m_State, " -> ", state); - } - return; - case eWSCClose: - if(state == eWSCEnd) { - LogPrint(eLogDebug, "websocks: socket ended"); - Kill(); - auto me = shared_from_this(); - Done(me); - } else { - LogPrint(eLogWarning, "websocks: invalid state change ", m_State, " -> ", state); - } - return; - default: - LogPrint(eLogError, "websocks: bad state ", m_State); - } - } - - void StartForwarding() - { - LogPrint(eLogDebug, "websocks: begin forwarding data"); - uint8_t b[1]; - m_Stream->Send(b, 0); - AsyncRecv(); - } - - void HandleAsyncRecv(const boost::system::error_code &ec, std::size_t n) - { - if(ec) { - // error - LogPrint(eLogWarning, "websocks: connection error ", ec.message()); - EnterState(eWSCClose); - } else { - // forward data - LogPrint(eLogDebug, "websocks recv ", n); - - std::string str((char*)m_RecvBuf, n); - auto conn = m_Parent->GetConn(m_Conn); - if(!conn) { - LogPrint(eLogWarning, "websocks: connection is gone"); - EnterState(eWSCClose); - return; - } - conn->send(str); - AsyncRecv(); - - } - } - - void AsyncRecv() - { - m_Stream->AsyncReceive( - boost::asio::buffer(m_RecvBuf, sizeof(m_RecvBuf)), - std::bind(&WebSocksConn::HandleAsyncRecv, this, std::placeholders::_1, std::placeholders::_2), 60); - } - - /** @brief send error message or empty string for success */ - void SendResponse(const std::string & errormsg) - { - boost::property_tree::ptree resp; - if(errormsg.size()) { - resp.put("error", errormsg); - resp.put("success", 0); - } else { - resp.put("success", 1); - } - std::ostringstream ss; - write_json(ss, resp); - auto conn = m_Parent->GetConn(m_Conn); - if(conn) conn->send(ss.str()); - } - - void ConnectResult(Stream_t stream) - { - m_Stream = stream; - if(m_State == eWSCClose) { - // premature close of websocket - Close(); - return; - } - if(m_Stream) { - // connect good - EnterState(eWSCOkayConnect); - StartForwarding(); - } else { - // connect failed - EnterState(eWSCFailConnect); - } - } - - virtual void GotMessage(const websocketpp::connection_hdl & conn, WebSocksServerImpl::message_ptr msg) - { - (void) conn; - std::string payload = msg->get_payload(); - if(m_State == eWSCOkayConnect) - { - // forward to server - LogPrint(eLogDebug, "websocks: forward ", payload.size()); - m_Stream->Send((uint8_t*)payload.c_str(), payload.size()); - } else if (m_State == eWSCInitial) { - // recv connect request - auto itr = payload.find(":"); - if(itr == std::string::npos) { - // no port - m_RemotePort = 0; - m_RemoteAddr = payload; - } else { - // includes port - m_RemotePort = std::stoi(payload.substr(itr+1)); - m_RemoteAddr = payload.substr(0, itr); - } - m_IsDatagram = m_RemoteAddr == "DATAGRAM"; - if(m_IsDatagram) - EnterState(eWSCDatagram); - else - EnterState(eWSCTryConnect); - } else if (m_State == eWSCDatagram) { - // send datagram - // format is "host:port\npayload" - auto idx = payload.find("\n"); - std::string line = payload.substr(0, idx); - auto itr = line.find(":"); - auto & addressbook = i2p::client::context.GetAddressBook(); - std::string addr; - int port = 0; - if (itr == std::string::npos) - { - addr = line; - } - else - { - addr = line.substr(0, itr); - port = std::atoi(line.substr(itr+1).c_str()); - } - auto a = addressbook.GetAddress (addr); - if (a && a->IsIdentHash ()) - { - const char * data = payload.c_str() + idx + 1; - size_t len = payload.size() - (1 + line.size()); - m_Datagram->SendDatagramTo((const uint8_t*)data, len, a->identHash, m_RemotePort, port); - } - } else { - // wtf? - LogPrint(eLogWarning, "websocks: got message in invalid state ", m_State); - } - } - - virtual void Close() - { - if(m_State == eWSCClose) { - LogPrint(eLogDebug, "websocks: closing connection"); - if(m_Stream) m_Stream->Close(); - if(m_Datagram) m_Datagram->ResetReceiver(m_RemotePort); - m_Parent->CloseConn(m_Conn); - EnterState(eWSCEnd); - } else { - EnterState(eWSCClose); - } - } - }; - - WebSocksConn_ptr CreateWebSocksConn(const websocketpp::connection_hdl & conn, WebSocksImpl * parent) - { - auto ptr = std::make_shared(conn, parent); - auto c = parent->GetConn(conn); - c->set_message_handler(std::bind(&WebSocksConn::GotMessage, ptr.get(), std::placeholders::_1, std::placeholders::_2)); - return ptr; - } - -} -} -#else - -// no websocket support - namespace i2p { namespace client @@ -504,7 +19,7 @@ namespace client void Start() { - LogPrint(eLogInfo, "WebSockets not enabled on compile time"); + LogPrint(eLogInfo, "[Tunnels] starting websocks tunnel at %s:%d is rejected: WebSockets is deprecated", m_Addr, m_Port); } void Stop() @@ -527,7 +42,6 @@ namespace client } } -#endif namespace i2p { namespace client diff --git a/libi2pd_client/Websocket.cpp b/libi2pd_client/Websocket.cpp deleted file mode 100644 index 3d456655..00000000 --- a/libi2pd_client/Websocket.cpp +++ /dev/null @@ -1,195 +0,0 @@ -#ifdef WITH_EVENTS -#include "Websocket.h" -#include "Log.h" - -#include -#include - -#include -#include -#include -#define GCC47_BOOST149 ((BOOST_VERSION == 104900) && (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) -#if !GCC47_BOOST149 -#include -#endif - -#include - -namespace i2p -{ - namespace event - { - - typedef websocketpp::server ServerImpl; - typedef websocketpp::connection_hdl ServerConn; - - class WebsocketServerImpl : public EventListener - { - private: - typedef ServerImpl::message_ptr MessagePtr; - public: - - WebsocketServerImpl(const std::string & addr, int port) : - m_run(false), - m_ws_thread(nullptr), - m_ev_thread(nullptr), - m_WebsocketTicker(m_Service) - { - m_server.init_asio(); - m_server.set_open_handler(std::bind(&WebsocketServerImpl::ConnOpened, this, std::placeholders::_1)); - m_server.set_close_handler(std::bind(&WebsocketServerImpl::ConnClosed, this, std::placeholders::_1)); - m_server.set_message_handler(std::bind(&WebsocketServerImpl::OnConnMessage, this, std::placeholders::_1, std::placeholders::_2)); - - m_server.listen(boost::asio::ip::address::from_string(addr), port); - } - - ~WebsocketServerImpl() - { - } - - void Start() { - m_run = true; - m_server.start_accept(); - m_ws_thread = new std::thread([&] () { - while(m_run) { - try { - m_server.run(); - } catch (std::exception & e ) { - LogPrint(eLogError, "Websocket server: ", e.what()); - } - } - }); - m_ev_thread = new std::thread([&] () { - while(m_run) { - try { - m_Service.run(); - break; - } catch (std::exception & e ) { - LogPrint(eLogError, "Websocket service: ", e.what()); - } - } - }); - ScheduleTick(); - } - - void Stop() { - m_run = false; - m_Service.stop(); - m_server.stop(); - - if(m_ev_thread) { - m_ev_thread->join(); - delete m_ev_thread; - } - m_ev_thread = nullptr; - - if(m_ws_thread) { - m_ws_thread->join(); - delete m_ws_thread; - } - m_ws_thread = nullptr; - } - - void ConnOpened(ServerConn c) - { - std::lock_guard lock(m_connsMutex); - m_conns.insert(c); - } - - void ConnClosed(ServerConn c) - { - std::lock_guard lock(m_connsMutex); - m_conns.erase(c); - } - - void OnConnMessage(ServerConn conn, ServerImpl::message_ptr msg) - { - (void) conn; - (void) msg; - } - - void HandleTick(const boost::system::error_code & ec) - { - - if(ec != boost::asio::error::operation_aborted) - LogPrint(eLogError, "Websocket ticker: ", ec.message()); - // pump collected events to us - i2p::event::core.PumpCollected(this); - ScheduleTick(); - } - - void ScheduleTick() - { - LogPrint(eLogDebug, "Websocket schedule tick"); - boost::posix_time::seconds dlt(1); - m_WebsocketTicker.expires_from_now(dlt); - m_WebsocketTicker.async_wait(std::bind(&WebsocketServerImpl::HandleTick, this, std::placeholders::_1)); - } - - /** @brief called from m_ev_thread */ - void HandlePumpEvent(const EventType & ev, const uint64_t & val) - { - EventType e; - for (const auto & i : ev) - e[i.first] = i.second; - - e["number"] = std::to_string(val); - HandleEvent(e); - } - - /** @brief called from m_ws_thread */ - void HandleEvent(const EventType & ev) - { - std::lock_guard lock(m_connsMutex); - boost::property_tree::ptree event; - for (const auto & item : ev) { - event.put(item.first, item.second); - } - std::ostringstream ss; - write_json(ss, event); - std::string s = ss.str(); - - ConnList::iterator it; - for (it = m_conns.begin(); it != m_conns.end(); ++it) { - ServerImpl::connection_ptr con = m_server.get_con_from_hdl(*it); - con->send(s); - } - } - - private: - typedef std::set > ConnList; - bool m_run; - std::thread * m_ws_thread; - std::thread * m_ev_thread; - std::mutex m_connsMutex; - ConnList m_conns; - ServerImpl m_server; - boost::asio::io_service m_Service; - boost::asio::deadline_timer m_WebsocketTicker; - }; - - - WebsocketServer::WebsocketServer(const std::string & addr, int port) : m_impl(new WebsocketServerImpl(addr, port)) {} - WebsocketServer::~WebsocketServer() - { - delete m_impl; - } - - - void WebsocketServer::Start() - { - m_impl->Start(); - } - - void WebsocketServer::Stop() - { - m_impl->Stop(); - } - - EventListener * WebsocketServer::ToListener() - { - return m_impl; - } - } -} -#endif diff --git a/libi2pd_client/Websocket.h b/libi2pd_client/Websocket.h deleted file mode 100644 index 3a754e49..00000000 --- a/libi2pd_client/Websocket.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef WEBSOCKET_H__ -#define WEBSOCKET_H__ -#include "Event.h" -namespace i2p -{ - namespace event - { - - class WebsocketServerImpl; - - class WebsocketServer - { - public: - WebsocketServer(const std::string & addr, int port); - ~WebsocketServer(); - - void Start(); - void Stop(); - - EventListener * ToListener(); - - private: - WebsocketServerImpl * m_impl; - }; - - } -} -#endif diff --git a/qt/i2pd_qt/generalsettingswidget.ui b/qt/i2pd_qt/generalsettingswidget.ui index a7f07e5d..9e59132f 100644 --- a/qt/i2pd_qt/generalsettingswidget.ui +++ b/qt/i2pd_qt/generalsettingswidget.ui @@ -2135,121 +2135,6 @@ Comma separated list of base64 identities: - - - - - 0 - 0 - - - - - 0 - 105 - - - - - 16777215 - 105 - - - - Websockets server - - - - - 0 - 20 - 85 - 21 - - - - Enable - - - - - - 0 - 40 - 661 - 31 - - - - - - - Address to bind websocket server on: - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 70 - 661 - 31 - - - - - - - Port to bind websocket server on: - - - - - - - - 80 - 16777215 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - diff --git a/qt/i2pd_qt/i2pd_qt.pro b/qt/i2pd_qt/i2pd_qt.pro index caa0bd50..1f01cb4b 100644 --- a/qt/i2pd_qt/i2pd_qt.pro +++ b/qt/i2pd_qt/i2pd_qt.pro @@ -74,7 +74,6 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \ ../../libi2pd_client/MatchedDestination.cpp \ ../../libi2pd_client/SAM.cpp \ ../../libi2pd_client/SOCKS.cpp \ - ../../libi2pd_client/Websocket.cpp \ ../../libi2pd_client/WebSocks.cpp \ ../../daemon/Daemon.cpp \ ../../daemon/HTTPServer.cpp \ @@ -161,7 +160,6 @@ HEADERS += DaemonQT.h mainwindow.h \ ../../libi2pd_client/MatchedDestination.h \ ../../libi2pd_client/SAM.h \ ../../libi2pd_client/SOCKS.h \ - ../../libi2pd_client/Websocket.h \ ../../libi2pd_client/WebSocks.h \ ../../daemon/Daemon.h \ ../../daemon/HTTPServer.h \ diff --git a/qt/i2pd_qt/mainwindow.cpp b/qt/i2pd_qt/mainwindow.cpp index e4c9f2a7..76a6fda8 100644 --- a/qt/i2pd_qt/mainwindow.cpp +++ b/qt/i2pd_qt/mainwindow.cpp @@ -258,10 +258,6 @@ 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); - initIPAddressBox( OPTION("websockets","address",[]{return "127.0.0.1";}), uiSettings->lineEdit_webSock_addr, tr("Websocket server -> IP address")); - initTCPPortBox( OPTION("websockets","port",[]{return "7666";}), uiSettings->lineEdit_webSock_port, tr("Websocket server -> Port")); - # undef OPTION //widgetlocks.add(new widgetlock(widget,lockbtn)); From bca0809918a2843b3d5b853a129a3068b0d9882a Mon Sep 17 00:00:00 2001 From: R4SAS Date: Fri, 28 Feb 2020 18:48:43 +0300 Subject: [PATCH 04/44] cleanup removed websockets funtions Signed-off-by: R4SAS --- build/CMakeLists.txt | 1 - filelist.mk | 2 +- libi2pd/Event.cpp | 42 --------------------------------- libi2pd/Event.h | 46 ------------------------------------- libi2pd/Tunnel.h | 24 ------------------- libi2pd_client/WebSocks.cpp | 1 - qt/i2pd_qt/i2pd_qt.pro | 2 -- 7 files changed, 1 insertion(+), 117 deletions(-) delete mode 100644 libi2pd/Event.cpp delete mode 100644 libi2pd/Event.h diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 324ac468..d39dd113 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -74,7 +74,6 @@ set (LIBI2PD_SRC "${LIBI2PD_SRC_DIR}/Signature.cpp" "${LIBI2PD_SRC_DIR}/Timestamp.cpp" "${LIBI2PD_SRC_DIR}/api.cpp" - "${LIBI2PD_SRC_DIR}/Event.cpp" "${LIBI2PD_SRC_DIR}/Gost.cpp" "${LIBI2PD_SRC_DIR}/ChaCha20.cpp" "${LIBI2PD_SRC_DIR}/Poly1305.cpp" diff --git a/filelist.mk b/filelist.mk index 8d451dc9..72773975 100644 --- a/filelist.mk +++ b/filelist.mk @@ -5,7 +5,7 @@ # SSUSession.cpp SSUData.cpp Streaming.cpp Identity.cpp TransitTunnel.cpp \ # Transports.cpp Tunnel.cpp TunnelEndpoint.cpp TunnelPool.cpp TunnelGateway.cpp \ # Destination.cpp Base.cpp I2PEndian.cpp FS.cpp Config.cpp Family.cpp \ -# Config.cpp HTTP.cpp Timestamp.cpp util.cpp api.cpp Event.cpp Gost.cpp +# Config.cpp HTTP.cpp Timestamp.cpp util.cpp api.cpp Gost.cpp LIB_SRC = $(wildcard $(LIB_SRC_DIR)/*.cpp) diff --git a/libi2pd/Event.cpp b/libi2pd/Event.cpp deleted file mode 100644 index 90c5ed97..00000000 --- a/libi2pd/Event.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "Event.h" -#include "Log.h" - -namespace i2p -{ - namespace event - { - void EventCore::SetListener(EventListener * l) - { - m_listener = l; - LogPrint(eLogInfo, "Event: listener set"); - } - - void EventCore::QueueEvent(const EventType & ev) - { - if(m_listener) m_listener->HandleEvent(ev); - } - - void EventCore::CollectEvent(const std::string & type, const std::string & ident, uint64_t val) - { - std::unique_lock lock(m_collect_mutex); - std::string key = type + "." + ident; - if (m_collected.find(key) == m_collected.end()) - { - m_collected[key] = {type, key, 0}; - } - m_collected[key].Val += val; - } - - void EventCore::PumpCollected(EventListener * listener) - { - std::unique_lock lock(m_collect_mutex); - if(listener) - { - for(const auto & ev : m_collected) { - listener->HandlePumpEvent({{"type", ev.second.Key}, {"ident", ev.second.Ident}}, ev.second.Val); - } - } - m_collected.clear(); - } - } -} diff --git a/libi2pd/Event.h b/libi2pd/Event.h deleted file mode 100644 index 74eed1db..00000000 --- a/libi2pd/Event.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef EVENT_H__ -#define EVENT_H__ -#include -#include -#include -#include -#include - -#include - -typedef std::map EventType; - -namespace i2p -{ - namespace event - { - class EventListener { - public: - virtual ~EventListener() {}; - virtual void HandleEvent(const EventType & ev) = 0; - /** @brief handle collected event when pumped */ - virtual void HandlePumpEvent(const EventType & ev, const uint64_t & val) = 0; - }; - - class EventCore - { - public: - void QueueEvent(const EventType & ev); - void CollectEvent(const std::string & type, const std::string & ident, uint64_t val); - void SetListener(EventListener * l); - void PumpCollected(EventListener * l); - - private: - std::mutex m_collect_mutex; - struct CollectedEvent - { - std::string Key; - std::string Ident; - uint64_t Val; - }; - std::map m_collected; - EventListener * m_listener = nullptr; - }; - } -} -#endif diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index 66b620b8..f97bcc63 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -19,35 +19,11 @@ #include "TunnelGateway.h" #include "TunnelBase.h" #include "I2NPProtocol.h" -#include "Event.h" namespace i2p { namespace tunnel { - template - static void EmitTunnelEvent(const std::string & ev, const TunnelT & t) - { - (void) ev; - (void) t; - } - - template - static void EmitTunnelEvent(const std::string & ev, TunnelT * t, const T & val) - { - (void) ev; - (void) t; - (void) val; - } - - template - static void EmitTunnelEvent(const std::string & ev, TunnelT * t, const std::string & val) - { - (void) ev; - (void) t; - (void) val; - } - const int TUNNEL_EXPIRATION_TIMEOUT = 660; // 11 minutes const int TUNNEL_EXPIRATION_THRESHOLD = 60; // 1 minute const int TUNNEL_RECREATION_THRESHOLD = 90; // 1.5 minutes diff --git a/libi2pd_client/WebSocks.cpp b/libi2pd_client/WebSocks.cpp index 95abf455..a3e8c1bf 100644 --- a/libi2pd_client/WebSocks.cpp +++ b/libi2pd_client/WebSocks.cpp @@ -70,4 +70,3 @@ namespace client } } } - diff --git a/qt/i2pd_qt/i2pd_qt.pro b/qt/i2pd_qt/i2pd_qt.pro index 1f01cb4b..ce3ec1ca 100644 --- a/qt/i2pd_qt/i2pd_qt.pro +++ b/qt/i2pd_qt/i2pd_qt.pro @@ -28,7 +28,6 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \ ../../libi2pd/Datagram.cpp \ ../../libi2pd/Destination.cpp \ ../../libi2pd/Ed25519.cpp \ - ../../libi2pd/Event.cpp \ ../../libi2pd/Family.cpp \ ../../libi2pd/FS.cpp \ ../../libi2pd/Garlic.cpp \ @@ -106,7 +105,6 @@ HEADERS += DaemonQT.h mainwindow.h \ ../../libi2pd/Datagram.h \ ../../libi2pd/Destination.h \ ../../libi2pd/Ed25519.h \ - ../../libi2pd/Event.h \ ../../libi2pd/Family.h \ ../../libi2pd/FS.h \ ../../libi2pd/Garlic.h \ From b02c9fb118be455c73873d7ec291b089323da4e3 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 28 Feb 2020 14:03:08 -0500 Subject: [PATCH 05/44] enable C++17 for gcc --- Makefile.linux | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Makefile.linux b/Makefile.linux index d1ccf143..9db660c2 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -15,13 +15,14 @@ ifeq ($(shell expr match $(CXX) 'clang'),5) NEEDED_CXXFLAGS += -std=c++11 else ifeq ($(shell expr match ${CXXVER} "4\.[0-9][0-9]"),4) # gcc >= 4.10 NEEDED_CXXFLAGS += -std=c++11 -else ifeq ($(shell expr match ${CXXVER} "4\.[7-9]"),3) # >= 4.7 +else ifeq ($(shell expr match ${CXXVER} "4\.[7-9]"),3) # gcc 4.7 - 4.9 NEEDED_CXXFLAGS += -std=c++11 -D_GLIBCXX_USE_NANOSLEEP=1 -else ifeq ($(shell expr match ${CXXVER} "4\.6"),3) # = 4.6 - NEEDED_CXXFLAGS += -std=c++0x -else ifeq ($(shell expr match ${CXXVER} "[5-9]"),1) # gcc >= 5 +else ifeq ($(shell expr match ${CXXVER} "[5-6]"),1) # gcc 5 - 6 NEEDED_CXXFLAGS += -std=c++11 LDLIBS = -latomic +else ifeq ($(shell expr match ${CXXVER} "[7-9]"),1) # gcc >= 7 + NEEDED_CXXFLAGS += -std=c++17 + LDLIBS = -latomic else # not supported $(error Compiler too old) endif From 1893127e8468e67e0cc5ccd7ffcda8686d441490 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 28 Feb 2020 14:05:51 -0500 Subject: [PATCH 06/44] use fold expression if C++17 --- libi2pd/Log.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libi2pd/Log.h b/libi2pd/Log.h index b11c6763..ba10b5e9 100644 --- a/libi2pd/Log.h +++ b/libi2pd/Log.h @@ -161,6 +161,7 @@ void LogPrint (std::stringstream& s, TValue&& arg) noexcept s << std::forward(arg); } +#if (__cplusplus < 201703L) // below C++ 17 /** internal usage only -- folding args array to single string */ template void LogPrint (std::stringstream& s, TValue&& arg, TArgs&&... args) noexcept @@ -168,6 +169,7 @@ void LogPrint (std::stringstream& s, TValue&& arg, TArgs&&... args) noexcept LogPrint (s, std::forward(arg)); LogPrint (s, std::forward(args)...); } +#endif /** * @brief Create log message and send it to queue @@ -184,7 +186,11 @@ void LogPrint (LogLevel level, TArgs&&... args) noexcept // fold message to single string std::stringstream ss(""); +#if (__cplusplus >= 201703L) // C++ 17 or higher + (LogPrint (ss, std::forward(args)), ...); +#else LogPrint (ss, std::forward(args)...); +#endif auto msg = std::make_shared(level, std::time(nullptr), ss.str()); msg->tid = std::this_thread::get_id(); From e0cb26bd9e247c982219e639bc9b05cfacf46f11 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 28 Feb 2020 14:15:41 -0500 Subject: [PATCH 07/44] fixed fallthough warning for C++17 --- libi2pd/Garlic.cpp | 2 +- libi2pd/Identity.cpp | 2 +- libi2pd/RouterContext.cpp | 2 +- libi2pd/Streaming.cpp | 2 +- libi2pd_client/SOCKS.cpp | 1 + 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index c7d0e21d..597602fb 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -911,7 +911,7 @@ namespace garlic case eGarlicDeliveryTypeDestination: LogPrint (eLogDebug, "Garlic: type destination"); buf += 32; // TODO: check destination - // no break here + [[fallthrough]]; // no break here case eGarlicDeliveryTypeLocal: { LogPrint (eLogDebug, "Garlic: type local"); diff --git a/libi2pd/Identity.cpp b/libi2pd/Identity.cpp index de94732f..5116ecd8 100644 --- a/libi2pd/Identity.cpp +++ b/libi2pd/Identity.cpp @@ -723,7 +723,7 @@ namespace data case SIGNING_KEY_TYPE_RSA_SHA384_3072: case SIGNING_KEY_TYPE_RSA_SHA512_4096: LogPrint (eLogWarning, "Identity: RSA signature type is not supported. Creating EdDSA"); - // no break here + [[fallthrough]]; // no break here case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519: i2p::crypto::CreateEDDSA25519RandomKeys (priv, pub); break; diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 2c07c21b..c282f095 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -338,7 +338,7 @@ namespace i2p { case low : /* not set */; break; case extra : caps |= i2p::data::RouterInfo::eExtraBandwidth; break; // 'P' - case unlim : caps |= i2p::data::RouterInfo::eExtraBandwidth; // no break here, extra + high means 'X' + case unlim : caps |= i2p::data::RouterInfo::eExtraBandwidth; [[fallthrough]]; // no break here, extra + high means 'X' case high : caps |= i2p::data::RouterInfo::eHighBandwidth; break; } m_RouterInfo.SetCaps (caps); diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index d666d786..e486fa79 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -847,7 +847,7 @@ namespace stream break; case 2: m_RTO = INITIAL_RTO; // drop RTO to initial upon tunnels pair change first time - // no break here + [[fallthrough]]; // no break here case 4: if (m_RoutingSession) m_RoutingSession->SetSharedRoutingPath (nullptr); UpdateCurrentRemoteLease (); // pick another lease diff --git a/libi2pd_client/SOCKS.cpp b/libi2pd_client/SOCKS.cpp index 8a67901c..c01aa212 100644 --- a/libi2pd_client/SOCKS.cpp +++ b/libi2pd_client/SOCKS.cpp @@ -433,6 +433,7 @@ namespace proxy break; case CMD_UDP: if (m_socksv == SOCKS5) break; + [[fallthrough]]; default: LogPrint(eLogError, "SOCKS: invalid command: ", ((int)*sock_buff)); SocksRequestFailed(SOCKS5_GEN_FAIL); From ed574f9d792dd0d390d631a006b85055eea9b5bc Mon Sep 17 00:00:00 2001 From: R4SAS Date: Fri, 28 Feb 2020 23:05:26 +0300 Subject: [PATCH 08/44] use C++17 if available when configuring with cmake --- build/CMakeLists.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 2577fb1b..3a723c45 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -184,16 +184,16 @@ else() set( CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "-Wl,--gc-sections" ) # -flto is added from above endif () -# check for c++11 support +# check for c++17 & c++11 support include(CheckCXXCompilerFlag) +CHECK_CXX_COMPILER_FLAG("-std=c++17" CXX17_SUPPORTED) CHECK_CXX_COMPILER_FLAG("-std=c++11" CXX11_SUPPORTED) -CHECK_CXX_COMPILER_FLAG("-std=c++0x" CXX0X_SUPPORTED) -if (CXX11_SUPPORTED) +if (CXX17_SUPPORTED) + set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17" ) +elseif (CXX11_SUPPORTED) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11" ) -elseif (CXX0X_SUPPORTED) # gcc 4.6 - set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x" ) -elseif (NOT MSVC) - message(SEND_ERROR "C++11 standard not seems to be supported by compiler. Too old version?") +else + message(SEND_ERROR "C++17 nor C++11 standard not seems to be supported by compiler. Too old version?") endif () if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") From 2ac2da41cfa673b0ec001b700e310d63332fcc39 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Fri, 28 Feb 2020 23:28:41 +0300 Subject: [PATCH 09/44] cmake: fix else statement --- build/CMakeLists.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 3a723c45..f5c1280e 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -188,13 +188,13 @@ endif () include(CheckCXXCompilerFlag) CHECK_CXX_COMPILER_FLAG("-std=c++17" CXX17_SUPPORTED) CHECK_CXX_COMPILER_FLAG("-std=c++11" CXX11_SUPPORTED) -if (CXX17_SUPPORTED) - set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17" ) -elseif (CXX11_SUPPORTED) - set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11" ) -else +if(CXX17_SUPPORTED) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") +elseif(CXX11_SUPPORTED) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") +else() message(SEND_ERROR "C++17 nor C++11 standard not seems to be supported by compiler. Too old version?") -endif () +endif() if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pipe") From fe1724e7e694ab3c05492cb2dbfdae454fcf18a0 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Fri, 28 Feb 2020 23:41:42 +0300 Subject: [PATCH 10/44] switch travis-ci to xenial --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c55f1885..af47f458 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ cache: os: - linux #- osx -dist: trusty +dist: xenial sudo: required compiler: - g++ From 2ffe62ba41bffb03e2042bf4d7cc7188a2a2393d Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 29 Feb 2020 09:21:50 -0500 Subject: [PATCH 11/44] [[fallthrough]] if C++17 only --- libi2pd/Garlic.cpp | 5 ++++- libi2pd/Identity.cpp | 5 ++++- libi2pd/RouterContext.cpp | 6 +++++- libi2pd/Streaming.cpp | 5 ++++- libi2pd_client/SOCKS.cpp | 2 ++ 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 597602fb..45c97172 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -911,7 +911,10 @@ namespace garlic case eGarlicDeliveryTypeDestination: LogPrint (eLogDebug, "Garlic: type destination"); buf += 32; // TODO: check destination - [[fallthrough]]; // no break here +#if (__cplusplus >= 201703L) // C++ 17 or higher + [[fallthrough]]; +#endif + // no break here case eGarlicDeliveryTypeLocal: { LogPrint (eLogDebug, "Garlic: type local"); diff --git a/libi2pd/Identity.cpp b/libi2pd/Identity.cpp index 5116ecd8..3f9633ed 100644 --- a/libi2pd/Identity.cpp +++ b/libi2pd/Identity.cpp @@ -723,7 +723,10 @@ namespace data case SIGNING_KEY_TYPE_RSA_SHA384_3072: case SIGNING_KEY_TYPE_RSA_SHA512_4096: LogPrint (eLogWarning, "Identity: RSA signature type is not supported. Creating EdDSA"); - [[fallthrough]]; // no break here +#if (__cplusplus >= 201703L) // C++ 17 or higher + [[fallthrough]]; +#endif + // no break here case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519: i2p::crypto::CreateEDDSA25519RandomKeys (priv, pub); break; diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index c282f095..6c63ef79 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -338,7 +338,11 @@ namespace i2p { case low : /* not set */; break; case extra : caps |= i2p::data::RouterInfo::eExtraBandwidth; break; // 'P' - case unlim : caps |= i2p::data::RouterInfo::eExtraBandwidth; [[fallthrough]]; // no break here, extra + high means 'X' + case unlim : caps |= i2p::data::RouterInfo::eExtraBandwidth; + #if (__cplusplus >= 201703L) // C++ 17 or higher + [[fallthrough]]; + #endif + // no break here, extra + high means 'X' case high : caps |= i2p::data::RouterInfo::eHighBandwidth; break; } m_RouterInfo.SetCaps (caps); diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index e486fa79..b5f935fe 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -847,7 +847,10 @@ namespace stream break; case 2: m_RTO = INITIAL_RTO; // drop RTO to initial upon tunnels pair change first time - [[fallthrough]]; // no break here +#if (__cplusplus >= 201703L) // C++ 17 or higher + [[fallthrough]]; +#endif + // no break here case 4: if (m_RoutingSession) m_RoutingSession->SetSharedRoutingPath (nullptr); UpdateCurrentRemoteLease (); // pick another lease diff --git a/libi2pd_client/SOCKS.cpp b/libi2pd_client/SOCKS.cpp index c01aa212..8742d4c5 100644 --- a/libi2pd_client/SOCKS.cpp +++ b/libi2pd_client/SOCKS.cpp @@ -433,7 +433,9 @@ namespace proxy break; case CMD_UDP: if (m_socksv == SOCKS5) break; +#if (__cplusplus >= 201703L) // C++ 17 or higher [[fallthrough]]; +#endif default: LogPrint(eLogError, "SOCKS: invalid command: ", ((int)*sock_buff)); SocksRequestFailed(SOCKS5_GEN_FAIL); From 97f0347715920c2e628c7ac40c9a065cfe94b5ef Mon Sep 17 00:00:00 2001 From: r4sas Date: Sat, 29 Feb 2020 23:08:43 +0000 Subject: [PATCH 12/44] Update android stuff: * switch to c++17 * use boost 1.72.0 * disable minify in release * enable apk splitting (separate apk for every ABI) * add version to output apk name Signed-off-by: r4sas --- android/build.gradle | 21 ++++++++++++++++++--- android/jni/Android.mk | 16 ++++++++-------- android/jni/Application.mk | 6 +++--- android_binary_only/jni/Android.mk | 16 ++++++++-------- android_binary_only/jni/Application.mk | 6 +++--- 5 files changed, 40 insertions(+), 25 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 844615f8..6fcb4521 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -32,6 +32,7 @@ android { minSdkVersion 14 versionCode 2300 versionName "2.30.0" + setProperty("archivesBaseName", archivesBaseName + "-" + versionName) ndk { abiFilters 'armeabi-v7a' abiFilters 'x86' @@ -56,9 +57,10 @@ android { splits { abi { // change that to true if you need splitted apk - enable false + enable true reset() - include "armeabi-v7a", "arm64-v8a", "x86", "x86_64" + //include "armeabi-v7a", "arm64-v8a", "x86", "x86_64" + include "armeabi-v7a", "x86" universalApk true } } @@ -72,7 +74,7 @@ android { } buildTypes { release { - minifyEnabled true + minifyEnabled false signingConfig signingConfigs.orignal proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt' } @@ -87,3 +89,16 @@ android { targetCompatibility = '1.8' } } + +ext.abiCodes = ['armeabi-v7a':1, 'x86':2, 'arm64-v8a':3, 'x86_64':4] +import com.android.build.OutputFile + +android.applicationVariants.all { variant -> + variant.outputs.each { output -> + def baseAbiVersionCode = project.ext.abiCodes.get(output.getFilter(OutputFile.ABI)) + + if (baseAbiVersionCode != null) { + output.versionCodeOverride = baseAbiVersionCode + variant.versionCode + } + } +} diff --git a/android/jni/Android.mk b/android/jni/Android.mk index d44fcc5a..2376509e 100755 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -25,29 +25,29 @@ include $(BUILD_SHARED_LIBRARY) LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := boost_system -LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_68_0-clang/$(TARGET_ARCH_ABI)/lib/libboost_system.a -LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_68_0-clang/include +LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_system.a +LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include include $(PREBUILT_STATIC_LIBRARY) LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := boost_date_time -LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_68_0-clang/$(TARGET_ARCH_ABI)/lib/libboost_date_time.a -LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_68_0-clang/include +LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_date_time.a +LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include include $(PREBUILT_STATIC_LIBRARY) LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := boost_filesystem -LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_68_0-clang/$(TARGET_ARCH_ABI)/lib/libboost_filesystem.a -LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_68_0-clang/include +LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_filesystem.a +LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include include $(PREBUILT_STATIC_LIBRARY) LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := boost_program_options -LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_68_0-clang/$(TARGET_ARCH_ABI)/lib/libboost_program_options.a -LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_68_0-clang/include +LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_program_options.a +LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include include $(PREBUILT_STATIC_LIBRARY) LOCAL_PATH := $(call my-dir) diff --git a/android/jni/Application.mk b/android/jni/Application.mk index 6d51ac1a..0c291661 100755 --- a/android/jni/Application.mk +++ b/android/jni/Application.mk @@ -9,15 +9,15 @@ NDK_TOOLCHAIN_VERSION := clang #APP_STL := c++_shared APP_STL := c++_static -# Enable c++11 extensions in source code -APP_CPPFLAGS += -std=c++11 -fexceptions -frtti +# Enable c++17 extensions in source code +APP_CPPFLAGS += -std=c++17 -fexceptions -frtti APP_CPPFLAGS += -DANDROID -D__ANDROID__ -DUSE_UPNP ifeq ($(TARGET_ARCH_ABI),armeabi-v7a) APP_CPPFLAGS += -DANDROID_ARM7A endif -# git clone https://github.com/PurpleI2P/Boost-for-Android-Prebuilt.git +# git clone https://github.com/PurpleI2P/Boost-for-Android-Prebuilt.git -b boost-1_72_0 # git clone https://github.com/PurpleI2P/OpenSSL-for-Android-Prebuilt.git # git clone https://github.com/PurpleI2P/MiniUPnP-for-Android-Prebuilt.git # git clone https://github.com/PurpleI2P/android-ifaddrs.git diff --git a/android_binary_only/jni/Android.mk b/android_binary_only/jni/Android.mk index 7e73b23d..a59e32e5 100755 --- a/android_binary_only/jni/Android.mk +++ b/android_binary_only/jni/Android.mk @@ -26,29 +26,29 @@ include $(BUILD_EXECUTABLE) LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := boost_system -LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_68_0-clang/$(TARGET_ARCH_ABI)/lib/libboost_system.a -LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_68_0-clang/include +LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_system.a +LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include include $(PREBUILT_STATIC_LIBRARY) LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := boost_date_time -LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_68_0-clang/$(TARGET_ARCH_ABI)/lib/libboost_date_time.a -LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_68_0-clang/include +LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_date_time.a +LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include include $(PREBUILT_STATIC_LIBRARY) LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := boost_filesystem -LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_68_0-clang/$(TARGET_ARCH_ABI)/lib/libboost_filesystem.a -LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_68_0-clang/include +LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_filesystem.a +LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include include $(PREBUILT_STATIC_LIBRARY) LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := boost_program_options -LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_68_0-clang/$(TARGET_ARCH_ABI)/lib/libboost_program_options.a -LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_68_0-clang/include +LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_program_options.a +LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include include $(PREBUILT_STATIC_LIBRARY) LOCAL_PATH := $(call my-dir) diff --git a/android_binary_only/jni/Application.mk b/android_binary_only/jni/Application.mk index 655bf430..bb4afac3 100755 --- a/android_binary_only/jni/Application.mk +++ b/android_binary_only/jni/Application.mk @@ -9,8 +9,8 @@ APP_PLATFORM := android-14 NDK_TOOLCHAIN_VERSION := clang APP_STL := c++_static -# Enable c++11 extensions in source code -APP_CPPFLAGS += -std=c++11 -fvisibility=default -fPIE +# Enable c++17 extensions in source code +APP_CPPFLAGS += -std=c++17 -fvisibility=default -fPIE APP_CPPFLAGS += -DANDROID_BINARY -DANDROID -D__ANDROID__ -DUSE_UPNP APP_LDFLAGS += -rdynamic -fPIE -pie @@ -21,7 +21,7 @@ endif # Forcing debug optimization. Use `ndk-build NDK_DEBUG=1` instead. #APP_OPTIM := debug -# git clone https://github.com/PurpleI2P/Boost-for-Android-Prebuilt.git +# git clone https://github.com/PurpleI2P/Boost-for-Android-Prebuilt.git -b boost-1_72_0 # git clone https://github.com/PurpleI2P/OpenSSL-for-Android-Prebuilt.git # git clone https://github.com/PurpleI2P/MiniUPnP-for-Android-Prebuilt.git # git clone https://github.com/PurpleI2P/android-ifaddrs.git From 4f0da87a7a11e399aedb6fedb67c037de5a6aaa0 Mon Sep 17 00:00:00 2001 From: unlnown542a Date: Sun, 1 Mar 2020 14:35:24 +0000 Subject: [PATCH 13/44] add ntcp2proxy support --- libi2pd/Config.cpp | 7 +- libi2pd/NTCP2.cpp | 597 +++++++++++++++++++++++++++++------------ libi2pd/NTCP2.h | 67 +++-- libi2pd/Transports.cpp | 80 ++++-- 4 files changed, 533 insertions(+), 218 deletions(-) diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index b0f7572d..4050f769 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -61,6 +61,7 @@ namespace config { ("ntcp", value()->default_value(false), "Enable NTCP transport (default: disabled)") ("ssu", value()->default_value(true), "Enable SSU transport (default: enabled)") ("ntcpproxy", value()->default_value(""), "Proxy URL for NTCP transport") + ("ntcp2proxy", value()->default_value(""), "Proxy URL for NTCP2 transport") #ifdef _WIN32 ("svcctl", value()->default_value(""), "Windows service management ('install' or 'remove')") ("insomnia", bool_switch()->default_value(false), "Prevent system from sleeping (default: disabled)") @@ -305,16 +306,16 @@ namespace config { std::cout << "i2pd version " << I2PD_VERSION << " (" << I2P_VERSION << ")" << std::endl; std::cout << m_OptionsDesc; exit(EXIT_SUCCESS); - } + } else if (m_Options.count("version")) { std::cout << "i2pd version " << I2PD_VERSION << " (" << I2P_VERSION << ")" << std::endl; - std::cout << "Boost version " + std::cout << "Boost version " << BOOST_VERSION / 100000 << "." // maj. version << BOOST_VERSION / 100 % 1000 << "." // min. version << BOOST_VERSION % 100 // patch version << std::endl; -#if defined(OPENSSL_VERSION_TEXT) +#if defined(OPENSSL_VERSION_TEXT) std::cout << OPENSSL_VERSION_TEXT << std::endl; #endif #if defined(LIBRESSL_VERSION_TEXT) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 034f7e21..a3c42790 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -20,19 +20,21 @@ #include "Transports.h" #include "NetDb.hpp" #include "NTCP2.h" +#include "HTTP.h" +#include "util.h" namespace i2p { namespace transport { NTCP2Establisher::NTCP2Establisher (): - m_SessionRequestBuffer (nullptr), m_SessionCreatedBuffer (nullptr), m_SessionConfirmedBuffer (nullptr) - { + m_SessionRequestBuffer (nullptr), m_SessionCreatedBuffer (nullptr), m_SessionConfirmedBuffer (nullptr) + { } - NTCP2Establisher::~NTCP2Establisher () - { - delete[] m_SessionRequestBuffer; + NTCP2Establisher::~NTCP2Establisher () + { + delete[] m_SessionRequestBuffer; delete[] m_SessionCreatedBuffer; delete[] m_SessionConfirmedBuffer; } @@ -54,22 +56,22 @@ namespace transport void NTCP2Establisher::KeyDerivationFunction1 (const uint8_t * pub, i2p::crypto::X25519Keys& priv, const uint8_t * rs, const uint8_t * epub) { - static const uint8_t protocolNameHash[] = - { - 0x72, 0xe8, 0x42, 0xc5, 0x45, 0xe1, 0x80, 0x80, 0xd3, 0x9c, 0x44, 0x93, 0xbb, 0x91, 0xd7, 0xed, - 0xf2, 0x28, 0x98, 0x17, 0x71, 0x21, 0x8c, 0x1f, 0x62, 0x4e, 0x20, 0x6f, 0x28, 0xd3, 0x2f, 0x71 + static const uint8_t protocolNameHash[] = + { + 0x72, 0xe8, 0x42, 0xc5, 0x45, 0xe1, 0x80, 0x80, 0xd3, 0x9c, 0x44, 0x93, 0xbb, 0x91, 0xd7, 0xed, + 0xf2, 0x28, 0x98, 0x17, 0x71, 0x21, 0x8c, 0x1f, 0x62, 0x4e, 0x20, 0x6f, 0x28, 0xd3, 0x2f, 0x71 }; // SHA256 ("Noise_XKaesobfse+hs2+hs3_25519_ChaChaPoly_SHA256") - static const uint8_t hh[32] = - { - 0x49, 0xff, 0x48, 0x3f, 0xc4, 0x04, 0xb9, 0xb2, 0x6b, 0x11, 0x94, 0x36, 0x72, 0xff, 0x05, 0xb5, - 0x61, 0x27, 0x03, 0x31, 0xba, 0x89, 0xb8, 0xfc, 0x33, 0x15, 0x93, 0x87, 0x57, 0xdd, 0x3d, 0x1e + static const uint8_t hh[32] = + { + 0x49, 0xff, 0x48, 0x3f, 0xc4, 0x04, 0xb9, 0xb2, 0x6b, 0x11, 0x94, 0x36, 0x72, 0xff, 0x05, 0xb5, + 0x61, 0x27, 0x03, 0x31, 0xba, 0x89, 0xb8, 0xfc, 0x33, 0x15, 0x93, 0x87, 0x57, 0xdd, 0x3d, 0x1e }; // SHA256 (protocolNameHash) - memcpy (m_CK, protocolNameHash, 32); + memcpy (m_CK, protocolNameHash, 32); // h = SHA256(hh || rs) SHA256_CTX ctx; SHA256_Init (&ctx); - SHA256_Update (&ctx, hh, 32); - SHA256_Update (&ctx, rs, 32); + SHA256_Update (&ctx, hh, 32); + SHA256_Update (&ctx, rs, 32); SHA256_Final (m_H, &ctx); // h = SHA256(h || epub) MixHash (epub, 32); @@ -83,25 +85,25 @@ namespace transport { KeyDerivationFunction1 (m_RemoteStaticKey, m_EphemeralKeys, m_RemoteStaticKey, GetPub ()); } - + void NTCP2Establisher::KDF1Bob () { - KeyDerivationFunction1 (GetRemotePub (), i2p::context.GetStaticKeys (), i2p::context.GetNTCP2StaticPublicKey (), GetRemotePub ()); + KeyDerivationFunction1 (GetRemotePub (), i2p::context.GetStaticKeys (), i2p::context.GetNTCP2StaticPublicKey (), GetRemotePub ()); } void NTCP2Establisher::KeyDerivationFunction2 (const uint8_t * sessionRequest, size_t sessionRequestLen, const uint8_t * epub) - { - MixHash (sessionRequest + 32, 32); // encrypted payload + { + MixHash (sessionRequest + 32, 32); // encrypted payload int paddingLength = sessionRequestLen - 64; if (paddingLength > 0) MixHash (sessionRequest + 64, paddingLength); - MixHash (epub, 32); + MixHash (epub, 32); // x25519 between remote pub and ephemaral priv uint8_t inputKeyMaterial[32]; m_EphemeralKeys.Agree (GetRemotePub (), inputKeyMaterial); - + MixKey (inputKeyMaterial); } @@ -109,7 +111,7 @@ namespace transport { KeyDerivationFunction2 (m_SessionRequestBuffer, m_SessionRequestBufferLen, GetRemotePub ()); } - + void NTCP2Establisher::KDF2Bob () { KeyDerivationFunction2 (m_SessionRequestBuffer, m_SessionRequestBufferLen, GetPub ()); @@ -118,14 +120,14 @@ namespace transport void NTCP2Establisher::KDF3Alice () { uint8_t inputKeyMaterial[32]; - i2p::context.GetStaticKeys ().Agree (GetRemotePub (), inputKeyMaterial); + i2p::context.GetStaticKeys ().Agree (GetRemotePub (), inputKeyMaterial); MixKey (inputKeyMaterial); } void NTCP2Establisher::KDF3Bob () { uint8_t inputKeyMaterial[32]; - m_EphemeralKeys.Agree (m_RemoteStaticKey, inputKeyMaterial); + m_EphemeralKeys.Agree (m_RemoteStaticKey, inputKeyMaterial); MixKey (inputKeyMaterial); } @@ -146,30 +148,30 @@ namespace transport encryption.SetKey (m_RemoteIdentHash); encryption.SetIV (m_IV); encryption.Encrypt (GetPub (), 32, m_SessionRequestBuffer); // X - encryption.GetIV (m_IV); // save IV for SessionCreated + encryption.GetIV (m_IV); // save IV for SessionCreated // encryption key for next block KDF1Alice (); // fill options uint8_t options[32]; // actual options size is 16 bytes memset (options, 0, 16); options[0] = i2p::context.GetNetID (); // network ID - options[1] = 2; // ver + options[1] = 2; // ver htobe16buf (options + 2, paddingLength); // padLen - // m3p2Len + // m3p2Len auto bufLen = i2p::context.GetRouterInfo ().GetBufferLen (); - m3p2Len = bufLen + 4 + 16; // (RI header + RI + MAC for now) TODO: implement options + m3p2Len = bufLen + 4 + 16; // (RI header + RI + MAC for now) TODO: implement options htobe16buf (options + 4, m3p2Len); - // fill m3p2 payload (RouterInfo block) + // fill m3p2 payload (RouterInfo block) m_SessionConfirmedBuffer = new uint8_t[m3p2Len + 48]; // m3p1 is 48 bytes uint8_t * m3p2 = m_SessionConfirmedBuffer + 48; m3p2[0] = eNTCP2BlkRouterInfo; // block htobe16buf (m3p2 + 1, bufLen + 1); // flag + RI - m3p2[3] = 0; // flag + m3p2[3] = 0; // flag memcpy (m3p2 + 4, i2p::context.GetRouterInfo ().GetBuffer (), bufLen); // TODO: own RI should be protected by mutex // 2 bytes reserved htobe32buf (options + 8, i2p::util::GetSecondsSinceEpoch ()); // tsA // 4 bytes reserved - // sign and encrypt options, use m_H as AD + // sign and encrypt options, use m_H as AD uint8_t nonce[12]; memset (nonce, 0, 12); // set nonce to zero i2p::crypto::AEADChaCha20Poly1305 (options, 16, GetH (), 32, GetK (), nonce, m_SessionRequestBuffer + 32, 32, true); // encrypt @@ -179,7 +181,7 @@ namespace transport { auto paddingLen = rand () % (287 - 64); m_SessionCreatedBufferLen = paddingLen + 64; - m_SessionCreatedBuffer = new uint8_t[m_SessionCreatedBufferLen]; + m_SessionCreatedBuffer = new uint8_t[m_SessionCreatedBufferLen]; RAND_bytes (m_SessionCreatedBuffer + 64, paddingLen); // encrypt Y i2p::crypto::CBCEncryption encryption; @@ -187,12 +189,12 @@ namespace transport encryption.SetIV (m_IV); encryption.Encrypt (GetPub (), 32, m_SessionCreatedBuffer); // Y // encryption key for next block (m_K) - KDF2Bob (); + KDF2Bob (); uint8_t options[16]; memset (options, 0, 16); htobe16buf (options + 2, paddingLen); // padLen htobe32buf (options + 8, i2p::util::GetSecondsSinceEpoch ()); // tsB - // sign and encrypt options, use m_H as AD + // sign and encrypt options, use m_H as AD uint8_t nonce[12]; memset (nonce, 0, 12); // set nonce to zero i2p::crypto::AEADChaCha20Poly1305 (options, 16, GetH (), 32, GetK (), nonce, m_SessionCreatedBuffer + 32, 32, true); // encrypt @@ -205,9 +207,9 @@ namespace transport MixHash (m_SessionCreatedBuffer + 32, 32); // encrypted payload int paddingLength = m_SessionCreatedBufferLen - 64; if (paddingLength > 0) - MixHash (m_SessionCreatedBuffer + 64, paddingLength); + MixHash (m_SessionCreatedBuffer + 64, paddingLength); - // part1 48 bytes + // part1 48 bytes i2p::crypto::AEADChaCha20Poly1305 (i2p::context.GetNTCP2StaticPublicKey (), 32, GetH (), 32, GetK (), nonce, m_SessionConfirmedBuffer, 48, true); // encrypt } @@ -215,14 +217,14 @@ namespace transport { // part 2 // update AD again - MixHash (m_SessionConfirmedBuffer, 48); + MixHash (m_SessionConfirmedBuffer, 48); // encrypt m3p2, it must be filled in SessionRequest - KDF3Alice (); + KDF3Alice (); uint8_t * m3p2 = m_SessionConfirmedBuffer + 48; - i2p::crypto::AEADChaCha20Poly1305 (m3p2, m3p2Len - 16, GetH (), 32, GetK (), nonce, m3p2, m3p2Len, true); // encrypt + i2p::crypto::AEADChaCha20Poly1305 (m3p2, m3p2Len - 16, GetH (), 32, GetK (), nonce, m3p2, m3p2Len, true); // encrypt // update h again MixHash (m3p2, m3p2Len); //h = SHA256(h || ciphertext) - } + } bool NTCP2Establisher::ProcessSessionRequestMessage (uint16_t& paddingLen) { @@ -231,7 +233,7 @@ namespace transport decryption.SetKey (i2p::context.GetIdentHash ()); decryption.SetIV (i2p::context.GetNTCP2IV ()); decryption.Decrypt (m_SessionRequestBuffer, 32, GetRemotePub ()); - decryption.GetIV (m_IV); // save IV for SessionCreated + decryption.GetIV (m_IV); // save IV for SessionCreated // decryption key for next block KDF1Bob (); // verify MAC and decrypt options block (32 bytes), use m_H as AD @@ -245,7 +247,7 @@ namespace transport LogPrint (eLogWarning, "NTCP2: SessionRequest networkID ", (int)options[0], " mismatch. Expected ", i2p::context.GetNetID ()); return false; } - if (options[1] == 2) // ver is always 2 + if (options[1] == 2) // ver is always 2 { paddingLen = bufbe16toh (options + 2); m_SessionRequestBufferLen = paddingLen + 64; @@ -253,11 +255,11 @@ namespace transport if (m3p2Len < 16) { LogPrint (eLogWarning, "NTCP2: SessionRequest m3p2len=", m3p2Len, " is too short"); - return false; - } + return false; + } // check timestamp auto ts = i2p::util::GetSecondsSinceEpoch (); - uint32_t tsA = bufbe32toh (options + 8); + uint32_t tsA = bufbe32toh (options + 8); if (tsA < ts - NTCP2_CLOCK_SKEW || tsA > ts + NTCP2_CLOCK_SKEW) { LogPrint (eLogWarning, "NTCP2: SessionRequest time difference ", (int)(ts - tsA), " exceeds clock skew"); @@ -274,8 +276,8 @@ namespace transport { LogPrint (eLogWarning, "NTCP2: SessionRequest AEAD verification failed "); return false; - } - return true; + } + return true; } bool NTCP2Establisher::ProcessSessionCreatedMessage (uint16_t& paddingLen) @@ -294,11 +296,11 @@ namespace transport memset (nonce, 0, 12); // set nonce to zero if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionCreatedBuffer + 32, 16, GetH (), 32, GetK (), nonce, payload, 16, false)) // decrypt { - // options + // options paddingLen = bufbe16toh(payload + 2); // check timestamp auto ts = i2p::util::GetSecondsSinceEpoch (); - uint32_t tsB = bufbe32toh (payload + 8); + uint32_t tsB = bufbe32toh (payload + 8); if (tsB < ts - NTCP2_CLOCK_SKEW || tsB > ts + NTCP2_CLOCK_SKEW) { LogPrint (eLogWarning, "NTCP2: SessionCreated time difference ", (int)(ts - tsB), " exceeds clock skew"); @@ -306,10 +308,10 @@ namespace transport } } else - { + { LogPrint (eLogWarning, "NTCP2: SessionCreated AEAD verification failed "); return false; - } + } return true; } @@ -320,7 +322,7 @@ namespace transport int paddingLength = m_SessionCreatedBufferLen - 64; if (paddingLength > 0) MixHash (m_SessionCreatedBuffer + 64, paddingLength); - + if (!i2p::crypto::AEADChaCha20Poly1305 (m_SessionConfirmedBuffer, 32, GetH (), 32, GetK (), nonce, m_RemoteStaticKey, 32, false)) // decrypt S { LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part1 AEAD verification failed "); @@ -332,9 +334,9 @@ namespace transport bool NTCP2Establisher::ProcessSessionConfirmedMessagePart2 (const uint8_t * nonce, uint8_t * m3p2Buf) { // update AD again - MixHash (m_SessionConfirmedBuffer, 48); + MixHash (m_SessionConfirmedBuffer, 48); - KDF3Bob (); + KDF3Bob (); if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionConfirmedBuffer + 48, m3p2Len - 16, GetH (), 32, GetK (), nonce, m3p2Buf, m3p2Len - 16, false)) // decrypt { // caclulate new h again for KDF data @@ -350,8 +352,8 @@ namespace transport } NTCP2Session::NTCP2Session (NTCP2Server& server, std::shared_ptr in_RemoteRouter): - TransportSession (in_RemoteRouter, NTCP2_ESTABLISH_TIMEOUT), - m_Server (server), m_Socket (m_Server.GetService ()), + TransportSession (in_RemoteRouter, NTCP2_ESTABLISH_TIMEOUT), + m_Server (server), m_Socket (m_Server.GetService ()), m_IsEstablished (false), m_IsTerminated (false), m_Establisher (new NTCP2Establisher), m_SendSipKey (nullptr), m_ReceiveSipKey (nullptr), @@ -371,10 +373,82 @@ namespace transport memcpy (m_Establisher->m_IV, addr->ntcp2->iv, 16); } else - LogPrint (eLogWarning, "NTCP2: Missing NTCP2 parameters"); + LogPrint (eLogWarning, "NTCP2: Missing NTCP2 parameters"); } } + void NTCP2Server::AfterSocksHandshake(std::shared_ptr conn, std::shared_ptr timer, const std::string & host, uint16_t port, RemoteAddressType addrtype) + { + + // build request + size_t sz = 0; + uint8_t buff[256]; + uint8_t readbuff[256]; + buff[0] = 0x05; + buff[1] = 0x01; + buff[2] = 0x00; + + if(addrtype == eIP4Address) + { + buff[3] = 0x01; + auto addr = boost::asio::ip::address::from_string(host).to_v4(); + auto addrbytes = addr.to_bytes(); + auto addrsize = addrbytes.size(); + memcpy(buff+4, addrbytes.data(), addrsize); + } + else if (addrtype == eIP6Address) + { + buff[3] = 0x04; + auto addr = boost::asio::ip::address::from_string(host).to_v6(); + auto addrbytes = addr.to_bytes(); + auto addrsize = addrbytes.size(); + memcpy(buff+4, addrbytes.data(), addrsize); + } + else if (addrtype == eHostname) + { + buff[3] = 0x03; + size_t addrsize = host.size(); + sz = addrsize + 1 + 4; + if (2 + sz > sizeof(buff)) + { + // too big + return; + } + buff[4] = (uint8_t) addrsize; + memcpy(buff+5, host.c_str(), addrsize); + } + htobe16buf(buff+sz, port); + sz += 2; + boost::asio::async_write(conn->GetSocket(), boost::asio::buffer(buff, sz), boost::asio::transfer_all(), [=](const boost::system::error_code & ec, std::size_t written) { + if(ec) + { + LogPrint(eLogError, "NTCP2: failed to write handshake to socks proxy ", ec.message()); + return; + } + }); + + boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(readbuff, 10), [=](const boost::system::error_code & e, std::size_t transferred) { + if(e) + { + LogPrint(eLogError, "NTCP2: socks proxy read error ", e.message()); + } + else if(transferred == sz) + { + if( readbuff[1] == 0x00) + { + timer->cancel(); + conn->ClientLogin(); + return; + } + } + if(!e) + i2p::data::netdb.SetUnreachable (conn->GetRemoteIdentity ()->GetIdentHash (), true); + timer->cancel(); + conn->Terminate(); + }); + } + + NTCP2Session::~NTCP2Session () { delete[] m_NextReceivedBuffer; @@ -425,8 +499,8 @@ namespace transport void NTCP2Session::CreateNonce (uint64_t seqn, uint8_t * nonce) { - memset (nonce, 0, 4); - htole64buf (nonce + 4, seqn); + memset (nonce, 0, 4); + htole64buf (nonce + 4, seqn); } @@ -442,7 +516,7 @@ namespace transport memcpy (h + 32, "siphash", 7); i2p::crypto::HKDF (master, h, 39, "", master, 32); // sip_master = HKDF(ask_master, h || "siphash") i2p::crypto::HKDF (master, nullptr, 0, "", k); // sipkeys_ab, sipkeys_ba = HKDF(sip_master, zerolen) - memcpy (m_Sipkeysab, k, 32); memcpy (m_Sipkeysba, k + 32, 32); + memcpy (m_Sipkeysab, k, 32); memcpy (m_Sipkeysba, k + 32, 32); } @@ -451,8 +525,8 @@ namespace transport m_Establisher->CreateSessionRequestMessage (); // send message boost::asio::async_write (m_Socket, boost::asio::buffer (m_Establisher->m_SessionRequestBuffer, m_Establisher->m_SessionRequestBufferLen), boost::asio::transfer_all (), - std::bind(&NTCP2Session::HandleSessionRequestSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); - } + std::bind(&NTCP2Session::HandleSessionRequestSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); + } void NTCP2Session::HandleSessionRequestSent (const boost::system::error_code& ecode, std::size_t bytes_transferred) { @@ -500,7 +574,7 @@ namespace transport } else SendSessionCreated (); - } + } else Terminate (); } @@ -520,9 +594,9 @@ namespace transport void NTCP2Session::SendSessionCreated () { m_Establisher->CreateSessionCreatedMessage (); - // send message + // send message boost::asio::async_write (m_Socket, boost::asio::buffer (m_Establisher->m_SessionCreatedBuffer, m_Establisher->m_SessionCreatedBufferLen), boost::asio::transfer_all (), - std::bind(&NTCP2Session::HandleSessionCreatedSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); + std::bind(&NTCP2Session::HandleSessionCreatedSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); } void NTCP2Session::HandleSessionCreatedReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred) @@ -577,9 +651,9 @@ namespace transport { uint8_t nonce[12]; CreateNonce (1, nonce); // set nonce to 1 - m_Establisher->CreateSessionConfirmedMessagePart1 (nonce); + m_Establisher->CreateSessionConfirmedMessagePart1 (nonce); memset (nonce, 0, 12); // set nonce back to 0 - m_Establisher->CreateSessionConfirmedMessagePart2 (nonce); + m_Establisher->CreateSessionConfirmedMessagePart2 (nonce); // send message boost::asio::async_write (m_Socket, boost::asio::buffer (m_Establisher->m_SessionConfirmedBuffer, m_Establisher->m3p2Len + 48), boost::asio::transfer_all (), std::bind(&NTCP2Session::HandleSessionConfirmedSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); @@ -594,12 +668,12 @@ namespace transport Terminate (); } else - { + { LogPrint (eLogDebug, "NTCP2: SessionConfirmed sent"); KeyDerivationFunctionDataPhase (); // Alice data phase keys m_SendKey = m_Kab; - m_ReceiveKey = m_Kba; + m_ReceiveKey = m_Kba; SetSipKeys (m_Sipkeysab, m_Sipkeysba); memcpy (m_ReceiveIV.buf, m_Sipkeysba + 16, 8); memcpy (m_SendIV.buf, m_Sipkeysab + 16, 8); @@ -609,7 +683,7 @@ namespace transport // TODO: remove // m_SendQueue.push_back (CreateDeliveryStatusMsg (1)); // SendQueue (); - } + } } void NTCP2Session::HandleSessionCreatedSent (const boost::system::error_code& ecode, std::size_t bytes_transferred) @@ -623,7 +697,7 @@ namespace transport else { LogPrint (eLogDebug, "NTCP2: SessionCreated sent"); - m_Establisher->m_SessionConfirmedBuffer = new uint8_t[m_Establisher->m3p2Len + 48]; + m_Establisher->m_SessionConfirmedBuffer = new uint8_t[m_Establisher->m3p2Len + 48]; boost::asio::async_read (m_Socket, boost::asio::buffer(m_Establisher->m_SessionConfirmedBuffer, m_Establisher->m3p2Len + 48), boost::asio::transfer_all (), std::bind(&NTCP2Session::HandleSessionConfirmedReceived , shared_from_this (), std::placeholders::_1, std::placeholders::_2)); } @@ -652,7 +726,7 @@ namespace transport KeyDerivationFunctionDataPhase (); // Bob data phase keys m_SendKey = m_Kba; - m_ReceiveKey = m_Kab; + m_ReceiveKey = m_Kab; SetSipKeys (m_Sipkeysba, m_Sipkeysab); memcpy (m_ReceiveIV.buf, m_Sipkeysab + 16, 8); memcpy (m_SendIV.buf, m_Sipkeysba + 16, 8); @@ -660,8 +734,8 @@ namespace transport // process RI if (buf[0] != eNTCP2BlkRouterInfo) { - LogPrint (eLogWarning, "NTCP2: unexpected block ", (int)buf[0], " in SessionConfirmed"); - Terminate (); + LogPrint (eLogWarning, "NTCP2: unexpected block ", (int)buf[0], " in SessionConfirmed"); + Terminate (); return; } auto size = bufbe16toh (buf.data () + 1); @@ -675,33 +749,33 @@ namespace transport i2p::data::RouterInfo ri (buf.data () + 4, size - 1); // 1 byte block type + 2 bytes size + 1 byte flag if (ri.IsUnreachable ()) { - LogPrint (eLogError, "NTCP2: Signature verification failed in SessionConfirmed"); - SendTerminationAndTerminate (eNTCP2RouterInfoSignatureVerificationFail); + LogPrint (eLogError, "NTCP2: Signature verification failed in SessionConfirmed"); + SendTerminationAndTerminate (eNTCP2RouterInfoSignatureVerificationFail); return; } if (i2p::util::GetMillisecondsSinceEpoch () > ri.GetTimestamp () + i2p::data::NETDB_MIN_EXPIRATION_TIMEOUT*1000LL) // 90 minutes { - LogPrint (eLogError, "NTCP2: RouterInfo is too old in SessionConfirmed"); - SendTerminationAndTerminate (eNTCP2Message3Error); + LogPrint (eLogError, "NTCP2: RouterInfo is too old in SessionConfirmed"); + SendTerminationAndTerminate (eNTCP2Message3Error); return; } auto addr = ri.GetNTCP2Address (false); // any NTCP2 address if (!addr) { - LogPrint (eLogError, "NTCP2: No NTCP2 address found in SessionConfirmed"); + LogPrint (eLogError, "NTCP2: No NTCP2 address found in SessionConfirmed"); Terminate (); return; } if (memcmp (addr->ntcp2->staticKey, m_Establisher->m_RemoteStaticKey, 32)) { - LogPrint (eLogError, "NTCP2: Static key mismatch in SessionConfirmed"); - SendTerminationAndTerminate (eNTCP2IncorrectSParameter); + LogPrint (eLogError, "NTCP2: Static key mismatch in SessionConfirmed"); + SendTerminationAndTerminate (eNTCP2IncorrectSParameter); return; } i2p::data::netdb.PostI2NPMsg (CreateI2NPMessage (eI2NPDummyMsg, buf.data () + 3, size)); // TODO: should insert ri and not parse it twice // TODO: process options - - // ready to communicate + + // ready to communicate auto existing = i2p::data::netdb.FindRouter (ri.GetRouterIdentity ()->GetIdentHash ()); // check if exists already SetRemoteIdentity (existing ? existing->GetRouterIdentity () : ri.GetRouterIdentity ()); m_Server.AddNTCP2Session (shared_from_this (), true); @@ -720,13 +794,13 @@ namespace transport { #if OPENSSL_SIPHASH m_SendSipKey = EVP_PKEY_new_raw_private_key (EVP_PKEY_SIPHASH, nullptr, sendSipKey, 16); - m_SendMDCtx = EVP_MD_CTX_create (); + m_SendMDCtx = EVP_MD_CTX_create (); EVP_PKEY_CTX *ctx = nullptr; EVP_DigestSignInit (m_SendMDCtx, &ctx, nullptr, nullptr, m_SendSipKey); - EVP_PKEY_CTX_ctrl (ctx, -1, EVP_PKEY_OP_SIGNCTX, EVP_PKEY_CTRL_SET_DIGEST_SIZE, 8, nullptr); + EVP_PKEY_CTX_ctrl (ctx, -1, EVP_PKEY_OP_SIGNCTX, EVP_PKEY_CTRL_SET_DIGEST_SIZE, 8, nullptr); m_ReceiveSipKey = EVP_PKEY_new_raw_private_key (EVP_PKEY_SIPHASH, nullptr, receiveSipKey, 16); - m_ReceiveMDCtx = EVP_MD_CTX_create (); + m_ReceiveMDCtx = EVP_MD_CTX_create (); ctx = nullptr; EVP_DigestSignInit (m_ReceiveMDCtx, &ctx, NULL, NULL, m_ReceiveSipKey); EVP_PKEY_CTX_ctrl (ctx, -1, EVP_PKEY_OP_SIGNCTX, EVP_PKEY_CTRL_SET_DIGEST_SIZE, 8, nullptr); @@ -770,9 +844,9 @@ namespace transport { #if OPENSSL_SIPHASH EVP_DigestSignInit (m_ReceiveMDCtx, nullptr, nullptr, nullptr, nullptr); - EVP_DigestSignUpdate (m_ReceiveMDCtx, m_ReceiveIV.buf, 8); - size_t l = 8; - EVP_DigestSignFinal (m_ReceiveMDCtx, m_ReceiveIV.buf, &l); + EVP_DigestSignUpdate (m_ReceiveMDCtx, m_ReceiveIV.buf, 8); + size_t l = 8; + EVP_DigestSignFinal (m_ReceiveMDCtx, m_ReceiveIV.buf, &l); #else i2p::crypto::Siphash<8> (m_ReceiveIV.buf, m_ReceiveIV.buf, 8, m_ReceiveSipKey); #endif @@ -780,7 +854,7 @@ namespace transport m_NextReceivedLen = be16toh (m_NextReceivedLen) ^ le16toh (m_ReceiveIV.key); LogPrint (eLogDebug, "NTCP2: received length ", m_NextReceivedLen); if (m_NextReceivedLen >= 16) - { + { if (m_NextReceivedBuffer) delete[] m_NextReceivedBuffer; m_NextReceivedBuffer = new uint8_t[m_NextReceivedLen]; boost::system::error_code ec; @@ -798,7 +872,7 @@ namespace transport { LogPrint (eLogError, "NTCP2: received length ", m_NextReceivedLen, " is too short"); Terminate (); - } + } } } @@ -825,7 +899,7 @@ namespace transport uint8_t nonce[12]; CreateNonce (m_ReceiveSequenceNumber, nonce); m_ReceiveSequenceNumber++; if (i2p::crypto::AEADChaCha20Poly1305 (m_NextReceivedBuffer, m_NextReceivedLen-16, nullptr, 0, m_ReceiveKey, nonce, m_NextReceivedBuffer, m_NextReceivedLen, false)) - { + { LogPrint (eLogDebug, "NTCP2: received message decrypted"); ProcessNextFrame (m_NextReceivedBuffer, m_NextReceivedLen-16); delete[] m_NextReceivedBuffer; m_NextReceivedBuffer = nullptr; // we don't need received buffer anymore @@ -835,7 +909,7 @@ namespace transport { LogPrint (eLogWarning, "NTCP2: Received AEAD verification failed "); SendTerminationAndTerminate (eNTCP2DataPhaseAEADFailure); - } + } } } @@ -858,7 +932,7 @@ namespace transport { case eNTCP2BlkDateTime: LogPrint (eLogDebug, "NTCP2: datetime"); - break; + break; case eNTCP2BlkOptions: LogPrint (eLogDebug, "NTCP2: options"); break; @@ -881,11 +955,11 @@ namespace transport nextMsg->len = nextMsg->offset + size + 7; // 7 more bytes for full I2NP header memcpy (nextMsg->GetNTCP2Header (), frame + offset, size); nextMsg->FromNTCP2 (); - m_Handler.PutNextMessage (nextMsg); + m_Handler.PutNextMessage (nextMsg); break; } case eNTCP2BlkTermination: - if (size >= 9) + if (size >= 9) { LogPrint (eLogDebug, "NTCP2: termination. reason=", (int)(frame[offset + 8])); Terminate (); @@ -908,46 +982,46 @@ namespace transport { #if OPENSSL_SIPHASH EVP_DigestSignInit (m_SendMDCtx, nullptr, nullptr, nullptr, nullptr); - EVP_DigestSignUpdate (m_SendMDCtx, m_SendIV.buf, 8); - size_t l = 8; - EVP_DigestSignFinal (m_SendMDCtx, m_SendIV.buf, &l); + EVP_DigestSignUpdate (m_SendMDCtx, m_SendIV.buf, 8); + size_t l = 8; + EVP_DigestSignFinal (m_SendMDCtx, m_SendIV.buf, &l); #else i2p::crypto::Siphash<8> (m_SendIV.buf, m_SendIV.buf, 8, m_SendSipKey); #endif // length must be in BigEndian htobe16buf (lengthBuf, frameLen ^ le16toh (m_SendIV.key)); LogPrint (eLogDebug, "NTCP2: sent length ", frameLen); - } + } void NTCP2Session::SendI2NPMsgs (std::vector >& msgs) { if (msgs.empty () || IsTerminated ()) return; - + size_t totalLen = 0; std::vector > encryptBufs; - std::vector bufs; + std::vector bufs; std::shared_ptr first; uint8_t * macBuf = nullptr; - for (auto& it: msgs) - { + for (auto& it: msgs) + { it->ToNTCP2 (); auto buf = it->GetNTCP2Header (); auto len = it->GetNTCP2Length (); // block header - buf -= 3; + buf -= 3; buf[0] = eNTCP2BlkI2NPMessage; // blk htobe16buf (buf + 1, len); // size - len += 3; - totalLen += len; + len += 3; + totalLen += len; encryptBufs.push_back ( {buf, len} ); if (&it == &msgs.front ()) // first message { // allocate two bytes for length buf -= 2; len += 2; first = it; - } + } if (&it == &msgs.back () && it->len + 16 < it->maxLen) // last message - { + { // if it's long enough we add padding and MAC to it // create padding block auto paddingLen = CreatePaddingBlock (totalLen, buf + len, it->maxLen - it->len - 16); @@ -960,8 +1034,8 @@ namespace transport macBuf = buf + len; // allocate 16 bytes for MAC len += 16; - } - + } + bufs.push_back (boost::asio::buffer (buf, len)); } @@ -973,42 +1047,42 @@ namespace transport auto paddingLen = CreatePaddingBlock (totalLen, m_NextSendBuffer, 287 - 16); // and padding block to encrypt and send if (paddingLen) - encryptBufs.push_back ( {m_NextSendBuffer, paddingLen} ); + encryptBufs.push_back ( {m_NextSendBuffer, paddingLen} ); bufs.push_back (boost::asio::buffer (m_NextSendBuffer, paddingLen + 16)); macBuf = m_NextSendBuffer + paddingLen; - totalLen += paddingLen; + totalLen += paddingLen; } uint8_t nonce[12]; CreateNonce (m_SendSequenceNumber, nonce); m_SendSequenceNumber++; i2p::crypto::AEADChaCha20Poly1305Encrypt (encryptBufs, m_SendKey, nonce, macBuf); // encrypt buffers SetNextSentFrameLength (totalLen + 16, first->GetNTCP2Header () - 5); // frame length right before first block - + // send buffers - m_IsSending = true; + m_IsSending = true; boost::asio::async_write (m_Socket, bufs, boost::asio::transfer_all (), std::bind(&NTCP2Session::HandleI2NPMsgsSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2, msgs)); - } + } void NTCP2Session::HandleI2NPMsgsSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, std::vector > msgs) { HandleNextFrameSent (ecode, bytes_transferred); // msgs get destroyed here } - + void NTCP2Session::EncryptAndSendNextBuffer (size_t payloadLen) { - if (IsTerminated ()) + if (IsTerminated ()) { delete[] m_NextSendBuffer; m_NextSendBuffer = nullptr; - return; + return; } // encrypt uint8_t nonce[12]; CreateNonce (m_SendSequenceNumber, nonce); m_SendSequenceNumber++; - i2p::crypto::AEADChaCha20Poly1305Encrypt ({ {m_NextSendBuffer + 2, payloadLen} }, m_SendKey, nonce, m_NextSendBuffer + payloadLen + 2); + i2p::crypto::AEADChaCha20Poly1305Encrypt ({ {m_NextSendBuffer + 2, payloadLen} }, m_SendKey, nonce, m_NextSendBuffer + payloadLen + 2); SetNextSentFrameLength (payloadLen + 16, m_NextSendBuffer); // send - m_IsSending = true; + m_IsSending = true; boost::asio::async_write (m_Socket, boost::asio::buffer (m_NextSendBuffer, payloadLen + 16 + 2), boost::asio::transfer_all (), std::bind(&NTCP2Session::HandleNextFrameSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); } @@ -1017,23 +1091,23 @@ namespace transport { m_IsSending = false; delete[] m_NextSendBuffer; m_NextSendBuffer = nullptr; - + if (ecode) { if (ecode != boost::asio::error::operation_aborted) LogPrint (eLogWarning, "NTCP2: Couldn't send frame ", ecode.message ()); Terminate (); - } + } else - { + { m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); m_NumSentBytes += bytes_transferred; i2p::transport::transports.UpdateSentBytes (bytes_transferred); LogPrint (eLogDebug, "NTCP2: Next frame sent ", bytes_transferred); SendQueue (); - } + } } - + void NTCP2Session::SendQueue () { if (!m_SendQueue.empty ()) @@ -1043,7 +1117,7 @@ namespace transport while (!m_SendQueue.empty ()) { auto msg = m_SendQueue.front (); - size_t len = msg->GetNTCP2Length (); + size_t len = msg->GetNTCP2Length (); if (s + len + 3 <= NTCP2_UNENCRYPTED_FRAME_MAX_SIZE) // 3 bytes block header { msgs.push_back (msg); @@ -1059,12 +1133,12 @@ namespace transport break; } SendI2NPMsgs (msgs); - } + } } size_t NTCP2Session::CreatePaddingBlock (size_t msgLen, uint8_t * buf, size_t len) { - if (len < 3) return 0; + if (len < 3) return 0; len -= 3; if (msgLen < 256) msgLen = 256; // for short message padding should not be always zero size_t paddingSize = (msgLen*NTCP2_MAX_PADDING_RATIO)/100; @@ -1073,10 +1147,10 @@ namespace transport if (paddingSize) paddingSize = rand () % paddingSize; buf[0] = eNTCP2BlkPadding; // blk htobe16buf (buf + 1, paddingSize); // size - memset (buf + 3, 0, paddingSize); + memset (buf + 3, 0, paddingSize); return paddingSize + 3; - } - + } + void NTCP2Session::SendRouterInfo () { if (!IsEstablished ()) return; @@ -1094,14 +1168,158 @@ namespace transport EncryptAndSendNextBuffer (payloadLen); } + void NTCP2Server::UseProxy(ProxyType proxytype, const std::string & addr, uint16_t port) + { + m_ProxyType = proxytype; + m_ProxyAddress = addr; + m_ProxyPort = port; + } + + void NTCP2Server::HandleProxyConnect(const boost::system::error_code& ecode, std::shared_ptr conn, std::shared_ptr timer, const std::string & host, uint16_t port, RemoteAddressType addrtype) + { + if(ecode) + { + LogPrint(eLogWarning, "NTCP2: failed to connect to proxy ", ecode.message()); + timer->cancel(); + conn->Terminate(); + return; + } + if(m_ProxyType == eSocksProxy) + { + // TODO: support username/password auth etc + uint8_t buff[3] = {0x05, 0x01, 0x00}; + boost::asio::async_write(conn->GetSocket(), boost::asio::buffer(buff, 3), boost::asio::transfer_all(), [=] (const boost::system::error_code & ec, std::size_t transferred) { + (void) transferred; + if(ec) + { + LogPrint(eLogWarning, "NTCP2: socks5 write error ", ec.message()); + } + }); + uint8_t readbuff[2]; + boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(readbuff, 2), [=](const boost::system::error_code & ec, std::size_t transferred) + { + LogPrint(eLogError, "NTCP2: ", transferred); + if(ec) + { + LogPrint(eLogError, "NTCP2: socks5 read error ", ec.message()); + timer->cancel(); + conn->Terminate(); + return; + } + else if(transferred == 2) + { + if(readbuff[1] == 0xba) + { + AfterSocksHandshake(conn, timer, host, port, addrtype); + return; + } + else if (readbuff[1] == 0xff) + { + LogPrint(eLogError, "NTCP2: socks5 proxy rejected authentication"); + timer->cancel(); + conn->Terminate(); + return; + } + LogPrint(eLogError, "NTCP2:", readbuff[1]); + } + LogPrint(eLogError, "NTCP2: socks5 server gave invalid response"); + timer->cancel(); + conn->Terminate(); + }); + } + else if(m_ProxyType == eHTTPProxy) + { + i2p::http::HTTPReq req; + req.method = "CONNECT"; + req.version ="HTTP/1.1"; + if(addrtype == eIP6Address) + req.uri = "[" + host + "]:" + std::to_string(port); + else + req.uri = host + ":" + std::to_string(port); + + boost::asio::streambuf writebuff; + std::ostream out(&writebuff); + out << req.to_string(); + + boost::asio::async_write(conn->GetSocket(), writebuff.data(), boost::asio::transfer_all(), [=](const boost::system::error_code & ec, std::size_t transferred) { + (void) transferred; + if(ec) + LogPrint(eLogError, "NTCP2: http proxy write error ", ec.message()); + }); + + boost::asio::streambuf * readbuff = new boost::asio::streambuf; + boost::asio::async_read_until(conn->GetSocket(), *readbuff, "\r\n\r\n", [=] (const boost::system::error_code & ec, std::size_t transferred) { + if(ec) + { + LogPrint(eLogError, "NTCP2: http proxy read error ", ec.message()); + timer->cancel(); + conn->Terminate(); + } + else + { + readbuff->commit(transferred); + i2p::http::HTTPRes res; + if(res.parse(boost::asio::buffer_cast(readbuff->data()), readbuff->size()) > 0) + { + if(res.code == 200) + { + timer->cancel(); + conn->ClientLogin(); + delete readbuff; + return; + } + else + { + LogPrint(eLogError, "NTCP2: http proxy rejected request ", res.code); + } + } + else + LogPrint(eLogError, "NTCP2: http proxy gave malformed response"); + timer->cancel(); + conn->Terminate(); + delete readbuff; + } + }); + } + else + LogPrint(eLogError, "NTCP2: unknown proxy type, invalid state"); + } + + void NTCP2Server::ConnectWithProxy (const std::string& host, uint16_t port, RemoteAddressType addrtype, std::shared_ptr conn) + { + if(m_ProxyEndpoint == nullptr) + { + return; + } + GetService().post([=]() { + if (this->AddNTCP2Session (conn)) + { + + auto timer = std::make_shared(GetService()); + auto timeout = NTCP_CONNECT_TIMEOUT * 5; + conn->SetTerminationTimeout(timeout * 2); + timer->expires_from_now (boost::posix_time::seconds(timeout)); + timer->async_wait ([conn, timeout](const boost::system::error_code& ecode) { + if (ecode != boost::asio::error::operation_aborted) + { + LogPrint (eLogInfo, "NTCP2: Not connected in ", timeout, " seconds"); + i2p::data::netdb.SetUnreachable (conn->GetRemoteIdentity ()->GetIdentHash (), true); + conn->Terminate (); + } + }); + conn->GetSocket ().async_connect (*m_ProxyEndpoint, std::bind (&NTCP2Server::HandleProxyConnect, this, std::placeholders::_1, conn, timer, host, port, addrtype)); + } + }); + } + void NTCP2Session::SendTermination (NTCP2TerminationReason reason) { if (!m_SendKey || !m_SendSipKey) return; - m_NextSendBuffer = new uint8_t[49]; // 49 = 12 bytes message + 16 bytes MAC + 2 bytes size + up to 19 padding block + m_NextSendBuffer = new uint8_t[49]; // 49 = 12 bytes message + 16 bytes MAC + 2 bytes size + up to 19 padding block // termination block m_NextSendBuffer[2] = eNTCP2BlkTermination; m_NextSendBuffer[3] = 0; m_NextSendBuffer[4] = 9; // 9 bytes block size - htobe64buf (m_NextSendBuffer + 5, m_ReceiveSequenceNumber); + htobe64buf (m_NextSendBuffer + 5, m_ReceiveSequenceNumber); m_NextSendBuffer[13] = (uint8_t)reason; // padding block auto paddingSize = CreatePaddingBlock (12, m_NextSendBuffer + 14, 19); @@ -1125,13 +1343,13 @@ namespace transport if (m_IsTerminated) return; for (auto it: msgs) m_SendQueue.push_back (it); - if (!m_IsSending) - SendQueue (); + if (!m_IsSending) + SendQueue (); else if (m_SendQueue.size () > NTCP2_MAX_OUTGOING_QUEUE_SIZE) { LogPrint (eLogWarning, "NTCP2: outgoing messages queue size exceeds ", NTCP2_MAX_OUTGOING_QUEUE_SIZE); Terminate (); - } + } } void NTCP2Session::SendLocalRouterInfo () @@ -1142,6 +1360,7 @@ namespace transport NTCP2Server::NTCP2Server (): RunnableServiceWithWork ("NTCP2"), + m_ProxyType(eNoProxy), m_Resolver(GetService ()), m_ProxyEndpoint(nullptr), m_TerminationTimer (GetService ()) { } @@ -1156,45 +1375,69 @@ namespace transport if (!IsRunning ()) { StartIOService (); - auto& addresses = context.GetRouterInfo ().GetAddresses (); - for (const auto& address: addresses) + if(UsingProxy()) { - if (!address) continue; - if (address->IsPublishedNTCP2 ()) + LogPrint(eLogError, "NTCP2: USING PROXY "); + // TODO: resolve proxy until it is resolved + boost::asio::ip::tcp::resolver::query q(m_ProxyAddress, std::to_string(m_ProxyPort)); + boost::system::error_code e; + auto itr = m_Resolver.resolve(q, e); + if(e) { - if (address->host.is_v4()) + LogPrint(eLogError, "NTCP2: Failed to resolve proxy ", e.message()); + } + else + { + m_ProxyEndpoint = new boost::asio::ip::tcp::endpoint(*itr); + if (m_ProxyEndpoint) { - try - { - m_NTCP2Acceptor.reset (new boost::asio::ip::tcp::acceptor (GetService (), boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), address->port))); - } - catch ( std::exception & ex ) - { - LogPrint(eLogError, "NTCP2: Failed to bind to ip4 port ",address->port, ex.what()); - continue; - } - - LogPrint (eLogInfo, "NTCP2: Start listening TCP port ", address->port); - auto conn = std::make_shared(*this); - m_NTCP2Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAccept, this, conn, std::placeholders::_1)); + LogPrint(eLogError, "NTCP2: m_ProxyEndpoint %s", m_ProxyEndpoint); } - else if (address->host.is_v6() && context.SupportsV6 ()) + } + } + else + { + LogPrint(eLogError, "NTCP2: NOTUSING PROXY "); + auto& addresses = context.GetRouterInfo ().GetAddresses (); + for (const auto& address: addresses) + { + if (!address) continue; + if (address->IsPublishedNTCP2 ()) { - m_NTCP2V6Acceptor.reset (new boost::asio::ip::tcp::acceptor (GetService ())); - try + if (address->host.is_v4()) { - m_NTCP2V6Acceptor->open (boost::asio::ip::tcp::v6()); - m_NTCP2V6Acceptor->set_option (boost::asio::ip::v6_only (true)); - m_NTCP2V6Acceptor->set_option (boost::asio::socket_base::reuse_address (true)); - m_NTCP2V6Acceptor->bind (boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v6(), address->port)); - m_NTCP2V6Acceptor->listen (); + try + { + m_NTCP2Acceptor.reset (new boost::asio::ip::tcp::acceptor (GetService (), boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), address->port))); + } + catch ( std::exception & ex ) + { + LogPrint(eLogError, "NTCP2: Failed to bind to ip4 port ",address->port, ex.what()); + continue; + } - LogPrint (eLogInfo, "NTCP2: Start listening V6 TCP port ", address->port); - auto conn = std::make_shared (*this); - m_NTCP2V6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAcceptV6, this, conn, std::placeholders::_1)); - } catch ( std::exception & ex ) { - LogPrint(eLogError, "NTCP2: failed to bind to ip6 port ", address->port); - continue; + LogPrint (eLogInfo, "NTCP2: Start listening TCP port ", address->port); + auto conn = std::make_shared(*this); + m_NTCP2Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAccept, this, conn, std::placeholders::_1)); + } + else if (address->host.is_v6() && context.SupportsV6 ()) + { + m_NTCP2V6Acceptor.reset (new boost::asio::ip::tcp::acceptor (GetService ())); + try + { + m_NTCP2V6Acceptor->open (boost::asio::ip::tcp::v6()); + m_NTCP2V6Acceptor->set_option (boost::asio::ip::v6_only (true)); + m_NTCP2V6Acceptor->set_option (boost::asio::socket_base::reuse_address (true)); + m_NTCP2V6Acceptor->bind (boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v6(), address->port)); + m_NTCP2V6Acceptor->listen (); + + LogPrint (eLogInfo, "NTCP2: Start listening V6 TCP port ", address->port); + auto conn = std::make_shared (*this); + m_NTCP2V6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAcceptV6, this, conn, std::placeholders::_1)); + } catch ( std::exception & ex ) { + LogPrint(eLogError, "NTCP2: failed to bind to ip6 port ", address->port); + continue; + } } } } @@ -1216,14 +1459,21 @@ namespace transport m_NTCP2Sessions.clear (); if (IsRunning ()) + { m_TerminationTimer.cancel (); + if(m_ProxyEndpoint) + { + delete m_ProxyEndpoint; + m_ProxyEndpoint = nullptr; + } + } StopIOService (); } bool NTCP2Server::AddNTCP2Session (std::shared_ptr session, bool incoming) { if (!session) return false; - if (incoming) + if (incoming) m_PendingIncomingSessions.remove (session); if (!session->GetRemoteIdentity ()) return false; auto& ident = session->GetRemoteIdentity ()->GetIdentHash (); @@ -1255,7 +1505,7 @@ namespace transport void NTCP2Server::Connect(const boost::asio::ip::address & address, uint16_t port, std::shared_ptr conn) { LogPrint (eLogDebug, "NTCP2: Connecting to ", address ,":", port); - GetService ().post([this, address, port, conn]() + GetService ().post([this, address, port, conn]() { if (this->AddNTCP2Session (conn)) { @@ -1263,7 +1513,7 @@ namespace transport auto timeout = NTCP2_CONNECT_TIMEOUT * 5; conn->SetTerminationTimeout(timeout * 2); timer->expires_from_now (boost::posix_time::seconds(timeout)); - timer->async_wait ([conn, timeout](const boost::system::error_code& ecode) + timer->async_wait ([conn, timeout](const boost::system::error_code& ecode) { if (ecode != boost::asio::error::operation_aborted) { @@ -1391,4 +1641,3 @@ namespace transport } } } - diff --git a/libi2pd/NTCP2.h b/libi2pd/NTCP2.h index 7e3c53e8..9e784c88 100644 --- a/libi2pd/NTCP2.h +++ b/libi2pd/NTCP2.h @@ -28,7 +28,7 @@ namespace i2p namespace transport { - const size_t NTCP2_UNENCRYPTED_FRAME_MAX_SIZE = 65519; + const size_t NTCP2_UNENCRYPTED_FRAME_MAX_SIZE = 65519; const int NTCP2_MAX_PADDING_RATIO = 6; // in % const int NTCP2_CONNECT_TIMEOUT = 5; // 5 seconds @@ -36,7 +36,7 @@ namespace transport const int NTCP2_TERMINATION_TIMEOUT = 120; // 2 minutes const int NTCP2_TERMINATION_CHECK_TIMEOUT = 30; // 30 seconds - const int NTCP2_CLOCK_SKEW = 60; // in seconds + const int NTCP2_CLOCK_SKEW = 60; // in seconds const int NTCP2_MAX_OUTGOING_QUEUE_SIZE = 500; // how many messages we can queue up enum NTCP2BlockType @@ -46,8 +46,8 @@ namespace transport eNTCP2BlkRouterInfo, // 2 eNTCP2BlkI2NPMessage, // 3 eNTCP2BlkTermination, // 4 - eNTCP2BlkPadding = 254 - }; + eNTCP2BlkPadding = 254 + }; enum NTCP2TerminationReason { @@ -69,16 +69,16 @@ namespace transport eNTCP2RouterInfoSignatureVerificationFail, // 15 eNTCP2IncorrectSParameter, // 16 eNTCP2Banned, // 17 - }; - + }; + // RouterInfo flags - const uint8_t NTCP2_ROUTER_INFO_FLAG_REQUEST_FLOOD = 0x01; + const uint8_t NTCP2_ROUTER_INFO_FLAG_REQUEST_FLOOD = 0x01; struct NTCP2Establisher { NTCP2Establisher (); ~NTCP2Establisher (); - + const uint8_t * GetPub () const { return m_EphemeralKeys.GetPublicKey (); }; const uint8_t * GetRemotePub () const { return m_RemoteEphemeralPublicKey; }; // Y for Alice and X for Bob uint8_t * GetRemotePub () { return m_RemoteEphemeralPublicKey; }; // to set @@ -114,19 +114,20 @@ namespace transport uint8_t m_RemoteEphemeralPublicKey[32]; // x25519 uint8_t m_RemoteStaticKey[32], m_IV[16], m_H[32] /*h*/, m_CK[64] /* [ck, k]*/; i2p::data::IdentHash m_RemoteIdentHash; - uint16_t m3p2Len; + uint16_t m3p2Len; uint8_t * m_SessionRequestBuffer, * m_SessionCreatedBuffer, * m_SessionConfirmedBuffer; size_t m_SessionRequestBufferLen, m_SessionCreatedBufferLen; - }; + }; class NTCP2Server; class NTCP2Session: public TransportSession, public std::enable_shared_from_this { public: - NTCP2Session (NTCP2Server& server, std::shared_ptr in_RemoteRouter = nullptr); + + NTCP2Session (NTCP2Server& server, std::shared_ptr in_RemoteRouter = nullptr); ~NTCP2Session (); void Terminate (); void TerminateByTimeout (); @@ -138,9 +139,9 @@ namespace transport bool IsEstablished () const { return m_IsEstablished; }; bool IsTerminated () const { return m_IsTerminated; }; - void ClientLogin (); // Alice + void ClientLogin (); // Alice void ServerLogin (); // Bob - + void SendLocalRouterInfo (); // after handshake void SendI2NPMessages (const std::vector >& msgs); @@ -193,15 +194,15 @@ namespace transport std::unique_ptr m_Establisher; // data phase - uint8_t m_Kab[32], m_Kba[32], m_Sipkeysab[32], m_Sipkeysba[32]; + uint8_t m_Kab[32], m_Kba[32], m_Sipkeysab[32], m_Sipkeysba[32]; const uint8_t * m_SendKey, * m_ReceiveKey; -#if OPENSSL_SIPHASH +#if OPENSSL_SIPHASH EVP_PKEY * m_SendSipKey, * m_ReceiveSipKey; EVP_MD_CTX * m_SendMDCtx, * m_ReceiveMDCtx; #else const uint8_t * m_SendSipKey, * m_ReceiveSipKey; #endif - uint16_t m_NextReceivedLen; + uint16_t m_NextReceivedLen; uint8_t * m_NextReceivedBuffer, * m_NextSendBuffer; union { @@ -220,6 +221,20 @@ namespace transport { public: + enum RemoteAddressType + { + eIP4Address, + eIP6Address, + eHostname + }; + + enum ProxyType + { + eNoProxy, + eSocksProxy, + eHTTPProxy + }; + NTCP2Server (); ~NTCP2Server (); @@ -230,15 +245,23 @@ namespace transport bool AddNTCP2Session (std::shared_ptr session, bool incoming = false); void RemoveNTCP2Session (std::shared_ptr session); std::shared_ptr FindNTCP2Session (const i2p::data::IdentHash& ident); - + + void ConnectWithProxy (const std::string& addr, uint16_t port, RemoteAddressType addrtype, std::shared_ptr conn); void Connect(const boost::asio::ip::address & address, uint16_t port, std::shared_ptr conn); + void AfterSocksHandshake(std::shared_ptr conn, std::shared_ptr timer, const std::string & host, uint16_t port, RemoteAddressType addrtype); + + + bool UsingProxy() const { return m_ProxyType != eNoProxy; }; + void UseProxy(ProxyType proxy, const std::string & address, uint16_t port); + private: void HandleAccept (std::shared_ptr conn, const boost::system::error_code& error); void HandleAcceptV6 (std::shared_ptr conn, const boost::system::error_code& error); - void HandleConnect (const boost::system::error_code& ecode, std::shared_ptr conn, std::shared_ptr timer); + void HandleConnect (const boost::system::error_code& ecode, std::shared_ptr conn, std::shared_ptr timer); + void HandleProxyConnect(const boost::system::error_code& ecode, std::shared_ptr conn, std::shared_ptr timer, const std::string & host, uint16_t port, RemoteAddressType adddrtype); // timer void ScheduleTermination (); @@ -248,9 +271,15 @@ namespace transport boost::asio::deadline_timer m_TerminationTimer; std::unique_ptr m_NTCP2Acceptor, m_NTCP2V6Acceptor; - std::map > m_NTCP2Sessions; + std::map > m_NTCP2Sessions; std::list > m_PendingIncomingSessions; + ProxyType m_ProxyType; + std::string m_ProxyAddress; + uint16_t m_ProxyPort; + boost::asio::ip::tcp::resolver m_Resolver; + boost::asio::ip::tcp::endpoint * m_ProxyEndpoint; + public: // for HTTP/I2PControl diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 42a605a4..34ec25f4 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -157,6 +157,7 @@ namespace transport m_IsRunning = true; m_Thread = new std::thread (std::bind (&Transports::Run, this)); std::string ntcpproxy; i2p::config::GetOption("ntcpproxy", ntcpproxy); + std::string ntcp2proxy; i2p::config::GetOption("ntcp2proxy", ntcp2proxy); i2p::http::URL proxyurl; uint16_t softLimit, hardLimit, threads; i2p::config::GetOption("limits.ntcpsoft", softLimit); @@ -196,13 +197,36 @@ namespace transport LogPrint(eLogError, "Transports: invalid NTCP proxy url ", ntcpproxy); return; } - // create NTCP2. TODO: move to acceptor + // create NTCP2. TODO: move to acceptor bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); if (ntcp2) { - m_NTCP2Server = new NTCP2Server (); - m_NTCP2Server->Start (); - } + if(ntcp2proxy.size()) + { + if(proxyurl.parse(ntcp2proxy)) + { + if(proxyurl.schema == "socks" || proxyurl.schema == "http") + { + m_NTCP2Server = new NTCP2Server (); + NTCP2Server::ProxyType proxytype = NTCP2Server::eSocksProxy; + + if (proxyurl.schema == "http") + proxytype = NTCP2Server::eHTTPProxy; + + m_NTCP2Server->UseProxy(proxytype, proxyurl.host, proxyurl.port) ; + m_NTCP2Server->Start(); + } + else + LogPrint(eLogError, "Transports: unsupported NTCP2 proxy URL ", ntcp2proxy); + } + else + LogPrint(eLogError, "Transports: invalid NTCP2 proxy url ", ntcp2proxy); + return; + } + + // m_NTCP2Server = new NTCP2Server (); + // m_NTCP2Server->Start (); + } // create acceptors auto& addresses = context.GetRouterInfo ().GetAddresses (); @@ -405,24 +429,36 @@ namespace transport { if (peer.router) // we have RI already { - if (!peer.numAttempts) // NTCP2 - { - peer.numAttempts++; - if (m_NTCP2Server) // we support NTCP2 - { - // NTCP2 have priority over NTCP - auto address = peer.router->GetNTCP2Address (true, !context.SupportsV6 ()); // published only - if (address) - { - auto s = std::make_shared (*m_NTCP2Server, peer.router); - m_NTCP2Server->Connect (address->host, address->port, s); - return true; - } - } - } + if (!peer.numAttempts) // NTCP2 + { + peer.numAttempts++; + if (m_NTCP2Server) // we support NTCP2 + { + // NTCP2 have priority over NTCP + auto address = peer.router->GetNTCP2Address (true, !context.SupportsV6 ()); // published only + if (address) + { + auto s = std::make_shared (*m_NTCP2Server, peer.router); + + if(m_NTCP2Server->UsingProxy()) + { + NTCP2Server::RemoteAddressType remote = NTCP2Server::eIP4Address; + std::string addr = address->host.to_string(); + + if(address->host.is_v6()) + remote = NTCP2Server::eIP6Address; + + m_NTCP2Server->ConnectWithProxy(addr, address->port, remote, s); + } + else + m_NTCP2Server->Connect (address->host, address->port, s); + return true; + } + } + } if (peer.numAttempts == 1) // NTCP1 { - peer.numAttempts++; + peer.numAttempts++; auto address = peer.router->GetNTCPAddress (!context.SupportsV6 ()); if (address && m_NTCPServer) { @@ -650,14 +686,14 @@ namespace transport { auto before = it->second.sessions.size (); it->second.sessions.remove (session); - if (it->second.sessions.empty ()) + if (it->second.sessions.empty ()) { if (it->second.delayedMessages.size () > 0) { if (before > 0) // we had an active session before it->second.numAttempts = 0; // start over ConnectToPeer (ident, it->second); - } + } else { std::unique_lock l(m_PeersMutex); From ae20e3aa953fb9926b9ca14838df578d9dcefe40 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 1 Mar 2020 11:24:18 -0500 Subject: [PATCH 14/44] NTCP2 proxy --- libi2pd/NTCP2.cpp | 152 +++++++++++++++++++++++----------------------- libi2pd/NTCP2.h | 4 +- 2 files changed, 77 insertions(+), 79 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index a3c42790..10cc3d89 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1175,16 +1175,18 @@ namespace transport m_ProxyPort = port; } - void NTCP2Server::HandleProxyConnect(const boost::system::error_code& ecode, std::shared_ptr conn, std::shared_ptr timer, const std::string & host, uint16_t port, RemoteAddressType addrtype) + void NTCP2Server::HandleProxyConnect(const boost::system::error_code& ecode, std::shared_ptr conn, std::shared_ptr timer, const std::string & host, uint16_t port, RemoteAddressType addrtype) + { + if (ecode) { - if(ecode) - { - LogPrint(eLogWarning, "NTCP2: failed to connect to proxy ", ecode.message()); - timer->cancel(); - conn->Terminate(); - return; - } - if(m_ProxyType == eSocksProxy) + LogPrint(eLogWarning, "NTCP2: failed to connect to proxy ", ecode.message()); + timer->cancel(); + conn->Terminate(); + return; + } + switch (m_ProxyType) + { + case eSocksProxy: { // TODO: support username/password auth etc uint8_t buff[3] = {0x05, 0x01, 0x00}; @@ -1196,7 +1198,8 @@ namespace transport } }); uint8_t readbuff[2]; - boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(readbuff, 2), [=](const boost::system::error_code & ec, std::size_t transferred) + boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(readbuff, 2), + [=](const boost::system::error_code & ec, std::size_t transferred) { LogPrint(eLogError, "NTCP2: ", transferred); if(ec) @@ -1226,71 +1229,73 @@ namespace transport timer->cancel(); conn->Terminate(); }); + break; } - else if(m_ProxyType == eHTTPProxy) - { - i2p::http::HTTPReq req; - req.method = "CONNECT"; - req.version ="HTTP/1.1"; - if(addrtype == eIP6Address) - req.uri = "[" + host + "]:" + std::to_string(port); - else - req.uri = host + ":" + std::to_string(port); - - boost::asio::streambuf writebuff; - std::ostream out(&writebuff); - out << req.to_string(); - - boost::asio::async_write(conn->GetSocket(), writebuff.data(), boost::asio::transfer_all(), [=](const boost::system::error_code & ec, std::size_t transferred) { - (void) transferred; - if(ec) - LogPrint(eLogError, "NTCP2: http proxy write error ", ec.message()); - }); - - boost::asio::streambuf * readbuff = new boost::asio::streambuf; - boost::asio::async_read_until(conn->GetSocket(), *readbuff, "\r\n\r\n", [=] (const boost::system::error_code & ec, std::size_t transferred) { - if(ec) - { - LogPrint(eLogError, "NTCP2: http proxy read error ", ec.message()); - timer->cancel(); - conn->Terminate(); - } + case eHTTPProxy: + { + i2p::http::HTTPReq req; + req.method = "CONNECT"; + req.version ="HTTP/1.1"; + if(addrtype == eIP6Address) + req.uri = "[" + host + "]:" + std::to_string(port); else + req.uri = host + ":" + std::to_string(port); + + boost::asio::streambuf writebuff; + std::ostream out(&writebuff); + out << req.to_string(); + + boost::asio::async_write(conn->GetSocket(), writebuff.data(), boost::asio::transfer_all(), [=](const boost::system::error_code & ec, std::size_t transferred) { + (void) transferred; + if(ec) + LogPrint(eLogError, "NTCP2: http proxy write error ", ec.message()); + }); + + boost::asio::streambuf * readbuff = new boost::asio::streambuf; + boost::asio::async_read_until(conn->GetSocket(), *readbuff, "\r\n\r\n", + [=] (const boost::system::error_code & ec, std::size_t transferred) { - readbuff->commit(transferred); - i2p::http::HTTPRes res; - if(res.parse(boost::asio::buffer_cast(readbuff->data()), readbuff->size()) > 0) + if(ec) { - if(res.code == 200) - { - timer->cancel(); - conn->ClientLogin(); - delete readbuff; - return; - } - else - { - LogPrint(eLogError, "NTCP2: http proxy rejected request ", res.code); - } + LogPrint(eLogError, "NTCP2: http proxy read error ", ec.message()); + timer->cancel(); + conn->Terminate(); } else - LogPrint(eLogError, "NTCP2: http proxy gave malformed response"); - timer->cancel(); - conn->Terminate(); - delete readbuff; - } - }); - } - else - LogPrint(eLogError, "NTCP2: unknown proxy type, invalid state"); + { + readbuff->commit(transferred); + i2p::http::HTTPRes res; + if(res.parse(boost::asio::buffer_cast(readbuff->data()), readbuff->size()) > 0) + { + if(res.code == 200) + { + timer->cancel(); + conn->ClientLogin(); + delete readbuff; + return; + } + else + { + LogPrint(eLogError, "NTCP2: http proxy rejected request ", res.code); + } + } + else + LogPrint(eLogError, "NTCP2: http proxy gave malformed response"); + timer->cancel(); + conn->Terminate(); + delete readbuff; + } + }); + break; + } + default: + LogPrint(eLogError, "NTCP2: unknown proxy type, invalid state"); + } } void NTCP2Server::ConnectWithProxy (const std::string& host, uint16_t port, RemoteAddressType addrtype, std::shared_ptr conn) { - if(m_ProxyEndpoint == nullptr) - { - return; - } + if(!m_ProxyEndpoint) return GetService().post([=]() { if (this->AddNTCP2Session (conn)) { @@ -1359,9 +1364,8 @@ namespace transport } NTCP2Server::NTCP2Server (): - RunnableServiceWithWork ("NTCP2"), - m_ProxyType(eNoProxy), m_Resolver(GetService ()), m_ProxyEndpoint(nullptr), - m_TerminationTimer (GetService ()) + RunnableServiceWithWork ("NTCP2"), m_TerminationTimer (GetService ()), + m_Resolver(GetService ()) { } @@ -1388,11 +1392,9 @@ namespace transport } else { - m_ProxyEndpoint = new boost::asio::ip::tcp::endpoint(*itr); + m_ProxyEndpoint.reset (new boost::asio::ip::tcp::endpoint(*itr)); if (m_ProxyEndpoint) - { - LogPrint(eLogError, "NTCP2: m_ProxyEndpoint %s", m_ProxyEndpoint); - } + LogPrint(eLogError, "NTCP2: m_ProxyEndpoint ", *m_ProxyEndpoint); } } else @@ -1461,11 +1463,7 @@ namespace transport if (IsRunning ()) { m_TerminationTimer.cancel (); - if(m_ProxyEndpoint) - { - delete m_ProxyEndpoint; - m_ProxyEndpoint = nullptr; - } + m_ProxyEndpoint = nullptr; } StopIOService (); } diff --git a/libi2pd/NTCP2.h b/libi2pd/NTCP2.h index 9e784c88..11ae5995 100644 --- a/libi2pd/NTCP2.h +++ b/libi2pd/NTCP2.h @@ -274,11 +274,11 @@ namespace transport std::map > m_NTCP2Sessions; std::list > m_PendingIncomingSessions; - ProxyType m_ProxyType; + ProxyType m_ProxyType =eNoProxy; std::string m_ProxyAddress; uint16_t m_ProxyPort; boost::asio::ip::tcp::resolver m_Resolver; - boost::asio::ip::tcp::endpoint * m_ProxyEndpoint; + std::unique_ptr m_ProxyEndpoint; public: From e969d58689a6a5f57e896ef6b8e0dab649904c8b Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 1 Mar 2020 15:11:54 -0500 Subject: [PATCH 15/44] handle ntcp2.proxy parameter --- libi2pd/Config.cpp | 4 +- libi2pd/NTCP2.cpp | 139 +++++++++++++++++++++-------------------- libi2pd/Transports.cpp | 12 ++-- 3 files changed, 80 insertions(+), 75 deletions(-) diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 4050f769..521ebf65 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -60,8 +60,7 @@ namespace config { ("share", value()->default_value(100), "Limit of transit traffic from max bandwidth in percents. (default: 100)") ("ntcp", value()->default_value(false), "Enable NTCP transport (default: disabled)") ("ssu", value()->default_value(true), "Enable SSU transport (default: enabled)") - ("ntcpproxy", value()->default_value(""), "Proxy URL for NTCP transport") - ("ntcp2proxy", value()->default_value(""), "Proxy URL for NTCP2 transport") + ("ntcpproxy", value()->default_value(""), "Proxy URL for NTCP transport") #ifdef _WIN32 ("svcctl", value()->default_value(""), "Windows service management ('install' or 'remove')") ("insomnia", bool_switch()->default_value(false), "Prevent system from sleeping (default: disabled)") @@ -240,6 +239,7 @@ namespace config { ("ntcp2.published", value()->default_value(true), "Publish NTCP2 (default: enabled)") ("ntcp2.port", value()->default_value(0), "Port to listen for incoming NTCP2 connections (default: auto)") ("ntcp2.addressv6", value()->default_value("::"), "Address to bind NTCP2 on") + ("ntcp2.proxy", value()->default_value(""), "Proxy URL for NTCP2 transport") ; options_description nettime("Time sync options"); diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 10cc3d89..c46dbd81 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1189,46 +1189,48 @@ namespace transport case eSocksProxy: { // TODO: support username/password auth etc - uint8_t buff[3] = {0x05, 0x01, 0x00}; - boost::asio::async_write(conn->GetSocket(), boost::asio::buffer(buff, 3), boost::asio::transfer_all(), [=] (const boost::system::error_code & ec, std::size_t transferred) { - (void) transferred; - if(ec) - { - LogPrint(eLogWarning, "NTCP2: socks5 write error ", ec.message()); - } - }); - uint8_t readbuff[2]; - boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(readbuff, 2), - [=](const boost::system::error_code & ec, std::size_t transferred) - { - LogPrint(eLogError, "NTCP2: ", transferred); - if(ec) - { - LogPrint(eLogError, "NTCP2: socks5 read error ", ec.message()); - timer->cancel(); - conn->Terminate(); - return; - } - else if(transferred == 2) - { - if(readbuff[1] == 0xba) + static const uint8_t buff[3] = {0x05, 0x01, 0x00}; + boost::asio::async_write(conn->GetSocket(), boost::asio::buffer(buff, 3), boost::asio::transfer_all(), + [] (const boost::system::error_code & ec, std::size_t transferred) + { + (void) transferred; + if(ec) { - AfterSocksHandshake(conn, timer, host, port, addrtype); - return; + LogPrint(eLogWarning, "NTCP2: socks5 write error ", ec.message()); } - else if (readbuff[1] == 0xff) + }); + auto readbuff = std::make_shared >(); + boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(*readbuff, 2), + [this, readbuff, timer, conn, host, port, addrtype](const boost::system::error_code & ec, std::size_t transferred) + { + LogPrint(eLogError, "NTCP2: ", transferred); + if(ec) { - LogPrint(eLogError, "NTCP2: socks5 proxy rejected authentication"); + LogPrint(eLogError, "NTCP2: socks5 read error ", ec.message()); timer->cancel(); conn->Terminate(); return; } - LogPrint(eLogError, "NTCP2:", readbuff[1]); - } - LogPrint(eLogError, "NTCP2: socks5 server gave invalid response"); - timer->cancel(); - conn->Terminate(); - }); + else if(transferred == 2) + { + if((*readbuff)[1] == 0xba) + { + AfterSocksHandshake(conn, timer, host, port, addrtype); + return; + } + else if ((*readbuff)[1] == 0xff) + { + LogPrint(eLogError, "NTCP2: socks5 proxy rejected authentication"); + timer->cancel(); + conn->Terminate(); + return; + } + LogPrint(eLogError, "NTCP2:", (*readbuff)[1]); + } + LogPrint(eLogError, "NTCP2: socks5 server gave invalid response"); + timer->cancel(); + conn->Terminate(); + }); break; } case eHTTPProxy: @@ -1245,47 +1247,47 @@ namespace transport std::ostream out(&writebuff); out << req.to_string(); - boost::asio::async_write(conn->GetSocket(), writebuff.data(), boost::asio::transfer_all(), [=](const boost::system::error_code & ec, std::size_t transferred) { - (void) transferred; - if(ec) - LogPrint(eLogError, "NTCP2: http proxy write error ", ec.message()); - }); + boost::asio::async_write(conn->GetSocket(), writebuff.data(), boost::asio::transfer_all(), + [](const boost::system::error_code & ec, std::size_t transferred) + { + (void) transferred; + if(ec) + LogPrint(eLogError, "NTCP2: http proxy write error ", ec.message()); + }); boost::asio::streambuf * readbuff = new boost::asio::streambuf; boost::asio::async_read_until(conn->GetSocket(), *readbuff, "\r\n\r\n", - [=] (const boost::system::error_code & ec, std::size_t transferred) - { - if(ec) + [this, readbuff, timer, conn] (const boost::system::error_code & ec, std::size_t transferred) { - LogPrint(eLogError, "NTCP2: http proxy read error ", ec.message()); - timer->cancel(); - conn->Terminate(); - } - else - { - readbuff->commit(transferred); - i2p::http::HTTPRes res; - if(res.parse(boost::asio::buffer_cast(readbuff->data()), readbuff->size()) > 0) + if(ec) { - if(res.code == 200) - { - timer->cancel(); - conn->ClientLogin(); - delete readbuff; - return; - } - else - { - LogPrint(eLogError, "NTCP2: http proxy rejected request ", res.code); - } + LogPrint(eLogError, "NTCP2: http proxy read error ", ec.message()); + timer->cancel(); + conn->Terminate(); } else - LogPrint(eLogError, "NTCP2: http proxy gave malformed response"); - timer->cancel(); - conn->Terminate(); - delete readbuff; - } - }); + { + readbuff->commit(transferred); + i2p::http::HTTPRes res; + if(res.parse(boost::asio::buffer_cast(readbuff->data()), readbuff->size()) > 0) + { + if(res.code == 200) + { + timer->cancel(); + conn->ClientLogin(); + delete readbuff; + return; + } + else + LogPrint(eLogError, "NTCP2: http proxy rejected request ", res.code); + } + else + LogPrint(eLogError, "NTCP2: http proxy gave malformed response"); + timer->cancel(); + conn->Terminate(); + delete readbuff; + } + }); break; } default: @@ -1304,7 +1306,8 @@ namespace transport auto timeout = NTCP_CONNECT_TIMEOUT * 5; conn->SetTerminationTimeout(timeout * 2); timer->expires_from_now (boost::posix_time::seconds(timeout)); - timer->async_wait ([conn, timeout](const boost::system::error_code& ecode) { + timer->async_wait ([conn, timeout](const boost::system::error_code& ecode) + { if (ecode != boost::asio::error::operation_aborted) { LogPrint (eLogInfo, "NTCP2: Not connected in ", timeout, " seconds"); diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 34ec25f4..8a36c5aa 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -157,7 +157,7 @@ namespace transport m_IsRunning = true; m_Thread = new std::thread (std::bind (&Transports::Run, this)); std::string ntcpproxy; i2p::config::GetOption("ntcpproxy", ntcpproxy); - std::string ntcp2proxy; i2p::config::GetOption("ntcp2proxy", ntcp2proxy); + std::string ntcp2proxy; i2p::config::GetOption("ntcp2.proxy", ntcp2proxy); i2p::http::URL proxyurl; uint16_t softLimit, hardLimit, threads; i2p::config::GetOption("limits.ntcpsoft", softLimit); @@ -201,7 +201,7 @@ namespace transport bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); if (ntcp2) { - if(ntcp2proxy.size()) + if(!ntcp2proxy.empty()) { if(proxyurl.parse(ntcp2proxy)) { @@ -223,9 +223,11 @@ namespace transport LogPrint(eLogError, "Transports: invalid NTCP2 proxy url ", ntcp2proxy); return; } - - // m_NTCP2Server = new NTCP2Server (); - // m_NTCP2Server->Start (); + else + { + m_NTCP2Server = new NTCP2Server (); + m_NTCP2Server->Start (); + } } // create acceptors From 35e8424293e62be087e4a0b5daac11153e46169a Mon Sep 17 00:00:00 2001 From: potatowipedlifereverse Date: Mon, 2 Mar 2020 01:47:48 +0300 Subject: [PATCH 16/44] preinit webview+configparser+README.md tabulation fixes configparser to comments dont need pre init webview readme changes delete submodules webview in main menu webview pre init delete modules delete submodules --- .gitmodules | 0 android/AndroidManifest.xml | 1 + android/README.md | 19 ++++++++++++++++ android/res/layout/webview.xml | 13 +++++++++++ android/res/menu/options_main.xml | 4 ++++ android/res/values/strings.xml | 1 + .../src/org/purplei2p/i2pd/I2PDActivity.java | 22 +++++++++++++++++++ 7 files changed, 60 insertions(+) create mode 100644 .gitmodules create mode 100644 android/README.md create mode 100644 android/res/layout/webview.xml diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..e69de29b diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 71526701..a95e3773 100755 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -17,6 +17,7 @@ android:label="@string/app_name" android:theme="@android:style/Theme.Holo.Light.DarkActionBar" android:requestLegacyExternalStorage="true" + android:usesCleartextTraffic="true" > diff --git a/android/README.md b/android/README.md new file mode 100644 index 00000000..de6a16c3 --- /dev/null +++ b/android/README.md @@ -0,0 +1,19 @@ +# how to compile? +## Install the gradle + NDK or use android-studio +[![https://gradle.org/install/]](https://gradle.org/install/) + +## Install the depencies +``` +git clone https://github.com/PurpleI2P/Boost-for-Android-Prebuilt.git -b boost-1_72_0 +git clone https://github.com/PurpleI2P/android-ifaddrs.git +git clone https://github.com/PurpleI2P/OpenSSL-for-Android-Prebuilt.git +git clone https://github.com/PurpleI2P/MiniUPnP-for-Android-Prebuilt.git +``` +## Set libs in jni/Application.mk on 24 line: +``` +# change to your own +I2PD_LIBS_PATH = /home/user/i2pd/android/ +``` + +## compile apk file +gradle clean assembleRelease diff --git a/android/res/layout/webview.xml b/android/res/layout/webview.xml new file mode 100644 index 00000000..d13be23e --- /dev/null +++ b/android/res/layout/webview.xml @@ -0,0 +1,13 @@ + + + + + diff --git a/android/res/menu/options_main.xml b/android/res/menu/options_main.xml index 089c2700..b0f23bd2 100644 --- a/android/res/menu/options_main.xml +++ b/android/res/menu/options_main.xml @@ -12,6 +12,10 @@ android:id="@+id/action_graceful_stop" android:orderInCategory="98" android:title="@string/action_graceful_stop" /> + Battery Optimizations Your Android OS version does not support showing the dialog for battery optimizations for applications. Planned shutdown canceled + Start webview diff --git a/android/src/org/purplei2p/i2pd/I2PDActivity.java b/android/src/org/purplei2p/i2pd/I2PDActivity.java index 89881b42..7949e8d0 100755 --- a/android/src/org/purplei2p/i2pd/I2PDActivity.java +++ b/android/src/org/purplei2p/i2pd/I2PDActivity.java @@ -39,15 +39,23 @@ import android.view.MenuItem; import android.widget.TextView; import android.widget.Toast; + import androidx.annotation.NonNull; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; // For future package update checking +import android.webkit.WebSettings; +import android.webkit.WebView; +import android.webkit.WebViewClient; + + import static android.provider.Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS; public class I2PDActivity extends Activity { + private WebView webView; + private static final String TAG = "i2pdActvt"; private static final int MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE = 1; public static final int GRACEFUL_DELAY_MILLIS = 10 * 60 * 1000; @@ -56,6 +64,7 @@ public class I2PDActivity extends Activity { private TextView textView; private boolean assetsCopied; private String i2pdpath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/i2pd/"; + //private ConfigParser parser = new ConfigParser(i2pdpath); // TODO: private static final DaemonSingleton daemon = DaemonSingleton.getInstance(); @@ -262,6 +271,16 @@ public class I2PDActivity extends Activity { case R.id.action_battery_otimizations: onActionBatteryOptimizations(); return true; + case R.id.action_start_webview: + setContentView(R.layout.webview); + this.webView = (WebView) findViewById(R.id.webview1); + this.webView.setWebViewClient(new WebViewClient()); + + WebSettings webSettings = this.webView.getSettings(); + webSettings.setBuiltInZoomControls(true); + webSettings.setJavaScriptEnabled(false); + this.webView.loadUrl("http://127.0.0.1:7070"); // TODO: instead 7070 I2Pd....HttpPort + break; } return super.onOptionsItemSelected(item); @@ -617,4 +636,7 @@ public class I2PDActivity extends Activity { } System.exit(0); } + public String getI2pdpath(){ + return this.i2pdpath; + } } From b6368170ed4049859f8c3e22e11a3a1def7ce159 Mon Sep 17 00:00:00 2001 From: wipedlifepotato <60944239+wipedlifepotato@users.noreply.github.com> Date: Mon, 2 Mar 2020 04:00:28 +0300 Subject: [PATCH 17/44] Update README.md --- android/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/README.md b/android/README.md index de6a16c3..e0850b15 100644 --- a/android/README.md +++ b/android/README.md @@ -1,6 +1,6 @@ # how to compile? ## Install the gradle + NDK or use android-studio -[![https://gradle.org/install/]](https://gradle.org/install/) +[https://gradle.org/install/](https://gradle.org/install/) ## Install the depencies ``` From c6ccb373a22ed6df9f5c13f7ca20a77a9ecaf339 Mon Sep 17 00:00:00 2001 From: potatowipedlifereverse Date: Mon, 2 Mar 2020 05:04:37 +0300 Subject: [PATCH 18/44] del geti2pdpath --- android/src/org/purplei2p/i2pd/I2PDActivity.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/android/src/org/purplei2p/i2pd/I2PDActivity.java b/android/src/org/purplei2p/i2pd/I2PDActivity.java index 7949e8d0..258bafe2 100755 --- a/android/src/org/purplei2p/i2pd/I2PDActivity.java +++ b/android/src/org/purplei2p/i2pd/I2PDActivity.java @@ -636,7 +636,4 @@ public class I2PDActivity extends Activity { } System.exit(0); } - public String getI2pdpath(){ - return this.i2pdpath; - } } From 2d3fad2cdbf01f2fa19e4a9fb708db80ca432902 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 2 Mar 2020 16:24:00 -0500 Subject: [PATCH 19/44] correct proxy buffers --- libi2pd/NTCP2.cpp | 450 +++++++++++++++++++++++----------------------- 1 file changed, 226 insertions(+), 224 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index c46dbd81..3dfd6250 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -377,78 +377,6 @@ namespace transport } } - void NTCP2Server::AfterSocksHandshake(std::shared_ptr conn, std::shared_ptr timer, const std::string & host, uint16_t port, RemoteAddressType addrtype) - { - - // build request - size_t sz = 0; - uint8_t buff[256]; - uint8_t readbuff[256]; - buff[0] = 0x05; - buff[1] = 0x01; - buff[2] = 0x00; - - if(addrtype == eIP4Address) - { - buff[3] = 0x01; - auto addr = boost::asio::ip::address::from_string(host).to_v4(); - auto addrbytes = addr.to_bytes(); - auto addrsize = addrbytes.size(); - memcpy(buff+4, addrbytes.data(), addrsize); - } - else if (addrtype == eIP6Address) - { - buff[3] = 0x04; - auto addr = boost::asio::ip::address::from_string(host).to_v6(); - auto addrbytes = addr.to_bytes(); - auto addrsize = addrbytes.size(); - memcpy(buff+4, addrbytes.data(), addrsize); - } - else if (addrtype == eHostname) - { - buff[3] = 0x03; - size_t addrsize = host.size(); - sz = addrsize + 1 + 4; - if (2 + sz > sizeof(buff)) - { - // too big - return; - } - buff[4] = (uint8_t) addrsize; - memcpy(buff+5, host.c_str(), addrsize); - } - htobe16buf(buff+sz, port); - sz += 2; - boost::asio::async_write(conn->GetSocket(), boost::asio::buffer(buff, sz), boost::asio::transfer_all(), [=](const boost::system::error_code & ec, std::size_t written) { - if(ec) - { - LogPrint(eLogError, "NTCP2: failed to write handshake to socks proxy ", ec.message()); - return; - } - }); - - boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(readbuff, 10), [=](const boost::system::error_code & e, std::size_t transferred) { - if(e) - { - LogPrint(eLogError, "NTCP2: socks proxy read error ", e.message()); - } - else if(transferred == sz) - { - if( readbuff[1] == 0x00) - { - timer->cancel(); - conn->ClientLogin(); - return; - } - } - if(!e) - i2p::data::netdb.SetUnreachable (conn->GetRemoteIdentity ()->GetIdentHash (), true); - timer->cancel(); - conn->Terminate(); - }); - } - - NTCP2Session::~NTCP2Session () { delete[] m_NextReceivedBuffer; @@ -1168,158 +1096,6 @@ namespace transport EncryptAndSendNextBuffer (payloadLen); } - void NTCP2Server::UseProxy(ProxyType proxytype, const std::string & addr, uint16_t port) - { - m_ProxyType = proxytype; - m_ProxyAddress = addr; - m_ProxyPort = port; - } - - void NTCP2Server::HandleProxyConnect(const boost::system::error_code& ecode, std::shared_ptr conn, std::shared_ptr timer, const std::string & host, uint16_t port, RemoteAddressType addrtype) - { - if (ecode) - { - LogPrint(eLogWarning, "NTCP2: failed to connect to proxy ", ecode.message()); - timer->cancel(); - conn->Terminate(); - return; - } - switch (m_ProxyType) - { - case eSocksProxy: - { - // TODO: support username/password auth etc - static const uint8_t buff[3] = {0x05, 0x01, 0x00}; - boost::asio::async_write(conn->GetSocket(), boost::asio::buffer(buff, 3), boost::asio::transfer_all(), - [] (const boost::system::error_code & ec, std::size_t transferred) - { - (void) transferred; - if(ec) - { - LogPrint(eLogWarning, "NTCP2: socks5 write error ", ec.message()); - } - }); - auto readbuff = std::make_shared >(); - boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(*readbuff, 2), - [this, readbuff, timer, conn, host, port, addrtype](const boost::system::error_code & ec, std::size_t transferred) - { - LogPrint(eLogError, "NTCP2: ", transferred); - if(ec) - { - LogPrint(eLogError, "NTCP2: socks5 read error ", ec.message()); - timer->cancel(); - conn->Terminate(); - return; - } - else if(transferred == 2) - { - if((*readbuff)[1] == 0xba) - { - AfterSocksHandshake(conn, timer, host, port, addrtype); - return; - } - else if ((*readbuff)[1] == 0xff) - { - LogPrint(eLogError, "NTCP2: socks5 proxy rejected authentication"); - timer->cancel(); - conn->Terminate(); - return; - } - LogPrint(eLogError, "NTCP2:", (*readbuff)[1]); - } - LogPrint(eLogError, "NTCP2: socks5 server gave invalid response"); - timer->cancel(); - conn->Terminate(); - }); - break; - } - case eHTTPProxy: - { - i2p::http::HTTPReq req; - req.method = "CONNECT"; - req.version ="HTTP/1.1"; - if(addrtype == eIP6Address) - req.uri = "[" + host + "]:" + std::to_string(port); - else - req.uri = host + ":" + std::to_string(port); - - boost::asio::streambuf writebuff; - std::ostream out(&writebuff); - out << req.to_string(); - - boost::asio::async_write(conn->GetSocket(), writebuff.data(), boost::asio::transfer_all(), - [](const boost::system::error_code & ec, std::size_t transferred) - { - (void) transferred; - if(ec) - LogPrint(eLogError, "NTCP2: http proxy write error ", ec.message()); - }); - - boost::asio::streambuf * readbuff = new boost::asio::streambuf; - boost::asio::async_read_until(conn->GetSocket(), *readbuff, "\r\n\r\n", - [this, readbuff, timer, conn] (const boost::system::error_code & ec, std::size_t transferred) - { - if(ec) - { - LogPrint(eLogError, "NTCP2: http proxy read error ", ec.message()); - timer->cancel(); - conn->Terminate(); - } - else - { - readbuff->commit(transferred); - i2p::http::HTTPRes res; - if(res.parse(boost::asio::buffer_cast(readbuff->data()), readbuff->size()) > 0) - { - if(res.code == 200) - { - timer->cancel(); - conn->ClientLogin(); - delete readbuff; - return; - } - else - LogPrint(eLogError, "NTCP2: http proxy rejected request ", res.code); - } - else - LogPrint(eLogError, "NTCP2: http proxy gave malformed response"); - timer->cancel(); - conn->Terminate(); - delete readbuff; - } - }); - break; - } - default: - LogPrint(eLogError, "NTCP2: unknown proxy type, invalid state"); - } - } - - void NTCP2Server::ConnectWithProxy (const std::string& host, uint16_t port, RemoteAddressType addrtype, std::shared_ptr conn) - { - if(!m_ProxyEndpoint) return - GetService().post([=]() { - if (this->AddNTCP2Session (conn)) - { - - auto timer = std::make_shared(GetService()); - auto timeout = NTCP_CONNECT_TIMEOUT * 5; - conn->SetTerminationTimeout(timeout * 2); - timer->expires_from_now (boost::posix_time::seconds(timeout)); - timer->async_wait ([conn, timeout](const boost::system::error_code& ecode) - { - if (ecode != boost::asio::error::operation_aborted) - { - LogPrint (eLogInfo, "NTCP2: Not connected in ", timeout, " seconds"); - i2p::data::netdb.SetUnreachable (conn->GetRemoteIdentity ()->GetIdentHash (), true); - conn->Terminate (); - } - }); - conn->GetSocket ().async_connect (*m_ProxyEndpoint, std::bind (&NTCP2Server::HandleProxyConnect, this, std::placeholders::_1, conn, timer, host, port, addrtype)); - } - }); - } - void NTCP2Session::SendTermination (NTCP2TerminationReason reason) { if (!m_SendKey || !m_SendSipKey) return; @@ -1640,5 +1416,231 @@ namespace transport ScheduleTermination (); } } + + void NTCP2Server::UseProxy(ProxyType proxytype, const std::string & addr, uint16_t port) + { + m_ProxyType = proxytype; + m_ProxyAddress = addr; + m_ProxyPort = port; + } + + void NTCP2Server::HandleProxyConnect(const boost::system::error_code& ecode, std::shared_ptr conn, std::shared_ptr timer, const std::string & host, uint16_t port, RemoteAddressType addrtype) + { + if (ecode) + { + LogPrint(eLogWarning, "NTCP2: failed to connect to proxy ", ecode.message()); + timer->cancel(); + conn->Terminate(); + return; + } + switch (m_ProxyType) + { + case eSocksProxy: + { + // TODO: support username/password auth etc + static const uint8_t buff[3] = {0x05, 0x01, 0x00}; + boost::asio::async_write(conn->GetSocket(), boost::asio::buffer(buff, 3), boost::asio::transfer_all(), + [] (const boost::system::error_code & ec, std::size_t transferred) + { + (void) transferred; + if(ec) + { + LogPrint(eLogWarning, "NTCP2: socks5 write error ", ec.message()); + } + }); + auto readbuff = std::make_shared >(2); + boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(readbuff->data (), 2), + [this, readbuff, timer, conn, host, port, addrtype](const boost::system::error_code & ec, std::size_t transferred) + { + if(ec) + { + LogPrint(eLogError, "NTCP2: socks5 read error ", ec.message()); + timer->cancel(); + conn->Terminate(); + return; + } + else if(transferred == 2) + { + if((*readbuff)[1] == 0x00) + { + AfterSocksHandshake(conn, timer, host, port, addrtype); + return; + } + else if ((*readbuff)[1] == 0xff) + { + LogPrint(eLogError, "NTCP2: socks5 proxy rejected authentication"); + timer->cancel(); + conn->Terminate(); + return; + } + LogPrint(eLogError, "NTCP2:", (int)(*readbuff)[1]); + } + LogPrint(eLogError, "NTCP2: socks5 server gave invalid response"); + timer->cancel(); + conn->Terminate(); + }); + break; + } + case eHTTPProxy: + { + i2p::http::HTTPReq req; + req.method = "CONNECT"; + req.version ="HTTP/1.1"; + if(addrtype == eIP6Address) + req.uri = "[" + host + "]:" + std::to_string(port); + else + req.uri = host + ":" + std::to_string(port); + + boost::asio::streambuf writebuff; + std::ostream out(&writebuff); + out << req.to_string(); + + boost::asio::async_write(conn->GetSocket(), writebuff.data(), boost::asio::transfer_all(), + [](const boost::system::error_code & ec, std::size_t transferred) + { + (void) transferred; + if(ec) + LogPrint(eLogError, "NTCP2: http proxy write error ", ec.message()); + }); + + boost::asio::streambuf * readbuff = new boost::asio::streambuf; + boost::asio::async_read_until(conn->GetSocket(), *readbuff, "\r\n\r\n", + [this, readbuff, timer, conn] (const boost::system::error_code & ec, std::size_t transferred) + { + if(ec) + { + LogPrint(eLogError, "NTCP2: http proxy read error ", ec.message()); + timer->cancel(); + conn->Terminate(); + } + else + { + readbuff->commit(transferred); + i2p::http::HTTPRes res; + if(res.parse(boost::asio::buffer_cast(readbuff->data()), readbuff->size()) > 0) + { + if(res.code == 200) + { + timer->cancel(); + conn->ClientLogin(); + delete readbuff; + return; + } + else + LogPrint(eLogError, "NTCP2: http proxy rejected request ", res.code); + } + else + LogPrint(eLogError, "NTCP2: http proxy gave malformed response"); + timer->cancel(); + conn->Terminate(); + delete readbuff; + } + }); + break; + } + default: + LogPrint(eLogError, "NTCP2: unknown proxy type, invalid state"); + } + } + + void NTCP2Server::ConnectWithProxy (const std::string& host, uint16_t port, RemoteAddressType addrtype, std::shared_ptr conn) + { + if(!m_ProxyEndpoint) return; + GetService().post([this, host, port, addrtype, conn]() { + if (this->AddNTCP2Session (conn)) + { + + auto timer = std::make_shared(GetService()); + auto timeout = NTCP_CONNECT_TIMEOUT * 5; + conn->SetTerminationTimeout(timeout * 2); + timer->expires_from_now (boost::posix_time::seconds(timeout)); + timer->async_wait ([conn, timeout](const boost::system::error_code& ecode) + { + if (ecode != boost::asio::error::operation_aborted) + { + LogPrint (eLogInfo, "NTCP2: Not connected in ", timeout, " seconds"); + i2p::data::netdb.SetUnreachable (conn->GetRemoteIdentity ()->GetIdentHash (), true); + conn->Terminate (); + } + }); + conn->GetSocket ().async_connect (*m_ProxyEndpoint, std::bind (&NTCP2Server::HandleProxyConnect, this, std::placeholders::_1, conn, timer, host, port, addrtype)); + } + }); + } + + void NTCP2Server::AfterSocksHandshake(std::shared_ptr conn, std::shared_ptr timer, const std::string & host, uint16_t port, RemoteAddressType addrtype) + { + // build request + size_t sz = 0; + auto buff = std::make_shared >(256); + auto readbuff = std::make_shared >(256); + (*buff)[0] = 0x05; + (*buff)[1] = 0x01; + (*buff)[2] = 0x00; + + if(addrtype == eIP4Address) + { + (*buff)[3] = 0x01; + auto addr = boost::asio::ip::address::from_string(host).to_v4(); + auto addrbytes = addr.to_bytes(); + auto addrsize = addrbytes.size(); + memcpy(buff->data () + 4, addrbytes.data(), addrsize); + } + else if (addrtype == eIP6Address) + { + (*buff)[3] = 0x04; + auto addr = boost::asio::ip::address::from_string(host).to_v6(); + auto addrbytes = addr.to_bytes(); + auto addrsize = addrbytes.size(); + memcpy(buff->data () + 4, addrbytes.data(), addrsize); + } + else if (addrtype == eHostname) + { + (*buff)[3] = 0x03; + size_t addrsize = host.size(); + sz = addrsize + 1 + 4; + if (2 + sz > buff->size ()) + { + // too big + return; + } + (*buff)[4] = (uint8_t) addrsize; + memcpy(buff->data() + 5, host.c_str(), addrsize); + } + htobe16buf(buff->data () + sz, port); + sz += 2; + boost::asio::async_write(conn->GetSocket(), boost::asio::buffer(buff->data (), sz), boost::asio::transfer_all(), + [](const boost::system::error_code & ec, std::size_t written) + { + if(ec) + { + LogPrint(eLogError, "NTCP2: failed to write handshake to socks proxy ", ec.message()); + return; + } + }); + + boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(readbuff->data (), 10), + [timer, conn, sz, readbuff](const boost::system::error_code & e, std::size_t transferred) + { + if(e) + { + LogPrint(eLogError, "NTCP2: socks proxy read error ", e.message()); + } + else if(transferred == sz) + { + if((*readbuff)[1] == 0x00) + { + timer->cancel(); + conn->ClientLogin(); + return; + } + } + if(!e) + i2p::data::netdb.SetUnreachable (conn->GetRemoteIdentity ()->GetIdentHash (), true); + timer->cancel(); + conn->Terminate(); + }); + } + } } From 1e9a53da3fead5b1caaea7145ef90eb411bc2ff7 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 4 Mar 2020 15:54:09 -0500 Subject: [PATCH 20/44] delete stream by id for HTTP interface --- libi2pd/Destination.cpp | 10 ++++++++++ libi2pd/Destination.h | 1 + libi2pd/Streaming.cpp | 9 +++++++++ libi2pd/Streaming.h | 1 + 4 files changed, 21 insertions(+) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 6544d120..d4620ed9 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1191,6 +1191,16 @@ namespace client } } + bool ClientDestination::DeleteStream (uint32_t recvStreamID) + { + if (m_StreamingDestination->DeleteStream (recvStreamID)) + return true; + for (auto it: m_StreamingDestinationsByPorts) + if (it.second->DeleteStream (recvStreamID)) + return true; + return false; + } + RunnableClientDestination::RunnableClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map * params): RunnableService ("Destination"), ClientDestination (GetIOService (), keys, isPublic, params) diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index ed3abdfb..23ed5188 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -281,6 +281,7 @@ namespace client // for HTTP only std::vector > GetAllStreams () const; + bool DeleteStream (uint32_t recvStreamID); }; class RunnableClientDestination: private i2p::util::RunnableService, public ClientDestination diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index b5f935fe..97a653f5 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -1128,6 +1128,15 @@ namespace stream } } + bool StreamingDestination::DeleteStream (uint32_t recvStreamID) + { + auto it = m_Streams.find (recvStreamID); + if (it == m_Streams.end ()) + return false; + DeleteStream (it->second); + return true; + } + void StreamingDestination::SetAcceptor (const Acceptor& acceptor) { m_Acceptor = acceptor; // we must set it immediately for IsAcceptorSet diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 3424bb2d..9962ad8d 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -250,6 +250,7 @@ namespace stream std::shared_ptr CreateNewOutgoingStream (std::shared_ptr remote, int port = 0); void DeleteStream (std::shared_ptr stream); + bool DeleteStream (uint32_t recvStreamID); void SetAcceptor (const Acceptor& acceptor); void ResetAcceptor (); bool IsAcceptorSet () const { return m_Acceptor != nullptr; }; From 5eec580727df7d2865f6478ccb21498fafa2556f Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 4 Mar 2020 18:31:22 -0500 Subject: [PATCH 21/44] delete strem from destination upon termination --- libi2pd/Streaming.cpp | 7 ++++--- libi2pd/Streaming.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 97a653f5..3efcfb99 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -86,13 +86,14 @@ namespace stream LogPrint (eLogDebug, "Streaming: Stream deleted"); } - void Stream::Terminate () // shoudl be called from StreamingDestination::Stop only + void Stream::Terminate (bool deleteFromDestination) // shoudl be called from StreamingDestination::Stop only { m_AckSendTimer.cancel (); m_ReceiveTimer.cancel (); m_ResendTimer.cancel (); //CleanUp (); /* Need to recheck - broke working on windows */ - //m_LocalDestination.DeleteStream (shared_from_this ()); + if (deleteFromDestination) + m_LocalDestination.DeleteStream (shared_from_this ()); } void Stream::CleanUp () @@ -993,7 +994,7 @@ namespace stream { std::unique_lock l(m_StreamsMutex); for (auto it: m_Streams) - it.second->Terminate (); + it.second->Terminate (false); // we delete here m_Streams.clear (); m_IncomingStreams.clear (); } diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 9962ad8d..985a7eca 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -180,7 +180,7 @@ namespace stream int GetWindowSize () const { return m_WindowSize; }; int GetRTT () const { return m_RTT; }; - void Terminate (); + void Terminate (bool deleteFromDestination = true); private: From 51d018acc61c84aca55d669a2157fdcf3e8cd4c3 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Thu, 5 Mar 2020 04:14:39 +0300 Subject: [PATCH 22/44] webconsole: add stream closing Signed-off-by: R4SAS --- daemon/HTTPServer.cpp | 180 ++++++++++++++++++++++++++++-------------- daemon/HTTPServer.h | 1 + 2 files changed, 121 insertions(+), 60 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 7dc6a9d2..36e26785 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -54,6 +54,7 @@ namespace http { " body { font: 100%/1.5em sans-serif; margin: 0; padding: 1.5em; background: #FAFAFA; color: #103456; }\r\n" " a, .slide label { text-decoration: none; color: #894C84; }\r\n" " a:hover, .slide label:hover { color: #FAFAFA; background: #894C84; }\r\n" + " a.button { -webkit-appearance: button; -moz-appearance: button; appearance: button; text-decoration: none; color: initial;}\r\n" " .header { font-size: 2.5em; text-align: center; margin: 1.5em 0; color: #894C84; }\r\n" " .wrapper { margin: 0 auto; padding: 1em; max-width: 60em; }\r\n" " .left { float: left; position: absolute; }\r\n" @@ -64,10 +65,11 @@ namespace http { " .tunnel.building { color: #434343; }\r\n" " caption { font-size: 1.5em; text-align: center; color: #894C84; }\r\n" " table { width: 100%; border-collapse: collapse; text-align: center; }\r\n" - " .slide p, .slide [type='checkbox']{ display:none; }\r\n" - " .slide [type='checkbox']:checked ~ p { display:block; margin-top: 0; padding: 0; }\r\n" + " .slide p, .slide [type='checkbox'] { display: none; }\r\n" + " .slide [type='checkbox']:checked ~ p { display: block; margin-top: 0; padding: 0; }\r\n" " .disabled:after { color: #D33F3F; content: \"Disabled\" }\r\n" " .enabled:after { color: #56B734; content: \"Enabled\" }\r\n" + " .streamdest { width: 120px; max-width: 240px; overflow: hidden; text-overflow: ellipsis;}\r\n" "\r\n"; const char HTTP_PAGE_TUNNELS[] = "tunnels"; @@ -89,10 +91,12 @@ namespace http { const char HTTP_COMMAND_RUN_PEER_TEST[] = "run_peer_test"; const char HTTP_COMMAND_RELOAD_CONFIG[] = "reload_config"; const char HTTP_COMMAND_LOGLEVEL[] = "set_loglevel"; + const char HTTP_COMMAND_KILLSTREAM[] = "closestream"; const char HTTP_PARAM_SAM_SESSION_ID[] = "id"; const char HTTP_PARAM_ADDRESS[] = "address"; static std::string ConvertTime (uint64_t time); + std::map HTTPConnection::m_Tokens; static void ShowUptime (std::stringstream& s, int seconds) { @@ -203,10 +207,7 @@ namespace http { s << "ERROR: " << string << "
\r\n"; } - void ShowStatus ( - std::stringstream& s, - bool includeHiddenContent, - i2p::http::OutputFormatEnum outputFormat) + void ShowStatus (std::stringstream& s, bool includeHiddenContent, i2p::http::OutputFormatEnum outputFormat) { s << "Uptime: "; ShowUptime(s, i2p::context.GetUptime ()); @@ -253,12 +254,12 @@ namespace http { ShowTraffic (s, i2p::transport::transports.GetTotalTransitTransmittedBytes ()); s << " (" << (double) i2p::transport::transports.GetTransitBandwidth () / 1024 << " KiB/s)
\r\n"; s << "Data path: " << i2p::fs::GetDataDir() << "
\r\n"; - s << "
"; - if((outputFormat==OutputFormatEnum::forWebConsole)||!includeHiddenContent) { - s << "\r\n\r\n

\r\n"; - } - if(includeHiddenContent) { - s << "Router Ident: " << i2p::context.GetRouterInfo().GetIdentHashBase64() << "
\r\n"; + s << "

"; + if((outputFormat==OutputFormatEnum::forWebConsole)||!includeHiddenContent) { + s << "\r\n\r\n

\r\n"; + } + if(includeHiddenContent) { + s << "Router Ident: " << i2p::context.GetRouterInfo().GetIdentHashBase64() << "
\r\n"; s << "Router Family: " << i2p::context.GetRouterInfo().GetProperty("family") << "
\r\n"; s << "Router Caps: " << i2p::context.GetRouterInfo().GetProperty("caps") << "
\r\n"; s << "Our external address:" << "
\r\n" ; @@ -292,12 +293,12 @@ namespace http { } s << address->host.to_string() << ":" << address->port << "
\r\n"; } - } + } s << "

\r\n
\r\n"; - if(outputFormat==OutputFormatEnum::forQtUi) { - s << "
"; - } - s << "Routers: " << i2p::data::netdb.GetNumRouters () << " "; + if(outputFormat==OutputFormatEnum::forQtUi) { + s << "
"; + } + s << "Routers: " << i2p::data::netdb.GetNumRouters () << " "; s << "Floodfills: " << i2p::data::netdb.GetNumFloodfills () << " "; s << "LeaseSets: " << i2p::data::netdb.GetNumLeaseSets () << "
\r\n"; @@ -308,17 +309,17 @@ namespace http { s << "Client Tunnels: " << std::to_string(clientTunnelCount) << " "; s << "Transit Tunnels: " << std::to_string(transitTunnelCount) << "
\r\n
\r\n"; - if(outputFormat==OutputFormatEnum::forWebConsole) { - s << "\r\n"; - s << "\r\n"; - s << "\r\n"; - s << "\r\n"; - s << "\r\n"; - s << "\r\n"; - bool i2pcontrol; i2p::config::GetOption("i2pcontrol.enabled", i2pcontrol); - s << "\r\n"; - s << "
Services
ServiceState
" << "HTTP Proxy" << "
" << "SOCKS Proxy" << "
" << "BOB" << "
" << "SAM" << "
" << "I2CP" << "
" << "I2PControl" << "
\r\n"; - } + if(outputFormat==OutputFormatEnum::forWebConsole) { + s << "\r\n"; + s << "\r\n"; + s << "\r\n"; + s << "\r\n"; + s << "\r\n"; + s << "\r\n"; + bool i2pcontrol; i2p::config::GetOption("i2pcontrol.enabled", i2pcontrol); + s << "\r\n"; + s << "
Services
ServiceState
" << "HTTP Proxy" << "
" << "SOCKS Proxy" << "
" << "BOB" << "
" << "SAM" << "
" << "I2CP" << "
" << "I2PControl" << "
\r\n"; + } } void ShowLocalDestinations (std::stringstream& s) @@ -352,7 +353,7 @@ namespace http { static void ShowLeaseSetDestination (std::stringstream& s, std::shared_ptr dest) { - s << "Base64:
\r\n
\r\n
\r\n"; if (dest->IsEncryptedLeaseSet ()) { @@ -403,19 +404,21 @@ namespace http { s << "
\r\n"; } - void ShowLocalDestination (std::stringstream& s, const std::string& b32) + void ShowLocalDestination (std::stringstream& s, const std::string& b32, uint32_t token) { s << "Local Destination:
\r\n
\r\n"; i2p::data::IdentHash ident; ident.FromBase32 (b32); auto dest = i2p::client::context.FindLocalDestination (ident); + if (dest) { ShowLeaseSetDestination (s, dest); // show streams - s << "\r\n"; - s << ""; - s << ""; + s << "
Streams
StreamIDDestination
\r\n\r\n\r\n"; + s << ""; + s << ""; s << ""; s << ""; s << ""; @@ -424,13 +427,20 @@ namespace http { s << ""; s << ""; s << ""; - s << "\r\n"; + s << "\r\n\r\n\r\n"; for (const auto& it: dest->GetAllStreams ()) { + auto streamDest = i2p::client::context.GetAddressBook ().ToAddress(it->GetRemoteIdentity ()); s << ""; - s << ""; - s << ""; + s << ""; + if (it->GetRecvStreamID ()) { + s << ""; + } else { + s << ""; s << ""; s << ""; s << ""; @@ -441,7 +451,7 @@ namespace http { s << ""; s << "\r\n"; } - s << "
Streams
StreamID"; // Stream closing button column + s << "DestinationSentReceivedOutRTTWindowStatus
" << it->GetSendStreamID () << "" << i2p::client::context.GetAddressBook ().ToAddress(it->GetRemoteIdentity ()) << "" << it->GetRecvStreamID () << ""; + } + s << "" << streamDest << "" << it->GetNumSentBytes () << "" << it->GetNumReceivedBytes () << "" << it->GetSendQueueSize () << "" << (int)it->GetStatus () << "
"; + s << "\r\n"; } } @@ -858,7 +868,8 @@ namespace http { m_Socket->close (); } - bool HTTPConnection::CheckAuth (const HTTPReq & req) { + bool HTTPConnection::CheckAuth (const HTTPReq & req) + { /* method #1: http://user:pass@127.0.0.1:7070/ */ if (req.uri.find('@') != std::string::npos) { URL url; @@ -920,7 +931,7 @@ namespace http { } else if (req.uri.find("cmd=") != std::string::npos) { HandleCommand (req, res, s); } else { - ShowStatus (s, true, i2p::http::OutputFormatEnum::forWebConsole); + ShowStatus (s, true, i2p::http::OutputFormatEnum::forWebConsole); res.add_header("Refresh", "10"); } ShowPageTail (s); @@ -930,7 +941,23 @@ namespace http { SendReply (res, content); } - std::map HTTPConnection::m_Tokens; + uint32_t HTTPConnection::CreateToken () + { + uint32_t token; + RAND_bytes ((uint8_t *)&token, 4); + token &= 0x7FFFFFFF; // clear first bit + auto ts = i2p::util::GetSecondsSinceEpoch (); + for (auto it = m_Tokens.begin (); it != m_Tokens.end (); ) + { + if (ts > it->second + TOKEN_EXPIRATION_TIMEOUT) + it = m_Tokens.erase (it); + else + ++it; + } + m_Tokens[token] = ts; + return token; + } + void HTTPConnection::HandlePage (const HTTPReq& req, HTTPRes& res, std::stringstream& s) { std::map params; @@ -947,18 +974,7 @@ namespace http { ShowTunnels (s); else if (page == HTTP_PAGE_COMMANDS) { - uint32_t token; - RAND_bytes ((uint8_t *)&token, 4); - token &= 0x7FFFFFFF; // clear first bit - auto ts = i2p::util::GetSecondsSinceEpoch (); - for (auto it = m_Tokens.begin (); it != m_Tokens.end (); ) - { - if (ts > it->second + TOKEN_EXPIRATION_TIMEOUT) - it = m_Tokens.erase (it); - else - ++it; - } - m_Tokens[token] = ts; + uint32_t token = CreateToken (); ShowCommands (s, token); } else if (page == HTTP_PAGE_TRANSIT_TUNNELS) @@ -966,7 +982,10 @@ namespace http { else if (page == HTTP_PAGE_LOCAL_DESTINATIONS) ShowLocalDestinations (s); else if (page == HTTP_PAGE_LOCAL_DESTINATION) - ShowLocalDestination (s, params["b32"]); + { + uint32_t token = CreateToken (); + ShowLocalDestination (s, params["b32"], token); + } else if (page == HTTP_PAGE_I2CP_LOCAL_DESTINATION) ShowI2CPLocalDestination (s, params["i2cp_id"]); else if (page == HTTP_PAGE_SAM_SESSIONS) @@ -992,7 +1011,10 @@ namespace http { url.parse(req.uri); url.parse_query(params); + std::string webroot; i2p::config::GetOption("http.webroot", webroot); + std::string redirect = "5; url=" + webroot + "?page=commands"; std::string token = params["token"]; + if (token.empty () || m_Tokens.find (std::stoi (token)) == m_Tokens.end ()) { ShowError(s, "Invalid token"); @@ -1008,36 +1030,74 @@ namespace http { i2p::context.SetAcceptsTunnels (true); else if (cmd == HTTP_COMMAND_DISABLE_TRANSIT) i2p::context.SetAcceptsTunnels (false); - else if (cmd == HTTP_COMMAND_SHUTDOWN_START) { + else if (cmd == HTTP_COMMAND_SHUTDOWN_START) + { i2p::context.SetAcceptsTunnels (false); #if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY)) Daemon.gracefulShutdownInterval = 10*60; #elif defined(WIN32_APP) i2p::win32::GracefulShutdown (); #endif - } else if (cmd == HTTP_COMMAND_SHUTDOWN_CANCEL) { + } + else if (cmd == HTTP_COMMAND_SHUTDOWN_CANCEL) + { i2p::context.SetAcceptsTunnels (true); #if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY)) Daemon.gracefulShutdownInterval = 0; #elif defined(WIN32_APP) i2p::win32::StopGracefulShutdown (); #endif - } else if (cmd == HTTP_COMMAND_SHUTDOWN_NOW) { + } + else if (cmd == HTTP_COMMAND_SHUTDOWN_NOW) + { #ifndef WIN32_APP Daemon.running = false; #else i2p::win32::StopWin32App (); #endif - } else if (cmd == HTTP_COMMAND_LOGLEVEL){ + } + else if (cmd == HTTP_COMMAND_LOGLEVEL) + { std::string level = params["level"]; SetLogLevel (level); - } else { + } + else if (cmd == HTTP_COMMAND_KILLSTREAM) + { + std::string b32 = params["b32"]; + uint32_t streamID = std::stoul(params["streamID"], nullptr); + + i2p::data::IdentHash ident; + ident.FromBase32 (b32); + auto dest = i2p::client::context.FindLocalDestination (ident); + + if (streamID) + { + if (dest) + { + if(dest->DeleteStream (streamID)) + s << "SUCCESS: Stream closed

\r\n"; + else + s << "ERROR: Stream not found or already was closed

\r\n"; + } + else + s << "ERROR: Destination not found

\r\n"; + } + else + s << "ERROR: StreamID can be null

\r\n"; + + s << "Return to destination page
\r\n"; + s << "

You will be redirected back in 5 seconds"; + redirect = "5; url=" + webroot + "?page=local_destination&b32=" + b32; + res.add_header("Refresh", redirect.c_str()); + return; + } + else + { res.code = 400; ShowError(s, "Unknown command: " + cmd); return; } - std::string webroot; i2p::config::GetOption("http.webroot", webroot); - std::string redirect = "5; url=" + webroot + "?page=commands"; + s << "SUCCESS: Command accepted

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

You will be redirected in 5 seconds"; diff --git a/daemon/HTTPServer.h b/daemon/HTTPServer.h index 3d32ed2b..f5ac95fc 100644 --- a/daemon/HTTPServer.h +++ b/daemon/HTTPServer.h @@ -35,6 +35,7 @@ namespace http void HandlePage (const HTTPReq & req, HTTPRes & res, std::stringstream& data); void HandleCommand (const HTTPReq & req, HTTPRes & res, std::stringstream& data); void SendReply (HTTPRes & res, std::string & content); + uint32_t CreateToken (); private: From dd9b5faa5c072c24aadf4ca6c31d6ac00be992e1 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 5 Mar 2020 18:44:15 -0500 Subject: [PATCH 23/44] fixed crash on termination --- libi2pd_client/I2CP.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index a14588a8..c09b7f4d 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -814,8 +814,11 @@ namespace client { m_IsRunning = false; m_Acceptor.cancel (); - for (auto& it: m_Sessions) - it.second->Stop (); + { + auto sessions = m_Sessions; + for (auto& it: sessions) + it.second->Stop (); + } m_Sessions.clear (); m_Service.stop (); if (m_Thread) From 64da62dbe69be040215babad89fc481f0e429c00 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 7 Mar 2020 18:46:40 -0500 Subject: [PATCH 24/44] alsways store latest symmkey --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 33 ++++++++++++++--------- libi2pd/ECIESX25519AEADRatchetSession.h | 4 +-- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index d2d07343..a066dc17 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -39,25 +39,28 @@ namespace garlic return m_KeyData.GetTag (); } - const uint8_t * RatchetTagSet::GetSymmKey (int index) + void RatchetTagSet::GetSymmKey (int index, uint8_t * key) { - // TODO: store intermediate keys - if (m_NextSymmKeyIndex > 0 && index == m_NextSymmKeyIndex) + if (m_NextSymmKeyIndex > 0 && index >= m_NextSymmKeyIndex) { - i2p::crypto::HKDF (m_CurrentSymmKeyCK, nullptr, 0, "SymmetricRatchet", m_CurrentSymmKeyCK); - m_NextSymmKeyIndex++; + auto num = index + 1 - m_NextSymmKeyIndex; + for (int i = 0; i < num; i++) + i2p::crypto::HKDF (m_CurrentSymmKeyCK, nullptr, 0, "SymmetricRatchet", m_CurrentSymmKeyCK); + m_NextSymmKeyIndex += num; + memcpy (key, m_CurrentSymmKeyCK + 32, 32); } else - CalculateSymmKeyCK (index); - return m_CurrentSymmKeyCK + 32; + CalculateSymmKeyCK (index, key); } - void RatchetTagSet::CalculateSymmKeyCK (int index) + void RatchetTagSet::CalculateSymmKeyCK (int index, uint8_t * key) { - i2p::crypto::HKDF (m_SymmKeyCK, nullptr, 0, "SymmetricRatchet", m_CurrentSymmKeyCK); // keydata_0 = HKDF(symmKey_ck, SYMMKEY_CONSTANT, "SymmetricRatchet", 64) + // TODO: store intermediate keys + uint8_t currentSymmKeyCK[64]; + i2p::crypto::HKDF (m_SymmKeyCK, nullptr, 0, "SymmetricRatchet", currentSymmKeyCK); // keydata_0 = HKDF(symmKey_ck, SYMMKEY_CONSTANT, "SymmetricRatchet", 64) for (int i = 0; i < index; i++) - i2p::crypto::HKDF (m_CurrentSymmKeyCK, nullptr, 0, "SymmetricRatchet", m_CurrentSymmKeyCK); // keydata_n = HKDF(symmKey_chainKey_(n-1), SYMMKEY_CONSTANT, "SymmetricRatchet", 64) - m_NextSymmKeyIndex = index + 1; + i2p::crypto::HKDF (currentSymmKeyCK, nullptr, 0, "SymmetricRatchet", currentSymmKeyCK); // keydata_n = HKDF(symmKey_chainKey_(n-1), SYMMKEY_CONSTANT, "SymmetricRatchet", 64) + memcpy (key, currentSymmKeyCK + 32, 32); } ECIESX25519AEADRatchetSession::ECIESX25519AEADRatchetSession (GarlicDestination * owner): @@ -373,7 +376,9 @@ namespace garlic memcpy (out, &tag, 8); // ad = The session tag, 8 bytes // ciphertext = ENCRYPT(k, n, payload, ad) - if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, out, 8, m_SendTagset.GetSymmKey (index), nonce, out + 8, outLen - 8, true)) // encrypt + uint8_t key[32]; + m_SendTagset.GetSymmKey (index, key); + if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, out, 8, key, nonce, out + 8, outLen - 8, true)) // encrypt { LogPrint (eLogWarning, "Garlic: Payload section AEAD encryption failed"); return false; @@ -387,7 +392,9 @@ namespace garlic CreateNonce (index, nonce); // tag's index len -= 8; // tag std::vector payload (len - 16); - if (!i2p::crypto::AEADChaCha20Poly1305 (buf + 8, len - 16, buf, 8, m_ReceiveTagset.GetSymmKey (index), nonce, payload.data (), len - 16, false)) // decrypt + uint8_t key[32]; + m_ReceiveTagset.GetSymmKey (index, key); + if (!i2p::crypto::AEADChaCha20Poly1305 (buf + 8, len - 16, buf, 8, key, nonce, payload.data (), len - 16, false)) // decrypt { LogPrint (eLogWarning, "Garlic: Payload section AEAD decryption failed"); return false; diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index e5836cd4..f23c569c 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -22,11 +22,11 @@ namespace garlic void NextSessionTagRatchet (); uint64_t GetNextSessionTag (); int GetNextIndex () const { return m_NextIndex; }; - const uint8_t * GetSymmKey (int index); + void GetSymmKey (int index, uint8_t * key); private: - void CalculateSymmKeyCK (int index); + void CalculateSymmKeyCK (int index, uint8_t * key); private: From 4adc741de319ee2afc6f51f180fff33db63869b6 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 8 Mar 2020 18:13:41 -0400 Subject: [PATCH 25/44] send DeliveryStatusMsg for LeaseSet --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 53 ++++++++++++++++++-- libi2pd/ECIESX25519AEADRatchetSession.h | 1 + libi2pd/Garlic.cpp | 60 ++++++++++++++--------- libi2pd/Garlic.h | 11 +++-- 4 files changed, 96 insertions(+), 29 deletions(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index a066dc17..5f2eb5c8 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -6,6 +6,8 @@ #include "Tag.h" #include "I2PEndian.h" #include "Timestamp.h" +#include "Tunnel.h" +#include "TunnelPool.h" #include "ECIESX25519AEADRatchetSession.h" namespace i2p @@ -460,12 +462,22 @@ namespace garlic std::vector ECIESX25519AEADRatchetSession::CreatePayload (std::shared_ptr msg) { + uint64_t ts = i2p::util::GetMillisecondsSinceEpoch (); size_t payloadLen = 7; // datatime if (msg && m_Destination) payloadLen += msg->GetPayloadLength () + 13 + 32; - auto leaseSet = CreateDatabaseStoreMsg (GetOwner ()->GetLeaseSet ()); - if (leaseSet) + auto leaseSet = (GetLeaseSetUpdateStatus () == eLeaseSetUpdated) ? CreateDatabaseStoreMsg (GetOwner ()->GetLeaseSet ()) : nullptr; + std::shared_ptr deliveryStatus; + if (leaseSet) + { payloadLen += leaseSet->GetPayloadLength () + 13; + deliveryStatus = CreateEncryptedDeliveryStatusMsg (leaseSet->GetMsgID ()); + payloadLen += deliveryStatus->GetPayloadLength () + 49; + if (GetLeaseSetUpdateMsgID ()) GetOwner ()->RemoveDeliveryStatusSession (GetLeaseSetUpdateMsgID ()); // remove previous + SetLeaseSetUpdateStatus (eLeaseSetSubmitted); + SetLeaseSetUpdateMsgID (leaseSet->GetMsgID ()); + SetLeaseSetSubmissionTime (ts); + } uint8_t paddingSize; RAND_bytes (&paddingSize, 1); paddingSize &= 0x0F; paddingSize++; // 1 - 16 @@ -475,10 +487,13 @@ namespace garlic // DateTime v[offset] = eECIESx25519BlkDateTime; offset++; htobe16buf (v.data () + offset, 4); offset += 2; - htobe32buf (v.data () + offset, i2p::util::GetSecondsSinceEpoch ()); offset += 4; + htobe32buf (v.data () + offset, ts/1000); offset += 4; // in seconds // LeaseSet if (leaseSet) offset += CreateGarlicClove (leaseSet, v.data () + offset, payloadLen - offset); + // DeliveryStatus + if (deliveryStatus) + offset += CreateDeliveryStatusClove (deliveryStatus, v.data () + offset, payloadLen - offset); // msg if (msg && m_Destination) offset += CreateGarlicClove (msg, v.data () + offset, payloadLen - offset, true); @@ -513,6 +528,38 @@ namespace garlic return cloveSize + 3; } + size_t ECIESX25519AEADRatchetSession::CreateDeliveryStatusClove (std::shared_ptr msg, uint8_t * buf, size_t len) + { + uint16_t cloveSize = msg->GetPayloadLength () + 9 + 37 /* delivery instruction */; + if ((int)len < cloveSize + 3) return 0; + buf[0] = eECIESx25519BlkGalicClove; // clove type + htobe16buf (buf + 1, cloveSize); // size + buf += 3; + if (GetOwner ()) + { + auto inboundTunnel = GetOwner ()->GetTunnelPool ()->GetNextInboundTunnel (); + if (inboundTunnel) + { + // delivery instructions + *buf = eGarlicDeliveryTypeTunnel << 5; buf++; // delivery instructions flag tunnel + // hash and tunnelID sequence is reversed for Garlic + memcpy (buf, inboundTunnel->GetNextIdentHash (), 32); buf += 32;// To Hash + htobe32buf (buf, inboundTunnel->GetNextTunnelID ()); buf += 4;// tunnelID + } + else + { + LogPrint (eLogError, "Garlic: No inbound tunnels in the pool for DeliveryStatus"); + return 0; + } + htobe32buf (buf + 1, msg->GetMsgID ()); // msgID + htobe32buf (buf + 5, msg->GetExpiration ()/1000); // expiration in seconds + memcpy (buf + 9, msg->GetPayload (), msg->GetPayloadLength ()); + } + else + return 0; + return cloveSize + 3; + } + void ECIESX25519AEADRatchetSession::GenerateMoreReceiveTags (int numTags) { for (int i = 0; i < numTags; i++) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index f23c569c..4d273c13 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -107,6 +107,7 @@ namespace garlic std::vector CreatePayload (std::shared_ptr msg); size_t CreateGarlicClove (std::shared_ptr msg, uint8_t * buf, size_t len, bool isDestination = false); + size_t CreateDeliveryStatusClove (std::shared_ptr msg, uint8_t * buf, size_t len); void GenerateMoreReceiveTags (int numTags); diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 45c97172..dd63572c 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -58,6 +58,34 @@ namespace garlic m_SharedRoutingPath = path; } + bool GarlicRoutingSession::MessageConfirmed (uint32_t msgID) + { + if (msgID == GetLeaseSetUpdateMsgID ()) + { + SetLeaseSetUpdateStatus (eLeaseSetUpToDate); + SetLeaseSetUpdateMsgID (0); + LogPrint (eLogInfo, "Garlic: LeaseSet update confirmed"); + return true; + } + return false; + } + + std::shared_ptr GarlicRoutingSession::CreateEncryptedDeliveryStatusMsg (uint32_t msgID) + { + auto msg = CreateDeliveryStatusMsg (msgID); + if (GetOwner ()) + { + //encrypt + uint8_t key[32], tag[32]; + RAND_bytes (key, 32); // random session key + RAND_bytes (tag, 32); // random session tag + GetOwner ()->SubmitSessionKey (key, tag); + ElGamalAESSession garlic (key, tag); + msg = garlic.WrapSingleMessage (msg); + } + return msg; + } + ElGamalAESSession::ElGamalAESSession (GarlicDestination * owner, std::shared_ptr destination, int numTags, bool attachLeaseSet): GarlicRoutingSession (owner, attachLeaseSet), @@ -289,19 +317,12 @@ namespace garlic htobe32buf (buf + size, inboundTunnel->GetNextTunnelID ()); // tunnelID size += 4; // create msg - auto msg = CreateDeliveryStatusMsg (msgID); - if (GetOwner ()) - { - //encrypt - uint8_t key[32], tag[32]; - RAND_bytes (key, 32); // random session key - RAND_bytes (tag, 32); // random session tag - GetOwner ()->SubmitSessionKey (key, tag); - ElGamalAESSession garlic (key, tag); - msg = garlic.WrapSingleMessage (msg); - } - memcpy (buf + size, msg->GetBuffer (), msg->GetLength ()); - size += msg->GetLength (); + auto msg = CreateEncryptedDeliveryStatusMsg (msgID); + if (msg) + { + memcpy (buf + size, msg->GetBuffer (), msg->GetLength ()); + size += msg->GetLength (); + } // fill clove uint64_t ts = i2p::util::GetMillisecondsSinceEpoch () + 8000; // 8 sec uint32_t cloveID; @@ -334,17 +355,12 @@ namespace garlic return tags; } - void ElGamalAESSession::MessageConfirmed (uint32_t msgID) + bool ElGamalAESSession::MessageConfirmed (uint32_t msgID) { TagsConfirmed (msgID); - if (msgID == GetLeaseSetUpdateMsgID ()) - { - SetLeaseSetUpdateStatus (eLeaseSetUpToDate); - SetLeaseSetUpdateMsgID (0); - LogPrint (eLogInfo, "Garlic: LeaseSet update confirmed"); - } - else + if (!GarlicRoutingSession::MessageConfirmed (msgID)) CleanupExpiredTags (); + return true; } void ElGamalAESSession::TagsConfirmed (uint32_t msgID) @@ -775,7 +791,7 @@ namespace garlic void GarlicDestination::HandleDeliveryStatusMessage (uint32_t msgID) { - ElGamalAESSessionPtr session; + GarlicRoutingSessionPtr session; { std::unique_lock l(m_DeliveryStatusSessionsMutex); auto it = m_DeliveryStatusSessions.find (msgID); diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index 9c256b48..be0ac117 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -104,7 +104,8 @@ namespace garlic virtual ~GarlicRoutingSession (); virtual std::shared_ptr WrapSingleMessage (std::shared_ptr msg) = 0; virtual bool CleanupUnconfirmedTags () { return false; }; // for I2CP, override in ElGamalAESSession - + virtual bool MessageConfirmed (uint32_t msgID); + void SetLeaseSetUpdated () { if (m_LeaseSetUpdateStatus != eLeaseSetDoNotSend) m_LeaseSetUpdateStatus = eLeaseSetUpdated; @@ -118,7 +119,7 @@ namespace garlic GarlicDestination * GetOwner () const { return m_Owner; } void SetOwner (GarlicDestination * owner) { m_Owner = owner; } - + protected: LeaseSetUpdateStatus GetLeaseSetUpdateStatus () const { return m_LeaseSetUpdateStatus; } @@ -127,6 +128,8 @@ namespace garlic void SetLeaseSetUpdateMsgID (uint32_t msgID) { m_LeaseSetUpdateMsgID = msgID; } void SetLeaseSetSubmissionTime (uint64_t ts) { m_LeaseSetSubmissionTime = ts; } + std::shared_ptr CreateEncryptedDeliveryStatusMsg (uint32_t msgID); + private: GarlicDestination * m_Owner; @@ -165,7 +168,7 @@ namespace garlic std::shared_ptr WrapSingleMessage (std::shared_ptr msg); - void MessageConfirmed (uint32_t msgID); + bool MessageConfirmed (uint32_t msgID); bool CleanupExpiredTags (); // returns true if something left bool CleanupUnconfirmedTags (); // returns true if something has been deleted @@ -267,7 +270,7 @@ namespace garlic std::unordered_map m_ECIESx25519Tags; // session tag -> session // DeliveryStatus std::mutex m_DeliveryStatusSessionsMutex; - std::unordered_map m_DeliveryStatusSessions; // msgID -> session + std::unordered_map m_DeliveryStatusSessions; // msgID -> session public: From 3c534798643d9b0e7f7a529b24beacd679732281 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 8 Mar 2020 20:58:59 -0400 Subject: [PATCH 26/44] update LeaseSet for ECIESX25519AEADRatchet sessions --- libi2pd/Garlic.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index dd63572c..9ac5540f 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -810,8 +810,12 @@ namespace garlic void GarlicDestination::SetLeaseSetUpdated () { - std::unique_lock l(m_SessionsMutex); - for (auto& it: m_Sessions) + { + std::unique_lock l(m_SessionsMutex); + for (auto& it: m_Sessions) + it.second->SetLeaseSetUpdated (); + } + for (auto& it: m_ECIESx25519Sessions) it.second->SetLeaseSetUpdated (); } From ee73ee365f5d02a4fc29832745f70a381b085aa1 Mon Sep 17 00:00:00 2001 From: user Date: Tue, 10 Mar 2020 21:49:04 +0800 Subject: [PATCH 27/44] some work on qt --- .gitignore | 4 + qt/i2pd_qt/DelayedSaveManager.cpp | 3 + qt/i2pd_qt/DelayedSaveManager.h | 24 +++++ qt/i2pd_qt/DelayedSaveManagerImpl.cpp | 140 ++++++++++++++++++++++++++ qt/i2pd_qt/DelayedSaveManagerImpl.h | 82 +++++++++++++++ qt/i2pd_qt/Saver.cpp | 6 ++ qt/i2pd_qt/Saver.h | 22 ++++ qt/i2pd_qt/SaverImpl.cpp | 79 +++++++++++++++ qt/i2pd_qt/SaverImpl.h | 33 ++++++ qt/i2pd_qt/TunnelPane.cpp | 2 +- qt/i2pd_qt/i2pd_qt.pro | 14 ++- qt/i2pd_qt/mainwindow.cpp | 103 ++++++++----------- qt/i2pd_qt/mainwindow.h | 29 ++++-- 13 files changed, 466 insertions(+), 75 deletions(-) create mode 100644 qt/i2pd_qt/DelayedSaveManager.cpp create mode 100644 qt/i2pd_qt/DelayedSaveManager.h create mode 100644 qt/i2pd_qt/DelayedSaveManagerImpl.cpp create mode 100644 qt/i2pd_qt/DelayedSaveManagerImpl.h create mode 100644 qt/i2pd_qt/Saver.cpp create mode 100644 qt/i2pd_qt/Saver.h create mode 100644 qt/i2pd_qt/SaverImpl.cpp create mode 100644 qt/i2pd_qt/SaverImpl.h diff --git a/.gitignore b/.gitignore index c2db70e0..68aea504 100644 --- a/.gitignore +++ b/.gitignore @@ -264,3 +264,7 @@ qt/i2pd_qt/*.ui_* #unknown android stuff android/libs/ + +#various logs +*LOGS/ + diff --git a/qt/i2pd_qt/DelayedSaveManager.cpp b/qt/i2pd_qt/DelayedSaveManager.cpp new file mode 100644 index 00000000..8e17d111 --- /dev/null +++ b/qt/i2pd_qt/DelayedSaveManager.cpp @@ -0,0 +1,3 @@ +#include "DelayedSaveManager.h" + +DelayedSaveManager::DelayedSaveManager(){} diff --git a/qt/i2pd_qt/DelayedSaveManager.h b/qt/i2pd_qt/DelayedSaveManager.h new file mode 100644 index 00000000..9a9a997b --- /dev/null +++ b/qt/i2pd_qt/DelayedSaveManager.h @@ -0,0 +1,24 @@ +#ifndef DELAYEDSAVEMANAGER_H +#define DELAYEDSAVEMANAGER_H + +#include "Saver.h" + +class DelayedSaveManager +{ +public: + DelayedSaveManager(); + + virtual void setSaver(Saver* saver)=0; + + typedef unsigned int DATA_SERIAL_TYPE; + + virtual void delayedSave(DATA_SERIAL_TYPE dataSerial, bool needsTunnelFocus, std::string tunnelNameToFocus)=0; + + //returns false iff save failed + virtual bool appExiting()=0; + + virtual bool needsFocusOnTunnel()=0; + virtual std::string getTunnelNameToFocus()=0; +}; + +#endif // DELAYEDSAVEMANAGER_H diff --git a/qt/i2pd_qt/DelayedSaveManagerImpl.cpp b/qt/i2pd_qt/DelayedSaveManagerImpl.cpp new file mode 100644 index 00000000..5588d7e9 --- /dev/null +++ b/qt/i2pd_qt/DelayedSaveManagerImpl.cpp @@ -0,0 +1,140 @@ +#include "DelayedSaveManagerImpl.h" + +DelayedSaveManagerImpl::DelayedSaveManagerImpl() : + saver(nullptr), + lastDataSerialSeen(DelayedSaveManagerImpl::INITIAL_DATA_SERIAL), + lastSaveStartedTimestamp(A_VERY_OBSOLETE_TIMESTAMP), + exiting(false), + thread(new DelayedSaveThread(this)) +{ +} + +void DelayedSaveManagerImpl::setSaver(Saver* saver) { + this->saver = saver; +} + +void DelayedSaveManagerImpl::start() { + thread->start(); +} + +bool DelayedSaveManagerImpl::isSaverValid() { + return saver != nullptr; +} + +void DelayedSaveManagerImpl::delayedSave(DATA_SERIAL_TYPE dataSerial, bool focusOnTunnel, std::string tunnelNameToFocus) { + if(lastDataSerialSeen==dataSerial)return; + this->focusOnTunnel = focusOnTunnel; + this->tunnelNameToFocus = tunnelNameToFocus; + lastDataSerialSeen=dataSerial; + assert(isSaverValid()); + TIMESTAMP_TYPE now = getTime(); + TIMESTAMP_TYPE wakeTime = lastSaveStartedTimestamp + DelayedSaveThread::WAIT_TIME_MILLIS; + if(now < wakeTime) { + //defer save until lastSaveStartedTimestamp + DelayedSaveThread::WAIT_TIME_MILLIS + thread->deferSaveUntil(wakeTime); + return; + } + lastSaveStartedTimestamp = now; + thread->startSavingNow(); +} + +bool DelayedSaveManagerImpl::appExiting() { + exiting=true; + thread->wakeThreadAndJoinThread(); + assert(isSaverValid()); + saver->save(false, ""); + return true; +} + +DelayedSaveThread::DelayedSaveThread(DelayedSaveManagerImpl* delayedSaveManagerImpl_): + delayedSaveManagerImpl(delayedSaveManagerImpl_), + mutex(new QMutex()), + waitCondition(new QWaitCondition()), + saveNow(false), + defer(false) +{ + mutex->lock(); +} + +DelayedSaveThread::~DelayedSaveThread(){ + mutex->unlock(); + delete mutex; + delete waitCondition; +} + +void DelayedSaveThread::run() { + forever { + if(delayedSaveManagerImpl->isExiting())return; + waitCondition->wait(mutex, WAIT_TIME_MILLIS); + if(delayedSaveManagerImpl->isExiting())return; + Saver* saver = delayedSaveManagerImpl->getSaver(); + assert(saver!=nullptr); + if(saveNow) { + saveNow = false; + const bool focusOnTunnel = delayedSaveManagerImpl->needsFocusOnTunnel(); + const std::string tunnelNameToFocus = delayedSaveManagerImpl->getTunnelNameToFocus(); + saver->save(focusOnTunnel, tunnelNameToFocus); + continue; + } + if(defer) { + defer=false; +#define max(a,b) (((a)>(b))?(a):(b)) + forever { + TIMESTAMP_TYPE now = DelayedSaveManagerImpl::getTime(); + TIMESTAMP_TYPE millisToWait = max(wakeTime-now, 0); + if(millisToWait>0) { + waitCondition->wait(mutex, millisToWait); + if(delayedSaveManagerImpl->isExiting())return; + continue; + } + const bool focusOnTunnel = delayedSaveManagerImpl->needsFocusOnTunnel(); + const std::string tunnelNameToFocus = delayedSaveManagerImpl->getTunnelNameToFocus(); + saver->save(focusOnTunnel, tunnelNameToFocus); + break; //break inner loop + } + } + } +} + +void DelayedSaveThread::wakeThreadAndJoinThread() { + waitCondition->wakeAll(); + quit(); + wait();//join //"similar to the POSIX pthread_join()" +} + +DelayedSaveManagerImpl::TIMESTAMP_TYPE DelayedSaveManagerImpl::getTime() { + return QDateTime::currentMSecsSinceEpoch(); +} + +void DelayedSaveThread::deferSaveUntil(TIMESTAMP_TYPE wakeTime_) { + wakeTime = wakeTime_; + defer = true; + waitCondition->wakeAll(); +} + +void DelayedSaveThread::startSavingNow() { + //mutex->lock(); + saveNow=true; + waitCondition->wakeAll(); + //mutex->unlock(); +} + +DelayedSaveManagerImpl::~DelayedSaveManagerImpl() { + thread->wakeThreadAndJoinThread(); + delete thread; +} + +bool DelayedSaveManagerImpl::isExiting() { + return exiting; +} +Saver* DelayedSaveManagerImpl::getSaver() { + return saver; +} + +bool DelayedSaveManagerImpl::needsFocusOnTunnel() { + return focusOnTunnel; +} + +std::string DelayedSaveManagerImpl::getTunnelNameToFocus() { + return tunnelNameToFocus; +} diff --git a/qt/i2pd_qt/DelayedSaveManagerImpl.h b/qt/i2pd_qt/DelayedSaveManagerImpl.h new file mode 100644 index 00000000..0d8c7592 --- /dev/null +++ b/qt/i2pd_qt/DelayedSaveManagerImpl.h @@ -0,0 +1,82 @@ +#ifndef DELAYEDSAVEMANAGERIMPL_H +#define DELAYEDSAVEMANAGERIMPL_H + +#include +#include +#include +#include +#include + +#include "mainwindow.h" +#include "DelayedSaveManager.h" +#include "Saver.h" + +class DelayedSaveManagerImpl; + +class DelayedSaveThread : public QThread +{ + Q_OBJECT + +public: + static constexpr unsigned long WAIT_TIME_MILLIS = 1000L; + + typedef qint64 TIMESTAMP_TYPE; + static constexpr TIMESTAMP_TYPE A_VERY_OBSOLETE_TIMESTAMP=0; + + DelayedSaveThread(DelayedSaveManagerImpl* delayedSaveManagerImpl); + virtual ~DelayedSaveThread(); + + void run() override; + + void deferSaveUntil(TIMESTAMP_TYPE wakeTime); + void startSavingNow(); + + void wakeThreadAndJoinThread(); + +private: + DelayedSaveManagerImpl* delayedSaveManagerImpl; + QMutex* mutex; + QWaitCondition* waitCondition; + volatile bool saveNow; + volatile bool defer; + volatile TIMESTAMP_TYPE wakeTime; +}; + +class DelayedSaveManagerImpl : public DelayedSaveManager +{ +public: + DelayedSaveManagerImpl(); + virtual ~DelayedSaveManagerImpl(); + virtual void setSaver(Saver* saver); + virtual void start(); + virtual void delayedSave(DATA_SERIAL_TYPE dataSerial, bool focusOnTunnel, std::string tunnelNameToFocus); + virtual bool appExiting(); + + typedef DelayedSaveThread::TIMESTAMP_TYPE TIMESTAMP_TYPE; + + static constexpr DATA_SERIAL_TYPE INITIAL_DATA_SERIAL=0; + bool isExiting(); + Saver* getSaver(); + static TIMESTAMP_TYPE getTime(); + + bool needsFocusOnTunnel(); + std::string getTunnelNameToFocus(); + +private: + Saver* saver; + bool isSaverValid(); + + volatile DATA_SERIAL_TYPE lastDataSerialSeen; + + static constexpr TIMESTAMP_TYPE A_VERY_OBSOLETE_TIMESTAMP=DelayedSaveThread::A_VERY_OBSOLETE_TIMESTAMP; + TIMESTAMP_TYPE lastSaveStartedTimestamp; + + volatile bool exiting; + DelayedSaveThread* thread; + void wakeThreadAndJoinThread(); + + volatile bool focusOnTunnel; + std::string tunnelNameToFocus; +}; + +#endif // DELAYEDSAVEMANAGERIMPL_H diff --git a/qt/i2pd_qt/Saver.cpp b/qt/i2pd_qt/Saver.cpp new file mode 100644 index 00000000..4841acb0 --- /dev/null +++ b/qt/i2pd_qt/Saver.cpp @@ -0,0 +1,6 @@ +#include "Saver.h" + +Saver::Saver() +{ + +} diff --git a/qt/i2pd_qt/Saver.h b/qt/i2pd_qt/Saver.h new file mode 100644 index 00000000..cefe0220 --- /dev/null +++ b/qt/i2pd_qt/Saver.h @@ -0,0 +1,22 @@ +#ifndef SAVER_H +#define SAVER_H + +#include +#include +#include + +class Saver : public QObject +{ + Q_OBJECT + +public: + Saver(); + //false iff failures + virtual bool save(const bool focusOnTunnel, const std::string& tunnelNameToFocus)=0; + +signals: + void reloadTunnelsConfigAndUISignal(const QString); + +}; + +#endif // SAVER_H diff --git a/qt/i2pd_qt/SaverImpl.cpp b/qt/i2pd_qt/SaverImpl.cpp new file mode 100644 index 00000000..f35ef5b7 --- /dev/null +++ b/qt/i2pd_qt/SaverImpl.cpp @@ -0,0 +1,79 @@ +#include "SaverImpl.h" + +#include +#include +#include + +#include "QList" +#include "QString" + +#include "mainwindow.h" + +SaverImpl::SaverImpl(MainWindow *mainWindowPtr_, QList * configItems_, std::map* tunnelConfigs_) : + configItems(configItems_), tunnelConfigs(tunnelConfigs_), confpath(), tunconfpath(), mainWindowPtr(mainWindowPtr_) +{} + +SaverImpl::~SaverImpl() {} + +bool SaverImpl::save(const bool focusOnTunnel, const std::string& tunnelNameToFocus) { + //save main config + { + std::stringstream out; + for(QList::iterator it = configItems->begin(); it!= configItems->end(); ++it) { + MainWindowItem* item = *it; + item->saveToStringStream(out); + } + + using namespace std; + + + QString backup=confpath+"~"; + if(QFile::exists(backup)) QFile::remove(backup);//TODO handle errors + if(QFile::exists(confpath)) QFile::rename(confpath, backup);//TODO handle errors + ofstream outfile; + outfile.open(confpath.toStdString());//TODO handle errors + outfile << out.str().c_str(); + outfile.close(); + } + + //save tunnels config + { + std::stringstream out; + + for (std::map::iterator it=tunnelConfigs->begin(); it!=tunnelConfigs->end(); ++it) { + //const std::string& name = it->first; + TunnelConfig* tunconf = it->second; + tunconf->saveHeaderToStringStream(out); + tunconf->saveToStringStream(out); + tunconf->saveI2CPParametersToStringStream(out); + } + + using namespace std; + + QString backup=tunconfpath+"~"; + if(QFile::exists(backup)) QFile::remove(backup);//TODO handle errors + if(QFile::exists(tunconfpath)) QFile::rename(tunconfpath, backup);//TODO handle errors + ofstream outfile; + outfile.open(tunconfpath.toStdString());//TODO handle errors + outfile << out.str().c_str(); + outfile.close(); + } + + //reload saved configs +#if 0 + i2p::client::context.ReloadConfig(); +#endif + + if(focusOnTunnel) emit reloadTunnelsConfigAndUISignal(QString::fromStdString(tunnelNameToFocus)); + + return true; +} + +void SaverImpl::setConfPath(QString& confpath_) { confpath = confpath_; } + +void SaverImpl::setTunnelsConfPath(QString& tunconfpath_) { tunconfpath = tunconfpath_; } + +/*void SaverImpl::setTunnelFocus(bool focusOnTunnel, std::string tunnelNameToFocus) { + this->focusOnTunnel=focusOnTunnel; + this->tunnelNameToFocus=tunnelNameToFocus; +}*/ diff --git a/qt/i2pd_qt/SaverImpl.h b/qt/i2pd_qt/SaverImpl.h new file mode 100644 index 00000000..c44877a2 --- /dev/null +++ b/qt/i2pd_qt/SaverImpl.h @@ -0,0 +1,33 @@ +#ifndef SAVERIMPL_H +#define SAVERIMPL_H + +#include +#include + +#include +#include "QList" + +#include "mainwindow.h" +#include "TunnelConfig.h" +#include "Saver.h" + +class MainWindowItem; +class TunnelConfig; + +class SaverImpl : public Saver +{ +public: + SaverImpl(MainWindow *mainWindowPtr_, QList * configItems_, std::map* tunnelConfigs_); + virtual ~SaverImpl(); + virtual bool save(const bool focusOnTunnel, const std::string& tunnelNameToFocus); + void setConfPath(QString& confpath_); + void setTunnelsConfPath(QString& tunconfpath_); +private: + QList * configItems; + std::map* tunnelConfigs; + QString confpath; + QString tunconfpath; + MainWindow* mainWindowPtr; +}; + +#endif // SAVERIMPL_H diff --git a/qt/i2pd_qt/TunnelPane.cpp b/qt/i2pd_qt/TunnelPane.cpp index fb840276..3813eafc 100644 --- a/qt/i2pd_qt/TunnelPane.cpp +++ b/qt/i2pd_qt/TunnelPane.cpp @@ -64,7 +64,7 @@ void TunnelPane::setupTunnelPane( //type { - const QString& type = tunnelConfig->getType(); + //const QString& type = tunnelConfig->getType(); QHBoxLayout * horizontalLayout_ = new QHBoxLayout(); horizontalLayout_->setObjectName(QStringLiteral("horizontalLayout_")); typeLabel = new QLabel(gridLayoutWidget_2); diff --git a/qt/i2pd_qt/i2pd_qt.pro b/qt/i2pd_qt/i2pd_qt.pro index 15565c5c..0cb73a2f 100644 --- a/qt/i2pd_qt/i2pd_qt.pro +++ b/qt/i2pd_qt/i2pd_qt.pro @@ -62,6 +62,7 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \ ../../libi2pd/TunnelGateway.cpp \ ../../libi2pd/TunnelPool.cpp \ ../../libi2pd/util.cpp \ + ../../libi2pd/Elligator.cpp \ ../../libi2pd_client/AddressBook.cpp \ ../../libi2pd_client/BOB.cpp \ ../../libi2pd_client/ClientContext.cpp \ @@ -89,7 +90,11 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \ pagewithbackbutton.cpp \ widgetlock.cpp \ widgetlockregistry.cpp \ - logviewermanager.cpp + logviewermanager.cpp \ + DelayedSaveManager.cpp \ + Saver.cpp \ + DelayedSaveManagerImpl.cpp \ + SaverImpl.cpp HEADERS += DaemonQT.h mainwindow.h \ ../../libi2pd/api.h \ @@ -147,6 +152,7 @@ HEADERS += DaemonQT.h mainwindow.h \ ../../libi2pd/TunnelPool.h \ ../../libi2pd/util.h \ ../../libi2pd/version.h \ + ../../libi2pd/Elligator.h \ ../../libi2pd_client/AddressBook.h \ ../../libi2pd_client/BOB.h \ ../../libi2pd_client/ClientContext.h \ @@ -175,7 +181,11 @@ HEADERS += DaemonQT.h mainwindow.h \ widgetlock.h \ widgetlockregistry.h \ i2pd.rc \ - logviewermanager.h + logviewermanager.h \ + DelayedSaveManager.h \ + Saver.h \ + DelayedSaveManagerImpl.h \ + SaverImpl.h INCLUDEPATH += ../../libi2pd INCLUDEPATH += ../../libi2pd_client diff --git a/qt/i2pd_qt/mainwindow.cpp b/qt/i2pd_qt/mainwindow.cpp index e4c9f2a7..3b1890c4 100644 --- a/qt/i2pd_qt/mainwindow.cpp +++ b/qt/i2pd_qt/mainwindow.cpp @@ -1,11 +1,8 @@ -#include -#include #include "mainwindow.h" #include "ui_mainwindow.h" #include "ui_statusbuttons.h" #include "ui_routercommandswidget.h" #include "ui_generalsettingswidget.h" -#include #include #include #include @@ -29,17 +26,22 @@ #include "logviewermanager.h" +#include "DelayedSaveManagerImpl.h" +#include "SaverImpl.h" + std::string programOptionsWriterCurrentSection; MainWindow::MainWindow(std::shared_ptr logStream_, QWidget *parent) : QMainWindow(parent) ,logStream(logStream_) -#ifndef ANDROID - ,quitting(false) -#endif + ,delayedSaveManagerPtr(new DelayedSaveManagerImpl()) + ,dataSerial(DelayedSaveManagerImpl::INITIAL_DATA_SERIAL) ,wasSelectingAtStatusMainPage(false) ,showHiddenInfoStatusMainPage(false) ,logViewerManagerPtr(nullptr) +#ifndef ANDROID + ,quitting(false) +#endif ,ui(new Ui::MainWindow) ,statusButtonsUI(new Ui::StatusButtonsForm) ,routerCommandsUI(new Ui::routerCommandsWidget) @@ -51,9 +53,14 @@ MainWindow::MainWindow(std::shared_ptr logStream_, QWidget *paren ,datadir() ,confpath() ,tunconfpath() + ,tunnelConfigs() ,tunnelsPageUpdateListener(this) + ,saverPtr(new SaverImpl(this, &configItems, &tunnelConfigs)) { + assert(delayedSaveManagerPtr!=nullptr); + assert(saverPtr!=nullptr); + ui->setupUi(this); statusButtonsUI->setupUi(ui->statusButtonsPane); routerCommandsUI->setupUi(routerCommandsParent); @@ -75,7 +82,7 @@ MainWindow::MainWindow(std::shared_ptr logStream_, QWidget *paren ui->stackedWidget->setCurrentIndex(0); ui->settingsScrollArea->resize(uiSettings->settingsContentsGridLayout->sizeHint().width()+10,380); - QScrollBar* const barSett = ui->settingsScrollArea->verticalScrollBar(); + //QScrollBar* const barSett = ui->settingsScrollArea->verticalScrollBar(); int w = 683; int h = 3060; ui->settingsContents->setFixedSize(w, h); @@ -270,7 +277,13 @@ MainWindow::MainWindow(std::shared_ptr logStream_, QWidget *paren widgetlocks.add(new widgetlock(uiSettings->comboBox_httpPorxySignatureType,uiSettings->httpProxySignTypeComboEditPushButton)); widgetlocks.add(new widgetlock(uiSettings->comboBox_socksProxySignatureType,uiSettings->socksProxySignTypeComboEditPushButton)); - loadAllConfigs(); + loadAllConfigs(saverPtr); + + QObject::connect(saverPtr, SIGNAL(reloadTunnelsConfigAndUISignal(const QString)), + this, SLOT(reloadTunnelsConfigAndUI_QString(const QString))); + + delayedSaveManagerPtr->setSaver(saverPtr); + delayedSaveManagerPtr->start(); QObject::connect(uiSettings->logDestinationComboBox, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(logDestinationComboBoxValueChanged(const QString &))); @@ -292,7 +305,6 @@ MainWindow::MainWindow(std::shared_ptr logStream_, QWidget *paren QObject::connect(uiSettings->tunnelsConfigFileLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(reloadTunnelsConfigAndUI())); - QObject::connect(ui->addServerTunnelPushButton, SIGNAL(released()), this, SLOT(addServerTunnelPushButtonReleased())); QObject::connect(ui->addClientTunnelPushButton, SIGNAL(released()), this, SLOT(addClientTunnelPushButtonReleased())); @@ -307,7 +319,7 @@ MainWindow::MainWindow(std::shared_ptr logStream_, QWidget *paren logViewerManagerPtr=new LogViewerManager(logStream_,ui->logViewerTextEdit,this); assert(logViewerManagerPtr!=nullptr); - onLoggingOptionsChange(); + //onLoggingOptionsChange(); //QMetaObject::connectSlotsByName(this); } @@ -500,6 +512,8 @@ void MainWindow::handleQuitButton() { quitting=true; #endif close(); + delayedSaveManagerPtr->appExiting(); + qDebug("Performing quit"); QApplication::instance()->quit(); } @@ -526,6 +540,7 @@ void MainWindow::handleGracefulQuitTimerEvent() { quitting=true; #endif close(); + delayedSaveManagerPtr->appExiting(); qDebug("Performing quit"); QApplication::instance()->quit(); } @@ -534,6 +549,8 @@ MainWindow::~MainWindow() { qDebug("Destroying main window"); delete statusPageUpdateTimer; + delete delayedSaveManagerPtr; + delete saverPtr; for(QList::iterator it = configItems.begin(); it!= configItems.end(); ++it) { MainWindowItem* item = *it; item->deleteLater(); @@ -594,7 +611,7 @@ NonGUIOptionItem* MainWindow::initNonGUIOption(ConfigOption option) { return retValue; } -void MainWindow::loadAllConfigs(){ +void MainWindow::loadAllConfigs(SaverImpl* saverPtr){ //BORROWED FROM ??? //TODO move this code into single location std::string config; i2p::config::GetOption("conf", config); @@ -635,6 +652,9 @@ void MainWindow::loadAllConfigs(){ this->datadir = datadir.c_str(); this->tunconfpath = tunConf.c_str(); + saverPtr->setConfPath(this->confpath); + saverPtr->setTunnelsConfPath(this->tunconfpath); + for(QList::iterator it = configItems.begin(); it!= configItems.end(); ++it) { MainWindowItem* item = *it; item->loadFromConfigOption(); @@ -642,10 +662,10 @@ void MainWindow::loadAllConfigs(){ ReadTunnelsConfig(); - onLoggingOptionsChange(); + //onLoggingOptionsChange(); } /** returns false iff not valid items present and save was aborted */ -bool MainWindow::saveAllConfigs(){ +bool MainWindow::saveAllConfigs(bool focusOnTunnel, std::string tunnelNameToFocus){ QString cannotSaveSettings = QApplication::tr("Cannot save settings."); programOptionsWriterCurrentSection=""; /*if(!logFileNameOption->lineEdit->text().trimmed().isEmpty())logOption->optionValue=boost::any(std::string("file")); @@ -653,7 +673,6 @@ bool MainWindow::saveAllConfigs(){ daemonOption->optionValue=boost::any(false); serviceOption->optionValue=boost::any(false); - std::stringstream out; for(QList::iterator it = configItems.begin(); it!= configItems.end(); ++it) { MainWindowItem* item = *it; if(!item->isValid()){ @@ -661,27 +680,8 @@ bool MainWindow::saveAllConfigs(){ return false; } } - - for(QList::iterator it = configItems.begin(); it!= configItems.end(); ++it) { - MainWindowItem* item = *it; - item->saveToStringStream(out); - } - - using namespace std; - - - QString backup=confpath+"~"; - if(QFile::exists(backup)) QFile::remove(backup);//TODO handle errors - if(QFile::exists(confpath)) QFile::rename(confpath, backup);//TODO handle errors - ofstream outfile; - outfile.open(confpath.toStdString());//TODO handle errors - outfile << out.str().c_str(); - outfile.close(); - - SaveTunnelsConfig(); - - onLoggingOptionsChange(); - + delayedSaveManagerPtr->delayedSave(++dataSerial, focusOnTunnel, tunnelNameToFocus); + //onLoggingOptionsChange(); return true; } @@ -711,7 +711,7 @@ void MainWindow::updated() { adjustSizesAccordingToWrongLabel(); applyTunnelsUiToConfigs(); - saveAllConfigs(); + saveAllConfigs(false); } void MainWindowItem::installListeners(MainWindow *mainWindow) {} @@ -784,6 +784,10 @@ bool MainWindow::applyTunnelsUiToConfigs() { return true; } +void MainWindow::reloadTunnelsConfigAndUI_QString(const QString tunnelNameToFocus) { + reloadTunnelsConfigAndUI(tunnelNameToFocus.toStdString()); +} + void MainWindow::reloadTunnelsConfigAndUI(std::string tunnelNameToFocus) { deleteTunnelForms(); for (std::map::iterator it=tunnelConfigs.begin(); it!=tunnelConfigs.end(); ++it) { @@ -795,31 +799,6 @@ void MainWindow::reloadTunnelsConfigAndUI(std::string tunnelNameToFocus) { appendTunnelForms(tunnelNameToFocus); } -void MainWindow::SaveTunnelsConfig() { - std::stringstream out; - - for (std::map::iterator it=tunnelConfigs.begin(); it!=tunnelConfigs.end(); ++it) { - const std::string& name = it->first; - TunnelConfig* tunconf = it->second; - tunconf->saveHeaderToStringStream(out); - tunconf->saveToStringStream(out); - tunconf->saveI2CPParametersToStringStream(out); - } - - using namespace std; - - QString backup=tunconfpath+"~"; - if(QFile::exists(backup)) QFile::remove(backup);//TODO handle errors - if(QFile::exists(tunconfpath)) QFile::rename(tunconfpath, backup);//TODO handle errors - ofstream outfile; - outfile.open(tunconfpath.toStdString());//TODO handle errors - outfile << out.str().c_str(); - outfile.close(); - - i2p::client::context.ReloadConfig(); - -} - void MainWindow::TunnelsPageUpdateListenerMainWindowImpl::updated(std::string oldName, TunnelConfig* tunConf) { if(oldName!=tunConf->getName()) { //name has changed @@ -827,7 +806,7 @@ void MainWindow::TunnelsPageUpdateListenerMainWindowImpl::updated(std::string ol if(it!=mainWindow->tunnelConfigs.end())mainWindow->tunnelConfigs.erase(it); mainWindow->tunnelConfigs[tunConf->getName()]=tunConf; } - mainWindow->saveAllConfigs(); + mainWindow->saveAllConfigs(true, tunConf->getName()); } void MainWindow::TunnelsPageUpdateListenerMainWindowImpl::needsDeleting(std::string oldName){ diff --git a/qt/i2pd_qt/mainwindow.h b/qt/i2pd_qt/mainwindow.h index 048f44af..bfbc527f 100644 --- a/qt/i2pd_qt/mainwindow.h +++ b/qt/i2pd_qt/mainwindow.h @@ -62,6 +62,12 @@ #include "widgetlockregistry.h" #include "widgetlock.h" +#include "DelayedSaveManager.h" +#include "DelayedSaveManagerImpl.h" +#include "SaverImpl.h" + +class SaverImpl; + class LogViewerManager; template @@ -373,10 +379,14 @@ using namespace i2p::qt; class Controller; +class DelayedSaveManagerImpl; + class MainWindow : public QMainWindow { Q_OBJECT private: std::shared_ptr logStream; + DelayedSaveManagerImpl* delayedSaveManagerPtr; + DelayedSaveManager::DATA_SERIAL_TYPE dataSerial; public: explicit MainWindow(std::shared_ptr logStream_, QWidget *parent=nullptr); ~MainWindow(); @@ -502,16 +512,16 @@ protected: void initStringBox(ConfigOption option, QLineEdit* lineEdit); NonGUIOptionItem* initNonGUIOption(ConfigOption option); - void loadAllConfigs(); + void loadAllConfigs(SaverImpl* saverPtr); public slots: /** returns false iff not valid items present and save was aborted */ - bool saveAllConfigs(); - void SaveTunnelsConfig(); + bool saveAllConfigs(bool focusOnTunnel, std::string tunnelNameToFocus=""); void reloadTunnelsConfigAndUI(std::string tunnelNameToFocus); //focus none void reloadTunnelsConfigAndUI() { reloadTunnelsConfigAndUI(""); } + void reloadTunnelsConfigAndUI_QString(const QString tunnelNameToFocus); void addServerTunnelPushButtonReleased(); void addClientTunnelPushButtonReleased(); @@ -578,8 +588,7 @@ private: tunnelConfigs.erase(it); delete tc; } - saveAllConfigs(); - reloadTunnelsConfigAndUI(""); + saveAllConfigs(false); } std::string GenerateNewTunnelName() { @@ -614,8 +623,7 @@ private: destinationPort, sigType); - saveAllConfigs(); - reloadTunnelsConfigAndUI(name); + saveAllConfigs(true, name); } void CreateDefaultServerTunnel() {//TODO dedup default values with ReadTunnelsConfig() and with ClientContext.cpp::ReadTunnels () @@ -651,8 +659,7 @@ private: isUniqueLocal); - saveAllConfigs(); - reloadTunnelsConfigAndUI(name); + saveAllConfigs(true, name); } void ReadTunnelsConfig() //TODO deduplicate the code with ClientContext.cpp::ReadTunnels () @@ -793,7 +800,9 @@ private: TunnelsPageUpdateListenerMainWindowImpl tunnelsPageUpdateListener; - void onLoggingOptionsChange() {} + //void onLoggingOptionsChange() {} + + SaverImpl* saverPtr; }; #endif // MAINWINDOW_H From 0e38e43315836d1797caba87e82d5fc0340bf090 Mon Sep 17 00:00:00 2001 From: user Date: Tue, 10 Mar 2020 23:22:49 +0800 Subject: [PATCH 28/44] some qt work. fixed on slow computers; now faster as delayed save is implemented --- .gitignore | 4 ++- daemon/HTTPServer.h | 2 +- qt/i2pd_qt/DelayedSaveManager.h | 2 +- qt/i2pd_qt/DelayedSaveManagerImpl.cpp | 6 ++--- qt/i2pd_qt/DelayedSaveManagerImpl.h | 8 +++--- qt/i2pd_qt/TunnelConfig.h | 7 +++++- qt/i2pd_qt/TunnelPane.cpp | 5 ++++ qt/i2pd_qt/TunnelPane.h | 2 ++ qt/i2pd_qt/mainwindow.cpp | 36 ++++++++++++++++++++++++++- qt/i2pd_qt/mainwindow.h | 3 +++ 10 files changed, 63 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 68aea504..3319fa10 100644 --- a/.gitignore +++ b/.gitignore @@ -258,7 +258,7 @@ build/Makefile # qt -qt/i2pd_qt/*.ui.autosave +qt/i2pd_qt/*.autosave qt/i2pd_qt/*.ui.bk* qt/i2pd_qt/*.ui_* @@ -268,3 +268,5 @@ android/libs/ #various logs *LOGS/ +qt/build-*.sh* + diff --git a/daemon/HTTPServer.h b/daemon/HTTPServer.h index f5ac95fc..abc4fea5 100644 --- a/daemon/HTTPServer.h +++ b/daemon/HTTPServer.h @@ -89,7 +89,7 @@ namespace http void ShowTransports (std::stringstream& s); void ShowSAMSessions (std::stringstream& s); void ShowI2PTunnels (std::stringstream& s); - void ShowLocalDestination (std::stringstream& s, const std::string& b32); + void ShowLocalDestination (std::stringstream& s, const std::string& b32, uint32_t token); } // http } // i2p diff --git a/qt/i2pd_qt/DelayedSaveManager.h b/qt/i2pd_qt/DelayedSaveManager.h index 9a9a997b..b09aa28f 100644 --- a/qt/i2pd_qt/DelayedSaveManager.h +++ b/qt/i2pd_qt/DelayedSaveManager.h @@ -18,7 +18,7 @@ public: virtual bool appExiting()=0; virtual bool needsFocusOnTunnel()=0; - virtual std::string getTunnelNameToFocus()=0; + virtual std::string& getTunnelNameToFocus()=0; }; #endif // DELAYEDSAVEMANAGER_H diff --git a/qt/i2pd_qt/DelayedSaveManagerImpl.cpp b/qt/i2pd_qt/DelayedSaveManagerImpl.cpp index 5588d7e9..f6704c17 100644 --- a/qt/i2pd_qt/DelayedSaveManagerImpl.cpp +++ b/qt/i2pd_qt/DelayedSaveManagerImpl.cpp @@ -21,10 +21,10 @@ bool DelayedSaveManagerImpl::isSaverValid() { return saver != nullptr; } -void DelayedSaveManagerImpl::delayedSave(DATA_SERIAL_TYPE dataSerial, bool focusOnTunnel, std::string tunnelNameToFocus) { +void DelayedSaveManagerImpl::delayedSave(DATA_SERIAL_TYPE dataSerial, bool focusOnTunnel, std::string tunnelNameToFocus_) { if(lastDataSerialSeen==dataSerial)return; this->focusOnTunnel = focusOnTunnel; - this->tunnelNameToFocus = tunnelNameToFocus; + tunnelNameToFocus = tunnelNameToFocus_; lastDataSerialSeen=dataSerial; assert(isSaverValid()); TIMESTAMP_TYPE now = getTime(); @@ -135,6 +135,6 @@ bool DelayedSaveManagerImpl::needsFocusOnTunnel() { return focusOnTunnel; } -std::string DelayedSaveManagerImpl::getTunnelNameToFocus() { +std::string& DelayedSaveManagerImpl::getTunnelNameToFocus() { return tunnelNameToFocus; } diff --git a/qt/i2pd_qt/DelayedSaveManagerImpl.h b/qt/i2pd_qt/DelayedSaveManagerImpl.h index 0d8c7592..cb1f7568 100644 --- a/qt/i2pd_qt/DelayedSaveManagerImpl.h +++ b/qt/i2pd_qt/DelayedSaveManagerImpl.h @@ -60,22 +60,22 @@ public: static TIMESTAMP_TYPE getTime(); bool needsFocusOnTunnel(); - std::string getTunnelNameToFocus(); + std::string& getTunnelNameToFocus(); private: Saver* saver; bool isSaverValid(); - volatile DATA_SERIAL_TYPE lastDataSerialSeen; + DATA_SERIAL_TYPE lastDataSerialSeen; static constexpr TIMESTAMP_TYPE A_VERY_OBSOLETE_TIMESTAMP=DelayedSaveThread::A_VERY_OBSOLETE_TIMESTAMP; TIMESTAMP_TYPE lastSaveStartedTimestamp; - volatile bool exiting; + bool exiting; DelayedSaveThread* thread; void wakeThreadAndJoinThread(); - volatile bool focusOnTunnel; + bool focusOnTunnel; std::string tunnelNameToFocus; }; diff --git a/qt/i2pd_qt/TunnelConfig.h b/qt/i2pd_qt/TunnelConfig.h index 58a1fa0b..059d48b5 100644 --- a/qt/i2pd_qt/TunnelConfig.h +++ b/qt/i2pd_qt/TunnelConfig.h @@ -40,6 +40,9 @@ public: class ClientTunnelConfig; class ServerTunnelConfig; + +class TunnelPane; + class TunnelConfig { /* const char I2P_TUNNELS_SECTION_TYPE_CLIENT[] = "client"; @@ -54,6 +57,7 @@ class TunnelConfig { */ QString type; std::string name; + TunnelPane* tunnelPane; public: TunnelConfig(std::string name_, QString& type_, I2CPParameters& i2cpParameters_): type(type_), name(name_), i2cpParameters(i2cpParameters_) {} @@ -68,7 +72,8 @@ public: virtual void saveToStringStream(std::stringstream& out)=0; virtual ClientTunnelConfig* asClientTunnelConfig()=0; virtual ServerTunnelConfig* asServerTunnelConfig()=0; - + void setTunnelPane(TunnelPane* tp){this->tunnelPane = tp;} + TunnelPane* getTunnelPane() {return tunnelPane;} private: I2CPParameters i2cpParameters; }; diff --git a/qt/i2pd_qt/TunnelPane.cpp b/qt/i2pd_qt/TunnelPane.cpp index 3813eafc..c64b37ab 100644 --- a/qt/i2pd_qt/TunnelPane.cpp +++ b/qt/i2pd_qt/TunnelPane.cpp @@ -83,6 +83,11 @@ void TunnelPane::setupTunnelPane( retranslateTunnelForm(*this); } +void TunnelPane::deleteWidget() { + //gridLayoutWidget_2->deleteLater(); + tunnelGroupBox->deleteLater(); +} + void TunnelPane::appendControlsForI2CPParameters(I2CPParameters& i2cpParameters, int& gridIndex) { { //number of hops of an inbound tunnel diff --git a/qt/i2pd_qt/TunnelPane.h b/qt/i2pd_qt/TunnelPane.h index a7012810..71331b4e 100644 --- a/qt/i2pd_qt/TunnelPane.h +++ b/qt/i2pd_qt/TunnelPane.h @@ -41,6 +41,8 @@ public: virtual ServerTunnelPane* asServerTunnelPane()=0; virtual ClientTunnelPane* asClientTunnelPane()=0; + void deleteWidget(); + protected: MainWindow* mainWindow; QWidget * wrongInputPane; diff --git a/qt/i2pd_qt/mainwindow.cpp b/qt/i2pd_qt/mainwindow.cpp index 3b1890c4..97a4ee69 100644 --- a/qt/i2pd_qt/mainwindow.cpp +++ b/qt/i2pd_qt/mainwindow.cpp @@ -664,6 +664,36 @@ void MainWindow::loadAllConfigs(SaverImpl* saverPtr){ //onLoggingOptionsChange(); } + +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; + TunnelConfig* tunconf = it->second; + TunnelPane * tunnelPane=tunconf->getTunnelPane(); + if(!tunnelPane)continue; + int h=tunnelPane->height(); + height+=h; + //qDebug() << "tun.height:" << height << "sz:" << tunnelPanes.size(); + //int h=tunnelPane->appendClientTunnelForm(ctc, ui->tunnelsScrollAreaWidgetContents, tunnelPanes.size(), height); + } + //qDebug() << "tun.setting height:" << height; + ui->tunnelsScrollAreaWidgetContents->setGeometry(QRect(0, 0, 621, height)); + /*QList childWidgets = ui->tunnelsScrollAreaWidgetContents->findChildren(); + foreach(QWidget* widget, childWidgets) + widget->show();*/ +} + +void MainWindow::deleteTunnelFromUI(std::string tunnelName, TunnelConfig* cnf) { + TunnelPane* tp = cnf->getTunnelPane(); + if(!tp)return; + tunnelPanes.remove(tp); + tp->deleteWidget(); + layoutTunnels(); +} + /** returns false iff not valid items present and save was aborted */ bool MainWindow::saveAllConfigs(bool focusOnTunnel, std::string tunnelNameToFocus){ QString cannotSaveSettings = QApplication::tr("Cannot save settings."); @@ -681,6 +711,7 @@ bool MainWindow::saveAllConfigs(bool focusOnTunnel, std::string tunnelNameToFocu } } delayedSaveManagerPtr->delayedSave(++dataSerial, focusOnTunnel, tunnelNameToFocus); + //onLoggingOptionsChange(); return true; } @@ -725,6 +756,7 @@ void MainWindow::appendTunnelForms(std::string tunnelNameToFocus) { ServerTunnelConfig* stc = tunconf->asServerTunnelConfig(); if(stc){ ServerTunnelPane * tunnelPane=new ServerTunnelPane(&tunnelsPageUpdateListener, stc, ui->wrongInputLabel, ui->wrongInputLabel, this); + tunconf->setTunnelPane(tunnelPane); int h=tunnelPane->appendServerTunnelForm(stc, ui->tunnelsScrollAreaWidgetContents, tunnelPanes.size(), height); height+=h; //qDebug() << "tun.height:" << height << "sz:" << tunnelPanes.size(); @@ -738,6 +770,7 @@ void MainWindow::appendTunnelForms(std::string tunnelNameToFocus) { ClientTunnelConfig* ctc = tunconf->asClientTunnelConfig(); if(ctc){ ClientTunnelPane * tunnelPane=new ClientTunnelPane(&tunnelsPageUpdateListener, ctc, ui->wrongInputLabel, ui->wrongInputLabel, this); + tunconf->setTunnelPane(tunnelPane); int h=tunnelPane->appendClientTunnelForm(ctc, ui->tunnelsScrollAreaWidgetContents, tunnelPanes.size(), height); height+=h; //qDebug() << "tun.height:" << height << "sz:" << tunnelPanes.size(); @@ -854,7 +887,8 @@ void MainWindow::anchorClickedHandler(const QUrl & link) { pageWithBackButton->show(); textBrowser->hide(); std::stringstream s; - i2p::http::ShowLocalDestination(s,str.toStdString()); + std::string strstd = str.toStdString(); + i2p::http::ShowLocalDestination(s,strstd,0); childTextBrowser->setHtml(QString::fromStdString(s.str())); } } diff --git a/qt/i2pd_qt/mainwindow.h b/qt/i2pd_qt/mainwindow.h index bfbc527f..91c99122 100644 --- a/qt/i2pd_qt/mainwindow.h +++ b/qt/i2pd_qt/mainwindow.h @@ -513,6 +513,7 @@ protected: NonGUIOptionItem* initNonGUIOption(ConfigOption option); void loadAllConfigs(SaverImpl* saverPtr); + void layoutTunnels(); public slots: /** returns false iff not valid items present and save was aborted */ @@ -540,6 +541,7 @@ private: void appendTunnelForms(std::string tunnelNameToFocus); void deleteTunnelForms(); + void deleteTunnelFromUI(std::string tunnelName, TunnelConfig* cnf); template std::string GetI2CPOption (const Section& section, const std::string& name, const Type& value) const @@ -585,6 +587,7 @@ private: std::map::const_iterator it=tunnelConfigs.find(name); if(it!=tunnelConfigs.end()){ TunnelConfig* tc=it->second; + deleteTunnelFromUI(name, tc); tunnelConfigs.erase(it); delete tc; } From dd8200e8b0a9f2f7bf56a95db2ccacace81eb572 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Thu, 12 Mar 2020 03:50:21 +0300 Subject: [PATCH 29/44] cleanup websocks Signed-off-by: R4SAS --- build/CMakeLists.txt | 1 - filelist.mk | 2 +- libi2pd_client/ClientContext.cpp | 7 +--- libi2pd_client/WebSocks.cpp | 72 -------------------------------- libi2pd_client/WebSocks.h | 34 --------------- qt/i2pd_qt/i2pd_qt.pro | 2 - 6 files changed, 3 insertions(+), 115 deletions(-) delete mode 100644 libi2pd_client/WebSocks.cpp delete mode 100644 libi2pd_client/WebSocks.h diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 8b3553d2..2bdfb396 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -117,7 +117,6 @@ set (CLIENT_SRC "${LIBI2PD_CLIENT_SRC_DIR}/SOCKS.cpp" "${LIBI2PD_CLIENT_SRC_DIR}/HTTPProxy.cpp" "${LIBI2PD_CLIENT_SRC_DIR}/I2CP.cpp" - "${LIBI2PD_CLIENT_SRC_DIR}/WebSocks.cpp" ) add_library(libi2pdclient ${CLIENT_SRC}) diff --git a/filelist.mk b/filelist.mk index 72773975..7d13fb2f 100644 --- a/filelist.mk +++ b/filelist.mk @@ -11,7 +11,7 @@ LIB_SRC = $(wildcard $(LIB_SRC_DIR)/*.cpp) #LIB_CLIENT_SRC = \ # AddressBook.cpp BOB.cpp ClientContext.cpp I2PTunnel.cpp I2PService.cpp MatchedDestination.cpp \ -# SAM.cpp SOCKS.cpp HTTPProxy.cpp I2CP.cpp WebSocks.cpp +# SAM.cpp SOCKS.cpp HTTPProxy.cpp I2CP.cpp LIB_CLIENT_SRC = $(wildcard $(LIB_CLIENT_SRC_DIR)/*.cpp) diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index d72f40a8..722fb242 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -9,7 +9,6 @@ #include "util.h" #include "ClientContext.h" #include "SOCKS.h" -#include "WebSocks.h" #include "MatchedDestination.h" namespace i2p @@ -598,10 +597,8 @@ namespace client } else if (type == I2P_TUNNELS_SECTION_TYPE_WEBSOCKS) { - // websocks proxy - auto tun = std::make_shared(address, port, localDestination); - clientTunnel = tun; - clientEndpoint = tun->GetLocalEndpoint(); + LogPrint(eLogError, "Clients: I2P Client tunnel websocks is deprecated"); + continue; } else { diff --git a/libi2pd_client/WebSocks.cpp b/libi2pd_client/WebSocks.cpp deleted file mode 100644 index a3e8c1bf..00000000 --- a/libi2pd_client/WebSocks.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "WebSocks.h" -#include "Log.h" -#include - -namespace i2p -{ -namespace client -{ - class WebSocksImpl - { - public: - WebSocksImpl(const std::string & addr, int port) : m_Addr(addr), m_Port(port) - { - } - - ~WebSocksImpl() - { - } - - void Start() - { - LogPrint(eLogInfo, "[Tunnels] starting websocks tunnel at %s:%d is rejected: WebSockets is deprecated", m_Addr, m_Port); - } - - void Stop() - { - } - - void InitializeDestination(WebSocks * parent) - { - } - - boost::asio::ip::tcp::endpoint GetLocalEndpoint() - { - return boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(m_Addr), m_Port); - } - - std::string m_Addr; - int m_Port; - - }; -} -} - -namespace i2p -{ -namespace client -{ - WebSocks::WebSocks(const std::string & addr, int port, std::shared_ptr localDestination) : m_Impl(new WebSocksImpl(addr, port)) - { - m_Impl->InitializeDestination(this); - } - WebSocks::~WebSocks() { delete m_Impl; } - - void WebSocks::Start() - { - m_Impl->Start(); - GetLocalDestination()->Start(); - } - - boost::asio::ip::tcp::endpoint WebSocks::GetLocalEndpoint() const - { - return m_Impl->GetLocalEndpoint(); - } - - void WebSocks::Stop() - { - m_Impl->Stop(); - GetLocalDestination()->Stop(); - } -} -} diff --git a/libi2pd_client/WebSocks.h b/libi2pd_client/WebSocks.h deleted file mode 100644 index 2314659f..00000000 --- a/libi2pd_client/WebSocks.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef WEBSOCKS_H_ -#define WEBSOCKS_H_ -#include -#include -#include "I2PService.h" -#include "Destination.h" - -namespace i2p -{ -namespace client -{ - - class WebSocksImpl; - - /** @brief websocket socks proxy server */ - class WebSocks : public i2p::client::I2PService - { - public: - WebSocks(const std::string & addr, int port, std::shared_ptr localDestination); - ~WebSocks(); - - void Start(); - void Stop(); - - boost::asio::ip::tcp::endpoint GetLocalEndpoint() const; - - const char * GetName() { return "WebSOCKS Proxy"; } - - private: - WebSocksImpl * m_Impl; - }; -} -} -#endif diff --git a/qt/i2pd_qt/i2pd_qt.pro b/qt/i2pd_qt/i2pd_qt.pro index aa87a765..6eec3a16 100644 --- a/qt/i2pd_qt/i2pd_qt.pro +++ b/qt/i2pd_qt/i2pd_qt.pro @@ -73,7 +73,6 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \ ../../libi2pd_client/MatchedDestination.cpp \ ../../libi2pd_client/SAM.cpp \ ../../libi2pd_client/SOCKS.cpp \ - ../../libi2pd_client/WebSocks.cpp \ ../../daemon/Daemon.cpp \ ../../daemon/HTTPServer.cpp \ ../../daemon/I2PControl.cpp \ @@ -162,7 +161,6 @@ HEADERS += DaemonQT.h mainwindow.h \ ../../libi2pd_client/MatchedDestination.h \ ../../libi2pd_client/SAM.h \ ../../libi2pd_client/SOCKS.h \ - ../../libi2pd_client/WebSocks.h \ ../../daemon/Daemon.h \ ../../daemon/HTTPServer.h \ ../../daemon/I2PControl.h \ From 45145fa50af40a5270223930cd92d33df452db82 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 14 Mar 2020 09:33:48 -0400 Subject: [PATCH 30/44] add ECIESX25519AEADRatchet session to delivery status --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 1 + libi2pd/Garlic.cpp | 2 +- libi2pd/Garlic.h | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 5f2eb5c8..4705c708 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -477,6 +477,7 @@ namespace garlic SetLeaseSetUpdateStatus (eLeaseSetSubmitted); SetLeaseSetUpdateMsgID (leaseSet->GetMsgID ()); SetLeaseSetSubmissionTime (ts); + GetOwner ()->DeliveryStatusSent (shared_from_this (), leaseSet->GetMsgID ()); } uint8_t paddingSize; RAND_bytes (&paddingSize, 1); diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 9ac5540f..99b737b1 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -783,7 +783,7 @@ namespace garlic m_DeliveryStatusSessions.erase (msgID); } - void GarlicDestination::DeliveryStatusSent (ElGamalAESSessionPtr session, uint32_t msgID) + void GarlicDestination::DeliveryStatusSent (GarlicRoutingSessionPtr session, uint32_t msgID) { std::unique_lock l(m_DeliveryStatusSessionsMutex); m_DeliveryStatusSessions[msgID] = session; diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index be0ac117..396a38fe 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -226,7 +226,7 @@ namespace garlic void AddSessionKey (const uint8_t * key, const uint8_t * tag); // one tag virtual bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag); // from different thread - void DeliveryStatusSent (ElGamalAESSessionPtr session, uint32_t msgID); + void DeliveryStatusSent (GarlicRoutingSessionPtr session, uint32_t msgID); void AddECIESx25519SessionTag (int index, uint64_t tag, ECIESX25519AEADRatchetSessionPtr session); void AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session); void HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len); From b5bc05ac2b2ed9375d689207190af89b5344c37d Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 14 Mar 2020 16:35:34 -0400 Subject: [PATCH 31/44] delete unconfirmed LeaseSet and DeliveryStatus --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 6 ++++++ libi2pd/ECIESX25519AEADRatchetSession.h | 2 +- libi2pd/Garlic.cpp | 19 ++++++++++++------- libi2pd/Garlic.h | 3 ++- 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 4705c708..8c293f15 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -571,6 +571,12 @@ namespace garlic } m_NumReceiveTags += numTags; } + + bool ECIESX25519AEADRatchetSession::CheckExpired (uint64_t ts) + { + CleanupUnconfirmedLeaseSet (ts); + return ts > m_LastActivityTimestamp + ECIESX25519_EXPIRATION_TIMEOUT; + } } } diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index 4d273c13..db9807a5 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -85,7 +85,7 @@ namespace garlic if (!m_Destination) m_Destination.reset (new i2p::data::IdentHash (dest)); } - bool IsExpired (uint64_t ts) const { return ts > m_LastActivityTimestamp + ECIESX25519_EXPIRATION_TIMEOUT; } + bool CheckExpired (uint64_t ts); // true is expired bool CanBeRestarted (uint64_t ts) const { return ts > m_LastActivityTimestamp + ECIESX25519_RESTART_TIMEOUT; } private: diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 99b737b1..97f80b41 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -70,6 +70,16 @@ namespace garlic return false; } + void GarlicRoutingSession::CleanupUnconfirmedLeaseSet (uint64_t ts) + { + if (m_LeaseSetUpdateMsgID && ts*1000LL > m_LeaseSetSubmissionTime + LEASET_CONFIRMATION_TIMEOUT) + { + if (GetOwner ()) + GetOwner ()->RemoveDeliveryStatusSession (m_LeaseSetUpdateMsgID); + m_LeaseSetUpdateMsgID = 0; + } + } + std::shared_ptr GarlicRoutingSession::CreateEncryptedDeliveryStatusMsg (uint32_t msgID) { auto msg = CreateDeliveryStatusMsg (msgID); @@ -390,12 +400,7 @@ namespace garlic ++it; } CleanupUnconfirmedTags (); - if (GetLeaseSetUpdateMsgID () && ts*1000LL > GetLeaseSetSubmissionTime () + LEASET_CONFIRMATION_TIMEOUT) - { - if (GetOwner ()) - GetOwner ()->RemoveDeliveryStatusSession (GetLeaseSetUpdateMsgID ()); - SetLeaseSetUpdateMsgID (0); - } + CleanupUnconfirmedLeaseSet (ts); return !m_SessionTags.empty () || !m_UnconfirmedTagsMsgs.empty (); } @@ -767,7 +772,7 @@ namespace garlic for (auto it = m_ECIESx25519Sessions.begin (); it != m_ECIESx25519Sessions.end ();) { - if (it->second->IsExpired (ts)) + if (it->second->CheckExpired (ts)) { it->second->SetOwner (nullptr); it = m_ECIESx25519Sessions.erase (it); diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index 396a38fe..06da679d 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -113,7 +113,8 @@ namespace garlic bool IsLeaseSetNonConfirmed () const { return m_LeaseSetUpdateStatus == eLeaseSetSubmitted; }; bool IsLeaseSetUpdated () const { return m_LeaseSetUpdateStatus == eLeaseSetUpdated; }; uint64_t GetLeaseSetSubmissionTime () const { return m_LeaseSetSubmissionTime; } - + void CleanupUnconfirmedLeaseSet (uint64_t ts); + std::shared_ptr GetSharedRoutingPath (); void SetSharedRoutingPath (std::shared_ptr path); From 5da92437a136cf5938062c5ec4ceaf28832c5aff Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 16 Mar 2020 16:41:07 -0400 Subject: [PATCH 32/44] set msg type for deliverystatus --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 8c293f15..8d300a16 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -552,6 +552,7 @@ namespace garlic LogPrint (eLogError, "Garlic: No inbound tunnels in the pool for DeliveryStatus"); return 0; } + *buf = msg->GetTypeID (); // I2NP msg type htobe32buf (buf + 1, msg->GetMsgID ()); // msgID htobe32buf (buf + 5, msg->GetExpiration ()/1000); // expiration in seconds memcpy (buf + 9, msg->GetPayload (), msg->GetPayloadLength ()); From f3b0e57a5440586c3f7de2ed97b5b742f52c995c Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 18 Mar 2020 18:03:03 -0400 Subject: [PATCH 33/44] publish multiple encryption keys --- libi2pd/Destination.cpp | 5 +++-- libi2pd/LeaseSet.cpp | 18 ++++++++++++------ libi2pd/LeaseSet.h | 9 ++++++++- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index d4620ed9..60f5062c 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1149,10 +1149,11 @@ namespace client else { // standard LS2 (type 3) first - auto keyLen = m_Decryptor ? m_Decryptor->GetPublicKeyLen () : 256; + uint16_t keyLen = m_Decryptor ? m_Decryptor->GetPublicKeyLen () : 256; bool isPublishedEncrypted = GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2; auto ls2 = std::make_shared (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2, - m_Keys, m_EncryptionKeyType, keyLen, m_EncryptionPublicKey, tunnels, IsPublic (), isPublishedEncrypted); + m_Keys, i2p::data::LocalLeaseSet2::KeySections { {m_EncryptionKeyType, keyLen, m_EncryptionPublicKey} }, + tunnels, IsPublic (), isPublishedEncrypted); if (isPublishedEncrypted) // encrypt if type 5 ls2 = std::make_shared (ls2, m_Keys, GetAuthType (), m_AuthKeys); leaseSet = ls2; diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index 8d1b9524..e2da1d21 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -748,7 +748,7 @@ namespace data } LocalLeaseSet2::LocalLeaseSet2 (uint8_t storeType, const i2p::data::PrivateKeys& keys, - uint16_t keyType, uint16_t keyLen, const uint8_t * encryptionPublicKey, + const KeySections& encryptionKeys, std::vector > tunnels, bool isPublic, bool isPublishedEncrypted): LocalLeaseSet (keys.GetPublic (), nullptr, 0) @@ -757,8 +757,11 @@ namespace data // assume standard LS2 int num = tunnels.size (); if (num > MAX_NUM_LEASES) num = MAX_NUM_LEASES; + size_t keySectionsLen = 0; + for (const auto& it: encryptionKeys) + keySectionsLen += 2/*key type*/ + 2/*key len*/ + it.keyLen/*key*/; m_BufferLen = identity->GetFullLen () + 4/*published*/ + 2/*expires*/ + 2/*flag*/ + 2/*properties len*/ + - 1/*num keys*/ + 2/*key type*/ + 2/*key len*/ + keyLen/*key*/ + 1/*num leases*/ + num*LEASE2_SIZE + keys.GetSignatureLen (); + 1/*num keys*/ + keySectionsLen + 1/*num leases*/ + num*LEASE2_SIZE + keys.GetSignatureLen (); uint16_t flags = 0; if (keys.IsOfflineSignature ()) { @@ -789,10 +792,13 @@ namespace data } htobe16buf (m_Buffer + offset, 0); offset += 2; // properties len // keys - m_Buffer[offset] = 1; offset++; // 1 key - htobe16buf (m_Buffer + offset, keyType); offset += 2; // key type - htobe16buf (m_Buffer + offset, keyLen); offset += 2; // key len - memcpy (m_Buffer + offset, encryptionPublicKey, keyLen); offset += keyLen; // key + m_Buffer[offset] = encryptionKeys.size (); offset++; // 1 key + for (const auto& it: encryptionKeys) + { + htobe16buf (m_Buffer + offset, it.keyType); offset += 2; // key type + htobe16buf (m_Buffer + offset, it.keyLen); offset += 2; // key len + memcpy (m_Buffer + offset, it.encryptionPublicKey, it.keyLen); offset += it.keyLen; // key + } // leases uint32_t expirationTime = 0; // in seconds m_Buffer[offset] = num; offset++; // num leases diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index a51570f7..791d77e3 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -231,8 +231,15 @@ namespace data { public: + struct KeySection + { + uint16_t keyType, keyLen; + const uint8_t * encryptionPublicKey; + }; + typedef std::vector KeySections; + LocalLeaseSet2 (uint8_t storeType, const i2p::data::PrivateKeys& keys, - uint16_t keyType, uint16_t keyLen, const uint8_t * encryptionPublicKey, + const KeySections& encryptionKeys, std::vector > tunnels, bool isPublic, bool isPublishedEncrypted = false); LocalLeaseSet2 (uint8_t storeType, std::shared_ptr identity, const uint8_t * buf, size_t len); // from I2CP From 2fcaa7d260fa9b657e9e1e24f00a03f964c7febf Mon Sep 17 00:00:00 2001 From: R4SAS Date: Thu, 19 Mar 2020 02:26:55 +0300 Subject: [PATCH 34/44] [webconsole] rework spoilers; print tags, leases, router info in table Signed-off-by: R4SAS --- daemon/HTTPServer.cpp | 240 ++++++++++++++++++++++++------------------ 1 file changed, 137 insertions(+), 103 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 36e26785..a7bd693f 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -54,7 +54,7 @@ namespace http { " body { font: 100%/1.5em sans-serif; margin: 0; padding: 1.5em; background: #FAFAFA; color: #103456; }\r\n" " a, .slide label { text-decoration: none; color: #894C84; }\r\n" " a:hover, .slide label:hover { color: #FAFAFA; background: #894C84; }\r\n" - " a.button { -webkit-appearance: button; -moz-appearance: button; appearance: button; text-decoration: none; color: initial;}\r\n" + " a.button { -webkit-appearance: button; -moz-appearance: button; appearance: button; text-decoration: none; color: initial; width: 1.5em;}\r\n" " .header { font-size: 2.5em; text-align: center; margin: 1.5em 0; color: #894C84; }\r\n" " .wrapper { margin: 0 auto; padding: 1em; max-width: 60em; }\r\n" " .left { float: left; position: absolute; }\r\n" @@ -64,12 +64,13 @@ namespace http { " .tunnel.failed { color: #D33F3F; }\r\n" " .tunnel.building { color: #434343; }\r\n" " caption { font-size: 1.5em; text-align: center; color: #894C84; }\r\n" - " table { width: 100%; border-collapse: collapse; text-align: center; }\r\n" - " .slide p, .slide [type='checkbox'] { display: none; }\r\n" - " .slide [type='checkbox']:checked ~ p { display: block; margin-top: 0; padding: 0; }\r\n" + " table { display: table; border-collapse: collapse; text-align: center; }\r\n" + " table.extaddr { text-align: left; }\r\n table.services { width: 100%; }" + " .streamdest { width: 120px; max-width: 240px; overflow: hidden; text-overflow: ellipsis;}\r\n" + " .slide div.content, .slide [type='checkbox'] { display: none; }\r\n" + " .slide [type='checkbox']:checked ~ div.content { display: block; margin-top: 0; padding: 0; }\r\n" " .disabled:after { color: #D33F3F; content: \"Disabled\" }\r\n" " .enabled:after { color: #56B734; content: \"Enabled\" }\r\n" - " .streamdest { width: 120px; max-width: 240px; overflow: hidden; text-overflow: ellipsis;}\r\n" "\r\n"; const char HTTP_PAGE_TUNNELS[] = "tunnels"; @@ -181,8 +182,10 @@ namespace http { "

\r\n" " Main page
\r\n
\r\n" " Router commands
\r\n" - " Local destinations
\r\n" - " LeaseSets
\r\n" + " Local destinations
\r\n"; + if (i2p::context.IsFloodfill ()) + s << " LeaseSets
\r\n"; + s << " Tunnels
\r\n" " Transit tunnels
\r\n" " Transports
\r\n" @@ -234,11 +237,8 @@ namespace http { } s << "
\r\n"; #if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY)) - if (auto remains = Daemon.gracefulShutdownInterval) { - s << "Stopping in: "; - s << remains << " seconds"; - s << "
\r\n"; - } + if (auto remains = Daemon.gracefulShutdownInterval) + s << "Stopping in: " << remains << " seconds
\r\n"; #endif auto family = i2p::context.GetFamily (); if (family.length () > 0) @@ -256,45 +256,50 @@ namespace http { s << "Data path: " << i2p::fs::GetDataDir() << "
\r\n"; s << "
"; if((outputFormat==OutputFormatEnum::forWebConsole)||!includeHiddenContent) { - s << "\r\n\r\n

\r\n"; + s << "\r\n\r\n

\r\n"; } if(includeHiddenContent) { s << "Router Ident: " << i2p::context.GetRouterInfo().GetIdentHashBase64() << "
\r\n"; - s << "Router Family: " << i2p::context.GetRouterInfo().GetProperty("family") << "
\r\n"; + if (!i2p::context.GetRouterInfo().GetProperty("family").empty()) + s << "Router Family: " << i2p::context.GetRouterInfo().GetProperty("family") << "
\r\n"; s << "Router Caps: " << i2p::context.GetRouterInfo().GetProperty("caps") << "
\r\n"; - s << "Our external address:" << "
\r\n" ; + s << "Our external address:" << "
\r\n\r\n"; for (const auto& address : i2p::context.GetRouterInfo().GetAddresses()) { + s << "\r\n"; if (address->IsNTCP2 () && !address->IsPublishedNTCP2 ()) { - s << "NTCP2"; + s << "\r\n\r\n"; continue; } switch (address->transportStyle) { case i2p::data::RouterInfo::eTransportNTCP: { - s << "NTCP"; + s << "\r\n"; break; } case i2p::data::RouterInfo::eTransportSSU: + { + s << "\r\n"; + break; + } default: - s << "Unknown  "; + s << "\r\n"; } - s << address->host.to_string() << ":" << address->port << "
\r\n"; + s << "\r\n\r\n"; } + s << "
NTCP2"; if (address->host.is_v6 ()) s << "v6"; - s << "   supported
\r\n"; + s << "
supported
NTCP"; if (address->IsPublishedNTCP2 ()) s << "2"; if (address->host.is_v6 ()) s << "v6"; - s << "  "; + s << "SSU"; if (address->host.is_v6 ()) - s << "SSUv6     "; - else - s << "SSU     "; - break; + s << "v6"; + s << "Unknown" << address->host.to_string() << ":" << address->port << "
\r\n"; } - s << "

\r\n
\r\n"; + s << "\r\n
\r\n
\r\n"; if(outputFormat==OutputFormatEnum::forQtUi) { s << "
"; } @@ -310,15 +315,15 @@ namespace http { s << "Transit Tunnels: " << std::to_string(transitTunnelCount) << "
\r\n
\r\n"; if(outputFormat==OutputFormatEnum::forWebConsole) { - s << "\r\n"; - s << "\r\n"; - s << "\r\n"; - s << "\r\n"; - s << "\r\n"; - s << "\r\n"; bool i2pcontrol; i2p::config::GetOption("i2pcontrol.enabled", i2pcontrol); - s << "\r\n"; - s << "
Services
ServiceState
" << "HTTP Proxy" << "
" << "SOCKS Proxy" << "
" << "BOB" << "
" << "SAM" << "
" << "I2CP" << "
" << "I2PControl" << "
\r\n"; + s << "\r\n"; + s << "\r\n"; + s << "\r\n"; + s << "\r\n"; + s << "\r\n"; + s << "\r\n"; + s << "\r\n"; + s << "
Services
" << "HTTP Proxy" << "
" << "SOCKS Proxy" << "
" << "BOB" << "
" << "SAM" << "
" << "I2CP" << "
" << "I2PControl" << "
\r\n"; } } @@ -358,19 +363,20 @@ namespace http { if (dest->IsEncryptedLeaseSet ()) { i2p::data::BlindedPublicKey blinded (dest->GetIdentity (), dest->IsPerClientAuth ()); - s << "
\r\n\r\n

\r\n"; + s << "

\r\n\r\n
\r\n"; s << blinded.ToB33 () << ".b32.i2p
\r\n"; - s << "

\r\n
\r\n"; + s << "
\r\n
\r\n"; } if(dest->GetNumRemoteLeaseSets()) { - s << "
\r\n\r\n

\r\n"; + s << "

\r\n\r\n
\r\n"; for(auto& it: dest->GetLeaseSets ()) - s << it.first.ToBase32 () << " " << (int)it.second->GetStoreType () << "
\r\n"; - s << "

\r\n\r\n"; + s << "\r\n"; + s << "
AddressTypeEncType
" << it.first.ToBase32 () << "" << (int)it.second->GetStoreType () << "" << (int)it.second->GetEncryptionType () <<"
\r\n
\r\n
\r\n
\r\n"; } else - s << "LeaseSets: 0
\r\n"; + s << "LeaseSets: 0
\r\n
\r\n"; auto pool = dest->GetTunnelPool (); if (pool) { @@ -395,10 +401,11 @@ namespace http { if (!dest->GetSessions ().empty ()) { std::stringstream tmp_s; uint32_t out_tags = 0; for (const auto& it: dest->GetSessions ()) { - tmp_s << i2p::client::context.GetAddressBook ().ToAddress(it.first) << " " << it.second->GetNumOutgoingTags () << "
\r\n"; + tmp_s << "" << i2p::client::context.GetAddressBook ().ToAddress(it.first) << "" << it.second->GetNumOutgoingTags () << "\r\n"; out_tags = out_tags + it.second->GetNumOutgoingTags (); } - s << "
\r\n\r\n

\r\n" << tmp_s.str () << "

\r\n
\r\n"; + s << "
\r\n\r\n" + << "
\r\n\r\n" << tmp_s.str () << "
DestinationAmount
\r\n
\r\n
\r\n"; } else s << "Outgoing: 0
\r\n"; s << "
\r\n"; @@ -473,46 +480,57 @@ namespace http { void ShowLeasesSets(std::stringstream& s) { - s << "LeaseSets:
\r\n
\r\n"; - int counter = 1; - // for each lease set - i2p::data::netdb.VisitLeaseSets( - [&s, &counter](const i2p::data::IdentHash dest, std::shared_ptr leaseSet) - { - // create copy of lease set so we extract leases - auto storeType = leaseSet->GetStoreType (); - std::unique_ptr ls; - if (storeType == i2p::data::NETDB_STORE_TYPE_LEASESET) - ls.reset (new i2p::data::LeaseSet (leaseSet->GetBuffer(), leaseSet->GetBufferLen())); - else - ls.reset (new i2p::data::LeaseSet2 (storeType, leaseSet->GetBuffer(), leaseSet->GetBufferLen())); - if (!ls) return; - s << "
\r\n"; - if (!ls->IsValid()) - s << "
!! Invalid !!
\r\n"; - s << "
\r\n"; - s << "\r\n

\r\n"; - s << "Store type: " << (int)storeType << "
\r\n"; - s << "Expires: " << ConvertTime(ls->GetExpirationTime()) << "
\r\n"; - if (storeType == i2p::data::NETDB_STORE_TYPE_LEASESET || storeType == i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2) - { - // leases information is available - auto leases = ls->GetNonExpiredLeases(); - s << "Non Expired Leases: " << leases.size() << "
\r\n"; - for ( auto & l : leases ) + if (i2p::data::netdb.GetNumLeaseSets ()) + { + s << "LeaseSets:
\r\n
\r\n"; + int counter = 1; + // for each lease set + i2p::data::netdb.VisitLeaseSets( + [&s, &counter](const i2p::data::IdentHash dest, std::shared_ptr leaseSet) + { + // create copy of lease set so we extract leases + auto storeType = leaseSet->GetStoreType (); + std::unique_ptr ls; + if (storeType == i2p::data::NETDB_STORE_TYPE_LEASESET) + ls.reset (new i2p::data::LeaseSet (leaseSet->GetBuffer(), leaseSet->GetBufferLen())); + else + ls.reset (new i2p::data::LeaseSet2 (storeType, leaseSet->GetBuffer(), leaseSet->GetBufferLen())); + if (!ls) return; + s << "

\r\n"; + if (!ls->IsValid()) + s << "
!! Invalid !!
\r\n"; + s << "
\r\n"; + s << "\r\n
\r\n"; + s << "Store type: " << (int)storeType << "
\r\n"; + s << "Expires: " << ConvertTime(ls->GetExpirationTime()) << "
\r\n"; + if (storeType == i2p::data::NETDB_STORE_TYPE_LEASESET || storeType == i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2) { - s << "Gateway: " << l->tunnelGateway.ToBase64() << "
\r\n"; - s << "TunnelID: " << l->tunnelID << "
\r\n"; - s << "EndDate: " << ConvertTime(l->endDate) << "
\r\n"; + // leases information is available + auto leases = ls->GetNonExpiredLeases(); + s << "Non Expired Leases: " << leases.size() << "
\r\n"; + for ( auto & l : leases ) + { + s << "Gateway: " << l->tunnelGateway.ToBase64() << "
\r\n"; + s << "TunnelID: " << l->tunnelID << "
\r\n"; + s << "EndDate: " << ConvertTime(l->endDate) << "
\r\n"; + } } - } - s << "

\r\n
\r\n
\r\n"; - } - ); - // end for each lease set + s << "
\r\n
\r\n
\r\n"; + } + ); + // end for each lease set + } + else if (!i2p::context.IsFloodfill ()) + { + s << "LeaseSets: not floodfill.
\r\n"; + } + else + { + s << "LeaseSets: 0
\r\n"; + } } void ShowTunnels (std::stringstream& s) @@ -574,16 +592,23 @@ namespace http { void ShowTransitTunnels (std::stringstream& s) { - s << "Transit tunnels:
\r\n
\r\n"; - for (const auto& it: i2p::tunnel::tunnels.GetTransitTunnels ()) + if(i2p::tunnel::tunnels.CountTransitTunnels()) { - if (std::dynamic_pointer_cast(it)) - s << it->GetTunnelID () << " ⇒ "; - else if (std::dynamic_pointer_cast(it)) - s << " ⇒ " << it->GetTunnelID (); - else - s << " ⇒ " << it->GetTunnelID () << " ⇒ "; - s << " " << it->GetNumTransmittedBytes () << "
\r\n"; + s << "Transit tunnels:
\r\n
\r\n"; + for (const auto& it: i2p::tunnel::tunnels.GetTransitTunnels ()) + { + if (std::dynamic_pointer_cast(it)) + s << it->GetTunnelID () << " ⇒ "; + else if (std::dynamic_pointer_cast(it)) + s << " ⇒ " << it->GetTunnelID (); + else + s << " ⇒ " << it->GetTunnelID () << " ⇒ "; + s << " " << it->GetNumTransmittedBytes () << "
\r\n"; + } + } + else + { + s << "Transit tunnels: no transit tunnels currently built.
\r\n"; } } @@ -617,13 +642,15 @@ namespace http { } if (!tmp_s.str ().empty ()) { - s << "
\r\n\r\n

"; - s << tmp_s.str () << "

\r\n
\r\n"; + s << "
\r\n\r\n
" + << tmp_s.str () << "
\r\n
\r\n"; } if (!tmp_s6.str ().empty ()) { - s << "
\r\n\r\n

"; - s << tmp_s6.str () << "

\r\n
\r\n"; + s << "
\r\n\r\n
" + << tmp_s6.str () << "
\r\n
\r\n"; } } @@ -650,7 +677,7 @@ namespace http { auto sessions = ssuServer->GetSessions (); if (!sessions.empty ()) { - s << "
\r\n\r\n

"; + s << "

\r\n\r\n
"; for (const auto& it: sessions) { auto endpoint = it.second->GetRemoteEndpoint (); @@ -662,12 +689,12 @@ namespace http { s << " [itag:" << it.second->GetRelayTag () << "]"; s << "
\r\n" << std::endl; } - s << "

\r\n
\r\n"; + s << "
\r\n
\r\n"; } auto sessions6 = ssuServer->GetSessionsV6 (); if (!sessions6.empty ()) { - s << "
\r\n\r\n

"; + s << "

\r\n\r\n
"; for (const auto& it: sessions6) { auto endpoint = it.second->GetRemoteEndpoint (); @@ -679,7 +706,7 @@ namespace http { s << " [itag:" << it.second->GetRelayTag () << "]"; s << "
\r\n" << std::endl; } - s << "

\r\n
\r\n"; + s << "
\r\n
\r\n"; } } } @@ -688,17 +715,24 @@ namespace http { { std::string webroot; i2p::config::GetOption("http.webroot", webroot); auto sam = i2p::client::context.GetSAMBridge (); - if (!sam) { + if (!sam) + { ShowError(s, "SAM disabled"); return; } - s << "SAM Sessions:
\r\n
\r\n"; - for (auto& it: sam->GetSessions ()) + + if(sam->GetSessions ().size ()) { - auto& name = it.second->localDestination->GetNickname (); - s << ""; - s << name << " (" << it.first << ")
\r\n" << std::endl; + s << "SAM Sessions:
\r\n
\r\n"; + for (auto& it: sam->GetSessions ()) + { + auto& name = it.second->localDestination->GetNickname (); + s << ""; + s << name << " (" << it.first << ")
\r\n" << std::endl; + } } + else + s << "SAM Sessions: no sessions currently running.
\r\n"; } static void ShowSAMSession (std::stringstream& s, const std::string& id) From 22497080973e25e8b9b5fd93b86af44f795a18e3 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Thu, 19 Mar 2020 02:34:45 +0300 Subject: [PATCH 35/44] [webconsole] remove excess tag Signed-off-by: R4SAS --- daemon/HTTPServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index a7bd693f..5eac08a9 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -299,7 +299,7 @@ namespace http { } s << "\r\n"; } - s << "\r\n
\r\n
\r\n"; + s << "\r\n\r\n"; if(outputFormat==OutputFormatEnum::forQtUi) { s << "
"; } From 3ca17fdc039f46996038d5bb501539a728e06f8a Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 19 Mar 2020 18:33:42 -0400 Subject: [PATCH 36/44] support multiple encryption keys --- libi2pd/Destination.cpp | 11 +++++++++-- libi2pd/Destination.h | 9 +++++---- libi2pd/ECIESX25519AEADRatchetSession.cpp | 4 ++-- libi2pd/Garlic.cpp | 4 ++-- libi2pd/Identity.h | 4 ++-- libi2pd_client/I2CP.h | 3 ++- 6 files changed, 22 insertions(+), 13 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 60f5062c..46d3fc57 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -388,7 +388,7 @@ namespace client if (buf[DATABASE_STORE_TYPE_OFFSET] == i2p::data::NETDB_STORE_TYPE_LEASESET) leaseSet = std::make_shared (buf + offset, len - offset); // LeaseSet else - leaseSet = std::make_shared (buf[DATABASE_STORE_TYPE_OFFSET], buf + offset, len - offset, true, GetEncryptionType ()); // LeaseSet2 + leaseSet = std::make_shared (buf[DATABASE_STORE_TYPE_OFFSET], buf + offset, len - offset, true, GetPreferredCryptoType () ); // LeaseSet2 if (leaseSet->IsValid () && leaseSet->GetIdentHash () == key) { if (leaseSet->GetIdentHash () != GetIdentHash ()) @@ -412,7 +412,7 @@ namespace client auto it2 = m_LeaseSetRequests.find (key); if (it2 != m_LeaseSetRequests.end () && it2->second->requestedBlindedKey) { - auto ls2 = std::make_shared (buf + offset, len - offset, it2->second->requestedBlindedKey, m_LeaseSetPrivKey ? *m_LeaseSetPrivKey : nullptr, GetEncryptionType ()); + auto ls2 = std::make_shared (buf + offset, len - offset, it2->second->requestedBlindedKey, m_LeaseSetPrivKey ? *m_LeaseSetPrivKey : nullptr, GetPreferredCryptoType ()); if (ls2->IsValid ()) { m_RemoteLeaseSets[ls2->GetIdentHash ()] = ls2; // ident is not key @@ -822,6 +822,13 @@ namespace client } } + i2p::data::CryptoKeyType LeaseSetDestination::GetPreferredCryptoType () const + { + if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET)) + return i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET; + return i2p::data::CRYPTO_KEY_TYPE_ELGAMAL; + } + ClientDestination::ClientDestination (boost::asio::io_service& service, const i2p::data::PrivateKeys& keys, bool isPublic, const std::map * params): LeaseSetDestination (service, isPublic, params), diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 23ed5188..f26200a0 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -161,6 +161,7 @@ namespace client void HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest); void HandleCleanupTimer (const boost::system::error_code& ecode); void CleanupRemoteLeaseSets (); + i2p::data::CryptoKeyType GetPreferredCryptoType () const; private: @@ -232,14 +233,14 @@ namespace client int GetStreamingAckDelay () const { return m_StreamingAckDelay; } // datagram - i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; }; - i2p::datagram::DatagramDestination * CreateDatagramDestination (); + i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; }; + i2p::datagram::DatagramDestination * CreateDatagramDestination (); // implements LocalDestination bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const; std::shared_ptr GetIdentity () const { return m_Keys.GetPublic (); }; - i2p::data::CryptoKeyType GetEncryptionType () const { return m_EncryptionKeyType; }; - const uint8_t * GetEncryptionPublicKey () const { return m_EncryptionPublicKey; }; + bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const { return m_EncryptionKeyType == keyType; }; + const uint8_t * GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const { return m_EncryptionPublicKey; }; protected: diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 8d300a16..2cea2172 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -126,7 +126,7 @@ namespace garlic if (!GetOwner ()) return false; // we are Bob // KDF1 - MixHash (GetOwner ()->GetEncryptionPublicKey (), 32); // h = SHA256(h || bpk) + MixHash (GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET), 32); // h = SHA256(h || bpk) if (!i2p::crypto::GetElligator ()->Decode (buf, m_Aepk)) { @@ -235,7 +235,7 @@ namespace garlic // encrypt static key section uint8_t nonce[12]; CreateNonce (0, nonce); - if (!i2p::crypto::AEADChaCha20Poly1305 (GetOwner ()->GetEncryptionPublicKey (), 32, m_H, 32, m_CK + 32, nonce, out + offset, 48, true)) // encrypt + if (!i2p::crypto::AEADChaCha20Poly1305 (GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET), 32, m_H, 32, m_CK + 32, nonce, out + offset, 48, true)) // encrypt { LogPrint (eLogWarning, "Garlic: Static section AEAD encryption failed "); return false; diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 97f80b41..629e0d76 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -488,7 +488,7 @@ namespace garlic else { // tag not found. Handle depending on encryption type - if (GetEncryptionType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET) + if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET)) { HandleECIESx25519 (buf, length); return; @@ -680,7 +680,7 @@ namespace garlic std::shared_ptr destination, bool attachLeaseSet) { if (destination->GetEncryptionType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET && - GetEncryptionType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET) + SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET)) { ECIESX25519AEADRatchetSessionPtr session; uint8_t staticKey[32]; diff --git a/libi2pd/Identity.h b/libi2pd/Identity.h index f217f3c5..9c78f552 100644 --- a/libi2pd/Identity.h +++ b/libi2pd/Identity.h @@ -228,8 +228,8 @@ namespace data virtual std::shared_ptr GetIdentity () const = 0; const IdentHash& GetIdentHash () const { return GetIdentity ()->GetIdentHash (); }; - virtual CryptoKeyType GetEncryptionType () const { return GetIdentity ()->GetCryptoKeyType (); }; // override for LeaseSet - virtual const uint8_t * GetEncryptionPublicKey () const { return GetIdentity ()->GetEncryptionPublicKey (); }; // override for LeaseSet + virtual bool SupportsEncryptionType (CryptoKeyType keyType) const { return GetIdentity ()->GetCryptoKeyType () == keyType; }; // override for LeaseSet + virtual const uint8_t * GetEncryptionPublicKey (CryptoKeyType keyType) const { return GetIdentity ()->GetEncryptionPublicKey (); }; // override for LeaseSet }; } } diff --git a/libi2pd_client/I2CP.h b/libi2pd_client/I2CP.h index 68b4415a..848378e0 100644 --- a/libi2pd_client/I2CP.h +++ b/libi2pd_client/I2CP.h @@ -80,7 +80,8 @@ namespace client // implements LocalDestination bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const; - i2p::data::CryptoKeyType GetEncryptionType () const { return m_EncryptionKeyType; }; + bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const { return m_EncryptionKeyType == keyType; }; + // TODO: implement GetEncryptionPublicKey std::shared_ptr GetIdentity () const { return m_Identity; }; protected: From b6b25dc9f3c6d57c11f8fd8c2980e64133f4a682 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Fri, 20 Mar 2020 17:44:53 +0300 Subject: [PATCH 37/44] update log messages Signed-off-by: R4SAS --- libi2pd/Garlic.cpp | 2 +- libi2pd/LeaseSet.cpp | 2 +- libi2pd/SSUData.cpp | 6 +++--- libi2pd/Transports.cpp | 13 +++++++------ 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 629e0d76..02d1cd83 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -890,7 +890,7 @@ namespace garlic m_Tags.insert (std::make_pair (SessionTag (tag, ts), decryption)); } if (!m_Tags.empty ()) - LogPrint (eLogInfo, m_Tags.size (), " loaded for ", ident); + LogPrint (eLogInfo, "Garlic: " m_Tags.size (), " tags loaded for ", ident); } } i2p::fs::Remove (path); diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index e2da1d21..bcfede33 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -159,7 +159,7 @@ namespace data } } else - LogPrint (eLogWarning, "LeaseSet: Lease is expired already "); + LogPrint (eLogWarning, "LeaseSet: Lease is expired already"); } uint64_t LeaseSet::ExtractTimestamp (const uint8_t * buf, size_t len) const diff --git a/libi2pd/SSUData.cpp b/libi2pd/SSUData.cpp index add58739..866da277 100644 --- a/libi2pd/SSUData.cpp +++ b/libi2pd/SSUData.cpp @@ -442,7 +442,7 @@ namespace transport } catch (boost::system::system_error& ec) { - LogPrint (eLogWarning, "SSU: Can't resend data fragment ", ec.what ()); + LogPrint (eLogWarning, "SSU: Can't resend message ", it->first, " data fragment: ", ec.what ()); } } @@ -452,7 +452,7 @@ namespace transport } else { - LogPrint (eLogInfo, "SSU: message has not been ACKed after ", MAX_NUM_RESENDS, " attempts, deleted"); + LogPrint (eLogInfo, "SSU: message ", it->first, " has not been ACKed after ", MAX_NUM_RESENDS, " attempts, deleted"); it = m_SentMessages.erase (it); } } @@ -488,7 +488,7 @@ namespace transport { if (ts > it->second->lastFragmentInsertTime + INCOMPLETE_MESSAGES_CLEANUP_TIMEOUT) { - LogPrint (eLogWarning, "SSU: message ", it->first, " was not completed in ", INCOMPLETE_MESSAGES_CLEANUP_TIMEOUT, " seconds, deleted"); + LogPrint (eLogWarning, "SSU: message ", it->first, " was not completed in ", INCOMPLETE_MESSAGES_CLEANUP_TIMEOUT, " seconds, deleted"); it = m_IncompleteMessages.erase (it); } else diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 97c29c70..804f26cb 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -271,11 +271,11 @@ namespace transport m_PeerCleanupTimer->expires_from_now (boost::posix_time::seconds(5*SESSION_CREATION_TIMEOUT)); m_PeerCleanupTimer->async_wait (std::bind (&Transports::HandlePeerCleanupTimer, this, std::placeholders::_1)); - if (m_IsNAT) - { - m_PeerTestTimer->expires_from_now (boost::posix_time::minutes(PEER_TEST_INTERVAL)); - m_PeerTestTimer->async_wait (std::bind (&Transports::HandlePeerTestTimer, this, std::placeholders::_1)); - } + if (m_IsNAT) + { + m_PeerTestTimer->expires_from_now (boost::posix_time::minutes(PEER_TEST_INTERVAL)); + m_PeerTestTimer->async_wait (std::bind (&Transports::HandlePeerTestTimer, this, std::placeholders::_1)); + } } void Transports::Stop () @@ -589,6 +589,7 @@ namespace transport if (RoutesRestricted() || !i2p::context.SupportsV4 ()) return; if (m_SSUServer) { + LogPrint (eLogInfo, "Transports: Started peer test"); bool statusChanged = false; for (int i = 0; i < 5; i++) { @@ -604,7 +605,7 @@ namespace transport } } if (!statusChanged) - LogPrint (eLogWarning, "Can't find routers for peer test"); + LogPrint (eLogWarning, "Transports: Can't find routers for peer test"); } } From 168da33d8bc5689ee0ecb01e4c05ca785e3662ba Mon Sep 17 00:00:00 2001 From: R4SAS Date: Fri, 20 Mar 2020 18:43:54 +0300 Subject: [PATCH 38/44] add comma Signed-off-by: R4SAS --- libi2pd/Garlic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 02d1cd83..ae6599fc 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -890,7 +890,7 @@ namespace garlic m_Tags.insert (std::make_pair (SessionTag (tag, ts), decryption)); } if (!m_Tags.empty ()) - LogPrint (eLogInfo, "Garlic: " m_Tags.size (), " tags loaded for ", ident); + LogPrint (eLogInfo, "Garlic: ", m_Tags.size (), " tags loaded for ", ident); } } i2p::fs::Remove (path); From 962c2160c77cce4460950fb6a231725235daf89d Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 20 Mar 2020 17:43:37 -0400 Subject: [PATCH 39/44] set actual LeaseSet2 buffer size --- libi2pd/LeaseSet.cpp | 15 +++++++++++++++ libi2pd/LeaseSet.h | 1 + 2 files changed, 16 insertions(+) diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index bcfede33..b411ca0e 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -251,6 +251,13 @@ namespace data memcpy (m_Buffer, buf, len); } + void LeaseSet::SetBufferLen (size_t len) + { + if (len <= m_BufferLen) m_BufferLen = len; + else + LogPrint (eLogError, "LeaseSet2: actual buffer size ", len , " exceeds full buffer size ", m_BufferLen); + } + LeaseSet2::LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases, CryptoKeyType preferredCrypto): LeaseSet (storeLeases), m_StoreType (storeType), m_EncryptionType (preferredCrypto) { @@ -331,6 +338,8 @@ namespace data VerifySignature (identity, buf, len, offset); SetIsValid (verified); } + offset += m_TransientVerifier ? m_TransientVerifier->GetSignatureLen () : identity->GetSignatureLen (); + SetBufferLen (offset); } template @@ -537,6 +546,12 @@ namespace data else LogPrint (eLogError, "LeaseSet2: unexpected LeaseSet type ", (int)innerPlainText[0], " inside encrypted LeaseSet"); } + else + { + // we set actual length of encrypted buffer + offset += m_TransientVerifier ? m_TransientVerifier->GetSignatureLen () : blindedVerifier->GetSignatureLen (); + SetBufferLen (offset); + } } // helper for ExtractClientAuthData diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index 791d77e3..0d255644 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -97,6 +97,7 @@ namespace data // called from LeaseSet2 LeaseSet (bool storeLeases); void SetBuffer (const uint8_t * buf, size_t len); + void SetBufferLen (size_t len); void SetIdentity (std::shared_ptr identity) { m_Identity = identity; }; void SetExpirationTime (uint64_t t) { m_ExpirationTime = t; }; void SetIsValid (bool isValid) { m_IsValid = isValid; }; From ff19bab80087947c7f364d60edfd8af63478b9c7 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 21 Mar 2020 16:21:51 -0400 Subject: [PATCH 40/44] set only key correctly --- libi2pd_client/I2CP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index c09b7f4d..ccd94e46 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -572,7 +572,7 @@ namespace client uint16_t keyType = bufbe16toh (buf + offset); offset += 2; // encryption type uint16_t keyLen = bufbe16toh (buf + offset); offset += 2; // private key length if (offset + keyLen > len) return; - if (keyType > currentKeyType) + if (!currentKey || keyType > currentKeyType) { currentKeyType = keyType; currentKey = buf + offset; From 6fb80f226acd76c50e4f615111a8ba01e279c4d5 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 22 Mar 2020 08:14:20 -0400 Subject: [PATCH 41/44] reopen socked and restart receiver on exception --- libi2pd/SSU.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libi2pd/SSU.cpp b/libi2pd/SSU.cpp index daf7e1e9..4eb958de 100644 --- a/libi2pd/SSU.cpp +++ b/libi2pd/SSU.cpp @@ -160,6 +160,13 @@ namespace transport catch (std::exception& ex) { LogPrint (eLogError, "SSU: receivers runtime exception: ", ex.what ()); + if (m_IsRunning) + { + // restart socket + m_Socket.close (); + OpenSocket (); + Receive (); + } } } } @@ -175,6 +182,12 @@ namespace transport catch (std::exception& ex) { LogPrint (eLogError, "SSU: v6 receivers runtime exception: ", ex.what ()); + if (m_IsRunning) + { + m_SocketV6.close (); + OpenSocketV6 (); + ReceiveV6 (); + } } } } From fe9ac10f02da049c7966c0ecb2cd84c8e94698c8 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 22 Mar 2020 21:21:12 -0400 Subject: [PATCH 42/44] generate new tags based on last received index --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 4 +--- libi2pd/ECIESX25519AEADRatchetSession.h | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 2cea2172..5dd78747 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -402,8 +402,7 @@ namespace garlic return false; } HandlePayload (payload.data (), len - 16); - if (m_NumReceiveTags > 0)m_NumReceiveTags--; - if (m_NumReceiveTags <= GetOwner ()->GetNumTags ()*2/3) + if (m_ReceiveTagset.GetNextIndex () - index <= GetOwner ()->GetNumTags ()*2/3) GenerateMoreReceiveTags (GetOwner ()->GetNumTags ()); return true; } @@ -570,7 +569,6 @@ namespace garlic uint64_t tag = m_ReceiveTagset.GetNextSessionTag (); GetOwner ()->AddECIESx25519SessionTag (index, tag, shared_from_this ()); } - m_NumReceiveTags += numTags; } bool ECIESX25519AEADRatchetSession::CheckExpired (uint64_t ts) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index db9807a5..95875013 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -119,7 +119,6 @@ namespace garlic SessionState m_State = eSessionStateNew; uint64_t m_LastActivityTimestamp = 0; // incoming RatchetTagSet m_SendTagset, m_ReceiveTagset; - int m_NumReceiveTags = 0; std::unique_ptr m_Destination;// TODO: might not need it }; } From 744e893dcef13db3d47aea1d877cf97032fa0c03 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 23 Mar 2020 18:09:57 -0400 Subject: [PATCH 43/44] check message length --- libi2pd_client/I2CP.cpp | 12 ++++++++++-- libi2pd_client/I2CP.h | 3 ++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index ccd94e46..eec21f06 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -246,8 +246,16 @@ namespace client m_PayloadLen = bufbe32toh (m_Header + I2CP_HEADER_LENGTH_OFFSET); if (m_PayloadLen > 0) { - m_Payload = new uint8_t[m_PayloadLen]; - ReceivePayload (); + if (m_PayloadLen <= I2CP_MAX_MESSAGE_LENGTH) + { + m_Payload = new uint8_t[m_PayloadLen]; + ReceivePayload (); + } + else + { + LogPrint (eLogError, "I2CP: Unexpected payload length ", m_PayloadLen); + Terminate (); + } } else // no following payload { diff --git a/libi2pd_client/I2CP.h b/libi2pd_client/I2CP.h index 848378e0..f675318f 100644 --- a/libi2pd_client/I2CP.h +++ b/libi2pd_client/I2CP.h @@ -24,7 +24,8 @@ namespace client { const uint8_t I2CP_PROTOCOL_BYTE = 0x2A; const size_t I2CP_SESSION_BUFFER_SIZE = 4096; - + const size_t I2CP_MAX_MESSAGE_LENGTH = 65535; + const size_t I2CP_HEADER_LENGTH_OFFSET = 0; const size_t I2CP_HEADER_TYPE_OFFSET = I2CP_HEADER_LENGTH_OFFSET + 4; const size_t I2CP_HEADER_SIZE = I2CP_HEADER_TYPE_OFFSET + 1; From 869d0156ce38de301e32c5a35a698059c4a0d5d9 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 26 Mar 2020 19:03:38 -0400 Subject: [PATCH 44/44] handle Ack request --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 25 +++++++++++++++++++++-- libi2pd/ECIESX25519AEADRatchetSession.h | 6 +++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 5dd78747..c57553d4 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -38,6 +38,7 @@ namespace garlic { i2p::crypto::HKDF (m_KeyData.GetSessTagCK (), m_SessTagConstant, 32, "SessionTagKeyGen", m_KeyData.buf); // [sessTag_ck, tag] = HKDF(sessTag_chainkey, SESSTAG_CONSTANT, "SessionTagKeyGen", 64) m_NextIndex++; + if (m_NextIndex >= 65535) m_NextIndex = 0; // TODO: dirty hack, should create new tagset return m_KeyData.GetTag (); } @@ -178,7 +179,7 @@ namespace garlic return true; } - void ECIESX25519AEADRatchetSession::HandlePayload (const uint8_t * buf, size_t len) + void ECIESX25519AEADRatchetSession::HandlePayload (const uint8_t * buf, size_t len, int index) { size_t offset = 0; while (offset < len) @@ -207,6 +208,12 @@ namespace garlic case eECIESx25519BlkPadding: LogPrint (eLogDebug, "Garlic: padding"); break; + case eECIESx25519BlkAckRequest: + { + LogPrint (eLogDebug, "Garlic: ack request"); + m_AckRequests.push_back ( {bufbe16toh (buf + offset), index}); + break; + } default: LogPrint (eLogWarning, "Garlic: Unknown block type ", (int)blk); } @@ -401,7 +408,7 @@ namespace garlic LogPrint (eLogWarning, "Garlic: Payload section AEAD decryption failed"); return false; } - HandlePayload (payload.data (), len - 16); + HandlePayload (payload.data (), len - 16, index); if (m_ReceiveTagset.GetNextIndex () - index <= GetOwner ()->GetNumTags ()*2/3) GenerateMoreReceiveTags (GetOwner ()->GetNumTags ()); return true; @@ -478,6 +485,8 @@ namespace garlic SetLeaseSetSubmissionTime (ts); GetOwner ()->DeliveryStatusSent (shared_from_this (), leaseSet->GetMsgID ()); } + if (m_AckRequests.size () > 0) + payloadLen += m_AckRequests.size ()*4 + 3; uint8_t paddingSize; RAND_bytes (&paddingSize, 1); paddingSize &= 0x0F; paddingSize++; // 1 - 16 @@ -497,6 +506,18 @@ namespace garlic // msg if (msg && m_Destination) offset += CreateGarlicClove (msg, v.data () + offset, payloadLen - offset, true); + // ack + if (m_AckRequests.size () > 0) + { + v[offset] = eECIESx25519BlkAck; offset++; + htobe16buf (v.data () + offset, m_AckRequests.size ()*4); offset += 2; + for (auto& it: m_AckRequests) + { + htobe16buf (v.data () + offset, it.first); offset += 2; + htobe16buf (v.data () + offset, it.second); offset += 2; + } + m_AckRequests.clear (); + } // padding v[offset] = eECIESx25519BlkPadding; offset++; htobe16buf (v.data () + offset, paddingSize); offset += 2; diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index 95875013..56fb48cf 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -6,6 +6,7 @@ #include #include #include +#include #include "Identity.h" #include "Crypto.h" #include "Garlic.h" @@ -51,6 +52,8 @@ namespace garlic eECIESx25519BlkTermination = 4, eECIESx25519BlkOptions = 5, eECIESx25519BlkNextSessionKey = 7, + eECIESx25519BlkAck = 8, + eECIESx25519BlkAckRequest = 9, eECIESx25519BlkGalicClove = 11, eECIESx25519BlkPadding = 254 }; @@ -99,7 +102,7 @@ namespace garlic bool HandleNewIncomingSession (const uint8_t * buf, size_t len); bool HandleNewOutgoingSessionReply (const uint8_t * buf, size_t len); bool HandleExistingSessionMessage (const uint8_t * buf, size_t len, int index); - void HandlePayload (const uint8_t * buf, size_t len); + void HandlePayload (const uint8_t * buf, size_t len, int index = 0); bool NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen); bool NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen); @@ -120,6 +123,7 @@ namespace garlic uint64_t m_LastActivityTimestamp = 0; // incoming RatchetTagSet m_SendTagset, m_ReceiveTagset; std::unique_ptr m_Destination;// TODO: might not need it + std::list > m_AckRequests; // (key_id, indeX) }; } }