From 5bfab0a79639924b666ce20647a8fe469838f0fe Mon Sep 17 00:00:00 2001 From: R4SAS Date: Fri, 18 Jun 2021 06:38:10 +0300 Subject: [PATCH 01/24] add certsdir option (#1642) Signed-off-by: R4SAS --- contrib/i2pd.conf | 4 ++++ libi2pd/Config.cpp | 1 + libi2pd/Family.cpp | 9 ++++++++- libi2pd/Reseed.cpp | 9 ++++++++- 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/contrib/i2pd.conf b/contrib/i2pd.conf index f3cea2b5..7b85a61b 100644 --- a/contrib/i2pd.conf +++ b/contrib/i2pd.conf @@ -15,6 +15,10 @@ ## Default: ~/.i2pd/tunnels.d or /var/lib/i2pd/tunnels.d # tunnelsdir = /var/lib/i2pd/tunnels.d +## Path to certificates used for verifying .su3, families +## Default: ~/.i2pd/certificates or /var/lib/i2pd/certificates +# certsdir = /var/lib/i2pd/certificates + ## Where to write pidfile (default: i2pd.pid, not used in Windows) # pidfile = /run/i2pd.pid diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index a80778a1..16d50e8c 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -37,6 +37,7 @@ namespace config { ("conf", value()->default_value(""), "Path to main i2pd config file (default: try ~/.i2pd/i2pd.conf or /var/lib/i2pd/i2pd.conf)") ("tunconf", value()->default_value(""), "Path to config with tunnels list and options (default: try ~/.i2pd/tunnels.conf or /var/lib/i2pd/tunnels.conf)") ("tunnelsdir", value()->default_value(""), "Path to extra tunnels' configs folder (default: ~/.i2pd/tunnels.d or /var/lib/i2pd/tunnels.d") + ("certsdir", value()->default_value(""), "Path to certificates used for verifying .su3, families (default: ~/.i2pd/certificates or /var/lib/i2pd/certificates") ("pidfile", value()->default_value(""), "Path to pidfile (default: ~/i2pd/i2pd.pid or /var/lib/i2pd/i2pd.pid)") ("log", value()->default_value(""), "Logs destination: stdout, file, syslog (stdout if not set)") ("logfile", value()->default_value(""), "Path to logfile (stdout if not set, autodetect if daemon)") diff --git a/libi2pd/Family.cpp b/libi2pd/Family.cpp index fbb7b9ee..baf846f6 100644 --- a/libi2pd/Family.cpp +++ b/libi2pd/Family.cpp @@ -98,7 +98,14 @@ namespace data void Families::LoadCertificates () { - std::string certDir = i2p::fs::DataDirPath("certificates", "family"); + std::string certDir; + std::string certsdir; i2p::config::GetOption("certsdir", certsdir); + if (!i2p::config::IsDefault("certsdir")) + certDir = certsdir + i2p::fs::dirSep + "family"; + + if (certDir.empty() || !i2p::fs::Exists(certDir)) + std::string certDir = i2p::fs::DataDirPath("certificates", "family"); + std::vector files; int numCertificates = 0; diff --git a/libi2pd/Reseed.cpp b/libi2pd/Reseed.cpp index 41111ecc..a78058cf 100644 --- a/libi2pd/Reseed.cpp +++ b/libi2pd/Reseed.cpp @@ -497,7 +497,14 @@ namespace data void Reseeder::LoadCertificates () { - std::string certDir = i2p::fs::DataDirPath("certificates", "reseed"); + std::string certDir; + std::string certsdir; i2p::config::GetOption("certsdir", certsdir); + if (!i2p::config::IsDefault("certsdir")) + certDir = certsdir + i2p::fs::dirSep + "reseed"; + + if (certDir.empty() || !i2p::fs::Exists(certDir)) + std::string certDir = i2p::fs::DataDirPath("certificates", "reseed"); + std::vector files; int numCertificates = 0; From d3a49e513c75ba4a78ac8d68a4def828feb6bfcb Mon Sep 17 00:00:00 2001 From: R4SAS Date: Fri, 18 Jun 2021 06:40:58 +0300 Subject: [PATCH 02/24] remove repeatable type definition, add include (#1642) Signed-off-by: R4SAS --- libi2pd/Family.cpp | 3 ++- libi2pd/Reseed.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libi2pd/Family.cpp b/libi2pd/Family.cpp index baf846f6..f37a5f54 100644 --- a/libi2pd/Family.cpp +++ b/libi2pd/Family.cpp @@ -13,6 +13,7 @@ #include "FS.h" #include "Log.h" #include "Family.h" +#include "Config.h" namespace i2p { @@ -104,7 +105,7 @@ namespace data certDir = certsdir + i2p::fs::dirSep + "family"; if (certDir.empty() || !i2p::fs::Exists(certDir)) - std::string certDir = i2p::fs::DataDirPath("certificates", "family"); + certDir = i2p::fs::DataDirPath("certificates", "family"); std::vector files; int numCertificates = 0; diff --git a/libi2pd/Reseed.cpp b/libi2pd/Reseed.cpp index a78058cf..482506b2 100644 --- a/libi2pd/Reseed.cpp +++ b/libi2pd/Reseed.cpp @@ -503,7 +503,7 @@ namespace data certDir = certsdir + i2p::fs::dirSep + "reseed"; if (certDir.empty() || !i2p::fs::Exists(certDir)) - std::string certDir = i2p::fs::DataDirPath("certificates", "reseed"); + certDir = i2p::fs::DataDirPath("certificates", "reseed"); std::vector files; int numCertificates = 0; From e8ad7b4f79292c8ccded1c22e80089ad9f6a501f Mon Sep 17 00:00:00 2001 From: R4SAS Date: Fri, 18 Jun 2021 10:04:48 +0300 Subject: [PATCH 03/24] rework of storing certificates path (#1642) Signed-off-by: R4SAS --- daemon/Daemon.cpp | 6 ++++++ libi2pd/FS.cpp | 20 ++++++++++++++++++++ libi2pd/FS.h | 18 +++++++++++++++++- libi2pd/Family.cpp | 8 +------- libi2pd/Reseed.cpp | 8 +------- 5 files changed, 45 insertions(+), 15 deletions(-) diff --git a/daemon/Daemon.cpp b/daemon/Daemon.cpp index f7f2ef2f..445c4dfd 100644 --- a/daemon/Daemon.cpp +++ b/daemon/Daemon.cpp @@ -94,6 +94,11 @@ namespace util i2p::config::GetOption("daemon", isDaemon); + std::string certsdir; i2p::config::GetOption("certsdir", certsdir); + i2p::fs::SetCertsDir(certsdir); + + certsdir = i2p::fs::GetCertsDir(); + std::string logs = ""; i2p::config::GetOption("log", logs); std::string logfile = ""; i2p::config::GetOption("logfile", logfile); std::string loglevel = ""; i2p::config::GetOption("loglevel", loglevel); @@ -132,6 +137,7 @@ namespace util LogPrint(eLogNone, "i2pd v", VERSION, " starting"); LogPrint(eLogDebug, "FS: main config file: ", config); LogPrint(eLogDebug, "FS: data directory: ", datadir); + LogPrint(eLogDebug, "FS: certificates directory: ", certsdir); bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation); bool aesni; i2p::config::GetOption("cpuext.aesni", aesni); diff --git a/libi2pd/FS.cpp b/libi2pd/FS.cpp index 6ac302b0..f6653e55 100644 --- a/libi2pd/FS.cpp +++ b/libi2pd/FS.cpp @@ -24,6 +24,7 @@ namespace i2p { namespace fs { std::string appName = "i2pd"; std::string dataDir = ""; + std::string certsDir = ""; #ifdef _WIN32 std::string dirSep = "\\"; #else @@ -42,6 +43,10 @@ namespace fs { return dataDir; } + const std::string & GetCertsDir () { + return certsDir; + } + const std::string GetUTF8DataDir () { #ifdef _WIN32 boost::filesystem::wpath path (dataDir); @@ -126,6 +131,21 @@ namespace fs { #endif } + void SetCertsDir(const std::string & cmdline_certsdir) { + if (cmdline_certsdir != "") + { + if (cmdline_certsdir[cmdline_certsdir.length()-1] == '/') + certsDir = cmdline_certsdir.substr(0, cmdline_certsdir.size()-1); // strip trailing slash + else + certsDir = cmdline_certsdir; + } + else + { + certsDir = i2p::fs::DataDirPath("certificates"); + } + return; + } + bool Init() { if (!boost::filesystem::exists(dataDir)) boost::filesystem::create_directory(dataDir); diff --git a/libi2pd/FS.h b/libi2pd/FS.h index f07ee35c..d51aa955 100644 --- a/libi2pd/FS.h +++ b/libi2pd/FS.h @@ -75,6 +75,9 @@ namespace fs { /** @brief Returns datadir path */ const std::string & GetDataDir(); + /** @brief Returns certsdir path */ + const std::string & GetCertsDir(); + /** @brief Returns datadir path in UTF-8 encoding */ const std::string GetUTF8DataDir(); @@ -90,7 +93,20 @@ namespace fs { * Mac: /Library/Application Support/i2pd/ or ~/Library/Application Support/i2pd/ * Unix: /var/lib/i2pd/ (system=1) >> ~/.i2pd/ or /tmp/i2pd/ */ - void DetectDataDir(const std::string & cmdline_datadir, bool isService = false); + void DetectDataDir(const std::string & cmdline_datadir, bool isService = false); + + /** + * @brief Set certsdir either from cmdline option or using autodetection + * @param cmdline_param Value of cmdline parameter --certsdir= + * + * Examples of autodetected paths: + * + * Windows < Vista: C:\Documents and Settings\Username\Application Data\i2pd\certificates + * Windows >= Vista: C:\Users\Username\AppData\Roaming\i2pd\certificates + * Mac: /Library/Application Support/i2pd/ or ~/Library/Application Support/i2pd/certificates + * Unix: /var/lib/i2pd/certificates (system=1) >> ~/.i2pd/ or /tmp/i2pd/certificates + */ + void SetCertsDir(const std::string & cmdline_certsdir); /** * @brief Create subdirectories inside datadir diff --git a/libi2pd/Family.cpp b/libi2pd/Family.cpp index f37a5f54..a6f0e2ee 100644 --- a/libi2pd/Family.cpp +++ b/libi2pd/Family.cpp @@ -99,13 +99,7 @@ namespace data void Families::LoadCertificates () { - std::string certDir; - std::string certsdir; i2p::config::GetOption("certsdir", certsdir); - if (!i2p::config::IsDefault("certsdir")) - certDir = certsdir + i2p::fs::dirSep + "family"; - - if (certDir.empty() || !i2p::fs::Exists(certDir)) - certDir = i2p::fs::DataDirPath("certificates", "family"); + std::string certDir = i2p::fs::GetCertsDir() + i2p::fs::dirSep + "family"; std::vector files; int numCertificates = 0; diff --git a/libi2pd/Reseed.cpp b/libi2pd/Reseed.cpp index 482506b2..aec683d4 100644 --- a/libi2pd/Reseed.cpp +++ b/libi2pd/Reseed.cpp @@ -497,13 +497,7 @@ namespace data void Reseeder::LoadCertificates () { - std::string certDir; - std::string certsdir; i2p::config::GetOption("certsdir", certsdir); - if (!i2p::config::IsDefault("certsdir")) - certDir = certsdir + i2p::fs::dirSep + "reseed"; - - if (certDir.empty() || !i2p::fs::Exists(certDir)) - certDir = i2p::fs::DataDirPath("certificates", "reseed"); + std::string certDir = i2p::fs::GetCertsDir() + i2p::fs::dirSep + "reseed"; std::vector files; int numCertificates = 0; From 8e5d2e1b73fa28133c0e51aa0455bd77155ecdf9 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Fri, 18 Jun 2021 17:26:18 +0300 Subject: [PATCH 04/24] [readme] add gha container build badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 92a2f46f..37c4553a 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ Build instructions: * Alpine, ArchLinux, openSUSE, Gentoo, Debian, Ubuntu, etc. * Windows - [![Build on Windows](https://github.com/PurpleI2P/i2pd/actions/workflows/build-windows.yml/badge.svg)](https://github.com/PurpleI2P/i2pd/actions/workflows/build-windows.yml) * Mac OS X - [![Build on OSX](https://github.com/PurpleI2P/i2pd/actions/workflows/build-osx.yml/badge.svg)](https://github.com/PurpleI2P/i2pd/actions/workflows/build-osx.yml) -* Docker image - [![Build Status](https://img.shields.io/docker/cloud/build/purplei2p/i2pd)](https://hub.docker.com/r/purplei2p/i2pd/builds/) +* Docker image - [![Build Status](https://img.shields.io/docker/cloud/build/purplei2p/i2pd)](https://hub.docker.com/r/purplei2p/i2pd/builds/) [![Build containers](https://github.com/PurpleI2P/i2pd/actions/workflows/docker.yml/badge.svg)](https://github.com/PurpleI2P/i2pd/actions/workflows/docker.yml) * Snap - [![i2pd](https://snapcraft.io/i2pd/badge.svg)](https://snapcraft.io/i2pd) [![i2pd](https://snapcraft.io/i2pd/trending.svg?name=0)](https://snapcraft.io/i2pd) * FreeBSD - [![Build on FreeBSD](https://github.com/PurpleI2P/i2pd/actions/workflows/build-freebsd.yml/badge.svg)](https://github.com/PurpleI2P/i2pd/actions/workflows/build-freebsd.yml) * Android - [![Android CI](https://github.com/PurpleI2P/i2pd-android/actions/workflows/android.yml/badge.svg)](https://github.com/PurpleI2P/i2pd-android/actions/workflows/android.yml) From 6ca28adcbb29df8fd94d1e735ae5791bbd2e5a54 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 18 Jun 2021 18:19:05 -0400 Subject: [PATCH 05/24] set address caps and available transports for new address --- libi2pd/RouterContext.cpp | 23 ++++++++++++++--------- libi2pd/RouterInfo.cpp | 16 ++++++++++++++-- libi2pd/RouterInfo.h | 3 ++- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index c527aede..adce291c 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -568,16 +568,21 @@ namespace i2p { bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); bool ntcp2Published; i2p::config::GetOption("ntcp2.published", ntcp2Published); - if (ntcp2 && ntcp2Published) + if (ntcp2) { - std::string ntcp2Host; - if (!i2p::config::IsDefault ("ntcp2.addressv6")) - i2p::config::GetOption ("ntcp2.addressv6", ntcp2Host); + if (ntcp2Published) + { + std::string ntcp2Host; + if (!i2p::config::IsDefault ("ntcp2.addressv6")) + i2p::config::GetOption ("ntcp2.addressv6", ntcp2Host); + else + ntcp2Host = "::1"; + uint16_t ntcp2Port; i2p::config::GetOption ("ntcp2.port", ntcp2Port); + if (!ntcp2Port) ntcp2Port = port; + m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address::from_string (ntcp2Host), ntcp2Port); + } else - ntcp2Host = "::1"; - uint16_t ntcp2Port; i2p::config::GetOption ("ntcp2.port", ntcp2Port); - if (!ntcp2Port) ntcp2Port = port; - m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address::from_string (ntcp2Host), ntcp2Port); + m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address(), 0, i2p::data::RouterInfo::eV6); } } m_RouterInfo.EnableV6 (); @@ -632,7 +637,7 @@ namespace i2p m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address::from_string (host), ntcp2Port); } else - m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv); + m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address(), 0, i2p::data::RouterInfo::eV4); } } m_RouterInfo.EnableV4 (); diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 3f50a4b7..a426d9b7 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -840,21 +840,33 @@ namespace data for (const auto& it: *m_Addresses) // don't insert same address twice if (*it == *addr) return; m_SupportedTransports |= addr->host.is_v6 () ? eSSUV6 : eSSUV4; + m_ReachableTransports |= addr->host.is_v6 () ? eSSUV6 : eSSUV4; m_Addresses->push_back(std::move(addr)); } - void RouterInfo::AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv, const boost::asio::ip::address& host, int port) + void RouterInfo::AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv, + const boost::asio::ip::address& host, int port, uint8_t caps) { auto addr = std::make_shared
(); addr->host = host; addr->port = port; addr->transportStyle = eTransportNTCP; - addr->caps = 0; + addr->caps = caps; addr->date = 0; addr->ntcp2.reset (new NTCP2Ext ()); if (port) addr->published = true; memcpy (addr->ntcp2->staticKey, staticKey, 32); memcpy (addr->ntcp2->iv, iv, 16); + if (addr->IsV4 ()) + { + m_SupportedTransports |= eNTCP2V4; + if (addr->published) m_ReachableTransports |= eNTCP2V4; + } + if (addr->IsV6 ()) + { + m_SupportedTransports |= eNTCP2V6; + if (addr->published) m_ReachableTransports |= eNTCP2V6; + } m_Addresses->push_back(std::move(addr)); } diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 89654757..f27a5d68 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -179,7 +179,8 @@ namespace data std::shared_ptr GetYggdrasilAddress () const; void AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu = 0); - void AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv, const boost::asio::ip::address& host = boost::asio::ip::address(), int port = 0); + void AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv, + const boost::asio::ip::address& host = boost::asio::ip::address(), int port = 0, uint8_t caps = 0); bool AddIntroducer (const Introducer& introducer); bool RemoveIntroducer (const boost::asio::ip::udp::endpoint& e); void SetProperty (const std::string& key, const std::string& value); // called from RouterContext only From f5e7d87f5b8b63424e544729fd475bfd41a4892e Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 19 Jun 2021 14:25:50 -0400 Subject: [PATCH 06/24] don't disable floodfill if still reachable by ipv6 --- libi2pd/RouterContext.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index adce291c..b2a19890 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -470,7 +470,8 @@ namespace i2p uint8_t caps = m_RouterInfo.GetCaps (); caps &= ~i2p::data::RouterInfo::eReachable; caps |= i2p::data::RouterInfo::eUnreachable; - caps &= ~i2p::data::RouterInfo::eFloodfill; // can't be floodfill + if (v6 || !SupportsV6 ()) + caps &= ~i2p::data::RouterInfo::eFloodfill; // can't be floodfill m_RouterInfo.SetCaps (caps); } uint16_t port = 0; From fed04c1a199c4d97f46ae3f64915fbf4e1217934 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 19 Jun 2021 14:44:33 -0400 Subject: [PATCH 07/24] requsted router to send to if not in netdb --- libi2pd/Transports.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index c2bed2ab..181c3663 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -401,7 +401,7 @@ namespace transport try { auto r = netdb.FindRouter (ident); - if (!r || r->IsUnreachable () || !r->IsReachableFrom (i2p::context.GetRouterInfo ())) return; + if (r && (r->IsUnreachable () || !r->IsReachableFrom (i2p::context.GetRouterInfo ()))) return; // router found but non-reachable { std::unique_lock l(m_PeersMutex); it = m_Peers.insert (std::pair(ident, { 0, r, {}, From 84d987810f9a6f657ea854069754d979e648442a Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sun, 20 Jun 2021 09:36:14 +0300 Subject: [PATCH 08/24] add afrikaans in config example --- contrib/i2pd.conf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contrib/i2pd.conf b/contrib/i2pd.conf index 7b85a61b..599a2081 100644 --- a/contrib/i2pd.conf +++ b/contrib/i2pd.conf @@ -108,7 +108,8 @@ port = 7070 # user = i2pd # pass = changeme ## Select webconsole language -## Currently supported english (default), russian, turkmen and ukrainian languages +## Currently supported english (default), afrikaans, russian, turkmen and ukrainian languages + # lang = english [httpproxy] From 6971b1e9da863a7260b145dde29f5961c74feaf0 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sun, 20 Jun 2021 20:02:20 +0300 Subject: [PATCH 09/24] fix typo in config option description Kudos @iBicha https://github.com/PurpleI2P/i2pd/pull/1662#pullrequestreview-687850246 Signed-off-by: R4SAS --- libi2pd/Config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 16d50e8c..e5640ad0 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -285,7 +285,7 @@ namespace config { options_description meshnets("Meshnet transports options"); meshnets.add_options() - ("meshnets.yggdrasil", bool_switch()->default_value(false), "Support transports through the Yggdrasil (deafult: false)") + ("meshnets.yggdrasil", bool_switch()->default_value(false), "Support transports through the Yggdrasil (default: false)") ("meshnets.yggaddress", value()->default_value(""), "Yggdrasil address to publish") ; From 35ba16ff3b986749aaf1b1a2065196a1578c1be4 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 20 Jun 2021 17:20:29 -0400 Subject: [PATCH 10/24] fixed #1665. cast to int64_t --- daemon/I2PControl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemon/I2PControl.cpp b/daemon/I2PControl.cpp index 12602c99..73dde618 100644 --- a/daemon/I2PControl.cpp +++ b/daemon/I2PControl.cpp @@ -406,7 +406,7 @@ namespace client void I2PControlService::UptimeHandler (std::ostringstream& results) { - InsertParam (results, "i2p.router.uptime", (int)i2p::context.GetUptime ()*1000); + InsertParam (results, "i2p.router.uptime", std::to_string (i2p::context.GetUptime ()*1000LL)); } void I2PControlService::VersionHandler (std::ostringstream& results) From 7d51b4c6ed83fe9e9edf0be04998df6404ff1be8 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 21 Jun 2021 21:16:25 +0300 Subject: [PATCH 11/24] [i18n] pull ukrainian translation from crowdin (closes #1666) Signed-off-by: R4SAS --- contrib/i18n/regex.txt | 3 + i18n/Ukrainian.cpp | 299 +++++++++++++++++++---------------------- 2 files changed, 139 insertions(+), 163 deletions(-) diff --git a/contrib/i18n/regex.txt b/contrib/i18n/regex.txt index 768a4b01..e74f9d2d 100644 --- a/contrib/i18n/regex.txt +++ b/contrib/i18n/regex.txt @@ -5,3 +5,6 @@ msgid\ \"(.*)\"\nmsgid_plural\ \"(.*)\"\nmsgstr\[0\]\ \"(.*)\"\nmsgstr\[1\]\ \"( msgid\ \"(.*)\"\nmsgstr\ \"(.*)\"\n {"$1", "$2"},\n + +^#:(.*)$\n + diff --git a/i18n/Ukrainian.cpp b/i18n/Ukrainian.cpp index 11878cde..5e856c52 100644 --- a/i18n/Ukrainian.cpp +++ b/i18n/Ukrainian.cpp @@ -28,23 +28,151 @@ namespace ukrainian // language static std::map strings { - // HTTP Proxy + {"Disabled", "Вимкнуто"}, + {"Enabled", "Увімкнуто"}, + {"KiB", "КіБ"}, + {"MiB", "МіБ"}, + {"GiB", "ГіБ"}, + {"building", "будується"}, + {"failed", "невдалий"}, + {"expiring", "завершується"}, + {"established", "працює"}, + {"unknown", "невідомо"}, + {"exploratory", "дослідницький"}, + {"i2pd webconsole", "Веб-консоль i2pd"}, + {"Main page", "Головна"}, + {"Router commands", "Команди маршрутизатора"}, + {"Local destinations", "Локальні призначення"}, + {"LeaseSets", "Лізсети"}, + {"Tunnels", "Тунелі"}, + {"Transit tunnels", "Транзитні тунелі"}, + {"Transports", "Транспорти"}, + {"I2P tunnels", "I2P тунелі"}, + {"SAM sessions", "SAM сесії"}, + {"ERROR", "ПОМИЛКА"}, + {"OK", "OK"}, + {"Testing", "Тестування"}, + {"Firewalled", "Заблоковано ззовні"}, + {"Unknown", "Невідомо"}, + {"Proxy", "Проксі"}, + {"Mesh", "MESH-мережа"}, + {"Error", "Помилка"}, + {"Clock skew", "Неточний час"}, + {"Offline", "Офлайн"}, + {"Symmetric NAT", "Симетричний NAT"}, + {"Uptime", "У мережі"}, + {"Network status", "Мережевий статус"}, + {"Network status v6", "Мережевий статус v6"}, + {"Stopping in", "Зупинка через"}, + {"Family", "Сімейство"}, + {"Tunnel creation success rate", "Успішно побудованих тунелів"}, + {"Received", "Отримано"}, + {"KiB/s", "КіБ/с"}, + {"Sent", "Відправлено"}, + {"Transit", "Транзит"}, + {"Data path", "Шлях до даних"}, + {"Hidden content. Press on text to see.", "Прихований вміст. Щоб відобразити, натисніть на текст."}, + {"Router Ident", "Ідентифікатор маршрутизатора"}, + {"Router Family", "Сімейство маршрутизатора"}, + {"Router Caps", "Прапорці маршрутизатора"}, + {"Version", "Версія"}, + {"Our external address", "Наша зовнішня адреса"}, + {"supported", "підтримується"}, + {"Routers", "Маршрутизатори"}, + {"Floodfills", "Флудфіли"}, + {"Client Tunnels", "Клієнтські Тунелі"}, + {"Transit Tunnels", "Транзитні Тунелі"}, + {"Services", "Сервіси"}, + {"Local Destinations", "Локальні Призначення"}, + {"Encrypted B33 address", "Шифровані B33 адреси"}, + {"Address registration line", "Рядок реєстрації адреси"}, + {"Domain", "Домен"}, + {"Generate", "Згенерувати"}, + {"Note: result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "Примітка: отриманий рядок може бути використаний тільки для реєстрації доменів другого рівня (example.i2p). Для реєстрації піддоменів використовуйте i2pd-tools."}, + {"Address", "Адреса"}, + {"Type", "Тип"}, + {"EncType", "ТипШифр"}, + {"Inbound tunnels", "Вхідні тунелі"}, + {"ms", "мс"}, + {"Outbound tunnels", "Вихідні тунелі"}, + {"Tags", "Теги"}, + {"Incoming", "Вхідні"}, + {"Outgoing", "Вихідні"}, + {"Destination", "Призначення"}, + {"Amount", "Кількість"}, + {"Incoming Tags", "Вхідні Теги"}, + {"Tags sessions", "Сесії Тегів"}, + {"Status", "Статус"}, + {"Local Destination", "Локальні Призначення"}, + {"Streams", "Потоки"}, + {"Close stream", "Закрити потік"}, + {"I2CP session not found", "I2CP сесія не знайдена"}, + {"I2CP is not enabled", "I2CP не увікнуто"}, + {"Invalid", "Некоректний"}, + {"Store type", "Тип сховища"}, + {"Expires", "Завершується"}, + {"Non Expired Leases", "Не завершені Lease-и"}, + {"Gateway", "Шлюз"}, + {"TunnelID", "ID тунеля"}, + {"EndDate", "Закінчується"}, + {"not floodfill", "не флудфіл"}, + {"Queue size", "Розмір черги"}, + {"Run peer test", "Запустити тестування"}, + {"Decline transit tunnels", "Відхиляти транзитні тунелі"}, + {"Accept transit tunnels", "Ухвалювати транзитні тунелі"}, + {"Cancel graceful shutdown", "Скасувати плавну зупинку"}, + {"Start graceful shutdown", "Запустити плавну зупинку"}, + {"Force shutdown", "Примусова зупинка"}, + {"Note: any action done here are not persistent and not changes your config files.", "Примітка: будь-яка зроблена тут дія не є постійною та не змінює ваші конфігураційні файли."}, + {"Logging level", "Рівень логування"}, + {"Transit tunnels limit", "Обмеження транзитних тунелів"}, + {"Change", "Змінити"}, + {"no transit tunnels currently built", "немає побудованих транзитних тунелів"}, + {"SAM disabled", "SAM вимкнуто"}, + {"no sessions currently running", "немає запущених сесій"}, + {"SAM session not found", "SAM сесія не знайдена"}, + {"SAM Session", "SAM сесія"}, + {"Server Tunnels", "Серверні Тунелі"}, + {"Client Forwards", "Клієнтські Переспрямування"}, + {"Server Forwards", "Серверні Переспрямування"}, + {"Unknown page", "Невідома сторінка"}, + {"Invalid token", "Невірний токен"}, + {"SUCCESS", "УСПІШНО"}, + {"Stream closed", "Потік зачинений"}, + {"Stream not found or already was closed", "Потік не знайдений або вже зачинений"}, + {"Destination not found", "Точка призначення не знайдена"}, + {"StreamID can't be null", "Ідентифікатор потоку не може бути порожнім"}, + {"Return to destination page", "Повернутися на сторінку точки призначення"}, + {"You will be redirected back in 5 seconds", "Ви будете переадресовані назад через 5 секунд"}, + {"Transit tunnels count must not exceed 65535", "Кількість транзитних тунелів не повинна перевищувати 65535"}, + {"Back to commands list", "Повернутися до списку команд"}, + {"Register at reg.i2p", "Зареєструвати на reg.i2p"}, + {"Description", "Опис"}, + {"A bit information about service on domain", "Трохи інформації про сервіс на домені"}, + {"Submit", "Надіслати"}, + {"Domain can't end with .b32.i2p", "Домен не може закінчуватися на .b32.i2p"}, + {"Domain must end with .i2p", "Домен повинен закінчуватися на .i2p"}, + {"Such destination is not found", "Така точка призначення не знайдена"}, + {"Unknown command", "Невідома команда"}, + {"Command accepted", "Команда прийнята"}, + {"You will be redirected in 5 seconds", "Ви будете переадресовані через 5 секунд"}, {"Proxy error", "Помилка проксі"}, {"Proxy info", "Інформація проксі"}, {"Proxy error: Host not found", "Помилка проксі: Адреса не знайдена"}, - {"Remote host not found in router's addressbook", "Віддалена адреса не знайдена в адресній книзі роутера"}, + {"Remote host not found in router's addressbook", "Віддалена адреса не знайдена в адресній книзі маршрутизатора"}, {"You may try to find this host on jump services below", "Ви можете спробувати знайти дану адресу на джамп сервісах нижче"}, {"Invalid request", "Некоректний запит"}, {"Proxy unable to parse your request", "Проксі не може розібрати ваш запит"}, {"addresshelper is not supported", "addresshelper не підтримується"}, {"Host", "Адреса"}, - {"added to router's addressbook from helper", "доданий в адресну книгу роутера через хелпер"}, - {"already in router's addressbook", "вже в адресній книзі роутера"}, + {"added to router's addressbook from helper", "доданий в адресну книгу маршрутизатора через хелпер"}, {"Click", "Натисніть"}, {"here", "тут"}, {"to proceed", "щоб продовжити"}, - {"to update record", "щоб оновити запис"}, {"Addresshelper found", "Знайдено addresshelper"}, + {"already in router's addressbook", "вже в адресній книзі маршрутизатора"}, + {"to update record", "щоб оновити запис"}, + {"Invalid Request", "Некоректний Запит"}, {"invalid request uri", "некоректний URI запиту"}, {"Can't detect destination host from request", "Не вдалось визначити адресу призначення з запиту"}, {"Outproxy failure", "Помилка зовнішнього проксі"}, @@ -64,169 +192,14 @@ namespace ukrainian // language {"http out proxy not implemented", "підтримка зовнішнього HTTP проксі сервера не реалізована"}, {"cannot connect to upstream http proxy", "не вдалося підключитися до висхідного HTTP проксі сервера"}, {"Host is down", "Вузол недоступний"}, - {"Can't create connection to requested host, it may be down. Please try again later.", - "Не вдалося встановити з'єднання до запитаного вузла, можливо він не в мережі. Спробуйте повторити запит пізніше."}, - - // Webconsole // - // cssStyles - {"Disabled", "Вимкнуто"}, - {"Enabled", "Увімкнуто"}, - // ShowTraffic - {"KiB", "КіБ"}, - {"MiB", "МіБ"}, - {"GiB", "ГіБ"}, - // ShowTunnelDetails - {"building", "будується"}, - {"failed", "невдалий"}, - {"expiring", "завершується"}, - {"established", "працює"}, - {"exploratory", "дослідницький"}, - {"unknown", "невідомо"}, - {"i2pd webconsole", "Веб-консоль i2pd"}, - // ShowPageHead - {"Main page", "Головна"}, - {"Router commands", "Команди роутера"}, - {"Local destinations", "Локальні призначення"}, - {"LeaseSets", "Лізсети"}, - {"Tunnels", "Тунелі"}, - {"Transit tunnels", "Транзитні тунелі"}, - {"Transports", "Транспорти"}, - {"I2P tunnels", "I2P тунелі"}, - {"SAM sessions", "SAM сесії"}, - // Network Status - {"OK", "OK"}, - {"Testing", "Тестування"}, - {"Firewalled", "Заблоковано ззовні"}, - {"Unknown", "Невідомо"}, - {"Proxy", "Проксі"}, - {"Mesh", "MESH-мережа"}, - {"Error", "Помилка"}, - {"Clock skew", "Неточний час"}, - {"Offline", "Офлайн"}, - {"Symmetric NAT", "Симетричний NAT"}, - // Status - {"Uptime", "В мережі"}, - {"Network status", "Мережевий статус"}, - {"Network status v6", "Мережевий статус v6"}, - {"Stopping in", "Зупинка через"}, - {"Family", "Сімейство"}, - {"Tunnel creation success rate", "Успішно побудованих тунелів"}, - {"Received", "Отримано"}, - {"Sent", "Відправлено"}, - {"Transit", "Транзит"}, - {"KiB/s", "КіБ/с"}, - {"Data path", "Шлях до даних"}, - {"Hidden content. Press on text to see.", "Прихований вміст. Натисніть на текст щоб відобразити."}, - {"Router Ident", "Ідентифікатор Роутера"}, - {"Router Family", "Сімейство Роутера"}, - {"Router Caps", "Прапорці Роутера"}, - {"Version", "Версія"}, - {"Our external address", "Наша зовнішня адреса"}, - {"supported", "підтримується"}, - {"Routers", "Роутери"}, - {"Floodfills", "Флудфіли"}, - {"Client Tunnels", "Клієнтські Тунелі"}, - {"Transit Tunnels", "Транзитні Тунелі"}, - {"Services", "Сервіси"}, - // ShowLocalDestinations - {"Local Destinations", "Локальні Призначення"}, - // ShowLeaseSetDestination - {"Encrypted B33 address", "Шифровані B33 адреси"}, - {"Address registration line", "Рядок реєстрації адреси"}, - {"Domain", "Домен"}, - {"Generate", "Згенерувати"}, - {"Note: result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", - "Примітка: отриманий рядок може бути використаний тільки для реєстрації доменів другого рівня. Для реєстрації піддоменів використовуйте i2pd-tools."}, - {"Address", "Адреса"}, - {"Type", "Тип"}, - {"EncType", "ТипШифр"}, - {"Inbound tunnels", "Вхідні тунелі"}, - {"Outbound tunnels", "Вихідні тунелі"}, - {"ms", "мс"}, // milliseconds - {"Tags", "Теги"}, - {"Incoming", "Вхідні"}, - {"Outgoing", "Вихідні"}, - {"Destination", "Призначення"}, - {"Amount", "Кількість"}, - {"Incoming Tags", "Вхідні Теги"}, - {"Tags sessions", "Сесії тегів"}, - {"Status", "Статус"}, - // ShowLocalDestination - {"Local Destination", "Локальні Призначення"}, - {"Streams", "Потоки"}, - {"Close stream", "Закрити потік"}, - // ShowI2CPLocalDestination - {"I2CP session not found", "I2CP сесія не знайдена"}, - {"I2CP is not enabled", "I2CP не увікнуто"}, - // ShowLeasesSets - {"Invalid", "Некоректний"}, - {"Store type", "Тип сховища"}, - {"Expires", "Завершується"}, - {"Non Expired Leases", "Не завершені Lease-и"}, - {"Gateway", "Шлюз"}, - {"TunnelID", "ID тунеля"}, - {"EndDate", "Закінчується"}, - {"not floodfill", "не флудфіл"}, - // ShowTunnels - {"Queue size", "Розмір черги"}, - // ShowCommands - {"Run peer test", "Запустити тестування"}, - {"Decline transit tunnels", "Відхиляти транзитні тунелі"}, - {"Accept transit tunnels", "Ухвалювати транзитні тунелі"}, - {"Cancel graceful shutdown", "Скасувати плавну зупинку"}, - {"Start graceful shutdown", "Запустити плавну зупинку"}, - {"Force shutdown", "Примусова зупинка"}, - {"Note: any action done here are not persistent and not changes your config files.", - "Примітка: будь-яка зроблена тут дія не є постійною та не змінює ваші конфігураційні файли."}, - {"Logging level", "Рівень логування"}, - {"Transit tunnels limit", "Обмеження транзитних тунелів"}, - {"Change", "Змінити"}, - // ShowTransitTunnels - {"no transit tunnels currently built", "немає побудованих транзитних тунелів"}, - // ShowSAMSessions/ShowSAMSession - {"SAM disabled", "SAM вимкнуто"}, - {"SAM session not found", "SAM сесія не знайдена"}, - {"no sessions currently running", "немає запущених сесій"}, - {"SAM Session", "SAM сесія"}, - // ShowI2PTunnels - {"Server Tunnels", "Серверні Тунелі"}, - {"Client Forwards", "Клієнтські Переспрямування"}, - {"Server Forwards", "Серверні Переспрямування"}, - // HandlePage - {"Unknown page", "Невідома сторінка"}, - // HandleCommand, ShowError - {"Invalid token", "Невірний токен"}, - {"SUCCESS", "УСПІШНО"}, - {"ERROR", "ПОМИЛКА"}, - {"Unknown command", "Невідома команда"}, - {"Command accepted", "Команда прийнята"}, - {"Back to commands list", "Повернутися до списку команд"}, - {"You will be redirected in 5 seconds", "Ви будете переадресовані через 5 секунд"}, - // HTTP_COMMAND_KILLSTREAM - {"Stream closed", "Потік зачинений"}, - {"Stream not found or already was closed", "Потік не знайдений або вже зачинений"}, - {"Destination not found", "Точка призначення не знайдена"}, - {"StreamID can't be null", "Ідентифікатор потоку не може бути порожнім"}, - {"Return to destination page", "Повернутися на сторінку точки призначення"}, - {"You will be redirected back in 5 seconds", "Ви будете переадресовані назад через 5 секунд"}, - // HTTP_COMMAND_LIMITTRANSIT - {"Transit tunnels count must not exceed 65535", "Кількість транзитних тунелів не повинна перевищувати 65535"}, - // HTTP_COMMAND_GET_REG_STRING - {"Register at reg.i2p", "Зареєструвати на reg.i2p"}, - {"Description", "Опис"}, - {"A bit information about service on domain", "Трохи інформації про сервіс на домені"}, - {"Submit", "Надіслати"}, - {"Domain can't end with .b32.i2p", "Домен не може закінчуватися на .b32.i2p"}, - {"Domain must end with .i2p", "Домен повинен закінчуватися на .i2p"}, - {"Such destination is not found", "Така точка призначення не знайдена"}, + {"Can't create connection to requested host, it may be down. Please try again later.", "Не вдалося встановити з'єднання до запитаного вузла, можливо він не в мережі. Спробуйте повторити запит пізніше."}, {"", ""}, }; static std::map> plurals { - // ShowUptime - {"days", {"день", "дня", "днів"}}, - {"hours", {"годину", "години", "годин"}}, + {"days", {"день", "дня", "днів"}}, + {"hours", {"годину", "години", "годин"}}, {"minutes", {"хвилину", "хвилини", "хвилин"}}, {"seconds", {"секунду", "секунди", "секунд"}}, {"", {"", "", ""}}, From f7f50d049b98366726a6fd2518c109930f23e997 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 22 Jun 2021 13:11:02 -0400 Subject: [PATCH 12/24] reduce short tunnel build record length --- libi2pd/I2NPProtocol.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/I2NPProtocol.h b/libi2pd/I2NPProtocol.h index ee143734..cc7c94af 100644 --- a/libi2pd/I2NPProtocol.h +++ b/libi2pd/I2NPProtocol.h @@ -55,7 +55,7 @@ namespace i2p // TunnelBuild const size_t TUNNEL_BUILD_RECORD_SIZE = 528; - const size_t SHORT_TUNNEL_BUILD_RECORD_SIZE = 236; + const size_t SHORT_TUNNEL_BUILD_RECORD_SIZE = 218; //BuildRequestRecordClearText const size_t BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET = 0; @@ -113,7 +113,7 @@ namespace i2p const size_t SHORT_REQUEST_RECORD_REQUEST_TIME_OFFSET = SHORT_REQUEST_RECORD_LAYER_ENCRYPTION_TYPE + 1; const size_t SHORT_REQUEST_RECORD_REQUEST_EXPIRATION_OFFSET = SHORT_REQUEST_RECORD_REQUEST_TIME_OFFSET + 4; const size_t SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET = SHORT_REQUEST_RECORD_REQUEST_EXPIRATION_OFFSET + 4; - const size_t SHORT_REQUEST_RECORD_CLEAR_TEXT_SIZE = 172; + const size_t SHORT_REQUEST_RECORD_CLEAR_TEXT_SIZE = 154; enum I2NPMessageType { From 3c076654794c619eed228adcac075e9c1dea732f Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 22 Jun 2021 15:35:44 -0400 Subject: [PATCH 13/24] use unordered_map for incomplete messages --- libi2pd/TunnelEndpoint.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libi2pd/TunnelEndpoint.h b/libi2pd/TunnelEndpoint.h index 43b836f1..6466df3a 100644 --- a/libi2pd/TunnelEndpoint.h +++ b/libi2pd/TunnelEndpoint.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2021, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -11,6 +11,7 @@ #include #include +#include #include #include "I2NPProtocol.h" #include "TunnelBase.h" @@ -54,7 +55,7 @@ namespace tunnel private: - std::map m_IncompleteMessages; + std::unordered_map m_IncompleteMessages; std::map, Fragment> m_OutOfSequenceFragments; // (msgID, fragment#)->fragment bool m_IsInbound; size_t m_NumReceivedBytes; From d0c5732e16d28f0be86c4026ef23e0b70518f8ea Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 26 Jun 2021 07:18:42 -0400 Subject: [PATCH 14/24] eliminate extra lookups for sequential fragments --- libi2pd/TunnelEndpoint.cpp | 143 +++++++++++++++++++++++++++---------- libi2pd/TunnelEndpoint.h | 12 ++-- 2 files changed, 113 insertions(+), 42 deletions(-) diff --git a/libi2pd/TunnelEndpoint.cpp b/libi2pd/TunnelEndpoint.cpp index eb70bdca..a07230cb 100644 --- a/libi2pd/TunnelEndpoint.cpp +++ b/libi2pd/TunnelEndpoint.cpp @@ -52,11 +52,13 @@ namespace tunnel bool isFollowOnFragment = flag & 0x80, isLastFragment = true; uint32_t msgID = 0; int fragmentNum = 0; - TunnelMessageBlockEx m; + TunnelMessageBlockEx& m = m_CurrentMessage; if (!isFollowOnFragment) { // first fragment - + if (m_CurrentMsgID) + AddIncompleteCurrentMessage (); // we have got a new message while previous is not complete + m.deliveryType = (TunnelDeliveryType)((flag >> 5) & 0x03); switch (m.deliveryType) { @@ -81,6 +83,7 @@ namespace tunnel // Message ID msgID = bufbe32toh (fragment); fragment += 4; + m_CurrentMsgID = msgID; isLastFragment = false; } } @@ -96,11 +99,20 @@ namespace tunnel uint16_t size = bufbe16toh (fragment); fragment += 2; + if (isFollowOnFragment && m_CurrentMsgID && m_CurrentMsgID == msgID && + m_CurrentMessage.nextFragmentNum == fragmentNum) + { + HandleCurrenMessageFollowOnFragment (fragment, size, isLastFragment); + fragment += size; + continue; + } + msg->offset = fragment - msg->buf; msg->len = msg->offset + size; if (msg->len > msg->maxLen) { LogPrint (eLogError, "TunnelMessage: fragment is too long ", (int)size); + m_CurrentMsgID = 0; m_CurrentMessage.data = nullptr; return; } if (fragment + size < decrypted + TUNNEL_DATA_ENCRYPTED_SIZE) @@ -114,31 +126,31 @@ namespace tunnel else m.data = msg; - if (!isFollowOnFragment && isLastFragment) - HandleNextMessage (m); + if (!isFollowOnFragment) + { + if (isLastFragment) + { + HandleNextMessage (m); + m_CurrentMsgID = 0; m_CurrentMessage.data = nullptr; + } + else if (msgID) + { + m_CurrentMessage.nextFragmentNum = 1; + m_CurrentMessage.receiveTime = i2p::util::GetMillisecondsSinceEpoch (); + HandleOutOfSequenceFragments (msgID, m_CurrentMessage); + } + else + { + LogPrint (eLogError, "TunnelMessage: Message is fragmented, but msgID is not presented"); + m_CurrentMsgID = 0; m_CurrentMessage.data = nullptr; + } + } else { - if (msgID) // msgID is presented, assume message is fragmented - { - if (!isFollowOnFragment) // create new incomlete message - { - m.nextFragmentNum = 1; - m.receiveTime = i2p::util::GetMillisecondsSinceEpoch (); - auto ret = m_IncompleteMessages.insert (std::pair(msgID, m)); - if (ret.second) - HandleOutOfSequenceFragments (msgID, ret.first->second); - else - LogPrint (eLogError, "TunnelMessage: Incomplete message ", msgID, " already exists"); - } - else - { - m.nextFragmentNum = fragmentNum; - HandleFollowOnFragment (msgID, isLastFragment, m); - } - } - else - LogPrint (eLogError, "TunnelMessage: Message is fragmented, but msgID is not presented"); - } + m.nextFragmentNum = fragmentNum; + HandleFollowOnFragment (msgID, isLastFragment, m); + m_CurrentMsgID = 0; m_CurrentMessage.data = nullptr; + } fragment += size; } @@ -157,17 +169,8 @@ namespace tunnel auto& msg = it->second; if (m.nextFragmentNum == msg.nextFragmentNum) { - if (msg.data->len + size < I2NP_MAX_MESSAGE_SIZE) // check if message is not too long + if (ConcatFollowOnFragment (msg, fragment, size)) { - if (msg.data->len + size > msg.data->maxLen) - { - // LogPrint (eLogWarning, "TunnelMessage: I2NP message size ", msg.data->maxLen, " is not enough"); - auto newMsg = NewI2NPMessage (); - *newMsg = *(msg.data); - msg.data = newMsg; - } - if (msg.data->Concat (fragment, size) < size) // concatenate fragment - LogPrint (eLogError, "TunnelMessage: I2NP buffer overflow ", msg.data->maxLen); if (isLastFragment) { // message complete @@ -199,9 +202,67 @@ namespace tunnel } } + bool TunnelEndpoint::ConcatFollowOnFragment (TunnelMessageBlockEx& msg, const uint8_t * fragment, size_t size) const + { + if (msg.data->len + size < I2NP_MAX_MESSAGE_SIZE) // check if message is not too long + { + if (msg.data->len + size > msg.data->maxLen) + { + // LogPrint (eLogWarning, "TunnelMessage: I2NP message size ", msg.data->maxLen, " is not enough"); + auto newMsg = NewI2NPMessage (); + *newMsg = *(msg.data); + msg.data = newMsg; + } + if (msg.data->Concat (fragment, size) < size) // concatenate fragment + { + LogPrint (eLogError, "TunnelMessage: I2NP buffer overflow ", msg.data->maxLen); + return false; + } + } + else + return false; + return true; + } + + void TunnelEndpoint::HandleCurrenMessageFollowOnFragment (const uint8_t * fragment, size_t size, bool isLastFragment) + { + if (ConcatFollowOnFragment (m_CurrentMessage, fragment, size)) + { + if (isLastFragment) + { + // message complete + HandleNextMessage (m_CurrentMessage); + m_CurrentMsgID = 0; m_CurrentMessage.data = nullptr; + } + else + { + m_CurrentMessage.nextFragmentNum++; + HandleOutOfSequenceFragments (m_CurrentMsgID, m_CurrentMessage); + } + } + else + { + LogPrint (eLogError, "TunnelMessage: Fragment ", m_CurrentMessage.nextFragmentNum, " of message ", m_CurrentMsgID, " exceeds max I2NP message size, message dropped"); + m_CurrentMsgID = 0; m_CurrentMessage.data = nullptr; + } + } + + void TunnelEndpoint::AddIncompleteCurrentMessage () + { + if (m_CurrentMsgID) + { + auto ret = m_IncompleteMessages.emplace (m_CurrentMsgID, m_CurrentMessage); + if (!ret.second) + LogPrint (eLogError, "TunnelMessage: Incomplete message ", m_CurrentMsgID, " already exists"); + m_CurrentMessage.data = nullptr; + m_CurrentMsgID = 0; + } + } + void TunnelEndpoint::AddOutOfSequenceFragment (uint32_t msgID, uint8_t fragmentNum, bool isLastFragment, std::shared_ptr data) { - if (!m_OutOfSequenceFragments.insert ({{msgID, fragmentNum}, {isLastFragment, data, i2p::util::GetMillisecondsSinceEpoch () }}).second) + if (!m_OutOfSequenceFragments.insert ({(uint64_t)msgID << 32 | fragmentNum, + {isLastFragment, data, i2p::util::GetMillisecondsSinceEpoch () }}).second) LogPrint (eLogInfo, "TunnelMessage: duplicate out-of-sequence fragment ", fragmentNum, " of message ", msgID); } @@ -212,7 +273,13 @@ namespace tunnel if (!msg.nextFragmentNum) // message complete { HandleNextMessage (msg); - m_IncompleteMessages.erase (msgID); + if (&msg == &m_CurrentMessage) + { + m_CurrentMsgID = 0; + m_CurrentMessage.data = nullptr; + } + else + m_IncompleteMessages.erase (msgID); break; } } @@ -220,7 +287,7 @@ namespace tunnel bool TunnelEndpoint::ConcatNextOutOfSequenceFragment (uint32_t msgID, TunnelMessageBlockEx& msg) { - auto it = m_OutOfSequenceFragments.find ({msgID, msg.nextFragmentNum}); + auto it = m_OutOfSequenceFragments.find ((uint64_t)msgID << 32 | msg.nextFragmentNum); if (it != m_OutOfSequenceFragments.end ()) { LogPrint (eLogDebug, "TunnelMessage: Out-of-sequence fragment ", (int)msg.nextFragmentNum, " of message ", msgID, " found"); diff --git a/libi2pd/TunnelEndpoint.h b/libi2pd/TunnelEndpoint.h index 6466df3a..70514e35 100644 --- a/libi2pd/TunnelEndpoint.h +++ b/libi2pd/TunnelEndpoint.h @@ -10,7 +10,6 @@ #define TUNNEL_ENDPOINT_H__ #include -#include #include #include #include "I2NPProtocol.h" @@ -37,7 +36,7 @@ namespace tunnel public: - TunnelEndpoint (bool isInbound): m_IsInbound (isInbound), m_NumReceivedBytes (0) {}; + TunnelEndpoint (bool isInbound): m_IsInbound (isInbound), m_NumReceivedBytes (0), m_CurrentMsgID (0) {}; ~TunnelEndpoint (); size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; }; void Cleanup (); @@ -47,18 +46,23 @@ namespace tunnel private: void HandleFollowOnFragment (uint32_t msgID, bool isLastFragment, const TunnelMessageBlockEx& m); + bool ConcatFollowOnFragment (TunnelMessageBlockEx& msg, const uint8_t * fragment, size_t size) const; // true if success + void HandleCurrenMessageFollowOnFragment (const uint8_t * frgament, size_t size, bool isLastFragment); void HandleNextMessage (const TunnelMessageBlock& msg); void AddOutOfSequenceFragment (uint32_t msgID, uint8_t fragmentNum, bool isLastFragment, std::shared_ptr data); bool ConcatNextOutOfSequenceFragment (uint32_t msgID, TunnelMessageBlockEx& msg); // true if something added void HandleOutOfSequenceFragments (uint32_t msgID, TunnelMessageBlockEx& msg); - + void AddIncompleteCurrentMessage (); + private: std::unordered_map m_IncompleteMessages; - std::map, Fragment> m_OutOfSequenceFragments; // (msgID, fragment#)->fragment + std::unordered_map m_OutOfSequenceFragments; // ((msgID << 8) + fragment#)->fragment bool m_IsInbound; size_t m_NumReceivedBytes; + TunnelMessageBlockEx m_CurrentMessage; + uint32_t m_CurrentMsgID; }; } } From da20cae25ca13f66603d9095fff208fc066829a8 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sat, 26 Jun 2021 18:59:48 +0300 Subject: [PATCH 15/24] [webconsole] urldecode domain for registration string generator 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 7eb296c4..0b9e8f0f 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -1281,7 +1281,7 @@ namespace http { else if (cmd == HTTP_COMMAND_GET_REG_STRING) { std::string b32 = params["b32"]; - std::string name = params["name"]; + std::string name = i2p::http::UrlDecode(params["name"]); i2p::data::IdentHash ident; ident.FromBase32 (b32); From 377a50fa1301063e2c3398a87ec0e84790e8659e Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sat, 26 Jun 2021 23:45:55 +0300 Subject: [PATCH 16/24] [make] build translations as library Signed-off-by: R4SAS --- Makefile | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 40e72918..4117234e 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,8 @@ SHLIB := libi2pd.so ARLIB := libi2pd.a SHLIB_CLIENT := libi2pdclient.so ARLIB_CLIENT := libi2pdclient.a +SHLIB_LANG := libi2pdlang.so +ARLIB_LANG := libi2pdlang.a I2PD := i2pd LIB_SRC_DIR := libi2pd @@ -71,6 +73,7 @@ mk_obj_dir: api: mk_obj_dir $(SHLIB) $(ARLIB) client: mk_obj_dir $(SHLIB_CLIENT) $(ARLIB_CLIENT) api_client: mk_obj_dir $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT) +lang: mk_obj_dir $(SHLIB_LANG) $(ARLIB_LANG) ## NOTE: The NEEDED_CXXFLAGS are here so that CXXFLAGS can be specified at build time ## **without** overwriting the CXXFLAGS which we need in order to build. @@ -85,7 +88,7 @@ obj/%.o: %.cpp # '-' is 'ignore if missing' on first run -include $(DEPS) -$(I2PD): $(LANG_OBJS) $(DAEMON_OBJS) $(ARLIB) $(ARLIB_CLIENT) +$(I2PD): $(DAEMON_OBJS) $(ARLIB) $(ARLIB_CLIENT) $(ARLIB_LANG) $(CXX) -o $@ $(LDFLAGS) $^ $(LDLIBS) $(SHLIB): $(LIB_OBJS) @@ -98,18 +101,26 @@ ifneq ($(USE_STATIC),yes) $(CXX) $(LDFLAGS) -shared -o $@ $^ $(LDLIBS) $(SHLIB) endif +$(SHLIB_LANG): $(LANG_OBJS) +ifneq ($(USE_STATIC),yes) + $(CXX) $(LDFLAGS) -shared -o $@ $^ $(LDLIBS) +endif + $(ARLIB): $(LIB_OBJS) $(AR) -r $@ $^ $(ARLIB_CLIENT): $(LIB_CLIENT_OBJS) $(AR) -r $@ $^ +$(ARLIB_LANG): $(LANG_OBJS) + $(AR) -r $@ $^ + clean: $(RM) -r obj $(RM) -r docs/generated - $(RM) $(I2PD) $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT) + $(RM) $(I2PD) $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT) $(SHLIB_LANG) $(ARLIB_LANG) -strip: $(I2PD) $(SHLIB_CLIENT) $(SHLIB) +strip: $(I2PD) $(SHLIB) $(SHLIB_CLIENT) $(SHLIB_LANG) strip $^ LATEST_TAG=$(shell git describe --tags --abbrev=0 openssl) @@ -133,6 +144,7 @@ doxygen: .PHONY: api .PHONY: api_client .PHONY: client +.PHONY: lang .PHONY: mk_obj_dir .PHONY: install .PHONY: strip From 9fb8e8a582e8f23e39da0c635ee8c0efe4fcf0c5 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sat, 26 Jun 2021 23:59:34 +0300 Subject: [PATCH 17/24] [cmake] build translations as library Signed-off-by: R4SAS --- .gitignore | 2 ++ build/CMakeLists.txt | 17 ++++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 2506fd93..1fc6cefe 100644 --- a/.gitignore +++ b/.gitignore @@ -7,8 +7,10 @@ netDb /i2pd /libi2pd.a /libi2pdclient.a +/libi2pdlang.a /libi2pd.so /libi2pdclient.so +/libi2pdlang.so *.exe diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index d1b51f23..d1502deb 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -69,6 +69,16 @@ if(WITH_LIBRARY) endif() FILE(GLOB LANG_SRC ${LANG_SRC_DIR}/*.cpp) +add_library(libi2pdlang ${LANG_SRC}) +set_target_properties(libi2pdlang PROPERTIES PREFIX "") + +if(WITH_LIBRARY) + install(TARGETS libi2pdlang + EXPORT libi2pdlang + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib + COMPONENT Libraries) +endif() set(DAEMON_SRC "${DAEMON_SRC_DIR}/Daemon.cpp" @@ -198,10 +208,11 @@ if(WITH_PCH) ) target_compile_options(libi2pd PRIVATE -include libi2pd/stdafx.h) target_compile_options(libi2pdclient PRIVATE -include libi2pd/stdafx.h) + target_compile_options(libi2pdlang PRIVATE -include libi2pd/stdafx.h) target_link_libraries(libi2pd stdafx) endif() -target_link_libraries(libi2pdclient libi2pd) +target_link_libraries(libi2pdclient libi2pd libi2pdlang) find_package(Boost COMPONENTS system filesystem program_options date_time REQUIRED) if(NOT DEFINED Boost_INCLUDE_DIRS) @@ -265,7 +276,7 @@ message(STATUS "---------------------------------------") include(GNUInstallDirs) if(WITH_BINARY) - add_executable("${PROJECT_NAME}" ${LANG_SRC} ${DAEMON_SRC}) + add_executable("${PROJECT_NAME}" ${DAEMON_SRC}) if(WITH_STATIC) set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-static") @@ -295,7 +306,7 @@ if(WITH_BINARY) endif() target_link_libraries(libi2pd ${Boost_LIBRARIES} ${ZLIB_LIBRARY}) - target_link_libraries("${PROJECT_NAME}" libi2pd libi2pdclient ${DL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${UPNP_LIB} ${ZLIB_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MINGW_EXTRA} ${DL_LIB} ${CMAKE_REQUIRED_LIBRARIES}) + target_link_libraries("${PROJECT_NAME}" libi2pd libi2pdclient libi2pdlang ${DL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${UPNP_LIB} ${ZLIB_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MINGW_EXTRA} ${DL_LIB} ${CMAKE_REQUIRED_LIBRARIES}) install(TARGETS "${PROJECT_NAME}" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT Runtime) set(APPS "\${CMAKE_INSTALL_PREFIX}/bin/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX}") From b9476791f4b6b2a46f5f2fc59d491c5d34b85db1 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 26 Jun 2021 17:40:25 -0400 Subject: [PATCH 18/24] eliminated extra I2NP messages for fragments --- libi2pd/TunnelEndpoint.cpp | 115 +++++++++++++++++++------------------ libi2pd/TunnelEndpoint.h | 10 ++-- 2 files changed, 65 insertions(+), 60 deletions(-) diff --git a/libi2pd/TunnelEndpoint.cpp b/libi2pd/TunnelEndpoint.cpp index a07230cb..70004ede 100644 --- a/libi2pd/TunnelEndpoint.cpp +++ b/libi2pd/TunnelEndpoint.cpp @@ -52,26 +52,25 @@ namespace tunnel bool isFollowOnFragment = flag & 0x80, isLastFragment = true; uint32_t msgID = 0; int fragmentNum = 0; - TunnelMessageBlockEx& m = m_CurrentMessage; if (!isFollowOnFragment) { // first fragment if (m_CurrentMsgID) AddIncompleteCurrentMessage (); // we have got a new message while previous is not complete - m.deliveryType = (TunnelDeliveryType)((flag >> 5) & 0x03); - switch (m.deliveryType) + m_CurrentMessage.deliveryType = (TunnelDeliveryType)((flag >> 5) & 0x03); + switch (m_CurrentMessage.deliveryType) { case eDeliveryTypeLocal: // 0 break; case eDeliveryTypeTunnel: // 1 - m.tunnelID = bufbe32toh (fragment); + m_CurrentMessage.tunnelID = bufbe32toh (fragment); fragment += 4; // tunnelID - m.hash = i2p::data::IdentHash (fragment); + m_CurrentMessage.hash = i2p::data::IdentHash (fragment); fragment += 32; // hash break; case eDeliveryTypeRouter: // 2 - m.hash = i2p::data::IdentHash (fragment); + m_CurrentMessage.hash = i2p::data::IdentHash (fragment); fragment += 32; // to hash break; default: ; @@ -99,42 +98,51 @@ namespace tunnel uint16_t size = bufbe16toh (fragment); fragment += 2; - if (isFollowOnFragment && m_CurrentMsgID && m_CurrentMsgID == msgID && - m_CurrentMessage.nextFragmentNum == fragmentNum) - { - HandleCurrenMessageFollowOnFragment (fragment, size, isLastFragment); - fragment += size; - continue; + // handle fragment + if (isFollowOnFragment) + { + // existing message + if (m_CurrentMsgID && m_CurrentMsgID == msgID && m_CurrentMessage.nextFragmentNum == fragmentNum) + HandleCurrenMessageFollowOnFragment (fragment, size, isLastFragment); // previous + else + { + HandleFollowOnFragment (msgID, isLastFragment, fragmentNum, fragment, size); // another + m_CurrentMsgID = 0; m_CurrentMessage.data = nullptr; + } } - - msg->offset = fragment - msg->buf; - msg->len = msg->offset + size; - if (msg->len > msg->maxLen) - { - LogPrint (eLogError, "TunnelMessage: fragment is too long ", (int)size); - m_CurrentMsgID = 0; m_CurrentMessage.data = nullptr; - return; - } - if (fragment + size < decrypted + TUNNEL_DATA_ENCRYPTED_SIZE) - { - // this is not last message. we have to copy it - m.data = NewI2NPTunnelMessage (); - m.data->offset += TUNNEL_GATEWAY_HEADER_SIZE; // reserve room for TunnelGateway header - m.data->len += TUNNEL_GATEWAY_HEADER_SIZE; - *(m.data) = *msg; - } else - m.data = msg; - - if (!isFollowOnFragment) - { + { + // new message + msg->offset = fragment - msg->buf; + msg->len = msg->offset + size; + // check message size + if (msg->len > msg->maxLen) + { + LogPrint (eLogError, "TunnelMessage: fragment is too long ", (int)size); + m_CurrentMsgID = 0; m_CurrentMessage.data = nullptr; + return; + } + // create new or assign I2NP message + if (fragment + size < decrypted + TUNNEL_DATA_ENCRYPTED_SIZE) + { + // this is not last message. we have to copy it + m_CurrentMessage.data = NewI2NPTunnelMessage (); + m_CurrentMessage.data->offset += TUNNEL_GATEWAY_HEADER_SIZE; // reserve room for TunnelGateway header + m_CurrentMessage.data->len += TUNNEL_GATEWAY_HEADER_SIZE; + *(m_CurrentMessage.data) = *msg; + } + else + m_CurrentMessage.data = msg; + if (isLastFragment) { - HandleNextMessage (m); + // single message + HandleNextMessage (m_CurrentMessage); m_CurrentMsgID = 0; m_CurrentMessage.data = nullptr; } else if (msgID) { + // first fragment of a new message m_CurrentMessage.nextFragmentNum = 1; m_CurrentMessage.receiveTime = i2p::util::GetMillisecondsSinceEpoch (); HandleOutOfSequenceFragments (msgID, m_CurrentMessage); @@ -145,13 +153,7 @@ namespace tunnel m_CurrentMsgID = 0; m_CurrentMessage.data = nullptr; } } - else - { - m.nextFragmentNum = fragmentNum; - HandleFollowOnFragment (msgID, isLastFragment, m); - m_CurrentMsgID = 0; m_CurrentMessage.data = nullptr; - } - + fragment += size; } } @@ -159,15 +161,14 @@ namespace tunnel LogPrint (eLogError, "TunnelMessage: zero not found"); } - void TunnelEndpoint::HandleFollowOnFragment (uint32_t msgID, bool isLastFragment, const TunnelMessageBlockEx& m) + void TunnelEndpoint::HandleFollowOnFragment (uint32_t msgID, bool isLastFragment, + uint8_t fragmentNum, const uint8_t * fragment, size_t size) { - auto fragment = m.data->GetBuffer (); - auto size = m.data->GetLength (); auto it = m_IncompleteMessages.find (msgID); if (it != m_IncompleteMessages.end()) { auto& msg = it->second; - if (m.nextFragmentNum == msg.nextFragmentNum) + if (fragmentNum == msg.nextFragmentNum) { if (ConcatFollowOnFragment (msg, fragment, size)) { @@ -185,20 +186,20 @@ namespace tunnel } else { - LogPrint (eLogError, "TunnelMessage: Fragment ", m.nextFragmentNum, " of message ", msgID, "exceeds max I2NP message size, message dropped"); + LogPrint (eLogError, "TunnelMessage: Fragment ", fragmentNum, " of message ", msgID, "exceeds max I2NP message size, message dropped"); m_IncompleteMessages.erase (it); } } else { - LogPrint (eLogWarning, "TunnelMessage: Unexpected fragment ", (int)m.nextFragmentNum, " instead ", (int)msg.nextFragmentNum, " of message ", msgID, ", saved"); - AddOutOfSequenceFragment (msgID, m.nextFragmentNum, isLastFragment, m.data); + LogPrint (eLogWarning, "TunnelMessage: Unexpected fragment ", (int)fragmentNum, " instead ", (int)msg.nextFragmentNum, " of message ", msgID, ", saved"); + AddOutOfSequenceFragment (msgID, fragmentNum, isLastFragment, fragment, size); } } else { LogPrint (eLogWarning, "TunnelMessage: First fragment of message ", msgID, " not found, saved"); - AddOutOfSequenceFragment (msgID, m.nextFragmentNum, isLastFragment, m.data); + AddOutOfSequenceFragment (msgID, fragmentNum, isLastFragment, fragment, size); } } @@ -259,10 +260,12 @@ namespace tunnel } } - void TunnelEndpoint::AddOutOfSequenceFragment (uint32_t msgID, uint8_t fragmentNum, bool isLastFragment, std::shared_ptr data) + void TunnelEndpoint::AddOutOfSequenceFragment (uint32_t msgID, uint8_t fragmentNum, + bool isLastFragment, const uint8_t * fragment, size_t size) { - if (!m_OutOfSequenceFragments.insert ({(uint64_t)msgID << 32 | fragmentNum, - {isLastFragment, data, i2p::util::GetMillisecondsSinceEpoch () }}).second) + std::unique_ptr f(new Fragment (isLastFragment, i2p::util::GetMillisecondsSinceEpoch (), size)); + memcpy (f->data.data (), fragment, size); + if (!m_OutOfSequenceFragments.emplace ((uint64_t)msgID << 32 | fragmentNum, std::move (f)).second) LogPrint (eLogInfo, "TunnelMessage: duplicate out-of-sequence fragment ", fragmentNum, " of message ", msgID); } @@ -291,7 +294,7 @@ namespace tunnel if (it != m_OutOfSequenceFragments.end ()) { LogPrint (eLogDebug, "TunnelMessage: Out-of-sequence fragment ", (int)msg.nextFragmentNum, " of message ", msgID, " found"); - size_t size = it->second.data->GetLength (); + size_t size = it->second->data.size (); if (msg.data->len + size > msg.data->maxLen) { LogPrint (eLogWarning, "TunnelMessage: Tunnel endpoint I2NP message size ", msg.data->maxLen, " is not enough"); @@ -299,9 +302,9 @@ namespace tunnel *newMsg = *(msg.data); msg.data = newMsg; } - if (msg.data->Concat (it->second.data->GetBuffer (), size) < size) // concatenate out-of-sync fragment + if (msg.data->Concat (it->second->data.data (), size) < size) // concatenate out-of-sync fragment LogPrint (eLogError, "TunnelMessage: Tunnel endpoint I2NP buffer overflow ", msg.data->maxLen); - if (it->second.isLastFragment) + if (it->second->isLastFragment) // message complete msg.nextFragmentNum = 0; else @@ -354,7 +357,7 @@ namespace tunnel // out-of-sequence fragments for (auto it = m_OutOfSequenceFragments.begin (); it != m_OutOfSequenceFragments.end ();) { - if (ts > it->second.receiveTime + i2p::I2NP_MESSAGE_EXPIRATION_TIMEOUT) + if (ts > it->second->receiveTime + i2p::I2NP_MESSAGE_EXPIRATION_TIMEOUT) it = m_OutOfSequenceFragments.erase (it); else ++it; diff --git a/libi2pd/TunnelEndpoint.h b/libi2pd/TunnelEndpoint.h index 70514e35..f9878165 100644 --- a/libi2pd/TunnelEndpoint.h +++ b/libi2pd/TunnelEndpoint.h @@ -11,6 +11,7 @@ #include #include +#include #include #include "I2NPProtocol.h" #include "TunnelBase.h" @@ -29,9 +30,10 @@ namespace tunnel struct Fragment { + Fragment (bool last, uint64_t t, size_t size): isLastFragment (last), receiveTime (t), data (size) {}; bool isLastFragment; - std::shared_ptr data; uint64_t receiveTime; // milliseconds since epoch + std::vector data; }; public: @@ -45,12 +47,12 @@ namespace tunnel private: - void HandleFollowOnFragment (uint32_t msgID, bool isLastFragment, const TunnelMessageBlockEx& m); + void HandleFollowOnFragment (uint32_t msgID, bool isLastFragment, uint8_t fragmentNum, const uint8_t * fragment, size_t size); bool ConcatFollowOnFragment (TunnelMessageBlockEx& msg, const uint8_t * fragment, size_t size) const; // true if success void HandleCurrenMessageFollowOnFragment (const uint8_t * frgament, size_t size, bool isLastFragment); void HandleNextMessage (const TunnelMessageBlock& msg); - void AddOutOfSequenceFragment (uint32_t msgID, uint8_t fragmentNum, bool isLastFragment, std::shared_ptr data); + void AddOutOfSequenceFragment (uint32_t msgID, uint8_t fragmentNum, bool isLastFragment, const uint8_t * fragment, size_t size); bool ConcatNextOutOfSequenceFragment (uint32_t msgID, TunnelMessageBlockEx& msg); // true if something added void HandleOutOfSequenceFragments (uint32_t msgID, TunnelMessageBlockEx& msg); void AddIncompleteCurrentMessage (); @@ -58,7 +60,7 @@ namespace tunnel private: std::unordered_map m_IncompleteMessages; - std::unordered_map m_OutOfSequenceFragments; // ((msgID << 8) + fragment#)->fragment + std::unordered_map > m_OutOfSequenceFragments; // ((msgID << 8) + fragment#)->fragment bool m_IsInbound; size_t m_NumReceivedBytes; TunnelMessageBlockEx m_CurrentMessage; From 66422d6d837ce25f4cf7eb2b90fa6f9e5f9a9d22 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 26 Jun 2021 21:44:51 -0400 Subject: [PATCH 19/24] double size tunnel message --- libi2pd/I2NPProtocol.cpp | 3 ++- libi2pd/TunnelEndpoint.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index 7c4d84c3..f570a2a1 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -38,7 +38,8 @@ namespace i2p std::shared_ptr NewI2NPTunnelMessage () { - auto msg = new I2NPMessageBuffer(); // reserved for alignment and NTCP 16 + 6 + 12 + // should fit two tunnel message, enough for one garlic encrypted streaming packet + auto msg = new I2NPMessageBuffer<2*i2p::tunnel::TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + 34>(); // reserved for alignment and NTCP 16 + 6 + 12 msg->Align (12); return std::shared_ptr(msg); } diff --git a/libi2pd/TunnelEndpoint.cpp b/libi2pd/TunnelEndpoint.cpp index 70004ede..109f3120 100644 --- a/libi2pd/TunnelEndpoint.cpp +++ b/libi2pd/TunnelEndpoint.cpp @@ -198,7 +198,7 @@ namespace tunnel } else { - LogPrint (eLogWarning, "TunnelMessage: First fragment of message ", msgID, " not found, saved"); + LogPrint (eLogDebug, "TunnelMessage: First fragment of message ", msgID, " not found, saved"); AddOutOfSequenceFragment (msgID, fragmentNum, isLastFragment, fragment, size); } } @@ -283,6 +283,7 @@ namespace tunnel } else m_IncompleteMessages.erase (msgID); + LogPrint (eLogDebug, "TunnelMessage: All fragments of message ", msgID, " found"); break; } } From 6d2c9e367bb35e0d3b4d19db734a243744a92fc9 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sun, 27 Jun 2021 12:24:41 +0300 Subject: [PATCH 20/24] remove unused CI and docker files Signed-off-by: R4SAS --- .travis.yml | 54 ---------------------- appveyor.yml | 57 ------------------------ build/docker/README.md | 34 -------------- build/docker/old-ubuntu-based/Dockerfile | 11 ----- build/fig.yml | 2 - contrib/docker/Dockerfile | 2 +- 6 files changed, 1 insertion(+), 159 deletions(-) delete mode 100644 .travis.yml delete mode 100644 appveyor.yml delete mode 100644 build/docker/README.md delete mode 100644 build/docker/old-ubuntu-based/Dockerfile delete mode 100644 build/fig.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index af47f458..00000000 --- a/.travis.yml +++ /dev/null @@ -1,54 +0,0 @@ -language: cpp -cache: - apt: true -os: -- linux -#- osx -dist: xenial -sudo: required -compiler: -- g++ -- clang++ -env: - global: - - MAKEFLAGS="-j 2" - matrix: - - BUILD_TYPE=make UPNP=ON MAKE_UPNP=yes - - BUILD_TYPE=make UPNP=OFF MAKE_UPNP=no - - BUILD_TYPE=cmake UPNP=ON MAKE_UPNP=yes - - BUILD_TYPE=cmake UPNP=OFF MAKE_UPNP=no -matrix: - exclude: - - os: osx - env: BUILD_TYPE=cmake UPNP=ON MAKE_UPNP=yes - - os: osx - env: BUILD_TYPE=cmake UPNP=OFF MAKE_UPNP=no - - os: linux - compiler: clang++ - env: BUILD_TYPE=make UPNP=ON MAKE_UPNP=yes - - os: linux - compiler: clang++ - env: BUILD_TYPE=make UPNP=OFF MAKE_UPNP=no -addons: - apt: - packages: - - build-essential - - cmake - - g++ - - clang - - libboost-chrono-dev - - libboost-date-time-dev - - libboost-filesystem-dev - - libboost-program-options-dev - - libboost-system-dev - - libboost-thread-dev - - libminiupnpc-dev - - libssl-dev -before_install: -- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi -- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install libressl miniupnpc ; fi -- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew outdated boost || brew upgrade boost ; fi -script: -- if [[ "$TRAVIS_OS_NAME" == "linux" && "$BUILD_TYPE" == "cmake" ]]; then cd build && cmake -DCMAKE_BUILD_TYPE=Release -DWITH_UPNP=${UPNP} && make ; fi -- if [[ "$TRAVIS_OS_NAME" == "linux" && "$BUILD_TYPE" == "make" ]]; then make USE_UPNP=${MAKE_UPNP} ; fi -- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then make HOMEBREW=1 USE_UPNP=${MAKE_UPNP} ; fi diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 89d85494..00000000 --- a/appveyor.yml +++ /dev/null @@ -1,57 +0,0 @@ -version: 2.38.0.{build} -pull_requests: - do_not_increment_build_number: true -branches: - only: - - openssl -skip_tags: true -os: Visual Studio 2015 -shallow_clone: true -clone_depth: 1 - -# avoid building 32-bit if 64-bit failed already -matrix: - fast_finish: true - -environment: - APPVEYOR_SAVE_CACHE_ON_ERROR: true - MSYS2_PATH_TYPE: inherit - CHERE_INVOKING: enabled_from_arguments - matrix: - - MSYSTEM: MINGW64 - - MSYSTEM: MINGW32 - -cache: - - c:\msys64\var\cache\pacman\pkg\ - -install: -# install new signing keyring -- c:\msys64\usr\bin\bash -lc "curl -O https://mirror.selfnet.de/msys2/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz" -- c:\msys64\usr\bin\bash -lc "curl -O https://mirror.selfnet.de/msys2/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig" -- c:\msys64\usr\bin\bash -lc "pacman-key --verify msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig" -- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -U msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz" -# remove packages which can break build -- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Rns gcc-fortran gcc mingw-w64-{i686,x86_64}-gcc-ada mingw-w64-{i686,x86_64}-gcc-objc" -# update runtime -- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu" -# Kill bash before next try -- taskkill /T /F /IM bash.exe /IM gpg.exe /IM gpg-agent.exe | exit /B 0 -# update packages and install required -- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu $MINGW_PACKAGE_PREFIX-boost $MINGW_PACKAGE_PREFIX-miniupnpc" - -build_script: -- c:\msys64\usr\bin\bash -lc "make USE_UPNP=yes DEBUG=no -j3" -# prepare archive for uploading -- set "FILELIST=i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates contrib/tunnels.d" -- echo This is development build, use it carefully! For running in portable mode, move all files from contrib directory here. > README.txt -- 7z a -tzip -mx9 -mmt i2pd-%APPVEYOR_BUILD_VERSION%-%APPVEYOR_REPO_COMMIT:~0,7%-mingw-win%MSYSTEM:~-2%.zip %FILELIST% - -after_build: -- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Sc" - -test: off - -deploy: off - -artifacts: -- path: i2pd-*.zip diff --git a/build/docker/README.md b/build/docker/README.md deleted file mode 100644 index 877a9ce5..00000000 --- a/build/docker/README.md +++ /dev/null @@ -1,34 +0,0 @@ -Howto build & run -================== - -**Build** - -Assuming you're in the root directory of the anoncoin source code. - -$ `cd build/docker` -$ `docker -t meeh/i2pd:latest .` - -**Run** - -To run either the local build, or if not found - fetched prebuild from hub.docker.io, run the following command. - -$ `docker run --name anonnode -v /path/to/i2pd/datadir/on/host:/var/lib/i2pd -p 7070:7070 -p 4444:4444 -p 4447:4447 -p 7656:7656 -p 2827:2827 -p 7654:7654 -p 7650:7650 -d meeh/i2pd` - -All the ports ( -p HOSTPORT:DOCKERPORT ) is optional. However the command above enable all features (Webconsole, HTTP Proxy, BOB, SAM, i2cp, etc) - -The volume ( -v HOSTDIR:DOCKERDIR ) is also optional, but if you don't use it, your config, routerid and private keys will die along with the container. - -**Options** - -Options are set via docker environment variables. This can be set at run with -e parameters. - -* **ENABLE_IPV6** - Enable IPv6 support. Any value can be used - it triggers as long as it's not empty. -* **LOGLEVEL** - Set the loglevel. -* **ENABLE_AUTH** - Enable auth for the webconsole. Username and password needs to be set manually in i2pd.conf cause security reasons. - -**Logging** - -Logging happens to STDOUT as the best practise with docker containers, since infrastructure systems like kubernetes with ELK integration can automatically forward the log to say, kibana or greylog without manual setup. :) - - - diff --git a/build/docker/old-ubuntu-based/Dockerfile b/build/docker/old-ubuntu-based/Dockerfile deleted file mode 100644 index 3faddf2e..00000000 --- a/build/docker/old-ubuntu-based/Dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM ubuntu - -RUN apt-get update && apt-get install -y libboost-dev libboost-filesystem-dev \ - libboost-program-options-dev libboost-date-time-dev \ - libssl-dev git build-essential - -RUN git clone https://github.com/PurpleI2P/i2pd.git -WORKDIR /i2pd -RUN make - -CMD ./i2pd diff --git a/build/fig.yml b/build/fig.yml deleted file mode 100644 index 372ef350..00000000 --- a/build/fig.yml +++ /dev/null @@ -1,2 +0,0 @@ -i2pd: - build: . diff --git a/contrib/docker/Dockerfile b/contrib/docker/Dockerfile index 6470e148..71af141e 100644 --- a/contrib/docker/Dockerfile +++ b/contrib/docker/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:3.13 +FROM alpine:latest LABEL authors "Mikal Villa , Darknet Villain " # Expose git branch, tag and URL variables as arguments From 12d6f03dc9d1adef53abeba13b0499d52242220d Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sun, 27 Jun 2021 17:14:45 +0300 Subject: [PATCH 21/24] [i18n] add language changing at runtime in webconsole Signed-off-by: R4SAS --- contrib/i18n/English.po | 296 +++++++++++++++++++------------------- daemon/HTTPServer.cpp | 75 ++++++---- i18n/Afrikaans.cpp | 7 +- i18n/English.cpp | 7 +- i18n/I18N.h | 13 +- i18n/I18N_langs.h | 28 +++- i18n/Russian.cpp | 310 ++++++++++++++++++---------------------- i18n/Turkmen.cpp | 7 +- i18n/Ukrainian.cpp | 7 +- 9 files changed, 396 insertions(+), 354 deletions(-) diff --git a/contrib/i18n/English.po b/contrib/i18n/English.po index 1de2ddaa..011d0fee 100644 --- a/contrib/i18n/English.po +++ b/contrib/i18n/English.po @@ -26,548 +26,554 @@ msgstr "" msgid "Enabled" msgstr "" -#: daemon/HTTPServer.cpp:141 +#: daemon/HTTPServer.cpp:147 msgid "day" msgid_plural "days" msgstr[0] "" msgstr[1] "" -#: daemon/HTTPServer.cpp:145 + +#: daemon/HTTPServer.cpp:151 msgid "hour" msgid_plural "hours" msgstr[0] "" msgstr[1] "" -#: daemon/HTTPServer.cpp:149 + +#: daemon/HTTPServer.cpp:155 msgid "minute" msgid_plural "minutes" msgstr[0] "" msgstr[1] "" -#: daemon/HTTPServer.cpp:152 +#: daemon/HTTPServer.cpp:158 msgid "second" msgid_plural "seconds" msgstr[0] "" msgstr[1] "" -#: daemon/HTTPServer.cpp:160 daemon/HTTPServer.cpp:188 +#: daemon/HTTPServer.cpp:166 daemon/HTTPServer.cpp:194 msgid "KiB" msgstr "" -#: daemon/HTTPServer.cpp:162 +#: daemon/HTTPServer.cpp:168 msgid "MiB" msgstr "" -#: daemon/HTTPServer.cpp:164 +#: daemon/HTTPServer.cpp:170 msgid "GiB" msgstr "" -#: daemon/HTTPServer.cpp:181 +#: daemon/HTTPServer.cpp:187 msgid "building" msgstr "" -#: daemon/HTTPServer.cpp:182 +#: daemon/HTTPServer.cpp:188 msgid "failed" msgstr "" -#: daemon/HTTPServer.cpp:183 +#: daemon/HTTPServer.cpp:189 msgid "expiring" msgstr "" -#: daemon/HTTPServer.cpp:184 +#: daemon/HTTPServer.cpp:190 msgid "established" msgstr "" -#: daemon/HTTPServer.cpp:185 +#: daemon/HTTPServer.cpp:191 msgid "unknown" msgstr "" -#: daemon/HTTPServer.cpp:187 +#: daemon/HTTPServer.cpp:193 msgid "exploratory" msgstr "" -#: daemon/HTTPServer.cpp:223 +#: daemon/HTTPServer.cpp:229 msgid "i2pd webconsole" msgstr "" -#: daemon/HTTPServer.cpp:226 +#: daemon/HTTPServer.cpp:232 msgid "Main page" msgstr "" -#: daemon/HTTPServer.cpp:227 daemon/HTTPServer.cpp:683 +#: daemon/HTTPServer.cpp:233 daemon/HTTPServer.cpp:689 msgid "Router commands" msgstr "" -#: daemon/HTTPServer.cpp:228 +#: daemon/HTTPServer.cpp:234 msgid "Local destinations" msgstr "" -#: daemon/HTTPServer.cpp:230 daemon/HTTPServer.cpp:382 -#: daemon/HTTPServer.cpp:463 daemon/HTTPServer.cpp:469 -#: daemon/HTTPServer.cpp:599 daemon/HTTPServer.cpp:642 -#: daemon/HTTPServer.cpp:646 +#: daemon/HTTPServer.cpp:236 daemon/HTTPServer.cpp:388 +#: daemon/HTTPServer.cpp:469 daemon/HTTPServer.cpp:475 +#: daemon/HTTPServer.cpp:605 daemon/HTTPServer.cpp:648 +#: daemon/HTTPServer.cpp:652 msgid "LeaseSets" msgstr "" -#: daemon/HTTPServer.cpp:232 daemon/HTTPServer.cpp:652 +#: daemon/HTTPServer.cpp:238 daemon/HTTPServer.cpp:658 msgid "Tunnels" msgstr "" -#: daemon/HTTPServer.cpp:233 daemon/HTTPServer.cpp:727 -#: daemon/HTTPServer.cpp:743 +#: daemon/HTTPServer.cpp:239 daemon/HTTPServer.cpp:746 +#: daemon/HTTPServer.cpp:762 msgid "Transit tunnels" msgstr "" -#: daemon/HTTPServer.cpp:234 daemon/HTTPServer.cpp:792 +#: daemon/HTTPServer.cpp:240 daemon/HTTPServer.cpp:811 msgid "Transports" msgstr "" -#: daemon/HTTPServer.cpp:235 +#: daemon/HTTPServer.cpp:241 msgid "I2P tunnels" msgstr "" -#: daemon/HTTPServer.cpp:237 daemon/HTTPServer.cpp:854 -#: daemon/HTTPServer.cpp:864 +#: daemon/HTTPServer.cpp:243 daemon/HTTPServer.cpp:873 +#: daemon/HTTPServer.cpp:883 msgid "SAM sessions" msgstr "" -#: daemon/HTTPServer.cpp:253 daemon/HTTPServer.cpp:1254 -#: daemon/HTTPServer.cpp:1257 daemon/HTTPServer.cpp:1260 -#: daemon/HTTPServer.cpp:1274 daemon/HTTPServer.cpp:1319 -#: daemon/HTTPServer.cpp:1322 daemon/HTTPServer.cpp:1325 +#: daemon/HTTPServer.cpp:259 daemon/HTTPServer.cpp:1273 +#: daemon/HTTPServer.cpp:1276 daemon/HTTPServer.cpp:1279 +#: daemon/HTTPServer.cpp:1293 daemon/HTTPServer.cpp:1338 +#: daemon/HTTPServer.cpp:1341 daemon/HTTPServer.cpp:1344 msgid "ERROR" msgstr "" -#: daemon/HTTPServer.cpp:260 +#: daemon/HTTPServer.cpp:266 msgid "OK" msgstr "" -#: daemon/HTTPServer.cpp:261 +#: daemon/HTTPServer.cpp:267 msgid "Testing" msgstr "" -#: daemon/HTTPServer.cpp:262 +#: daemon/HTTPServer.cpp:268 msgid "Firewalled" msgstr "" -#: daemon/HTTPServer.cpp:263 daemon/HTTPServer.cpp:284 -#: daemon/HTTPServer.cpp:370 +#: daemon/HTTPServer.cpp:269 daemon/HTTPServer.cpp:290 +#: daemon/HTTPServer.cpp:376 msgid "Unknown" msgstr "" -#: daemon/HTTPServer.cpp:264 daemon/HTTPServer.cpp:394 -#: daemon/HTTPServer.cpp:395 daemon/HTTPServer.cpp:922 -#: daemon/HTTPServer.cpp:931 +#: daemon/HTTPServer.cpp:270 daemon/HTTPServer.cpp:400 +#: daemon/HTTPServer.cpp:401 daemon/HTTPServer.cpp:941 +#: daemon/HTTPServer.cpp:950 msgid "Proxy" msgstr "" -#: daemon/HTTPServer.cpp:265 +#: daemon/HTTPServer.cpp:271 msgid "Mesh" msgstr "" -#: daemon/HTTPServer.cpp:268 +#: daemon/HTTPServer.cpp:274 msgid "Error" msgstr "" -#: daemon/HTTPServer.cpp:272 +#: daemon/HTTPServer.cpp:278 msgid "Clock skew" msgstr "" -#: daemon/HTTPServer.cpp:275 +#: daemon/HTTPServer.cpp:281 msgid "Offline" msgstr "" -#: daemon/HTTPServer.cpp:278 +#: daemon/HTTPServer.cpp:284 msgid "Symmetric NAT" msgstr "" -#: daemon/HTTPServer.cpp:290 +#: daemon/HTTPServer.cpp:296 msgid "Uptime" msgstr "" -#: daemon/HTTPServer.cpp:293 +#: daemon/HTTPServer.cpp:299 msgid "Network status" msgstr "" -#: daemon/HTTPServer.cpp:298 +#: daemon/HTTPServer.cpp:304 msgid "Network status v6" msgstr "" -#: daemon/HTTPServer.cpp:304 daemon/HTTPServer.cpp:311 +#: daemon/HTTPServer.cpp:310 daemon/HTTPServer.cpp:317 msgid "Stopping in" msgstr "" -#: daemon/HTTPServer.cpp:318 +#: daemon/HTTPServer.cpp:324 msgid "Family" msgstr "" -#: daemon/HTTPServer.cpp:319 +#: daemon/HTTPServer.cpp:325 msgid "Tunnel creation success rate" msgstr "" -#: daemon/HTTPServer.cpp:320 +#: daemon/HTTPServer.cpp:326 msgid "Received" msgstr "" -#: daemon/HTTPServer.cpp:322 daemon/HTTPServer.cpp:325 -#: daemon/HTTPServer.cpp:328 +#: daemon/HTTPServer.cpp:328 daemon/HTTPServer.cpp:331 +#: daemon/HTTPServer.cpp:334 msgid "KiB/s" msgstr "" -#: daemon/HTTPServer.cpp:323 +#: daemon/HTTPServer.cpp:329 msgid "Sent" msgstr "" -#: daemon/HTTPServer.cpp:326 +#: daemon/HTTPServer.cpp:332 msgid "Transit" msgstr "" -#: daemon/HTTPServer.cpp:329 +#: daemon/HTTPServer.cpp:335 msgid "Data path" msgstr "" -#: daemon/HTTPServer.cpp:332 +#: daemon/HTTPServer.cpp:338 msgid "Hidden content. Press on text to see." msgstr "" -#: daemon/HTTPServer.cpp:335 +#: daemon/HTTPServer.cpp:341 msgid "Router Ident" msgstr "" -#: daemon/HTTPServer.cpp:337 +#: daemon/HTTPServer.cpp:343 msgid "Router Family" msgstr "" -#: daemon/HTTPServer.cpp:338 +#: daemon/HTTPServer.cpp:344 msgid "Router Caps" msgstr "" -#: daemon/HTTPServer.cpp:339 +#: daemon/HTTPServer.cpp:345 msgid "Version" msgstr "" -#: daemon/HTTPServer.cpp:340 +#: daemon/HTTPServer.cpp:346 msgid "Our external address" msgstr "" -#: daemon/HTTPServer.cpp:348 +#: daemon/HTTPServer.cpp:354 msgid "supported" msgstr "" -#: daemon/HTTPServer.cpp:380 +#: daemon/HTTPServer.cpp:386 msgid "Routers" msgstr "" -#: daemon/HTTPServer.cpp:381 +#: daemon/HTTPServer.cpp:387 msgid "Floodfills" msgstr "" -#: daemon/HTTPServer.cpp:388 daemon/HTTPServer.cpp:908 +#: daemon/HTTPServer.cpp:394 daemon/HTTPServer.cpp:927 msgid "Client Tunnels" msgstr "" -#: daemon/HTTPServer.cpp:389 +#: daemon/HTTPServer.cpp:395 msgid "Transit Tunnels" msgstr "" -#: daemon/HTTPServer.cpp:393 +#: daemon/HTTPServer.cpp:399 msgid "Services" msgstr "" -#: daemon/HTTPServer.cpp:407 daemon/HTTPServer.cpp:419 +#: daemon/HTTPServer.cpp:413 daemon/HTTPServer.cpp:425 msgid "Local Destinations" msgstr "" -#: daemon/HTTPServer.cpp:442 +#: daemon/HTTPServer.cpp:448 msgid "Encrypted B33 address" msgstr "" -#: daemon/HTTPServer.cpp:451 +#: daemon/HTTPServer.cpp:457 msgid "Address registration line" msgstr "" -#: daemon/HTTPServer.cpp:456 +#: daemon/HTTPServer.cpp:462 msgid "Domain" msgstr "" -#: daemon/HTTPServer.cpp:457 +#: daemon/HTTPServer.cpp:463 msgid "Generate" msgstr "" -#: daemon/HTTPServer.cpp:458 +#: daemon/HTTPServer.cpp:464 msgid "" "Note: result string can be used only for registering 2LD domains " "(example.i2p). For registering subdomains please use i2pd-tools." msgstr "" -#: daemon/HTTPServer.cpp:464 +#: daemon/HTTPServer.cpp:470 msgid "Address" msgstr "" -#: daemon/HTTPServer.cpp:464 +#: daemon/HTTPServer.cpp:470 msgid "Type" msgstr "" -#: daemon/HTTPServer.cpp:464 +#: daemon/HTTPServer.cpp:470 msgid "EncType" msgstr "" -#: daemon/HTTPServer.cpp:474 daemon/HTTPServer.cpp:657 +#: daemon/HTTPServer.cpp:480 daemon/HTTPServer.cpp:663 msgid "Inbound tunnels" msgstr "" -#: daemon/HTTPServer.cpp:479 daemon/HTTPServer.cpp:489 -#: daemon/HTTPServer.cpp:662 daemon/HTTPServer.cpp:672 -#: Means milliseconds +#. Milliseconds +#: daemon/HTTPServer.cpp:485 daemon/HTTPServer.cpp:495 +#: daemon/HTTPServer.cpp:668 daemon/HTTPServer.cpp:678 msgid "ms" msgstr "" -#: daemon/HTTPServer.cpp:484 daemon/HTTPServer.cpp:667 +#: daemon/HTTPServer.cpp:490 daemon/HTTPServer.cpp:673 msgid "Outbound tunnels" msgstr "" -#: daemon/HTTPServer.cpp:496 +#: daemon/HTTPServer.cpp:502 msgid "Tags" msgstr "" -#: daemon/HTTPServer.cpp:496 +#: daemon/HTTPServer.cpp:502 msgid "Incoming" msgstr "" -#: daemon/HTTPServer.cpp:503 daemon/HTTPServer.cpp:506 +#: daemon/HTTPServer.cpp:509 daemon/HTTPServer.cpp:512 msgid "Outgoing" msgstr "" -#: daemon/HTTPServer.cpp:504 daemon/HTTPServer.cpp:520 +#: daemon/HTTPServer.cpp:510 daemon/HTTPServer.cpp:526 msgid "Destination" msgstr "" -#: daemon/HTTPServer.cpp:504 +#: daemon/HTTPServer.cpp:510 msgid "Amount" msgstr "" -#: daemon/HTTPServer.cpp:511 +#: daemon/HTTPServer.cpp:517 msgid "Incoming Tags" msgstr "" -#: daemon/HTTPServer.cpp:519 daemon/HTTPServer.cpp:522 +#: daemon/HTTPServer.cpp:525 daemon/HTTPServer.cpp:528 msgid "Tags sessions" msgstr "" -#: daemon/HTTPServer.cpp:520 +#: daemon/HTTPServer.cpp:526 msgid "Status" msgstr "" -#: daemon/HTTPServer.cpp:529 daemon/HTTPServer.cpp:584 +#: daemon/HTTPServer.cpp:535 daemon/HTTPServer.cpp:590 msgid "Local Destination" msgstr "" -#: daemon/HTTPServer.cpp:538 daemon/HTTPServer.cpp:887 +#: daemon/HTTPServer.cpp:544 daemon/HTTPServer.cpp:906 msgid "Streams" msgstr "" -#: daemon/HTTPServer.cpp:560 +#: daemon/HTTPServer.cpp:566 msgid "Close stream" msgstr "" -#: daemon/HTTPServer.cpp:589 +#: daemon/HTTPServer.cpp:595 msgid "I2CP session not found" msgstr "" -#: daemon/HTTPServer.cpp:592 +#: daemon/HTTPServer.cpp:598 msgid "I2CP is not enabled" msgstr "" -#: daemon/HTTPServer.cpp:618 +#: daemon/HTTPServer.cpp:624 msgid "Invalid" msgstr "" -#: daemon/HTTPServer.cpp:621 +#: daemon/HTTPServer.cpp:627 msgid "Store type" msgstr "" -#: daemon/HTTPServer.cpp:622 +#: daemon/HTTPServer.cpp:628 msgid "Expires" msgstr "" -#: daemon/HTTPServer.cpp:627 +#: daemon/HTTPServer.cpp:633 msgid "Non Expired Leases" msgstr "" -#: daemon/HTTPServer.cpp:630 +#: daemon/HTTPServer.cpp:636 msgid "Gateway" msgstr "" -#: daemon/HTTPServer.cpp:631 +#: daemon/HTTPServer.cpp:637 msgid "TunnelID" msgstr "" -#: daemon/HTTPServer.cpp:632 +#: daemon/HTTPServer.cpp:638 msgid "EndDate" msgstr "" -#: daemon/HTTPServer.cpp:642 +#: daemon/HTTPServer.cpp:648 msgid "not floodfill" msgstr "" -#: daemon/HTTPServer.cpp:653 +#: daemon/HTTPServer.cpp:659 msgid "Queue size" msgstr "" -#: daemon/HTTPServer.cpp:684 +#: daemon/HTTPServer.cpp:690 msgid "Run peer test" msgstr "" -#: daemon/HTTPServer.cpp:687 +#: daemon/HTTPServer.cpp:693 msgid "Decline transit tunnels" msgstr "" -#: daemon/HTTPServer.cpp:689 +#: daemon/HTTPServer.cpp:695 msgid "Accept transit tunnels" msgstr "" -#: daemon/HTTPServer.cpp:692 daemon/HTTPServer.cpp:697 +#: daemon/HTTPServer.cpp:698 daemon/HTTPServer.cpp:703 msgid "Cancel graceful shutdown" msgstr "" -#: daemon/HTTPServer.cpp:694 daemon/HTTPServer.cpp:699 +#: daemon/HTTPServer.cpp:700 daemon/HTTPServer.cpp:705 msgid "Start graceful shutdown" msgstr "" -#: daemon/HTTPServer.cpp:701 +#: daemon/HTTPServer.cpp:707 msgid "Force shutdown" msgstr "" -#: daemon/HTTPServer.cpp:704 +#: daemon/HTTPServer.cpp:710 msgid "" "Note: any action done here are not persistent and not changes your " "config files." msgstr "" -#: daemon/HTTPServer.cpp:706 +#: daemon/HTTPServer.cpp:712 msgid "Logging level" msgstr "" -#: daemon/HTTPServer.cpp:714 +#: daemon/HTTPServer.cpp:720 msgid "Transit tunnels limit" msgstr "" -#: daemon/HTTPServer.cpp:719 +#: daemon/HTTPServer.cpp:725 daemon/HTTPServer.cpp:737 msgid "Change" msgstr "" -#: daemon/HTTPServer.cpp:743 +#: daemon/HTTPServer.cpp:729 +msgid "Change language" +msgstr "" + +#: daemon/HTTPServer.cpp:762 msgid "no transit tunnels currently built" msgstr "" -#: daemon/HTTPServer.cpp:848 daemon/HTTPServer.cpp:871 +#: daemon/HTTPServer.cpp:867 daemon/HTTPServer.cpp:890 msgid "SAM disabled" msgstr "" -#: daemon/HTTPServer.cpp:864 +#: daemon/HTTPServer.cpp:883 msgid "no sessions currently running" msgstr "" -#: daemon/HTTPServer.cpp:877 +#: daemon/HTTPServer.cpp:896 msgid "SAM session not found" msgstr "" -#: daemon/HTTPServer.cpp:882 +#: daemon/HTTPServer.cpp:901 msgid "SAM Session" msgstr "" -#: daemon/HTTPServer.cpp:939 +#: daemon/HTTPServer.cpp:958 msgid "Server Tunnels" msgstr "" -#: daemon/HTTPServer.cpp:955 +#: daemon/HTTPServer.cpp:974 msgid "Client Forwards" msgstr "" -#: daemon/HTTPServer.cpp:969 +#: daemon/HTTPServer.cpp:988 msgid "Server Forwards" msgstr "" -#: daemon/HTTPServer.cpp:1175 +#: daemon/HTTPServer.cpp:1194 msgid "Unknown page" msgstr "" -#: daemon/HTTPServer.cpp:1194 +#: daemon/HTTPServer.cpp:1213 msgid "Invalid token" msgstr "" -#: daemon/HTTPServer.cpp:1252 daemon/HTTPServer.cpp:1309 -#: daemon/HTTPServer.cpp:1337 +#: daemon/HTTPServer.cpp:1271 daemon/HTTPServer.cpp:1328 +#: daemon/HTTPServer.cpp:1364 msgid "SUCCESS" msgstr "" -#: daemon/HTTPServer.cpp:1252 +#: daemon/HTTPServer.cpp:1271 msgid "Stream closed" msgstr "" -#: daemon/HTTPServer.cpp:1254 +#: daemon/HTTPServer.cpp:1273 msgid "Stream not found or already was closed" msgstr "" -#: daemon/HTTPServer.cpp:1257 +#: daemon/HTTPServer.cpp:1276 msgid "Destination not found" msgstr "" -#: daemon/HTTPServer.cpp:1260 +#: daemon/HTTPServer.cpp:1279 msgid "StreamID can't be null" msgstr "" -#: daemon/HTTPServer.cpp:1262 daemon/HTTPServer.cpp:1327 +#: daemon/HTTPServer.cpp:1281 daemon/HTTPServer.cpp:1346 msgid "Return to destination page" msgstr "" -#: daemon/HTTPServer.cpp:1263 daemon/HTTPServer.cpp:1276 +#: daemon/HTTPServer.cpp:1282 daemon/HTTPServer.cpp:1295 msgid "You will be redirected back in 5 seconds" msgstr "" -#: daemon/HTTPServer.cpp:1274 +#: daemon/HTTPServer.cpp:1293 msgid "Transit tunnels count must not exceed 65535" msgstr "" -#: daemon/HTTPServer.cpp:1275 daemon/HTTPServer.cpp:1338 +#: daemon/HTTPServer.cpp:1294 daemon/HTTPServer.cpp:1365 msgid "Back to commands list" msgstr "" -#: daemon/HTTPServer.cpp:1311 +#: daemon/HTTPServer.cpp:1330 msgid "Register at reg.i2p" msgstr "" -#: daemon/HTTPServer.cpp:1312 +#: daemon/HTTPServer.cpp:1331 msgid "Description" msgstr "" -#: daemon/HTTPServer.cpp:1312 +#: daemon/HTTPServer.cpp:1331 msgid "A bit information about service on domain" msgstr "" -#: daemon/HTTPServer.cpp:1313 +#: daemon/HTTPServer.cpp:1332 msgid "Submit" msgstr "" -#: daemon/HTTPServer.cpp:1319 +#: daemon/HTTPServer.cpp:1338 msgid "Domain can't end with .b32.i2p" msgstr "" -#: daemon/HTTPServer.cpp:1322 +#: daemon/HTTPServer.cpp:1341 msgid "Domain must end with .i2p" msgstr "" -#: daemon/HTTPServer.cpp:1325 +#: daemon/HTTPServer.cpp:1344 msgid "Such destination is not found" msgstr "" -#: daemon/HTTPServer.cpp:1333 +#: daemon/HTTPServer.cpp:1360 msgid "Unknown command" msgstr "" -#: daemon/HTTPServer.cpp:1337 +#: daemon/HTTPServer.cpp:1364 msgid "Command accepted" msgstr "" -#: daemon/HTTPServer.cpp:1339 +#: daemon/HTTPServer.cpp:1366 msgid "You will be redirected in 5 seconds" msgstr "" diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 0b9e8f0f..8ed4511f 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -68,11 +68,11 @@ namespace http { << " a.button { -webkit-appearance: button; -moz-appearance: button; appearance: button; text-decoration: none;\r\n" << " color: initial; padding: 0 5px; border: 1px solid #894C84; }\r\n" << " .header { font-size: 2.5em; text-align: center; margin: 1em 0; color: #894C84; }\r\n" - << " .wrapper { margin: 0 auto; padding: 1em; max-width: 58em; }\r\n" - << " .menu { float: left; } .menu a, .commands a { display: block; }\r\n" + << " .wrapper { margin: 0 auto; padding: 1em; max-width: 64em; }\r\n" + << " .menu { display: block; float: left; overflow: hidden; max-width: 12em; white-space: nowrap; text-overflow: ellipsis; }\r\n" << " .listitem { display: block; font-family: monospace; font-size: 1.2em; white-space: nowrap; }\r\n" << " .tableitem { font-family: monospace; font-size: 1.2em; white-space: nowrap; }\r\n" - << " .content { float: left; font-size: 1em; margin-left: 4em; max-width: 45em; overflow: auto; }\r\n" + << " .content { float: left; font-size: 1em; margin-left: 4em; max-width: 48em; overflow: auto; }\r\n" << " .tunnel.established { color: #56B734; } .tunnel.expiring { color: #D3AE3F; }\r\n" << " .tunnel.failed { color: #D33F3F; } .tunnel.building { color: #434343; }\r\n" << " caption { font-size: 1.5em; text-align: center; color: #894C84; }\r\n" @@ -84,19 +84,24 @@ namespace http { << " .slide [type=\"checkbox\"]:checked ~ div.slidecontent { display: block; margin-top: 0; padding: 0; }\r\n" << " .disabled:after { color: #D33F3F; content: \"" << tr("Disabled") << "\" }\r\n" << " .enabled:after { color: #56B734; content: \"" << tr("Enabled") << "\" }\r\n" - << " @media screen and (max-width: 980px) {\r\n" /* adaptive style */ + << " @media screen and (max-width: 1150px) {\r\n" /* adaptive style */ + << " .wrapper { max-width: 58em; } .menu { max-width: 10em; }\r\n" + << " .content { margin-left: 2em; max-width: 42em; }\r\n" + << " }\r\n" + << " @media screen and (max-width: 980px) {\r\n" << " body { padding: 1.5em 0 0 0; }\r\n" - << " .menu { width: 100%; display: block; float: none; position: unset; font-size: 16px;\r\n" + << " .menu { width: 100%; max-width: unset; display: block; float: none; position: unset; font-size: 16px;\r\n" << " text-align: center; }\r\n" - << " .menu a, .commands a { padding: 2px; }\r\n" + << " .menu a, .commands a { display: inline-block; padding: 4px; }\r\n" << " .content { float: none; margin-left: unset; margin-top: 16px; max-width: 100%; width: 100%;\r\n" << " text-align: center; }\r\n" << " a, .slide label { /* margin-right: 10px; */ display: block; /* font-size: 18px; */ }\r\n" << " .header { margin: unset; font-size: 1.5em; } small {display: block}\r\n" << " a.button { -webkit-appearance: button; -moz-appearance: button; appearance: button; text-decoration: none;\r\n" << " color: initial; margin-top: 10px; padding: 6px; border: 1px solid #894c84; width: -webkit-fill-available; }\r\n" - << " input { width: 35%; text-align: center; padding: 5px;\r\n" + << " input, select { width: 35%; text-align: center; padding: 5px;\r\n" << " border: 2px solid #ccc; -webkit-border-radius: 5px; border-radius: 5px; font-size: 18px; }\r\n" + << " table.extaddr { margin: auto; text-align: unset; }\r\n" << " textarea { width: -webkit-fill-available; height: auto; padding:5px; border:2px solid #ccc;\r\n" << " -webkit-border-radius: 5px; border-radius: 5px; font-size: 12px; }\r\n" << " button[type=submit] { padding: 5px 15px; background: #ccc; border: 0 none; cursor: pointer;\r\n" @@ -127,6 +132,7 @@ namespace http { const char HTTP_COMMAND_KILLSTREAM[] = "closestream"; const char HTTP_COMMAND_LIMITTRANSIT[] = "limittransit"; const char HTTP_COMMAND_GET_REG_STRING[] = "get_reg_string"; + const char HTTP_COMMAND_SETLANGUAGE[] = "setlanguage"; const char HTTP_PARAM_SAM_SESSION_ID[] = "id"; const char HTTP_PARAM_ADDRESS[] = "address"; @@ -223,18 +229,18 @@ namespace http { "
" << tr("i2pd webconsole") << "
\r\n" "
\r\n" "\r\n" "
"; @@ -476,7 +482,7 @@ namespace http { s << "
"; it->Print(s); if(it->LatencyIsKnown()) - s << " ( " << it->GetMeanLatency() << tr("ms") << " )"; + s << " ( " << it->GetMeanLatency() << tr(/* Milliseconds */ "ms") << " )"; ShowTunnelDetails(s, it->GetState (), false, it->GetNumReceivedBytes ()); s << "
\r\n"; } @@ -681,22 +687,22 @@ namespace http { std::string webroot; i2p::config::GetOption("http.webroot", webroot); /* commands */ s << "" << tr("Router commands") << "
\r\n
\r\n
\r\n"; - s << " " << tr("Run peer test") << "\r\n"; + s << " " << tr("Run peer test") << "
\r\n"; //s << " Reload config
\r\n"; if (i2p::context.AcceptsTunnels ()) - s << " " << tr("Decline transit tunnels") << "\r\n"; + s << " " << tr("Decline transit tunnels") << "
\r\n"; else - s << " " << tr("Accept transit tunnels") << "\r\n"; + s << " " << tr("Accept transit tunnels") << "
\r\n"; #if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY)) if (Daemon.gracefulShutdownInterval) - s << " " << tr("Cancel graceful shutdown") << "\r\n"; + s << " " << tr("Cancel graceful shutdown") << "
\r\n"; else - s << " " << tr("Start graceful shutdown") << "\r\n"; + s << " " << tr("Start graceful shutdown") << "
\r\n"; #elif defined(WIN32_APP) if (i2p::util::DaemonWin32::Instance().isGraceful) - s << " " << tr("Cancel graceful shutdown") << "\r\n"; + s << " " << tr("Cancel graceful shutdown") << "
\r\n"; else - s << " " << tr("Start graceful shutdown") << "\r\n"; + s << " " << tr("Start graceful shutdown") << "
\r\n"; #endif s << " " << tr("Force shutdown") << "\r\n"; s << "
"; @@ -718,6 +724,19 @@ namespace http { s << " \r\n"; s << " \r\n"; s << "\r\n
\r\n"; + + std::string currLang = i2p::context.GetLanguage ()->GetLanguage(); // get current used language + s << "" << tr("Change language") << "
\r\n"; + s << "
\r\n"; + s << " \r\n"; + s << " \r\n"; + s << " \r\n"; + s << " \r\n"; + s << "
\r\n
\r\n"; + } void ShowTransitTunnels (std::stringstream& s) @@ -1327,6 +1346,14 @@ namespace http { s << "" << tr("Return to destination page") << "\r\n"; return; } + else if (cmd == HTTP_COMMAND_SETLANGUAGE) + { + std::string lang = params["lang"]; + std::string currLang = i2p::context.GetLanguage ()->GetLanguage(); + + if (currLang.compare(lang) != 0) + i2p::i18n::SetLanguage(lang); + } else { res.code = 400; diff --git a/i18n/Afrikaans.cpp b/i18n/Afrikaans.cpp index d2b652b4..96ee52ee 100644 --- a/i18n/Afrikaans.cpp +++ b/i18n/Afrikaans.cpp @@ -18,8 +18,11 @@ namespace i2p { namespace i18n { -namespace afrikaans // language +namespace afrikaans // language namespace { + // language name in lowercase + static std::string language = "afrikaans"; + // See for language plural forms here: // https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html static int plural (int n) { @@ -65,7 +68,7 @@ namespace afrikaans // language std::shared_ptr GetLocale() { - return std::make_shared(strings, plurals, [] (int n)->int { return plural(n); }); + return std::make_shared(language, strings, plurals, [] (int n)->int { return plural(n); }); } } // language diff --git a/i18n/English.cpp b/i18n/English.cpp index 6015f8e1..2670e984 100644 --- a/i18n/English.cpp +++ b/i18n/English.cpp @@ -19,8 +19,11 @@ namespace i2p { namespace i18n { -namespace english // language +namespace english // language namespace { + // language name in lowercase + static std::string language = "english"; + // See for language plural forms here: // https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html static int plural (int n) { @@ -39,7 +42,7 @@ namespace english // language std::shared_ptr GetLocale() { - return std::make_shared(strings, plurals, [] (int n)->int { return plural(n); }); + return std::make_shared(language, strings, plurals, [] (int n)->int { return plural(n); }); } } // language diff --git a/i18n/I18N.h b/i18n/I18N.h index 272f65e8..03add48d 100644 --- a/i18n/I18N.h +++ b/i18n/I18N.h @@ -17,16 +17,11 @@ namespace i18n { inline void SetLanguage(const std::string &lang) { - if (!lang.compare("afrikaans")) - i2p::context.SetLanguage (i2p::i18n::afrikaans::GetLocale()); - else if (!lang.compare("russian")) - i2p::context.SetLanguage (i2p::i18n::russian::GetLocale()); - else if (!lang.compare("turkmen")) - i2p::context.SetLanguage (i2p::i18n::turkmen::GetLocale()); - else if (!lang.compare("ukrainian")) - i2p::context.SetLanguage (i2p::i18n::ukrainian::GetLocale()); - else // fallback + const auto it = i2p::i18n::languages.find(lang); + if (it == i2p::i18n::languages.end()) // fallback i2p::context.SetLanguage (i2p::i18n::english::GetLocale()); + else + i2p::context.SetLanguage (it->second.LocaleFunc()); } inline std::string translate (const std::string& arg) diff --git a/i18n/I18N_langs.h b/i18n/I18N_langs.h index 181a4793..949e5844 100644 --- a/i18n/I18N_langs.h +++ b/i18n/I18N_langs.h @@ -17,10 +17,17 @@ namespace i18n { public: Locale ( + const std::string& language, const std::map& strings, const std::map>& plurals, std::function formula - ): m_Strings (strings), m_Plurals (plurals), m_Formula (formula) { }; + ): m_Language (language), m_Strings (strings), m_Plurals (plurals), m_Formula (formula) { }; + + // Get activated language name for webconsole + std::string GetLanguage() const + { + return m_Language; + } std::string GetString (const std::string& arg) const { @@ -50,11 +57,18 @@ namespace i18n } private: + const std::string m_Language; const std::map m_Strings; const std::map> m_Plurals; std::function m_Formula; }; + struct langData + { + std::string LocaleName; //localized name + std::function (void)> LocaleFunc; + }; + // Add localization here with language name as namespace namespace afrikaans { std::shared_ptr GetLocale (); } namespace english { std::shared_ptr GetLocale (); } @@ -62,6 +76,18 @@ namespace i18n namespace turkmen { std::shared_ptr GetLocale (); } namespace ukrainian { std::shared_ptr GetLocale (); } + /** + * That map contains international language name lower-case and name in it's language + */ + static std::map languages + { + { "afrikaans", {"Afrikaans", i2p::i18n::afrikaans::GetLocale} }, + { "english", {"English", i2p::i18n::english::GetLocale} }, + { "russian", {"русский язык", i2p::i18n::russian::GetLocale} }, + { "turkmen", {"türkmen dili", i2p::i18n::turkmen::GetLocale} }, + { "ukrainian", {"украї́нська мо́ва", i2p::i18n::ukrainian::GetLocale} }, + }; + } // i18n } // i2p diff --git a/i18n/Russian.cpp b/i18n/Russian.cpp index 7df82d54..5e7f9c6b 100644 --- a/i18n/Russian.cpp +++ b/i18n/Russian.cpp @@ -18,8 +18,11 @@ namespace i2p { namespace i18n { -namespace russian // language +namespace russian // language namespace { + // language name in lowercase + static std::string language = "russian"; + // See for language plural forms here: // https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html static int plural (int n) { @@ -28,23 +31,152 @@ namespace russian // language static std::map strings { - // HTTP Proxy + {"Disabled", "Выключено"}, + {"Enabled", "Включено"}, + {"KiB", "КиБ"}, + {"MiB", "МиБ"}, + {"GiB", "ГиБ"}, + {"building", "строится"}, + {"failed", "неудачный"}, + {"expiring", "истекает"}, + {"established", "работает"}, + {"unknown", "неизвестно"}, + {"exploratory", "исследовательский"}, + {"i2pd webconsole", "Веб-консоль i2pd"}, + {"Main page", "Главная"}, + {"Router commands", "Команды роутера"}, + {"Local destinations", "Локальные назначения"}, + {"LeaseSets", "Лизсеты"}, + {"Tunnels", "Туннели"}, + {"Transit tunnels", "Транзитные туннели"}, + {"Transports", "Транспорты"}, + {"I2P tunnels", "I2P туннели"}, + {"SAM sessions", "SAM сессии"}, + {"ERROR", "ОШИБКА"}, + {"OK", "OK"}, + {"Testing", "Тестирование"}, + {"Firewalled", "Заблокировано извне"}, + {"Unknown", "Неизвестно"}, + {"Proxy", "Прокси"}, + {"Mesh", "MESH-сеть"}, + {"Error", "Ошибка"}, + {"Clock skew", "Не точное время"}, + {"Offline", "Оффлайн"}, + {"Symmetric NAT", "Симметричный NAT"}, + {"Uptime", "В сети"}, + {"Network status", "Сетевой статус"}, + {"Network status v6", "Сетевой статус v6"}, + {"Stopping in", "Остановка через"}, + {"Family", "Семейство"}, + {"Tunnel creation success rate", "Успешно построенных туннелей"}, + {"Received", "Получено"}, + {"KiB/s", "КиБ/с"}, + {"Sent", "Отправлено"}, + {"Transit", "Транзит"}, + {"Data path", "Путь к данным"}, + {"Hidden content. Press on text to see.", "Скрытый контент. Нажмите на текст чтобы отобразить."}, + {"Router Ident", "Идентификатор роутера"}, + {"Router Family", "Семейство роутера"}, + {"Router Caps", "Флаги роутера"}, + {"Version", "Версия"}, + {"Our external address", "Наш внешний адрес"}, + {"supported", "поддерживается"}, + {"Routers", "Роутеры"}, + {"Floodfills", "Флудфилы"}, + {"Client Tunnels", "Клиентские туннели"}, + {"Transit Tunnels", "Транзитные туннели"}, + {"Services", "Сервисы"}, + {"Local Destinations", "Локальные назначения"}, + {"Encrypted B33 address", "Шифрованные B33 адреса"}, + {"Address registration line", "Строка регистрации адреса"}, + {"Domain", "Домен"}, + {"Generate", "Сгенерировать"}, + {"Note: result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "Примечание: полученная строка может быть использована только для регистрации доменов второго уровня (example.i2p). Для регистрации поддоменов используйте i2pd-tools."}, + {"Address", "Адрес"}, + {"Type", "Тип"}, + {"EncType", "ТипШифр"}, + {"Inbound tunnels", "Входящие туннели"}, + {"ms", "мс"}, + {"Outbound tunnels", "Исходящие туннели"}, + {"Tags", "Теги"}, + {"Incoming", "Входящие"}, + {"Outgoing", "Исходящие"}, + {"Destination", "Назначение"}, + {"Amount", "Количество"}, + {"Incoming Tags", "Входящие Теги"}, + {"Tags sessions", "Сессии Тегов"}, + {"Status", "Статус"}, + {"Local Destination", "Локальное назначение"}, + {"Streams", "Стримы"}, + {"Close stream", "Закрыть стрим"}, + {"I2CP session not found", "I2CP сессия не найдена"}, + {"I2CP is not enabled", "I2CP не включен"}, + {"Invalid", "Некорректный"}, + {"Store type", "Тип хранилища"}, + {"Expires", "Истекает"}, + {"Non Expired Leases", "Не истекшие Lease-ы"}, + {"Gateway", "Шлюз"}, + {"TunnelID", "ID туннеля"}, + {"EndDate", "Заканчивается"}, + {"not floodfill", "не флудфил"}, + {"Queue size", "Размер очереди"}, + {"Run peer test", "Запустить тестирование"}, + {"Decline transit tunnels", "Отклонять транзитные туннели"}, + {"Accept transit tunnels", "Принимать транзитные туннели"}, + {"Cancel graceful shutdown", "Отменить плавную остановку"}, + {"Start graceful shutdown", "Запустить плавную остановку"}, + {"Force shutdown", "Принудительная остановка"}, + {"Note: any action done here are not persistent and not changes your config files.", "Примечание: любое действие произведенное здесь не является постоянным и не изменяет ваши конфигурационные файлы."}, + {"Logging level", "Уровень логирования"}, + {"Transit tunnels limit", "Лимит транзитных туннелей"}, + {"Change", "Изменить"}, + {"Change language", "Изменение языка"}, + {"no transit tunnels currently built", "нет построенных транзитных туннелей"}, + {"SAM disabled", "SAM выключен"}, + {"no sessions currently running", "нет запущенных сессий"}, + {"SAM session not found", "SAM сессия не найдена"}, + {"SAM Session", "SAM сессия"}, + {"Server Tunnels", "Серверные туннели"}, + {"Client Forwards", "Клиентские перенаправления"}, + {"Server Forwards", "Серверные перенаправления"}, + {"Unknown page", "Неизвестная страница"}, + {"Invalid token", "Неверный токен"}, + {"SUCCESS", "УСПЕШНО"}, + {"Stream closed", "Стрим закрыт"}, + {"Stream not found or already was closed", "Стрим не найден или уже закрыт"}, + {"Destination not found", "Точка назначения не найдена"}, + {"StreamID can't be null", "StreamID не может быть пустым"}, + {"Return to destination page", "Вернуться на страницу точки назначения"}, + {"You will be redirected back in 5 seconds", "Вы будете переадресованы назад через 5 секунд"}, + {"Transit tunnels count must not exceed 65535", "Число транзитных туннелей не должно превышать 65535"}, + {"Back to commands list", "Вернуться к списку команд"}, + {"Register at reg.i2p", "Зарегистрировать на reg.i2p"}, + {"Description", "Описание"}, + {"A bit information about service on domain", "Немного информации о сервисе на домене"}, + {"Submit", "Отправить"}, + {"Domain can't end with .b32.i2p", "Домен не может заканчиваться на .b32.i2p"}, + {"Domain must end with .i2p", "Домен должен заканчиваться на .i2p"}, + {"Such destination is not found", "Такая точка назначения не найдена"}, + {"Unknown command", "Неизвестная команда"}, + {"Command accepted", "Команда принята"}, + {"You will be redirected in 5 seconds", "Вы будете переадресованы через 5 секунд"}, {"Proxy error", "Ошибка прокси"}, {"Proxy info", "Информация прокси"}, - {"Proxy error: Host not found", "Ошибка прокси: Адрес не найден"}, - {"Remote host not found in router's addressbook", "Запрошенный адрес не найден в адресной книге роутера"}, - {"You may try to find this host on jump services below", "Вы можете попробовать найти адрес на джамп сервисах ниже"}, + {"Proxy error: Host not found", "Ошибка прокси: Узел не найден"}, + {"Remote host not found in router's addressbook", "Запрошенный узел не найден в адресной книге роутера"}, + {"You may try to find this host on jump services below", "Вы можете попробовать найти узел через джамп сервисы ниже"}, {"Invalid request", "Некорректный запрос"}, {"Proxy unable to parse your request", "Прокси не может разобрать ваш запрос"}, {"addresshelper is not supported", "addresshelper не поддерживается"}, - {"Host", "Адрес"}, + {"Host", "Узел"}, {"added to router's addressbook from helper", "добавлен в адресную книгу роутера через хелпер"}, - {"already in router's addressbook", "уже в адресной книге роутера"}, {"Click", "Нажмите"}, {"here", "здесь"}, {"to proceed", "чтобы продолжить"}, - {"to update record", "чтобы обновить запись"}, {"Addresshelper found", "Найден addresshelper"}, + {"already in router's addressbook", "уже в адресной книге роутера"}, + {"to update record", "чтобы обновить запись"}, + {"Invalid Request", "неверный запрос"}, {"invalid request uri", "некорректный URI запроса"}, {"Can't detect destination host from request", "Не удалось определить адрес назначения из запроса"}, {"Outproxy failure", "Ошибка внешнего прокси"}, @@ -63,169 +195,13 @@ namespace russian // language {"cannot connect", "не удалось подключиться"}, {"http out proxy not implemented", "поддержка внешнего HTTP прокси сервера не реализована"}, {"cannot connect to upstream http proxy", "не удалось подключиться к вышестоящему HTTP прокси серверу"}, - {"Host is down", "Адрес недоступен"}, - {"Can't create connection to requested host, it may be down. Please try again later.", - "Не удалось установить соединение к запрошенному адресу, возможно он не в сети. Попробуйте повторить запрос позже."}, - - // Webconsole // - // cssStyles - {"Disabled", "Выключено"}, - {"Enabled", "Включено"}, - // ShowTraffic - {"KiB", "КиБ"}, - {"MiB", "МиБ"}, - {"GiB", "ГиБ"}, - // ShowTunnelDetails - {"building", "строится"}, - {"failed", "неудачный"}, - {"expiring", "истекает"}, - {"established", "работает"}, - {"exploratory", "исследовательский"}, - {"unknown", "неизвестно"}, - {"i2pd webconsole", "Веб-консоль i2pd"}, - // ShowPageHead - {"Main page", "Главная"}, - {"Router commands", "Команды роутера"}, - {"Local destinations", "Локальные назнач."}, - {"LeaseSets", "Лизсеты"}, - {"Tunnels", "Туннели"}, - {"Transit tunnels", "Транзит. туннели"}, - {"Transports", "Транспорты"}, - {"I2P tunnels", "I2P туннели"}, - {"SAM sessions", "SAM сессии"}, - // Network Status - {"OK", "OK"}, - {"Testing", "Тестирование"}, - {"Firewalled", "Заблокировано извне"}, - {"Unknown", "Неизвестно"}, - {"Proxy", "Прокси"}, - {"Mesh", "MESH-сеть"}, - {"Error", "Ошибка"}, - {"Clock skew", "Не точное время"}, - {"Offline", "Оффлайн"}, - {"Symmetric NAT", "Симметричный NAT"}, - // Status - {"Uptime", "В сети"}, - {"Network status", "Сетевой статус"}, - {"Network status v6", "Сетевой статус v6"}, - {"Stopping in", "Остановка через"}, - {"Family", "Семейство"}, - {"Tunnel creation success rate", "Успешно построенных туннелей"}, - {"Received", "Получено"}, - {"Sent", "Отправлено"}, - {"Transit", "Транзит"}, - {"KiB/s", "КиБ/с"}, - {"Data path", "Путь к данным"}, - {"Hidden content. Press on text to see.", "Скрытый контент. Нажмите на текст чтобы отобразить."}, - {"Router Ident", "Идентификатор роутера"}, - {"Router Family", "Семейство роутера"}, - {"Router Caps", "Флаги роутера"}, - {"Version", "Версия"}, - {"Our external address", "Наш внешний адрес"}, - {"supported", "поддерживается"}, - {"Routers", "Роутеры"}, - {"Floodfills", "Флудфилы"}, - {"LeaseSets", "Лизсеты"}, - {"Client Tunnels", "Клиентские туннели"}, - {"Transit Tunnels", "Транзитные туннели"}, - {"Services", "Сервисы"}, - // ShowLocalDestinations - {"Local Destinations", "Локальные назначения"}, - // ShowLeaseSetDestination - {"Encrypted B33 address", "Шифрованные B33 адреса"}, - {"Address registration line", "Строка регистрации адреса"}, - {"Domain", "Домен"}, - {"Generate", "Сгенерировать"}, - {"Note: result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", - "Примечание: полученная строка может быть использована только для регистрации доменов второго уровня. Для регистрации поддоменов используйте i2pd-tools."}, - {"Address", "Адрес"}, - {"Type", "Тип"}, - {"EncType", "ТипШифр"}, - {"Inbound tunnels", "Входящие туннели"}, - {"Outbound tunnels", "Исходящие туннели"}, - {"ms", "мс"}, // milliseconds - {"Tags", "Теги"}, - {"Incoming", "Входящие"}, - {"Outgoing", "Исходящие"}, - {"Destination", "Назначение"}, - {"Amount", "Количество"}, - {"Incoming Tags", "Входящие Теги"}, - {"Tags sessions", "Сессии Тегов"}, - {"Status", "Статус"}, - // ShowLocalDestination - {"Local Destination", "Локальное назначение"}, - {"Streams", "Стримы"}, - {"Close stream", "Закрыть стрим"}, - // ShowI2CPLocalDestination - {"I2CP session not found", "I2CP сессия не найдена"}, - {"I2CP is not enabled", "I2CP не включен"}, - // ShowLeasesSets - {"Invalid", "Некорректный"}, - {"Store type", "Тип хранилища"}, - {"Expires", "Истекает"}, - {"Non Expired Leases", "Не истекшие Lease-ы"}, - {"Gateway", "Шлюз"}, - {"TunnelID", "ID туннеля"}, - {"EndDate", "Заканчивается"}, - {"not floodfill", "не флудфил"}, - // ShowTunnels - {"Queue size", "Размер очереди"}, - // ShowCommands - {"Run peer test", "Запустить тестирование"}, - {"Decline transit tunnels", "Отклонять транзитные туннели"}, - {"Accept transit tunnels", "Принимать транзитные туннели"}, - {"Cancel graceful shutdown", "Отменить плавную остановку"}, - {"Start graceful shutdown", "Запустить плавную остановку"}, - {"Force shutdown", "Принудительная остановка"}, - {"Note: any action done here are not persistent and not changes your config files.", - "Примечание: любое действие произведенное здесь не является постоянным и не изменяет ваши конфигурационные файлы."}, - {"Logging level", "Уровень логирования"}, - {"Transit tunnels limit", "Лимит транзитных туннелей"}, - {"Change", "Изменить"}, - // ShowTransitTunnels - {"no transit tunnels currently built", "нет построенных транзитных туннелей"}, - // ShowSAMSessions/ShowSAMSession - {"SAM disabled", "SAM выключен"}, - {"SAM session not found", "SAM сессия не найдена"}, - {"no sessions currently running", "нет запущенных сессий"}, - {"SAM Session", "SAM сессия"}, - // ShowI2PTunnels - {"Server Tunnels", "Серверные туннели"}, - {"Client Forwards", "Клиентские перенаправления"}, - {"Server Forwards", "Серверные перенаправления"}, - // HandlePage - {"Unknown page", "Неизвестная страница"}, - // HandleCommand, ShowError - {"Invalid token", "Неверный токен"}, - {"SUCCESS", "УСПЕШНО"}, - {"ERROR", "ОШИБКА"}, - {"Unknown command", "Неизвестная команда"}, - {"Command accepted", "Команда принята"}, - {"Back to commands list", "Вернуться к списку команд"}, - {"You will be redirected in 5 seconds", "Вы будете переадресованы через 5 секунд"}, - // HTTP_COMMAND_KILLSTREAM - {"Stream closed", "Стрим закрыт"}, - {"Stream not found or already was closed", "Стрим не найден или уже закрыт"}, - {"Destination not found", "Точка назначения не найдена"}, - {"StreamID can't be null", "StreamID не может быть пустым"}, - {"Return to destination page", "Вернуться на страницу точки назначения"}, - {"You will be redirected back in 5 seconds", "Вы будете переадресованы назад через 5 секунд"}, - // HTTP_COMMAND_LIMITTRANSIT - {"Transit tunnels count must not exceed 65535", "Число транзитных туннелей не должно превышать 65535"}, - // HTTP_COMMAND_GET_REG_STRING - {"Register at reg.i2p", "Зарегистрировать на reg.i2p"}, - {"Description", "Описание"}, - {"A bit information about service on domain", "Немного информации о сервисе на домене"}, - {"Submit", "Отправить"}, - {"Domain can't end with .b32.i2p", "Домен не может заканчиваться на .b32.i2p"}, - {"Domain must end with .i2p", "Домен должен заканчиваться на .i2p"}, - {"Such destination is not found", "Такая точка назначения не найдена"}, + {"Host is down", "Узел недоступен"}, + {"Can't create connection to requested host, it may be down. Please try again later.", "Не удалось установить соединение к запрошенному узлу, возможно он не в сети. Попробуйте повторить запрос позже."}, {"", ""}, }; static std::map> plurals { - // ShowUptime {"days", {"день", "дня", "дней"}}, {"hours", {"час", "часа", "часов"}}, {"minutes", {"минуту", "минуты", "минут"}}, @@ -235,7 +211,7 @@ namespace russian // language std::shared_ptr GetLocale() { - return std::make_shared(strings, plurals, [] (int n)->int { return plural(n); }); + return std::make_shared(language, strings, plurals, [] (int n)->int { return plural(n); }); } } // language diff --git a/i18n/Turkmen.cpp b/i18n/Turkmen.cpp index 0edc9a6e..8af89f6f 100644 --- a/i18n/Turkmen.cpp +++ b/i18n/Turkmen.cpp @@ -18,8 +18,11 @@ namespace i2p { namespace i18n { -namespace turkmen // language +namespace turkmen // language namespace { + // language name in lowercase + static std::string language = "turkmen"; + // See for language plural forms here: // https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html static int plural (int n) { @@ -234,7 +237,7 @@ namespace turkmen // language std::shared_ptr GetLocale() { - return std::make_shared(strings, plurals, [] (int n)->int { return plural(n); }); + return std::make_shared(language, strings, plurals, [] (int n)->int { return plural(n); }); } } // language diff --git a/i18n/Ukrainian.cpp b/i18n/Ukrainian.cpp index 5e856c52..8da132d7 100644 --- a/i18n/Ukrainian.cpp +++ b/i18n/Ukrainian.cpp @@ -18,8 +18,11 @@ namespace i2p { namespace i18n { -namespace ukrainian // language +namespace ukrainian // language namespace { + // language name in lowercase + static std::string language = "ukrainian"; + // See for language plural forms here: // https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html static int plural (int n) { @@ -207,7 +210,7 @@ namespace ukrainian // language std::shared_ptr GetLocale() { - return std::make_shared(strings, plurals, [] (int n)->int { return plural(n); }); + return std::make_shared(language, strings, plurals, [] (int n)->int { return plural(n); }); } } // language From 25f63ac22a8604f05cabee447c28337190be404d Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 27 Jun 2021 15:49:57 -0400 Subject: [PATCH 22/24] create different I2NP tunnel messages for endpoint and non-endpoint --- libi2pd/I2NPProtocol.cpp | 26 ++++++++++++++++++-------- libi2pd/I2NPProtocol.h | 4 ++-- libi2pd/TransitTunnel.cpp | 4 ++-- libi2pd/Tunnel.cpp | 2 +- libi2pd/TunnelEndpoint.cpp | 4 +--- libi2pd/TunnelGateway.cpp | 2 +- 6 files changed, 25 insertions(+), 17 deletions(-) diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index f570a2a1..a040e25b 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -36,11 +36,21 @@ namespace i2p return std::make_shared >(); } - std::shared_ptr NewI2NPTunnelMessage () + std::shared_ptr NewI2NPTunnelMessage (bool endpoint) { - // should fit two tunnel message, enough for one garlic encrypted streaming packet - auto msg = new I2NPMessageBuffer<2*i2p::tunnel::TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + 34>(); // reserved for alignment and NTCP 16 + 6 + 12 - msg->Align (12); + I2NPMessage * msg = nullptr; + if (endpoint) + { + // should fit two tunnel message + tunnel gateway header, enough for one garlic encrypted streaming packet + msg = new I2NPMessageBuffer<2*i2p::tunnel::TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE + 28>(); // reserved for alignment and NTCP 16 + 6 + 6 + msg->Align (6); + msg->offset += TUNNEL_GATEWAY_HEADER_SIZE; // reserve room for TunnelGateway header + } + else + { + msg = new I2NPMessageBuffer(); // reserved for alignment and NTCP 16 + 6 + 12 + msg->Align (12); + } return std::shared_ptr(msg); } @@ -692,7 +702,7 @@ namespace i2p std::shared_ptr CreateTunnelDataMsg (const uint8_t * buf) { - auto msg = NewI2NPTunnelMessage (); + auto msg = NewI2NPTunnelMessage (false); msg->Concat (buf, i2p::tunnel::TUNNEL_DATA_MSG_SIZE); msg->FillI2NPMessageHeader (eI2NPTunnelData); return msg; @@ -700,7 +710,7 @@ namespace i2p std::shared_ptr CreateTunnelDataMsg (uint32_t tunnelID, const uint8_t * payload) { - auto msg = NewI2NPTunnelMessage (); + auto msg = NewI2NPTunnelMessage (false); htobe32buf (msg->GetPayload (), tunnelID); msg->len += 4; // tunnelID msg->Concat (payload, i2p::tunnel::TUNNEL_DATA_MSG_SIZE - 4); @@ -708,9 +718,9 @@ namespace i2p return msg; } - std::shared_ptr CreateEmptyTunnelDataMsg () + std::shared_ptr CreateEmptyTunnelDataMsg (bool endpoint) { - auto msg = NewI2NPTunnelMessage (); + auto msg = NewI2NPTunnelMessage (endpoint); msg->len += i2p::tunnel::TUNNEL_DATA_MSG_SIZE; return msg; } diff --git a/libi2pd/I2NPProtocol.h b/libi2pd/I2NPProtocol.h index cc7c94af..69d6bb04 100644 --- a/libi2pd/I2NPProtocol.h +++ b/libi2pd/I2NPProtocol.h @@ -278,7 +278,7 @@ namespace tunnel std::shared_ptr NewI2NPMessage (); std::shared_ptr NewI2NPShortMessage (); - std::shared_ptr NewI2NPTunnelMessage (); + std::shared_ptr NewI2NPTunnelMessage (bool endpoint); std::shared_ptr NewI2NPMessage (size_t len); std::shared_ptr CreateI2NPMessage (I2NPMessageType msgType, const uint8_t * buf, size_t len, uint32_t replyMsgID = 0); @@ -307,7 +307,7 @@ namespace tunnel std::shared_ptr CreateTunnelDataMsg (const uint8_t * buf); std::shared_ptr CreateTunnelDataMsg (uint32_t tunnelID, const uint8_t * payload); - std::shared_ptr CreateEmptyTunnelDataMsg (); + std::shared_ptr CreateEmptyTunnelDataMsg (bool endpoint); std::shared_ptr CreateTunnelGatewayMsg (uint32_t tunnelID, const uint8_t * buf, size_t len); std::shared_ptr CreateTunnelGatewayMsg (uint32_t tunnelID, I2NPMessageType msgType, diff --git a/libi2pd/TransitTunnel.cpp b/libi2pd/TransitTunnel.cpp index 73ca977c..dc7655d1 100644 --- a/libi2pd/TransitTunnel.cpp +++ b/libi2pd/TransitTunnel.cpp @@ -39,7 +39,7 @@ namespace tunnel void TransitTunnelParticipant::HandleTunnelDataMsg (std::shared_ptr tunnelMsg) { - auto newMsg = CreateEmptyTunnelDataMsg (); + auto newMsg = CreateEmptyTunnelDataMsg (false); EncryptTunnelMsg (tunnelMsg, newMsg); m_NumTransmittedBytes += tunnelMsg->GetLength (); @@ -87,7 +87,7 @@ namespace tunnel void TransitTunnelEndpoint::HandleTunnelDataMsg (std::shared_ptr tunnelMsg) { - auto newMsg = CreateEmptyTunnelDataMsg (); + auto newMsg = CreateEmptyTunnelDataMsg (true); EncryptTunnelMsg (tunnelMsg, newMsg); LogPrint (eLogDebug, "TransitTunnel: handle msg for endpoint ", GetTunnelID ()); diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index e016e9e4..ba01ae20 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -234,7 +234,7 @@ namespace tunnel void InboundTunnel::HandleTunnelDataMsg (std::shared_ptr msg) { if (IsFailed ()) SetState (eTunnelStateEstablished); // incoming messages means a tunnel is alive - auto newMsg = CreateEmptyTunnelDataMsg (); + auto newMsg = CreateEmptyTunnelDataMsg (true); EncryptTunnelMsg (msg, newMsg); newMsg->from = shared_from_this (); m_Endpoint.HandleDecryptedTunnelDataMsg (newMsg); diff --git a/libi2pd/TunnelEndpoint.cpp b/libi2pd/TunnelEndpoint.cpp index 109f3120..4885c090 100644 --- a/libi2pd/TunnelEndpoint.cpp +++ b/libi2pd/TunnelEndpoint.cpp @@ -126,9 +126,7 @@ namespace tunnel if (fragment + size < decrypted + TUNNEL_DATA_ENCRYPTED_SIZE) { // this is not last message. we have to copy it - m_CurrentMessage.data = NewI2NPTunnelMessage (); - m_CurrentMessage.data->offset += TUNNEL_GATEWAY_HEADER_SIZE; // reserve room for TunnelGateway header - m_CurrentMessage.data->len += TUNNEL_GATEWAY_HEADER_SIZE; + m_CurrentMessage.data = NewI2NPTunnelMessage (true); *(m_CurrentMessage.data) = *msg; } else diff --git a/libi2pd/TunnelGateway.cpp b/libi2pd/TunnelGateway.cpp index 317926ae..08df569c 100644 --- a/libi2pd/TunnelGateway.cpp +++ b/libi2pd/TunnelGateway.cpp @@ -215,7 +215,7 @@ namespace tunnel const auto& tunnelDataMsgs = m_Buffer.GetTunnelDataMsgs (); for (auto& tunnelMsg : tunnelDataMsgs) { - auto newMsg = CreateEmptyTunnelDataMsg (); + auto newMsg = CreateEmptyTunnelDataMsg (false); m_Tunnel->EncryptTunnelMsg (tunnelMsg, newMsg); htobe32buf (newMsg->GetPayload (), m_Tunnel->GetNextTunnelID ()); newMsg->FillI2NPMessageHeader (eI2NPTunnelData); From f036b8df2dc74977b700bd543fec9d9754dbb4ce Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 28 Jun 2021 12:45:28 +0300 Subject: [PATCH 23/24] [i18n] update translatable strings (remove douplicates) Signed-off-by: R4SAS --- contrib/i18n/English.po | 180 +++++++++++++++++------------------ daemon/HTTPServer.cpp | 39 ++++---- libi2pd_client/HTTPProxy.cpp | 2 +- 3 files changed, 108 insertions(+), 113 deletions(-) diff --git a/contrib/i18n/English.po b/contrib/i18n/English.po index 011d0fee..76d58390 100644 --- a/contrib/i18n/English.po +++ b/contrib/i18n/English.po @@ -50,14 +50,17 @@ msgid_plural "seconds" msgstr[0] "" msgstr[1] "" +#. tr: Kibibit #: daemon/HTTPServer.cpp:166 daemon/HTTPServer.cpp:194 msgid "KiB" msgstr "" +#. tr: Mebibit #: daemon/HTTPServer.cpp:168 msgid "MiB" msgstr "" +#. tr: Gibibit #: daemon/HTTPServer.cpp:170 msgid "GiB" msgstr "" @@ -94,31 +97,32 @@ msgstr "" msgid "Main page" msgstr "" -#: daemon/HTTPServer.cpp:233 daemon/HTTPServer.cpp:689 +#: daemon/HTTPServer.cpp:233 daemon/HTTPServer.cpp:690 msgid "Router commands" msgstr "" -#: daemon/HTTPServer.cpp:234 -msgid "Local destinations" +#: daemon/HTTPServer.cpp:234 daemon/HTTPServer.cpp:413 +#: daemon/HTTPServer.cpp:425 +msgid "Local Destinations" msgstr "" #: daemon/HTTPServer.cpp:236 daemon/HTTPServer.cpp:388 #: daemon/HTTPServer.cpp:469 daemon/HTTPServer.cpp:475 -#: daemon/HTTPServer.cpp:605 daemon/HTTPServer.cpp:648 -#: daemon/HTTPServer.cpp:652 +#: daemon/HTTPServer.cpp:606 daemon/HTTPServer.cpp:649 +#: daemon/HTTPServer.cpp:653 msgid "LeaseSets" msgstr "" -#: daemon/HTTPServer.cpp:238 daemon/HTTPServer.cpp:658 +#: daemon/HTTPServer.cpp:238 daemon/HTTPServer.cpp:659 msgid "Tunnels" msgstr "" -#: daemon/HTTPServer.cpp:239 daemon/HTTPServer.cpp:746 -#: daemon/HTTPServer.cpp:762 -msgid "Transit tunnels" +#: daemon/HTTPServer.cpp:239 daemon/HTTPServer.cpp:395 +#: daemon/HTTPServer.cpp:753 daemon/HTTPServer.cpp:769 +msgid "Transit Tunnels" msgstr "" -#: daemon/HTTPServer.cpp:240 daemon/HTTPServer.cpp:811 +#: daemon/HTTPServer.cpp:240 daemon/HTTPServer.cpp:818 msgid "Transports" msgstr "" @@ -126,15 +130,15 @@ msgstr "" msgid "I2P tunnels" msgstr "" -#: daemon/HTTPServer.cpp:243 daemon/HTTPServer.cpp:873 -#: daemon/HTTPServer.cpp:883 +#: daemon/HTTPServer.cpp:243 daemon/HTTPServer.cpp:880 +#: daemon/HTTPServer.cpp:890 msgid "SAM sessions" msgstr "" -#: daemon/HTTPServer.cpp:259 daemon/HTTPServer.cpp:1273 -#: daemon/HTTPServer.cpp:1276 daemon/HTTPServer.cpp:1279 -#: daemon/HTTPServer.cpp:1293 daemon/HTTPServer.cpp:1338 -#: daemon/HTTPServer.cpp:1341 daemon/HTTPServer.cpp:1344 +#: daemon/HTTPServer.cpp:259 daemon/HTTPServer.cpp:1280 +#: daemon/HTTPServer.cpp:1283 daemon/HTTPServer.cpp:1286 +#: daemon/HTTPServer.cpp:1300 daemon/HTTPServer.cpp:1345 +#: daemon/HTTPServer.cpp:1348 daemon/HTTPServer.cpp:1351 msgid "ERROR" msgstr "" @@ -156,8 +160,8 @@ msgid "Unknown" msgstr "" #: daemon/HTTPServer.cpp:270 daemon/HTTPServer.cpp:400 -#: daemon/HTTPServer.cpp:401 daemon/HTTPServer.cpp:941 -#: daemon/HTTPServer.cpp:950 +#: daemon/HTTPServer.cpp:401 daemon/HTTPServer.cpp:948 +#: daemon/HTTPServer.cpp:957 msgid "Proxy" msgstr "" @@ -209,6 +213,7 @@ msgstr "" msgid "Received" msgstr "" +#. tr: Kibibit/s #: daemon/HTTPServer.cpp:328 daemon/HTTPServer.cpp:331 #: daemon/HTTPServer.cpp:334 msgid "KiB/s" @@ -262,22 +267,14 @@ msgstr "" msgid "Floodfills" msgstr "" -#: daemon/HTTPServer.cpp:394 daemon/HTTPServer.cpp:927 +#: daemon/HTTPServer.cpp:394 daemon/HTTPServer.cpp:934 msgid "Client Tunnels" msgstr "" -#: daemon/HTTPServer.cpp:395 -msgid "Transit Tunnels" -msgstr "" - #: daemon/HTTPServer.cpp:399 msgid "Services" msgstr "" -#: daemon/HTTPServer.cpp:413 daemon/HTTPServer.cpp:425 -msgid "Local Destinations" -msgstr "" - #: daemon/HTTPServer.cpp:448 msgid "Encrypted B33 address" msgstr "" @@ -312,17 +309,17 @@ msgstr "" msgid "EncType" msgstr "" -#: daemon/HTTPServer.cpp:480 daemon/HTTPServer.cpp:663 +#: daemon/HTTPServer.cpp:480 daemon/HTTPServer.cpp:664 msgid "Inbound tunnels" msgstr "" -#. Milliseconds +#. tr: Milliseconds #: daemon/HTTPServer.cpp:485 daemon/HTTPServer.cpp:495 -#: daemon/HTTPServer.cpp:668 daemon/HTTPServer.cpp:678 +#: daemon/HTTPServer.cpp:669 daemon/HTTPServer.cpp:679 msgid "ms" msgstr "" -#: daemon/HTTPServer.cpp:490 daemon/HTTPServer.cpp:673 +#: daemon/HTTPServer.cpp:490 daemon/HTTPServer.cpp:674 msgid "Outbound tunnels" msgstr "" @@ -358,225 +355,222 @@ msgstr "" msgid "Status" msgstr "" -#: daemon/HTTPServer.cpp:535 daemon/HTTPServer.cpp:590 +#: daemon/HTTPServer.cpp:535 daemon/HTTPServer.cpp:591 msgid "Local Destination" msgstr "" -#: daemon/HTTPServer.cpp:544 daemon/HTTPServer.cpp:906 +#: daemon/HTTPServer.cpp:545 daemon/HTTPServer.cpp:913 msgid "Streams" msgstr "" -#: daemon/HTTPServer.cpp:566 +#: daemon/HTTPServer.cpp:567 msgid "Close stream" msgstr "" -#: daemon/HTTPServer.cpp:595 +#: daemon/HTTPServer.cpp:596 msgid "I2CP session not found" msgstr "" -#: daemon/HTTPServer.cpp:598 +#: daemon/HTTPServer.cpp:599 msgid "I2CP is not enabled" msgstr "" -#: daemon/HTTPServer.cpp:624 +#: daemon/HTTPServer.cpp:625 msgid "Invalid" msgstr "" -#: daemon/HTTPServer.cpp:627 +#: daemon/HTTPServer.cpp:628 msgid "Store type" msgstr "" -#: daemon/HTTPServer.cpp:628 +#: daemon/HTTPServer.cpp:629 msgid "Expires" msgstr "" -#: daemon/HTTPServer.cpp:633 +#: daemon/HTTPServer.cpp:634 msgid "Non Expired Leases" msgstr "" -#: daemon/HTTPServer.cpp:636 +#: daemon/HTTPServer.cpp:637 msgid "Gateway" msgstr "" -#: daemon/HTTPServer.cpp:637 +#: daemon/HTTPServer.cpp:638 msgid "TunnelID" msgstr "" -#: daemon/HTTPServer.cpp:638 +#: daemon/HTTPServer.cpp:639 msgid "EndDate" msgstr "" -#: daemon/HTTPServer.cpp:648 +#: daemon/HTTPServer.cpp:649 msgid "not floodfill" msgstr "" -#: daemon/HTTPServer.cpp:659 +#: daemon/HTTPServer.cpp:660 msgid "Queue size" msgstr "" -#: daemon/HTTPServer.cpp:690 +#: daemon/HTTPServer.cpp:691 msgid "Run peer test" msgstr "" -#: daemon/HTTPServer.cpp:693 +#: daemon/HTTPServer.cpp:698 msgid "Decline transit tunnels" msgstr "" -#: daemon/HTTPServer.cpp:695 +#: daemon/HTTPServer.cpp:700 msgid "Accept transit tunnels" msgstr "" -#: daemon/HTTPServer.cpp:698 daemon/HTTPServer.cpp:703 +#: daemon/HTTPServer.cpp:704 daemon/HTTPServer.cpp:709 msgid "Cancel graceful shutdown" msgstr "" -#: daemon/HTTPServer.cpp:700 daemon/HTTPServer.cpp:705 +#: daemon/HTTPServer.cpp:706 daemon/HTTPServer.cpp:711 msgid "Start graceful shutdown" msgstr "" -#: daemon/HTTPServer.cpp:707 +#: daemon/HTTPServer.cpp:714 msgid "Force shutdown" msgstr "" -#: daemon/HTTPServer.cpp:710 +#: daemon/HTTPServer.cpp:717 msgid "" "Note: any action done here are not persistent and not changes your " "config files." msgstr "" -#: daemon/HTTPServer.cpp:712 +#: daemon/HTTPServer.cpp:719 msgid "Logging level" msgstr "" -#: daemon/HTTPServer.cpp:720 +#: daemon/HTTPServer.cpp:727 msgid "Transit tunnels limit" msgstr "" -#: daemon/HTTPServer.cpp:725 daemon/HTTPServer.cpp:737 +#: daemon/HTTPServer.cpp:732 daemon/HTTPServer.cpp:744 msgid "Change" msgstr "" -#: daemon/HTTPServer.cpp:729 +#: daemon/HTTPServer.cpp:736 msgid "Change language" msgstr "" -#: daemon/HTTPServer.cpp:762 +#: daemon/HTTPServer.cpp:769 msgid "no transit tunnels currently built" msgstr "" -#: daemon/HTTPServer.cpp:867 daemon/HTTPServer.cpp:890 +#: daemon/HTTPServer.cpp:874 daemon/HTTPServer.cpp:897 msgid "SAM disabled" msgstr "" -#: daemon/HTTPServer.cpp:883 +#: daemon/HTTPServer.cpp:890 msgid "no sessions currently running" msgstr "" -#: daemon/HTTPServer.cpp:896 +#: daemon/HTTPServer.cpp:903 msgid "SAM session not found" msgstr "" -#: daemon/HTTPServer.cpp:901 +#: daemon/HTTPServer.cpp:908 msgid "SAM Session" msgstr "" -#: daemon/HTTPServer.cpp:958 +#: daemon/HTTPServer.cpp:965 msgid "Server Tunnels" msgstr "" -#: daemon/HTTPServer.cpp:974 +#: daemon/HTTPServer.cpp:981 msgid "Client Forwards" msgstr "" -#: daemon/HTTPServer.cpp:988 +#: daemon/HTTPServer.cpp:995 msgid "Server Forwards" msgstr "" -#: daemon/HTTPServer.cpp:1194 +#: daemon/HTTPServer.cpp:1201 msgid "Unknown page" msgstr "" -#: daemon/HTTPServer.cpp:1213 +#: daemon/HTTPServer.cpp:1220 msgid "Invalid token" msgstr "" -#: daemon/HTTPServer.cpp:1271 daemon/HTTPServer.cpp:1328 -#: daemon/HTTPServer.cpp:1364 +#: daemon/HTTPServer.cpp:1278 daemon/HTTPServer.cpp:1335 +#: daemon/HTTPServer.cpp:1371 msgid "SUCCESS" msgstr "" -#: daemon/HTTPServer.cpp:1271 +#: daemon/HTTPServer.cpp:1278 msgid "Stream closed" msgstr "" -#: daemon/HTTPServer.cpp:1273 +#: daemon/HTTPServer.cpp:1280 msgid "Stream not found or already was closed" msgstr "" -#: daemon/HTTPServer.cpp:1276 +#: daemon/HTTPServer.cpp:1283 msgid "Destination not found" msgstr "" -#: daemon/HTTPServer.cpp:1279 +#: daemon/HTTPServer.cpp:1286 msgid "StreamID can't be null" msgstr "" -#: daemon/HTTPServer.cpp:1281 daemon/HTTPServer.cpp:1346 +#: daemon/HTTPServer.cpp:1288 daemon/HTTPServer.cpp:1353 msgid "Return to destination page" msgstr "" -#: daemon/HTTPServer.cpp:1282 daemon/HTTPServer.cpp:1295 -msgid "You will be redirected back in 5 seconds" +#: daemon/HTTPServer.cpp:1289 daemon/HTTPServer.cpp:1302 +#: daemon/HTTPServer.cpp:1373 +msgid "You will be redirected in 5 seconds" msgstr "" -#: daemon/HTTPServer.cpp:1293 +#: daemon/HTTPServer.cpp:1300 msgid "Transit tunnels count must not exceed 65535" msgstr "" -#: daemon/HTTPServer.cpp:1294 daemon/HTTPServer.cpp:1365 +#: daemon/HTTPServer.cpp:1301 daemon/HTTPServer.cpp:1372 msgid "Back to commands list" msgstr "" -#: daemon/HTTPServer.cpp:1330 +#: daemon/HTTPServer.cpp:1337 msgid "Register at reg.i2p" msgstr "" -#: daemon/HTTPServer.cpp:1331 +#: daemon/HTTPServer.cpp:1338 msgid "Description" msgstr "" -#: daemon/HTTPServer.cpp:1331 +#: daemon/HTTPServer.cpp:1338 msgid "A bit information about service on domain" msgstr "" -#: daemon/HTTPServer.cpp:1332 +#: daemon/HTTPServer.cpp:1339 msgid "Submit" msgstr "" -#: daemon/HTTPServer.cpp:1338 +#: daemon/HTTPServer.cpp:1345 msgid "Domain can't end with .b32.i2p" msgstr "" -#: daemon/HTTPServer.cpp:1341 +#: daemon/HTTPServer.cpp:1348 msgid "Domain must end with .i2p" msgstr "" -#: daemon/HTTPServer.cpp:1344 +#: daemon/HTTPServer.cpp:1351 msgid "Such destination is not found" msgstr "" -#: daemon/HTTPServer.cpp:1360 +#: daemon/HTTPServer.cpp:1367 msgid "Unknown command" msgstr "" -#: daemon/HTTPServer.cpp:1364 +#: daemon/HTTPServer.cpp:1371 msgid "Command accepted" msgstr "" -#: daemon/HTTPServer.cpp:1366 -msgid "You will be redirected in 5 seconds" -msgstr "" - #: libi2pd_client/HTTPProxy.cpp:157 msgid "Proxy error" msgstr "" @@ -598,7 +592,7 @@ msgid "You may try to find this host on jump services below" msgstr "" #: libi2pd_client/HTTPProxy.cpp:273 libi2pd_client/HTTPProxy.cpp:288 -#: libi2pd_client/HTTPProxy.cpp:365 +#: libi2pd_client/HTTPProxy.cpp:322 libi2pd_client/HTTPProxy.cpp:365 msgid "Invalid request" msgstr "" @@ -643,10 +637,6 @@ msgstr "" msgid "to update record" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:322 -msgid "Invalid Request" -msgstr "" - #: libi2pd_client/HTTPProxy.cpp:322 msgid "invalid request uri" msgstr "" diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 8ed4511f..fd26d8f1 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -163,11 +163,11 @@ namespace http { s << std::fixed << std::setprecision(2); auto numKBytes = (double) bytes / 1024; if (numKBytes < 1024) - s << numKBytes << " " << tr("KiB"); + s << numKBytes << " " << tr(/* tr: Kibibit */ "KiB"); else if (numKBytes < 1024 * 1024) - s << numKBytes / 1024 << " " << tr("MiB"); + s << numKBytes / 1024 << " " << tr(/* tr: Mebibit */ "MiB"); else - s << numKBytes / 1024 / 1024 << " " << tr("GiB"); + s << numKBytes / 1024 / 1024 << " " << tr(/* tr: Gibibit */ "GiB"); } static void ShowTunnelDetails (std::stringstream& s, enum i2p::tunnel::TunnelState eState, bool explr, int bytes) @@ -191,7 +191,7 @@ namespace http { else stateText = tr("unknown"); s << " " << stateText << ((explr) ? " (" + tr("exploratory") + ")" : "") << ", "; - s << " " << (int) (bytes / 1024) << " " << tr("KiB") << "\r\n"; + s << " " << (int) (bytes / 1024) << " " << tr(/* tr: Kibibit */ "KiB") << "\r\n"; } static void SetLogLevel (const std::string& level) @@ -231,12 +231,12 @@ namespace http { "
\r\n" " " << tr("Main page") << "

\r\n" " " << tr("Router commands") << "
\r\n" - " " << tr("Local destinations") << "
\r\n"; + " " << tr("Local Destinations") << "
\r\n"; if (i2p::context.IsFloodfill ()) s << " " << tr("LeaseSets") << "
\r\n"; s << " " << tr("Tunnels") << "
\r\n" - " " << tr("Transit tunnels") << "
\r\n" + " " << tr("Transit Tunnels") << "
\r\n" " " << tr ("Transports") << "
\r\n" " " << tr("I2P tunnels") << "
\r\n"; if (i2p::client::context.GetSAMBridge ()) @@ -325,13 +325,13 @@ namespace http { s << "" << tr("Tunnel creation success rate") << ": " << i2p::tunnel::tunnels.GetTunnelCreationSuccessRate () << "%
\r\n"; s << "" << tr("Received") << ": "; ShowTraffic (s, i2p::transport::transports.GetTotalReceivedBytes ()); - s << " (" << (double) i2p::transport::transports.GetInBandwidth () / 1024 << " " << tr("KiB/s") << ")
\r\n"; + s << " (" << (double) i2p::transport::transports.GetInBandwidth () / 1024 << " " << tr(/* tr: Kibibit/s */ "KiB/s") << ")
\r\n"; s << "" << tr("Sent") << ": "; ShowTraffic (s, i2p::transport::transports.GetTotalSentBytes ()); - s << " (" << (double) i2p::transport::transports.GetOutBandwidth () / 1024 << " " << tr("KiB/s") << ")
\r\n"; + s << " (" << (double) i2p::transport::transports.GetOutBandwidth () / 1024 << " " << tr(/* tr: Kibibit/s */ "KiB/s") << ")
\r\n"; s << "" << tr("Transit") << ": "; ShowTraffic (s, i2p::transport::transports.GetTotalTransitTransmittedBytes ()); - s << " (" << (double) i2p::transport::transports.GetTransitBandwidth () / 1024 << " " << tr("KiB/s") << ")
\r\n"; + s << " (" << (double) i2p::transport::transports.GetTransitBandwidth () / 1024 << " " << tr(/* tr: Kibibit/s */ "KiB/s") << ")
\r\n"; s << "" << tr("Data path") << ": " << i2p::fs::GetUTF8DataDir() << "
\r\n"; s << "
"; if((outputFormat == OutputFormatEnum::forWebConsole) || !includeHiddenContent) { @@ -482,7 +482,7 @@ namespace http { s << "
"; it->Print(s); if(it->LatencyIsKnown()) - s << " ( " << it->GetMeanLatency() << tr(/* Milliseconds */ "ms") << " )"; + s << " ( " << it->GetMeanLatency() << tr(/* tr: Milliseconds */ "ms") << " )"; ShowTunnelDetails(s, it->GetState (), false, it->GetNumReceivedBytes ()); s << "
\r\n"; } @@ -540,7 +540,8 @@ namespace http { if (dest) { ShowLeaseSetDestination (s, dest, token); - // show streams + + // Print table with streams information s << "\r\n\r\n\r\n"; s << ""; s << "
" << tr("Streams") << "
StreamID"; // Stream closing button column @@ -685,14 +686,17 @@ namespace http { static void ShowCommands (std::stringstream& s, uint32_t token) { std::string webroot; i2p::config::GetOption("http.webroot", webroot); - /* commands */ + s << "" << tr("Router commands") << "
\r\n
\r\n
\r\n"; s << " " << tr("Run peer test") << "
\r\n"; - //s << " Reload config
\r\n"; + + // s << " Reload config
\r\n"; + if (i2p::context.AcceptsTunnels ()) s << " " << tr("Decline transit tunnels") << "
\r\n"; else s << " " << tr("Accept transit tunnels") << "
\r\n"; + #if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY)) if (Daemon.gracefulShutdownInterval) s << " " << tr("Cancel graceful shutdown") << "
\r\n"; @@ -704,6 +708,7 @@ namespace http { else s << " " << tr("Start graceful shutdown") << "
\r\n"; #endif + s << " " << tr("Force shutdown") << "\r\n"; s << "
"; @@ -743,7 +748,7 @@ namespace http { { if(i2p::tunnel::tunnels.CountTransitTunnels()) { - s << "" << tr("Transit tunnels") << ":
\r\n
\r\n"; + s << "" << tr("Transit Tunnels") << ":
\r\n
\r\n"; for (const auto& it: i2p::tunnel::tunnels.GetTransitTunnels ()) { s << "
\r\n"; @@ -759,7 +764,7 @@ namespace http { } else { - s << "" << tr("Transit tunnels") << ": " << tr("no transit tunnels currently built") << ".
\r\n"; + s << "" << tr("Transit Tunnels") << ": " << tr("no transit tunnels currently built") << ".
\r\n"; } } @@ -1279,7 +1284,7 @@ namespace http { s << "" << tr("ERROR") << ": " << tr("StreamID can't be null") << "
\r\n
\r\n"; s << "" << tr("Return to destination page") << "
\r\n"; - s << "

" << tr("You will be redirected back in 5 seconds") << ""; + s << "

" << tr("You will be redirected in 5 seconds") << ""; redirect = "5; url=" + webroot + "?page=local_destination&b32=" + b32; res.add_header("Refresh", redirect.c_str()); return; @@ -1292,7 +1297,7 @@ namespace http { else { s << "" << tr("ERROR") << ": " << tr("Transit tunnels count must not exceed 65535") << "\r\n
\r\n
\r\n"; s << "" << tr("Back to commands list") << "\r\n
\r\n"; - s << "

" << tr("You will be redirected back in 5 seconds") << ""; + s << "

" << tr("You will be redirected in 5 seconds") << ""; res.add_header("Refresh", redirect.c_str()); return; } diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index d8b84e82..70cf78a8 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -319,7 +319,7 @@ namespace proxy { auto pos = uri.find(":"); if(pos == std::string::npos || pos == uri.size() - 1) { - GenericProxyError(tr("Invalid Request"), tr("invalid request uri")); + GenericProxyError(tr("Invalid request"), tr("invalid request uri")); return true; } else From 5781335814b1c3766ccaadb66418c715daa88e55 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 29 Jun 2021 19:08:11 -0400 Subject: [PATCH 24/24] save and check last stream --- libi2pd/Streaming.cpp | 21 +++++++++++++++------ libi2pd/Streaming.h | 11 ++++++----- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 612b1058..3269e040 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -1050,6 +1050,7 @@ namespace stream it.second->Terminate (false); // we delete here m_Streams.clear (); m_IncomingStreams.clear (); + m_LastStream = nullptr; } } @@ -1058,9 +1059,16 @@ namespace stream uint32_t sendStreamID = packet->GetSendStreamID (); if (sendStreamID) { - auto it = m_Streams.find (sendStreamID); - if (it != m_Streams.end ()) - it->second->HandleNextPacket (packet); + if (!m_LastStream || sendStreamID != m_LastStream->GetRecvStreamID ()) + { + auto it = m_Streams.find (sendStreamID); + if (it != m_Streams.end ()) + m_LastStream = it->second; + else + m_LastStream = nullptr; + } + if (m_LastStream) + m_LastStream->HandleNextPacket (packet); else if (packet->IsEcho () && m_Owner->IsStreamingAnswerPings ()) { // ping @@ -1166,7 +1174,7 @@ namespace stream { auto s = std::make_shared (m_Owner->GetService (), *this, remote, port); std::unique_lock l(m_StreamsMutex); - m_Streams[s->GetRecvStreamID ()] = s; + m_Streams.emplace (s->GetRecvStreamID (), s); return s; } @@ -1174,8 +1182,8 @@ namespace stream { auto s = std::make_shared (m_Owner->GetService (), *this); std::unique_lock l(m_StreamsMutex); - m_Streams[s->GetRecvStreamID ()] = s; - m_IncomingStreams[receiveStreamID] = s; + m_Streams.emplace (s->GetRecvStreamID (), s); + m_IncomingStreams.emplace (receiveStreamID, s); return s; } @@ -1186,6 +1194,7 @@ namespace stream std::unique_lock l(m_StreamsMutex); m_Streams.erase (stream->GetRecvStreamID ()); m_IncomingStreams.erase (stream->GetSendStreamID ()); + if (m_LastStream == stream) m_LastStream = nullptr; } } diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index fe035136..c40c49f5 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2021, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -11,7 +11,7 @@ #include #include -#include +#include #include #include #include @@ -297,12 +297,13 @@ namespace stream uint16_t m_LocalPort; bool m_Gzip; // gzip compression of data messages std::mutex m_StreamsMutex; - std::map > m_Streams; // sendStreamID->stream - std::map > m_IncomingStreams; // receiveStreamID->stream + std::unordered_map > m_Streams; // sendStreamID->stream + std::unordered_map > m_IncomingStreams; // receiveStreamID->stream + std::shared_ptr m_LastStream; Acceptor m_Acceptor; std::list > m_PendingIncomingStreams; boost::asio::deadline_timer m_PendingIncomingTimer; - std::map > m_SavedPackets; // receiveStreamID->packets, arrived before SYN + std::unordered_map > m_SavedPackets; // receiveStreamID->packets, arrived before SYN i2p::util::MemoryPool m_PacketsPool; i2p::util::MemoryPool > m_I2NPMsgsPool;