From b8590075e6d341e6a9f5882e3eed2201ee08405c Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 16 Feb 2023 22:14:02 -0500 Subject: [PATCH 0001/1171] initial commit for Kademlia DHT --- libi2pd/KadDHT.cpp | 238 +++++++++++++++++++++++++++++++++++++++++++++ libi2pd/KadDHT.h | 64 ++++++++++++ 2 files changed, 302 insertions(+) create mode 100644 libi2pd/KadDHT.cpp create mode 100644 libi2pd/KadDHT.h diff --git a/libi2pd/KadDHT.cpp b/libi2pd/KadDHT.cpp new file mode 100644 index 00000000..29664f79 --- /dev/null +++ b/libi2pd/KadDHT.cpp @@ -0,0 +1,238 @@ +/* +* Copyright (c) 2023, The PurpleI2P Project +* +* This file is part of Purple i2pd project and licensed under BSD3 +* +* See full license text in LICENSE file at top of project tree +* +*/ + +#include "KadDHT.h" + +namespace i2p +{ +namespace data +{ + DHTNode::DHTNode (): + zero (nullptr), one (nullptr), hash (nullptr) + { + } + + DHTNode::~DHTNode () + { + if (zero) delete zero; + if (one) delete one; + if (hash) delete hash; + } + + void DHTNode::MoveHashUp (bool fromOne) + { + DHTNode *& side = fromOne ? one : zero; + if (side) + { + if (hash) delete hash; // shouldn't happen + hash = side->hash; + side->hash = nullptr; + delete side; + side = nullptr; + } + } + + DHTTable::DHTTable (): + m_Size (0) + { + m_Root = new DHTNode; + } + + DHTTable::~DHTTable () + { + delete m_Root; + } + + DHTNode * DHTTable::Insert (const IdentHash& h) + { + return Insert (new IdentHash (h), m_Root, 0); + } + + DHTNode * DHTTable::Insert (IdentHash * h, DHTNode * root, int level) + { + if (root->hash) + { + if (*(root->hash) == *h) + { + delete h; + return root; + } + auto h2 = root->hash; + root->hash = nullptr; m_Size--; + int bit1, bit2; + do + { + bit1 = h->GetBit (level); + bit2 = h2->GetBit (level); + if (bit1 == bit2) + { + if (bit1) + { + if (root->one) return nullptr; // someting wrong + root->one = new DHTNode; + root = root->one; + } + else + { + if (root->zero) return nullptr; // someting wrong + root->zero = new DHTNode; + root = root->zero; + } + level++; + } + } + while (bit1 == bit2); + + if (!root->zero) + root->zero = new DHTNode; + if (!root->one) + root->one = new DHTNode; + if (bit1) + { + Insert (h2, root->zero, level + 1); + return Insert (h, root->one, level + 1); + } + else + { + Insert (h2, root->one, level + 1); + return Insert (h, root->zero, level + 1); + } + } + else + { + if (!root->zero && !root->one) + { + root->hash = h; m_Size++; + return root; + } + int bit = h->GetBit (level); + if (bit) + { + if (!root->one) + root->one = new DHTNode; + return Insert (h, root->one, level + 1); + } + else + { + if (!root->zero) + root->zero = new DHTNode; + return Insert (h, root->zero, level + 1); + } + } + return nullptr; + } + + bool DHTTable::Remove (const IdentHash& h) + { + return Remove (h, m_Root, 0); + } + + bool DHTTable::Remove (const IdentHash& h, DHTNode * root, int level) + { + if (root) + { + if (root->hash && *(root->hash) == h) + { + delete root->hash; root->hash = nullptr; + m_Size--; + return true; + } + int bit = h.GetBit (level); + if (bit) + { + if (root->one && Remove (h, root->one, level + 1)) + { + if (root->one->IsEmpty ()) + { + delete root->one; + root->one = nullptr; + if (root->zero && root->zero->hash) + root->MoveHashUp (false); + } + else if (root->one->hash && !root->zero) + root->MoveHashUp (true); + return true; + } + } + else + { + if (root->zero && Remove (h, root->zero, level + 1)) + { + if (root->zero->IsEmpty ()) + { + delete root->zero; + root->zero = nullptr; + if (root->one && root->one->hash) + root->MoveHashUp (true); + } + else if (root->zero->hash && !root->one) + root->MoveHashUp (false); + return true; + } + } + } + return false; + } + + IdentHash * DHTTable::FindClosest (const IdentHash& h) + { + return FindClosest (h, m_Root, 0); + } + + IdentHash * DHTTable::FindClosest (const IdentHash& h, DHTNode * root, int level) + { + if (root->hash) return root->hash; + int bit = h.GetBit (level); + if (bit) + { + if (root->one) + return FindClosest (h, root->one, level + 1); + if (root->zero) + return FindClosest (h, root->zero, level + 1); + } + else + { + if (root->zero) + return FindClosest (h, root->zero, level + 1); + if (root->one) + return FindClosest (h, root->one, level + 1); + } + return nullptr; + } + + void DHTTable::Print (std::stringstream& s) + { + Print (s, m_Root, 0); + } + + void DHTTable::Print (std::stringstream& s, DHTNode * root, int level) + { + if (!root) return; + s << std::string (level, '-'); + if (root->hash) + { + if (!root->zero && !root->one) + s << '>' << GetIdentHashAbbreviation (*(root->hash)); + else + s << "error"; + } + s << std::endl; + if (root->zero) + { + s << std::string (level, '-') << "0" << std::endl; + Print (s, root->zero, level + 1); + } + if (root->one) + { + s << std::string (level, '-') << "1" << std::endl; + Print (s, root->one, level + 1); + } + } +} +} diff --git a/libi2pd/KadDHT.h b/libi2pd/KadDHT.h new file mode 100644 index 00000000..4a1b61b6 --- /dev/null +++ b/libi2pd/KadDHT.h @@ -0,0 +1,64 @@ +/* +* Copyright (c) 2023, The PurpleI2P Project +* +* This file is part of Purple i2pd project and licensed under BSD3 +* +* See full license text in LICENSE file at top of project tree +* +*/ + +#ifndef KADDHT_H__ +#define KADDHT_H__ + +#include +#include +#include "Identity.h" + +// Kademlia DHT (XOR distance) + +namespace i2p +{ +namespace data +{ + struct DHTNode + { + DHTNode * zero, * one; + IdentHash * hash; + + DHTNode (); + ~DHTNode (); + + bool IsEmpty () const { return !zero && !one && !hash; }; + void MoveHashUp (bool fromOne); + }; + + class DHTTable + { + public: + + DHTTable (); + ~DHTTable (); + + DHTNode * Insert (const IdentHash& h); + bool Remove (const IdentHash& h); + IdentHash * FindClosest (const IdentHash& h); + + void Print (std::stringstream& s); + size_t GetSize () const { return m_Size; }; + + private: + + DHTNode * Insert (IdentHash * h, DHTNode * root, int level); // recursive + bool Remove (const IdentHash& h, DHTNode * root, int level); + IdentHash * FindClosest (const IdentHash& h, DHTNode * root, int level); + void Print (std::stringstream& s, DHTNode * root, int level); + + private: + + DHTNode * m_Root; + size_t m_Size; + }; +} +} + +#endif From bff12b06f417938168951ac7df429d61ebaf462d Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 17 Feb 2023 10:34:14 -0500 Subject: [PATCH 0002/1171] fixed race condition --- libi2pd/RouterInfo.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index afa8cbe0..f33e4198 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -945,9 +945,13 @@ namespace data std::shared_ptr RouterInfo::GetProfile () const { - if (!m_Profile) - m_Profile = GetRouterProfile (GetIdentHash ()); - return m_Profile; + auto profile = m_Profile; + if (!profile) + { + profile = GetRouterProfile (GetIdentHash ()); + m_Profile = profile; + } + return profile; } void RouterInfo::Encrypt (const uint8_t * data, uint8_t * encrypted) const From 289c3086003eaf624e1e42bcbe0bc0901f015bb7 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 17 Feb 2023 20:08:05 -0500 Subject: [PATCH 0003/1171] set proper caps if host is unspecified --- libi2pd/RouterInfo.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index f33e4198..3fb95814 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -661,11 +661,16 @@ namespace data addr->host = host; addr->port = port; addr->transportStyle = eTransportNTCP2; - addr->caps = 0; addr->date = 0; addr->published = true; memcpy (addr->s, staticKey, 32); memcpy (addr->i, iv, 16); + addr->caps = 0; + if (host.is_unspecified ()) + { + if (host.is_v4 ()) addr->caps |= eV4; + if (host.is_v6 ()) addr->caps |= eV6; + } if (addr->IsV4 ()) { m_SupportedTransports |= eNTCP2V4; @@ -737,12 +742,19 @@ namespace data addr->host = host; addr->port = port; addr->published = true; - addr->caps = i2p::data::RouterInfo::eSSUTesting | i2p::data::RouterInfo::eSSUIntroducer; // BC; addr->date = 0; addr->ssu.reset (new SSUExt ()); addr->ssu->mtu = 0; memcpy (addr->s, staticKey, 32); memcpy (addr->i, introKey, 32); + if (!host.is_unspecified ()) + addr->caps = i2p::data::RouterInfo::eSSUTesting | i2p::data::RouterInfo::eSSUIntroducer; // BC; + else + { + addr->caps = 0; + if (host.is_v4 ()) addr->caps |= eV4; + if (host.is_v6 ()) addr->caps |= eV6; + } if (addr->IsV4 ()) { m_SupportedTransports |= eSSU2V4; From e190dab7d69d48ee0bfcc9358fd8489bb81e021a Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 17 Feb 2023 21:13:50 -0500 Subject: [PATCH 0004/1171] fixed crash when shows leasesets --- daemon/HTTPServer.cpp | 5 ++++- libi2pd/LeaseSet.cpp | 4 ++-- libi2pd/LeaseSet.h | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index f78057b3..e42efb36 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -625,7 +625,10 @@ namespace http { if (storeType == i2p::data::NETDB_STORE_TYPE_LEASESET) ls.reset (new i2p::data::LeaseSet (leaseSet->GetBuffer(), leaseSet->GetBufferLen())); else - ls.reset (new i2p::data::LeaseSet2 (storeType, leaseSet->GetBuffer(), leaseSet->GetBufferLen())); + { + ls.reset (new i2p::data::LeaseSet2 (storeType)); + ls->Update (leaseSet->GetBuffer(), leaseSet->GetBufferLen(), false); + } if (!ls) return; s << "
IsExpired()) diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index d23fdcb8..8ccfa771 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -315,7 +315,7 @@ namespace data { // standard LS2 header std::shared_ptr identity; - if (readIdentity) + if (readIdentity || !GetIdentity ()) { identity = std::make_shared(buf, len); SetIdentity (identity); diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index a79a5870..566c4655 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2021, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -145,6 +145,7 @@ namespace data { public: + LeaseSet2 (uint8_t storeType): LeaseSet (true), m_StoreType (storeType) {}; // for update LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases = true, CryptoKeyType preferredCrypto = CRYPTO_KEY_TYPE_ELGAMAL); LeaseSet2 (const uint8_t * buf, size_t len, std::shared_ptr key, const uint8_t * secret = nullptr, CryptoKeyType preferredCrypto = CRYPTO_KEY_TYPE_ELGAMAL); // store type 5, called from local netdb only uint8_t GetStoreType () const { return m_StoreType; }; From ce05cce33131be6fcf7f317412bedd7a2d77cb35 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 18 Feb 2023 08:54:36 -0500 Subject: [PATCH 0005/1171] validate LeaseSet if signature verification was not requested --- libi2pd/LeaseSet.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index 8ccfa771..4d756bdb 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -366,6 +366,8 @@ namespace data VerifySignature (identity, buf, len, offset); SetIsValid (verified); } + else + SetIsValid (true); offset += m_TransientVerifier ? m_TransientVerifier->GetSignatureLen () : identity->GetSignatureLen (); if (offset > len) { LogPrint (eLogWarning, "LeaseSet2: short buffer: wanted ", int(offset), "bytes, have ", int(len)); From eaca435a5bd65e40bc0415a7b227bef4fda56fa7 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 18 Feb 2023 19:45:31 -0500 Subject: [PATCH 0006/1171] find multiple closest hashes --- libi2pd/KadDHT.cpp | 33 +++++++++++++++++++++++++++++++++ libi2pd/KadDHT.h | 3 +++ 2 files changed, 36 insertions(+) diff --git a/libi2pd/KadDHT.cpp b/libi2pd/KadDHT.cpp index 29664f79..c3905b7a 100644 --- a/libi2pd/KadDHT.cpp +++ b/libi2pd/KadDHT.cpp @@ -205,6 +205,39 @@ namespace data } return nullptr; } + + std::vector DHTTable::FindClosest (const IdentHash& h, size_t num) + { + std::vector vec; + if (num > 0) + FindClosest (h, num, m_Root, 0, vec); + return vec; + } + + void DHTTable::FindClosest (const IdentHash& h, size_t num, DHTNode * root, int level, std::vector& hashes) + { + if (hashes.size () >= num) return; + if (root->hash) + { + hashes.push_back (root->hash); + return; + } + int bit = h.GetBit (level); + if (bit) + { + if (root->one) + FindClosest (h, num, root->one, level + 1, hashes); + if (hashes.size () < num && root->zero) + FindClosest (h, num, root->zero, level + 1, hashes); + } + else + { + if (root->zero) + FindClosest (h, num, root->zero, level + 1, hashes); + if (hashes.size () < num && root->one) + FindClosest (h, num, root->one, level + 1, hashes); + } + } void DHTTable::Print (std::stringstream& s) { diff --git a/libi2pd/KadDHT.h b/libi2pd/KadDHT.h index 4a1b61b6..eb12aae7 100644 --- a/libi2pd/KadDHT.h +++ b/libi2pd/KadDHT.h @@ -11,6 +11,7 @@ #define KADDHT_H__ #include +#include #include #include "Identity.h" @@ -42,6 +43,7 @@ namespace data DHTNode * Insert (const IdentHash& h); bool Remove (const IdentHash& h); IdentHash * FindClosest (const IdentHash& h); + std::vector FindClosest (const IdentHash& h, size_t num); void Print (std::stringstream& s); size_t GetSize () const { return m_Size; }; @@ -51,6 +53,7 @@ namespace data DHTNode * Insert (IdentHash * h, DHTNode * root, int level); // recursive bool Remove (const IdentHash& h, DHTNode * root, int level); IdentHash * FindClosest (const IdentHash& h, DHTNode * root, int level); + void FindClosest (const IdentHash& h, size_t num, DHTNode * root, int level, std::vector& hashes); void Print (std::stringstream& s, DHTNode * root, int level); private: From b8a99878b67e93d642a11108a290fe49b10c06cc Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 19 Feb 2023 10:30:07 -0500 Subject: [PATCH 0007/1171] don't create profile for every new non-floodfill --- libi2pd/NetDb.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 34ad5efc..5bc9c47e 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -315,7 +315,7 @@ namespace data else { r = std::make_shared (buf, len); - if (!r->IsUnreachable () && r->HasValidAddresses () && !r->GetProfile ()->IsUnreachable () && + if (!r->IsUnreachable () && r->HasValidAddresses () && (!r->IsFloodfill () || !r->GetProfile ()->IsUnreachable ()) && i2p::util::GetMillisecondsSinceEpoch () + NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL > r->GetTimestamp ()) { bool inserted = false; @@ -1398,7 +1398,7 @@ namespace data std::unique_lock l(m_FloodfillsMutex); for (const auto& it: m_Floodfills) { - if (!it->IsUnreachable ()) + if (!it->IsUnreachable () && !it->GetProfile ()->IsUnreachable ()) { XORMetric m = destKey ^ it->GetIdentHash (); if (closeThanUsOnly && ourMetric < m) continue; From 82ac0aa492f400dfd5a2071c97b8d85e5db010e3 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 20 Feb 2023 05:49:59 +0300 Subject: [PATCH 0008/1171] 2.46.1 Signed-off-by: R4SAS --- ChangeLog | 6 ++++++ contrib/i2pd.conf | 3 ++- contrib/rpm/i2pd-git.spec | 5 ++++- contrib/rpm/i2pd.spec | 5 ++++- debian/changelog | 6 ++++++ libi2pd/version.h | 2 +- 6 files changed, 23 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1ef24b13..a361e198 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,12 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog +## [2.46.1] - 2023-02-20 +### Fixed +- Race condition while getting router's peer profile +- Creation of new router.info +- Displaying floodfills in the webconsole + ## [2.46.0] - 2023-02-15 ### Added - Limit number of acked SSU2 packets to 511 diff --git a/contrib/i2pd.conf b/contrib/i2pd.conf index c8baa046..84d00347 100644 --- a/contrib/i2pd.conf +++ b/contrib/i2pd.conf @@ -129,7 +129,8 @@ port = 7070 # pass = changeme ## Select webconsole language ## Currently supported english (default), afrikaans, armenian, chinese, czech, french, -## german, italian, russian, spanish, turkmen, ukrainian and uzbek languages +## german, italian, polish, portuguese, russian, spanish, turkish, turkmen, ukrainian +## and uzbek languages # lang = english [httpproxy] diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index e902d1fd..e758d42b 100644 --- a/contrib/rpm/i2pd-git.spec +++ b/contrib/rpm/i2pd-git.spec @@ -1,7 +1,7 @@ %define git_hash %(git rev-parse HEAD | cut -c -7) Name: i2pd-git -Version: 2.46.0 +Version: 2.46.1 Release: git%{git_hash}%{?dist} Summary: I2P router written in C++ Conflicts: i2pd @@ -158,6 +158,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Mon Feb 20 2023 r4sas - 2.46.1 +- update to 2.46.1 + * Wed Feb 15 2023 orignal - 2.46.0 - update to 2.46.0 diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 5ddd8727..6f413e52 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,5 +1,5 @@ Name: i2pd -Version: 2.46.0 +Version: 2.46.1 Release: 1%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git @@ -155,6 +155,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Mon Feb 20 2023 r4sas - 2.46.1 +- update to 2.46.1 + * Wed Feb 15 2023 orignal - 2.46.0 - update to 2.46.0 diff --git a/debian/changelog b/debian/changelog index 91d8f1dc..f13587c6 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i2pd (2.46.1-1) unstable; urgency=high + + * updated to version 2.46.1/0.9.57 + + -- r4sas Mon, 20 Feb 2023 02:45:00 +0000 + i2pd (2.46.0-1) unstable; urgency=high * updated to version 2.46.0/0.9.57 diff --git a/libi2pd/version.h b/libi2pd/version.h index e1206d21..b7de21a8 100644 --- a/libi2pd/version.h +++ b/libi2pd/version.h @@ -17,7 +17,7 @@ #define I2PD_VERSION_MAJOR 2 #define I2PD_VERSION_MINOR 46 -#define I2PD_VERSION_MICRO 0 +#define I2PD_VERSION_MICRO 1 #define I2PD_VERSION_PATCH 0 #ifdef GITVER #define I2PD_VERSION GITVER From 200ad5524de253b3739edcedfdc9364fc9070dbe Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 20 Feb 2023 02:57:56 +0000 Subject: [PATCH 0009/1171] 2.46.1 Signed-off-by: R4SAS --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index a361e198..870f2cc9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,7 +5,7 @@ ### Fixed - Race condition while getting router's peer profile - Creation of new router.info -- Displaying floodfills in the webconsole +- Displaying LeaseSets in the webconsole ## [2.46.0] - 2023-02-15 ### Added From 3adff82d4a3ee40f854615d850955e7ce3f6f091 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 20 Feb 2023 14:55:59 -0500 Subject: [PATCH 0010/1171] don't handle ack request for router --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index e240e925..7f9fb72d 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2021, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -335,7 +335,8 @@ namespace garlic case eECIESx25519BlkAckRequest: { LogPrint (eLogDebug, "Garlic: Ack request"); - m_AckRequests.push_back ({receiveTagset->GetTagSetID (), index}); + if (receiveTagset) + m_AckRequests.push_back ({receiveTagset->GetTagSetID (), index}); break; } case eECIESx25519BlkTermination: From ebee6c5f1353f71ce3d325f08c29d07783cdc44d Mon Sep 17 00:00:00 2001 From: R4SAS Date: Tue, 21 Feb 2023 05:53:51 +0300 Subject: [PATCH 0011/1171] 2.46.1-1 Signed-off-by: R4SAS --- ChangeLog | 1 + contrib/rpm/i2pd.spec | 2 +- debian/changelog | 6 ++++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 870f2cc9..385a3545 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,6 +6,7 @@ - Race condition while getting router's peer profile - Creation of new router.info - Displaying LeaseSets in the webconsole +- Crash when processing ACK request ## [2.46.0] - 2023-02-15 ### Added diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 6f413e52..32154a9c 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,6 +1,6 @@ Name: i2pd Version: 2.46.1 -Release: 1%{?dist} +Release: 2%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git diff --git a/debian/changelog b/debian/changelog index f13587c6..13691601 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i2pd (2.46.1-2) unstable; urgency=critical + + * re-pushed release due to new critical bug + + -- r4sas Mon, 20 Feb 2023 23:40:00 +0000 + i2pd (2.46.1-1) unstable; urgency=high * updated to version 2.46.1/0.9.57 From be2629aa5a1a98b64948a24c46d1016d99ef8cd7 Mon Sep 17 00:00:00 2001 From: Vort Date: Tue, 21 Feb 2023 11:14:53 +0200 Subject: [PATCH 0012/1171] Remove extra null characters from webconsole output --- i18n/I18N.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/i18n/I18N.h b/i18n/I18N.h index 395c18eb..6ec5b16e 100644 --- a/i18n/I18N.h +++ b/i18n/I18N.h @@ -95,9 +95,8 @@ std::string tr (TValue&& arg, TArgs&&... args) std::string tr_str = i2p::i18n::translate(std::forward(arg)); size_t size = std::snprintf(NULL, 0, tr_str.c_str(), std::forward(args)...); - size = size + 1; std::string str(size, 0); - std::snprintf(&str.front(), size, tr_str.c_str(), std::forward(args)...); + std::snprintf(&str.front(), size + 1, tr_str.c_str(), std::forward(args)...); return str; } @@ -127,9 +126,8 @@ std::string ntr (TValue&& arg, TValue2&& arg2, int& n, TArgs&&... args) std::string tr_str = i2p::i18n::translate(std::forward(arg), std::forward(arg2), std::forward(n)); size_t size = std::snprintf(NULL, 0, tr_str.c_str(), std::forward(args)...); - size = size + 1; std::string str(size, 0); - std::snprintf(&str.front(), size, tr_str.c_str(), std::forward(args)...); + std::snprintf(&str.front(), size + 1, tr_str.c_str(), std::forward(args)...); return str; } From abf687ff095671a52b45832e90613d4ec38840e2 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 21 Feb 2023 19:08:12 -0500 Subject: [PATCH 0013/1171] store RouterInfo in DHT --- libi2pd/KadDHT.cpp | 213 +++++++++++++++++++++++++++++++++------------ libi2pd/KadDHT.h | 27 +++--- libi2pd/NetDb.cpp | 7 +- libi2pd/NetDb.hpp | 2 +- 4 files changed, 177 insertions(+), 72 deletions(-) diff --git a/libi2pd/KadDHT.cpp b/libi2pd/KadDHT.cpp index c3905b7a..48486675 100644 --- a/libi2pd/KadDHT.cpp +++ b/libi2pd/KadDHT.cpp @@ -14,7 +14,7 @@ namespace i2p namespace data { DHTNode::DHTNode (): - zero (nullptr), one (nullptr), hash (nullptr) + zero (nullptr), one (nullptr) { } @@ -22,17 +22,16 @@ namespace data { if (zero) delete zero; if (one) delete one; - if (hash) delete hash; } - void DHTNode::MoveHashUp (bool fromOne) + void DHTNode::MoveRouterUp (bool fromOne) { DHTNode *& side = fromOne ? one : zero; if (side) { - if (hash) delete hash; // shouldn't happen - hash = side->hash; - side->hash = nullptr; + if (router) router = nullptr; // shouldn't happen + router = side->router; + side->router = nullptr; delete side; side = nullptr; } @@ -49,38 +48,46 @@ namespace data delete m_Root; } - DHTNode * DHTTable::Insert (const IdentHash& h) + void DHTTable::Clear () { - return Insert (new IdentHash (h), m_Root, 0); + m_Size = 0; + delete m_Root; + m_Root = new DHTNode; + } + + void DHTTable::Insert (const std::shared_ptr& r) + { + if (!r) return; + return Insert (r, m_Root, 0); } - DHTNode * DHTTable::Insert (IdentHash * h, DHTNode * root, int level) + void DHTTable::Insert (const std::shared_ptr& r, DHTNode * root, int level) { - if (root->hash) + if (root->router) { - if (*(root->hash) == *h) + if (root->router->GetIdentHash () == r->GetIdentHash ()) { - delete h; - return root; + root->router = r; // replace + return; } - auto h2 = root->hash; - root->hash = nullptr; m_Size--; + auto r2 = root->router; + root->router = nullptr; m_Size--; int bit1, bit2; do { - bit1 = h->GetBit (level); - bit2 = h2->GetBit (level); + bit1 = r->GetIdentHash ().GetBit (level); + bit2 = r2->GetIdentHash ().GetBit (level); if (bit1 == bit2) { if (bit1) { - if (root->one) return nullptr; // someting wrong + if (root->one) return; // someting wrong root->one = new DHTNode; root = root->one; } else { - if (root->zero) return nullptr; // someting wrong + if (root->zero) return; // someting wrong root->zero = new DHTNode; root = root->zero; } @@ -95,37 +102,36 @@ namespace data root->one = new DHTNode; if (bit1) { - Insert (h2, root->zero, level + 1); - return Insert (h, root->one, level + 1); + Insert (r2, root->zero, level + 1); + Insert (r, root->one, level + 1); } else { - Insert (h2, root->one, level + 1); - return Insert (h, root->zero, level + 1); + Insert (r2, root->one, level + 1); + Insert (r, root->zero, level + 1); } } else { if (!root->zero && !root->one) { - root->hash = h; m_Size++; - return root; + root->router = r; m_Size++; + return; } - int bit = h->GetBit (level); + int bit = r->GetIdentHash ().GetBit (level); if (bit) { if (!root->one) root->one = new DHTNode; - return Insert (h, root->one, level + 1); + Insert (r, root->one, level + 1); } else { if (!root->zero) root->zero = new DHTNode; - return Insert (h, root->zero, level + 1); + Insert (r, root->zero, level + 1); } } - return nullptr; } bool DHTTable::Remove (const IdentHash& h) @@ -137,9 +143,9 @@ namespace data { if (root) { - if (root->hash && *(root->hash) == h) + if (root->router && root->router->GetIdentHash () == h) { - delete root->hash; root->hash = nullptr; + root->router = nullptr; m_Size--; return true; } @@ -152,11 +158,11 @@ namespace data { delete root->one; root->one = nullptr; - if (root->zero && root->zero->hash) - root->MoveHashUp (false); + if (root->zero && root->zero->router) + root->MoveRouterUp (false); } - else if (root->one->hash && !root->zero) - root->MoveHashUp (true); + else if (root->one->router && !root->zero) + root->MoveRouterUp (true); return true; } } @@ -168,11 +174,11 @@ namespace data { delete root->zero; root->zero = nullptr; - if (root->one && root->one->hash) - root->MoveHashUp (true); + if (root->one && root->one->router) + root->MoveRouterUp (true); } - else if (root->zero->hash && !root->one) - root->MoveHashUp (false); + else if (root->zero->router && !root->one) + root->MoveRouterUp (false); return true; } } @@ -180,48 +186,95 @@ namespace data return false; } - IdentHash * DHTTable::FindClosest (const IdentHash& h) + std::shared_ptr DHTTable::FindClosest (const IdentHash& h, const Filter& filter) { - return FindClosest (h, m_Root, 0); + if (filter) m_Filter = filter; + auto r = FindClosest (h, m_Root, 0); + m_Filter = nullptr; + return r; } - IdentHash * DHTTable::FindClosest (const IdentHash& h, DHTNode * root, int level) + std::shared_ptr DHTTable::FindClosest (const IdentHash& h, DHTNode * root, int level) { - if (root->hash) return root->hash; + bool split = false; + do + { + if (root->router) + return (!m_Filter || m_Filter (root->router)) ? root->router : nullptr; + split = root->zero && root->one; + if (!split) + { + if (root->zero) root = root->zero; + else if (root->one) root = root->one; + else return nullptr; + level++; + } + } + while (!split); int bit = h.GetBit (level); if (bit) { if (root->one) - return FindClosest (h, root->one, level + 1); + { + auto r = FindClosest (h, root->one, level + 1); + if (r) return r; + } if (root->zero) - return FindClosest (h, root->zero, level + 1); + { + auto r = FindClosest (h, root->zero, level + 1); + if (r) return r; + } } else { if (root->zero) - return FindClosest (h, root->zero, level + 1); + { + auto r = FindClosest (h, root->zero, level + 1); + if (r) return r; + } if (root->one) - return FindClosest (h, root->one, level + 1); + { + auto r = FindClosest (h, root->one, level + 1); + if (r) return r; + } } return nullptr; } - std::vector DHTTable::FindClosest (const IdentHash& h, size_t num) + std::vector > DHTTable::FindClosest (const IdentHash& h, size_t num, const Filter& filter) { - std::vector vec; + std::vector > vec; if (num > 0) + { + if (filter) m_Filter = filter; FindClosest (h, num, m_Root, 0, vec); + m_Filter = nullptr; + } return vec; } - void DHTTable::FindClosest (const IdentHash& h, size_t num, DHTNode * root, int level, std::vector& hashes) + void DHTTable::FindClosest (const IdentHash& h, size_t num, DHTNode * root, int level, std::vector >& hashes) { if (hashes.size () >= num) return; - if (root->hash) + bool split = false; + do { - hashes.push_back (root->hash); - return; - } + if (root->router) + { + if (!m_Filter || m_Filter (root->router)) + hashes.push_back (root->router); + return; + } + split = root->zero && root->one; + if (!split) + { + if (root->zero) root = root->zero; + else if (root->one) root = root->one; + else return; + level++; + } + } + while (!split); int bit = h.GetBit (level); if (bit) { @@ -238,6 +291,54 @@ namespace data FindClosest (h, num, root->one, level + 1, hashes); } } + + void DHTTable::Cleanup (Filter filter) + { + if (filter) + { + m_Filter = filter; + Cleanup (m_Root); + m_Filter = nullptr; + } + else + Clear (); + } + + void DHTTable::Cleanup (DHTNode * root) + { + if (!root) return; + if (root->router) + { + if (!m_Filter || !m_Filter (root->router)) + { + m_Size--; + root->router = nullptr; + } + return; + } + if (root->zero) + { + Cleanup (root->zero); + if (root->zero->IsEmpty ()) + { + delete root->zero; + root->zero = nullptr; + } + } + if (root->one) + { + Cleanup (root->one); + if (root->one->IsEmpty ()) + { + delete root->one; + root->one = nullptr; + if (root->zero && root->zero->router) + root->MoveRouterUp (false); + } + else if (root->one->router && !root->zero) + root->MoveRouterUp (true); + } + } void DHTTable::Print (std::stringstream& s) { @@ -248,10 +349,10 @@ namespace data { if (!root) return; s << std::string (level, '-'); - if (root->hash) + if (root->router) { if (!root->zero && !root->one) - s << '>' << GetIdentHashAbbreviation (*(root->hash)); + s << '>' << GetIdentHashAbbreviation (root->router->GetIdentHash ()); else s << "error"; } diff --git a/libi2pd/KadDHT.h b/libi2pd/KadDHT.h index eb12aae7..c280a1de 100644 --- a/libi2pd/KadDHT.h +++ b/libi2pd/KadDHT.h @@ -13,7 +13,8 @@ #include #include #include -#include "Identity.h" +#include +#include "RouterInfo.h" // Kademlia DHT (XOR distance) @@ -24,42 +25,48 @@ namespace data struct DHTNode { DHTNode * zero, * one; - IdentHash * hash; + std::shared_ptr router; DHTNode (); ~DHTNode (); - bool IsEmpty () const { return !zero && !one && !hash; }; - void MoveHashUp (bool fromOne); + bool IsEmpty () const { return !zero && !one && !router; }; + void MoveRouterUp (bool fromOne); }; class DHTTable { + typedef std::function&)> Filter; public: DHTTable (); ~DHTTable (); - DHTNode * Insert (const IdentHash& h); + void Insert (const std::shared_ptr& r); bool Remove (const IdentHash& h); - IdentHash * FindClosest (const IdentHash& h); - std::vector FindClosest (const IdentHash& h, size_t num); + std::shared_ptr FindClosest (const IdentHash& h, const Filter& filter = nullptr); + std::vector > FindClosest (const IdentHash& h, size_t num, const Filter& filter = nullptr); void Print (std::stringstream& s); size_t GetSize () const { return m_Size; }; + void Clear (); + void Cleanup (Filter filter); private: - DHTNode * Insert (IdentHash * h, DHTNode * root, int level); // recursive + void Insert (const std::shared_ptr& r, DHTNode * root, int level); // recursive bool Remove (const IdentHash& h, DHTNode * root, int level); - IdentHash * FindClosest (const IdentHash& h, DHTNode * root, int level); - void FindClosest (const IdentHash& h, size_t num, DHTNode * root, int level, std::vector& hashes); + std::shared_ptr FindClosest (const IdentHash& h, DHTNode * root, int level); + void FindClosest (const IdentHash& h, size_t num, DHTNode * root, int level, std::vector >& hashes); + void Cleanup (DHTNode * root); void Print (std::stringstream& s, DHTNode * root, int level); private: DHTNode * m_Root; size_t m_Size; + // transient + Filter m_Filter; }; } } diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 5bc9c47e..685189ed 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -1355,15 +1355,12 @@ namespace data } std::shared_ptr NetDb::GetClosestFloodfill (const IdentHash& destination, - const std::set& excluded, bool closeThanUsOnly) const + const std::set& excluded) const { std::shared_ptr r; XORMetric minMetric; IdentHash destKey = CreateRoutingKey (destination); - if (closeThanUsOnly) - minMetric = destKey ^ i2p::context.GetIdentHash (); - else - minMetric.SetMax (); + minMetric.SetMax (); std::unique_lock l(m_FloodfillsMutex); for (const auto& it: m_Floodfills) { diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index f0315582..192d2644 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -93,7 +93,7 @@ namespace data std::shared_ptr GetHighBandwidthRandomRouter (std::shared_ptr compatibleWith, bool reverse) const; std::shared_ptr GetRandomSSU2PeerTestRouter (bool v4, const std::set& excluded) const; std::shared_ptr GetRandomSSU2Introducer (bool v4, const std::set& excluded) const; - std::shared_ptr GetClosestFloodfill (const IdentHash& destination, const std::set& excluded, bool closeThanUsOnly = false) const; + std::shared_ptr GetClosestFloodfill (const IdentHash& destination, const std::set& excluded) const; std::vector GetClosestFloodfills (const IdentHash& destination, size_t num, std::set& excluded, bool closeThanUsOnly = false) const; std::shared_ptr GetClosestNonFloodfill (const IdentHash& destination, const std::set& excluded) const; From 85442831105dac2a879116c4f66b0224b3951dd6 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 21 Feb 2023 21:33:30 -0500 Subject: [PATCH 0014/1171] don't expire connected routers --- libi2pd/NetDb.cpp | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 685189ed..11cf8066 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -664,21 +664,26 @@ namespace data if (it.second->IsUnreachable () && (total - deletedCount < NETDB_MIN_ROUTERS || isLowRate || (it.second->IsFloodfill () && totalFloodfills - deletedFloodfillsCount < NETDB_MIN_FLOODFILLS))) it.second->SetUnreachable (false); - // find & mark expired routers - if (!it.second->IsReachable () && (it.second->GetCompatibleTransports (true) & RouterInfo::eSSU2V4)) - // non-reachable router, but reachable by ipv4 SSU2 means introducers - { - if (ts > it.second->GetTimestamp () + NETDB_INTRODUCEE_EXPIRATION_TIMEOUT*1000LL) - // RouterInfo expires after 1 hour if uses introducer + if (!it.second->IsUnreachable ()) + { + // find & mark expired routers + if (!it.second->IsReachable () && (it.second->GetCompatibleTransports (true) & RouterInfo::eSSU2V4)) + // non-reachable router, but reachable by ipv4 SSU2 means introducers + { + if (ts > it.second->GetTimestamp () + NETDB_INTRODUCEE_EXPIRATION_TIMEOUT*1000LL) + // RouterInfo expires after 1 hour if uses introducer + it.second->SetUnreachable (true); + } + else if (checkForExpiration && ts > it.second->GetTimestamp () + expirationTimeout) it.second->SetUnreachable (true); - } - else if (checkForExpiration && ts > it.second->GetTimestamp () + expirationTimeout) - it.second->SetUnreachable (true); - else if (ts + NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < it.second->GetTimestamp ()) - { - LogPrint (eLogWarning, "NetDb: RouterInfo is from future for ", (it.second->GetTimestamp () - ts)/1000LL, " seconds"); - it.second->SetUnreachable (true); - } + else if (ts + NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < it.second->GetTimestamp ()) + { + LogPrint (eLogWarning, "NetDb: RouterInfo is from future for ", (it.second->GetTimestamp () - ts)/1000LL, " seconds"); + it.second->SetUnreachable (true); + } + if (it.second->IsUnreachable () && i2p::transport::transports.IsConnected (it.second->GetIdentHash ())) + it.second->SetUnreachable (false); // don't expire connected router + } if (it.second->IsUnreachable ()) { From 95cc544c92a0d941fdcad62fb730b04280d3431e Mon Sep 17 00:00:00 2001 From: Vort Date: Wed, 22 Feb 2023 19:31:24 +0200 Subject: [PATCH 0015/1171] Check for null pointer before dereferencing it --- libi2pd/NTCP2.cpp | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 813ea6d5..eaa186f8 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1457,7 +1457,7 @@ namespace transport void NTCP2Server::HandleAccept (std::shared_ptr conn, const boost::system::error_code& error) { - if (!error) + if (!error && conn) { boost::system::error_code ec; auto ep = conn->GetSocket ().remote_endpoint(ec); @@ -1466,17 +1466,14 @@ namespace transport LogPrint (eLogDebug, "NTCP2: Connected from ", ep); if (!i2p::util::net::IsInReservedRange(ep.address ())) { - if (conn) + if (m_PendingIncomingSessions.emplace (ep.address (), conn).second) { - if (m_PendingIncomingSessions.emplace (ep.address (), conn).second) - { - conn->SetRemoteEndpoint (ep); - conn->ServerLogin (); - conn = nullptr; - } - else - LogPrint (eLogInfo, "NTCP2: Incoming session from ", ep.address (), " is already pending"); + conn->SetRemoteEndpoint (ep); + conn->ServerLogin (); + conn = nullptr; } + else + LogPrint (eLogInfo, "NTCP2: Incoming session from ", ep.address (), " is already pending"); } else LogPrint (eLogError, "NTCP2: Incoming connection from invalid IP ", ep.address ()); @@ -1507,7 +1504,7 @@ namespace transport void NTCP2Server::HandleAcceptV6 (std::shared_ptr conn, const boost::system::error_code& error) { - if (!error) + if (!error && conn) { boost::system::error_code ec; auto ep = conn->GetSocket ().remote_endpoint(ec); @@ -1517,17 +1514,14 @@ namespace transport if (!i2p::util::net::IsInReservedRange(ep.address ()) || i2p::util::net::IsYggdrasilAddress (ep.address ())) { - if (conn) + if (m_PendingIncomingSessions.emplace (ep.address (), conn).second) { - if (m_PendingIncomingSessions.emplace (ep.address (), conn).second) - { - conn->SetRemoteEndpoint (ep); - conn->ServerLogin (); - conn = nullptr; - } - else - LogPrint (eLogInfo, "NTCP2: Incoming session from ", ep.address (), " is already pending"); + conn->SetRemoteEndpoint (ep); + conn->ServerLogin (); + conn = nullptr; } + else + LogPrint (eLogInfo, "NTCP2: Incoming session from ", ep.address (), " is already pending"); } else LogPrint (eLogError, "NTCP2: Incoming connection from invalid IP ", ep.address ()); From d40cd00cdb01ae3080f49bad2ef151fe474e6051 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 22 Feb 2023 15:58:20 -0500 Subject: [PATCH 0016/1171] use DHT table for floodfills --- libi2pd/KadDHT.cpp | 10 ++--- libi2pd/KadDHT.h | 12 ++--- libi2pd/NetDb.cpp | 108 +++++++++++++++------------------------------ libi2pd/NetDb.hpp | 6 +-- 4 files changed, 49 insertions(+), 87 deletions(-) diff --git a/libi2pd/KadDHT.cpp b/libi2pd/KadDHT.cpp index 48486675..b171cdbc 100644 --- a/libi2pd/KadDHT.cpp +++ b/libi2pd/KadDHT.cpp @@ -186,7 +186,7 @@ namespace data return false; } - std::shared_ptr DHTTable::FindClosest (const IdentHash& h, const Filter& filter) + std::shared_ptr DHTTable::FindClosest (const IdentHash& h, const Filter& filter) const { if (filter) m_Filter = filter; auto r = FindClosest (h, m_Root, 0); @@ -194,7 +194,7 @@ namespace data return r; } - std::shared_ptr DHTTable::FindClosest (const IdentHash& h, DHTNode * root, int level) + std::shared_ptr DHTTable::FindClosest (const IdentHash& h, DHTNode * root, int level) const { bool split = false; do @@ -241,7 +241,7 @@ namespace data return nullptr; } - std::vector > DHTTable::FindClosest (const IdentHash& h, size_t num, const Filter& filter) + std::vector > DHTTable::FindClosest (const IdentHash& h, size_t num, const Filter& filter) const { std::vector > vec; if (num > 0) @@ -253,7 +253,7 @@ namespace data return vec; } - void DHTTable::FindClosest (const IdentHash& h, size_t num, DHTNode * root, int level, std::vector >& hashes) + void DHTTable::FindClosest (const IdentHash& h, size_t num, DHTNode * root, int level, std::vector >& hashes) const { if (hashes.size () >= num) return; bool split = false; @@ -292,7 +292,7 @@ namespace data } } - void DHTTable::Cleanup (Filter filter) + void DHTTable::Cleanup (const Filter& filter) { if (filter) { diff --git a/libi2pd/KadDHT.h b/libi2pd/KadDHT.h index c280a1de..3bc31780 100644 --- a/libi2pd/KadDHT.h +++ b/libi2pd/KadDHT.h @@ -44,20 +44,20 @@ namespace data void Insert (const std::shared_ptr& r); bool Remove (const IdentHash& h); - std::shared_ptr FindClosest (const IdentHash& h, const Filter& filter = nullptr); - std::vector > FindClosest (const IdentHash& h, size_t num, const Filter& filter = nullptr); + std::shared_ptr FindClosest (const IdentHash& h, const Filter& filter = nullptr) const; + std::vector > FindClosest (const IdentHash& h, size_t num, const Filter& filter = nullptr) const; void Print (std::stringstream& s); size_t GetSize () const { return m_Size; }; void Clear (); - void Cleanup (Filter filter); + void Cleanup (const Filter& filter); private: void Insert (const std::shared_ptr& r, DHTNode * root, int level); // recursive bool Remove (const IdentHash& h, DHTNode * root, int level); - std::shared_ptr FindClosest (const IdentHash& h, DHTNode * root, int level); - void FindClosest (const IdentHash& h, size_t num, DHTNode * root, int level, std::vector >& hashes); + std::shared_ptr FindClosest (const IdentHash& h, DHTNode * root, int level) const; + void FindClosest (const IdentHash& h, size_t num, DHTNode * root, int level, std::vector >& hashes) const; void Cleanup (DHTNode * root); void Print (std::stringstream& s, DHTNode * root, int level); @@ -66,7 +66,7 @@ namespace data DHTNode * m_Root; size_t m_Size; // transient - Filter m_Filter; + mutable Filter m_Filter; }; } } diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 11cf8066..09d57bac 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -55,7 +55,7 @@ namespace data Load (); uint16_t threshold; i2p::config::GetOption("reseed.threshold", threshold); - if (m_RouterInfos.size () < threshold || m_Floodfills.size () < NETDB_MIN_FLOODFILLS) // reseed if # of router less than threshold or too few floodfiils + if (m_RouterInfos.size () < threshold || m_Floodfills.GetSize () < NETDB_MIN_FLOODFILLS) // reseed if # of router less than threshold or too few floodfiils { Reseed (); } @@ -66,13 +66,13 @@ namespace data if (it != m_RouterInfos.end ()) { // remove own router - m_Floodfills.remove (it->second); + m_Floodfills.Remove (it->second->GetIdentHash ()); m_RouterInfos.erase (it); } // insert own router m_RouterInfos.emplace (i2p::context.GetIdentHash (), i2p::context.GetSharedRouterInfo ()); if (i2p::context.IsFloodfill ()) - m_Floodfills.push_back (i2p::context.GetSharedRouterInfo ()); + m_Floodfills.Insert (i2p::context.GetSharedRouterInfo ()); i2p::config::GetOption("persist.profiles", m_PersistProfiles); @@ -88,7 +88,7 @@ namespace data SaveProfiles (); DeleteObsoleteProfiles (); m_RouterInfos.clear (); - m_Floodfills.clear (); + m_Floodfills.Clear (); if (m_Thread) { m_IsRunning = false; @@ -289,7 +289,7 @@ namespace data if (wasFloodfill) { std::unique_lock l(m_FloodfillsMutex); - m_Floodfills.remove (r); + m_Floodfills.Remove (r->GetIdentHash ()); } m_Requests.RequestComplete (ident, nullptr); return nullptr; @@ -301,9 +301,9 @@ namespace data LogPrint (eLogDebug, "NetDb: RouterInfo floodfill status updated: ", ident.ToBase64()); std::unique_lock l(m_FloodfillsMutex); if (wasFloodfill) - m_Floodfills.remove (r); + m_Floodfills.Remove (r->GetIdentHash ()); else if (r->IsEligibleFloodfill ()) - m_Floodfills.push_back (r); + m_Floodfills.Insert (r); } } else @@ -329,7 +329,7 @@ namespace data if (r->IsFloodfill () && r->IsEligibleFloodfill ()) { std::unique_lock l(m_FloodfillsMutex); - m_Floodfills.push_back (r); + m_Floodfills.Insert (r); } } else @@ -530,7 +530,7 @@ namespace data if (m_RouterInfos.emplace (r->GetIdentHash (), r).second) { if (r->IsFloodfill () && r->IsEligibleFloodfill ()) - m_Floodfills.push_back (r); + m_Floodfills.Insert (r); } } else @@ -614,7 +614,7 @@ namespace data { // make sure we cleanup netDb from previous attempts m_RouterInfos.clear (); - m_Floodfills.clear (); + m_Floodfills.Clear (); uint64_t ts = i2p::util::GetMillisecondsSinceEpoch(); std::vector files; @@ -622,14 +622,14 @@ namespace data for (const auto& path : files) LoadRouterInfo (path, ts); - LogPrint (eLogInfo, "NetDb: ", m_RouterInfos.size(), " routers loaded (", m_Floodfills.size (), " floodfils)"); + LogPrint (eLogInfo, "NetDb: ", m_RouterInfos.size(), " routers loaded (", m_Floodfills.GetSize (), " floodfils)"); } void NetDb::SaveUpdated () { int updatedCount = 0, deletedCount = 0, deletedFloodfillsCount = 0; auto total = m_RouterInfos.size (); - auto totalFloodfills = m_Floodfills.size (); + auto totalFloodfills = m_Floodfills.GetSize (); uint64_t expirationTimeout = NETDB_MAX_EXPIRATION_TIMEOUT*1000LL; uint64_t ts = i2p::util::GetMillisecondsSinceEpoch(); auto uptime = i2p::context.GetUptime (); @@ -721,11 +721,10 @@ namespace data // clean up expired floodfills or not floodfills anymore { std::unique_lock l(m_FloodfillsMutex); - for (auto it = m_Floodfills.begin (); it != m_Floodfills.end ();) - if ((*it)->IsUnreachable () || !(*it)->IsFloodfill ()) - it = m_Floodfills.erase (it); - else - it++; + m_Floodfills.Cleanup ([](const std::shared_ptr& r)->bool + { + return r && r->IsFloodfill () && !r->IsUnreachable (); + }); } } } @@ -1362,75 +1361,38 @@ namespace data std::shared_ptr NetDb::GetClosestFloodfill (const IdentHash& destination, const std::set& excluded) const { - std::shared_ptr r; - XORMetric minMetric; IdentHash destKey = CreateRoutingKey (destination); - minMetric.SetMax (); std::unique_lock l(m_FloodfillsMutex); - for (const auto& it: m_Floodfills) - { - if (!it->IsUnreachable () && !it->GetProfile ()->IsUnreachable ()) + return m_Floodfills.FindClosest (destKey, [&excluded](const std::shared_ptr& r)->bool { - XORMetric m = destKey ^ it->GetIdentHash (); - if (m < minMetric && !excluded.count (it->GetIdentHash ())) - { - minMetric = m; - r = it; - } - } - } - return r; + return r && !r->IsUnreachable () && !r->GetProfile ()->IsUnreachable () && + !excluded.count (r->GetIdentHash ()); + }); } std::vector NetDb::GetClosestFloodfills (const IdentHash& destination, size_t num, std::set& excluded, bool closeThanUsOnly) const { - struct Sorted - { - std::shared_ptr r; - XORMetric metric; - bool operator< (const Sorted& other) const { return metric < other.metric; }; - }; - - std::set sorted; + std::vector res; IdentHash destKey = CreateRoutingKey (destination); - XORMetric ourMetric; - if (closeThanUsOnly) ourMetric = destKey ^ i2p::context.GetIdentHash (); + std::vector > v; { std::unique_lock l(m_FloodfillsMutex); - for (const auto& it: m_Floodfills) - { - if (!it->IsUnreachable () && !it->GetProfile ()->IsUnreachable ()) + v = m_Floodfills.FindClosest (destKey, num, [&excluded](const std::shared_ptr& r)->bool { - XORMetric m = destKey ^ it->GetIdentHash (); - if (closeThanUsOnly && ourMetric < m) continue; - if (sorted.size () < num) - sorted.insert ({it, m}); - else if (m < sorted.rbegin ()->metric) - { - sorted.insert ({it, m}); - sorted.erase (std::prev (sorted.end ())); - } - } - } - } - - std::vector res; - size_t i = 0; - for (const auto& it: sorted) + return r && !r->IsUnreachable () && !r->GetProfile ()->IsUnreachable () && + !excluded.count (r->GetIdentHash ()); + }); + } + if (v.empty ()) return res; + + XORMetric ourMetric; + if (closeThanUsOnly) ourMetric = destKey ^ i2p::context.GetIdentHash (); + for (auto& it: v) { - if (i < num) - { - const auto& ident = it.r->GetIdentHash (); - if (!excluded.count (ident)) - { - res.push_back (ident); - i++; - } - } - else - break; - } + if (closeThanUsOnly && ourMetric < (destKey ^ it->GetIdentHash ())) break; + res.push_back (it->GetIdentHash ()); + } return res; } diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index 192d2644..74774f0d 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -31,6 +30,7 @@ #include "Family.h" #include "version.h" #include "util.h" +#include "KadDHT.h" namespace i2p { @@ -110,7 +110,7 @@ namespace data // for web interface int GetNumRouters () const { return m_RouterInfos.size (); }; - int GetNumFloodfills () const { return m_Floodfills.size (); }; + int GetNumFloodfills () const { return m_Floodfills.GetSize (); }; int GetNumLeaseSets () const { return m_LeaseSets.size (); }; /** visit all lease sets we currently store */ @@ -164,7 +164,7 @@ namespace data mutable std::mutex m_RouterInfosMutex; std::unordered_map > m_RouterInfos; mutable std::mutex m_FloodfillsMutex; - std::list > m_Floodfills; + DHTTable m_Floodfills; bool m_IsRunning; std::thread * m_Thread; From e3fbc246f407e2469b486f0833c2a511fb6ff616 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Thu, 23 Feb 2023 00:26:07 +0300 Subject: [PATCH 0017/1171] [gha] try to fix deb build Signed-off-by: R4SAS --- .github/workflows/build-deb.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index bda12dbc..4d981c90 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -13,15 +13,17 @@ jobs: - uses: actions/checkout@v2 with: fetch-depth: 0 - - name: change debian changelog - run: | - sudo apt-get update - sudo apt-get install devscripts - debchange -v "`git describe --tags`-${{ matrix.dist }}" -b -M --distribution ${{ matrix.dist }} "trunk build" + #- name: change debian changelog + # run: | + # sudo apt-get update + # sudo apt-get install devscripts + # debchange -v "`git describe --tags`-${{ matrix.dist }}" -b -M --distribution ${{ matrix.dist }} "trunk build" - uses: jtdor/build-deb-action@v1 with: docker-image: debian:${{ matrix.dist }}-slim buildpackage-opts: --build=binary --no-sign + before-build-hook: debchange --controlmaint --local="+$(git describe --tags)" "CI build" + extra-build-deps: devscripts - uses: actions/upload-artifact@v3 with: name: i2pd_${{ matrix.dist }} From f33b0cad2e768b6f84787090510fb8cd58977d12 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Thu, 23 Feb 2023 14:13:59 +0000 Subject: [PATCH 0018/1171] [gha] update deb build action Signed-off-by: R4SAS --- .github/workflows/build-deb.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 4d981c90..032cf4c0 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -7,22 +7,18 @@ jobs: name: ${{ matrix.dist }} runs-on: ubuntu-latest strategy: + fail-fast: false matrix: dist: ['buster', 'bullseye', 'bookworm'] steps: - uses: actions/checkout@v2 with: fetch-depth: 0 - #- name: change debian changelog - # run: | - # sudo apt-get update - # sudo apt-get install devscripts - # debchange -v "`git describe --tags`-${{ matrix.dist }}" -b -M --distribution ${{ matrix.dist }} "trunk build" - uses: jtdor/build-deb-action@v1 with: docker-image: debian:${{ matrix.dist }}-slim buildpackage-opts: --build=binary --no-sign - before-build-hook: debchange --controlmaint --local="+$(git describe --tags)" "CI build" + before-build-hook: debchange -v "$(git describe --tags)-${{ matrix.dist }}" -b -M --distribution ${{ matrix.dist }} "CI build" extra-build-deps: devscripts - uses: actions/upload-artifact@v3 with: From db0f2fab117a0684edfaf9d4238659f209b4b672 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Thu, 23 Feb 2023 14:24:15 +0000 Subject: [PATCH 0019/1171] [gha] update deb build action Signed-off-by: R4SAS --- .github/workflows/build-deb.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 032cf4c0..6c659497 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -18,8 +18,8 @@ jobs: with: docker-image: debian:${{ matrix.dist }}-slim buildpackage-opts: --build=binary --no-sign - before-build-hook: debchange -v "$(git describe --tags)-${{ matrix.dist }}" -b -M --distribution ${{ matrix.dist }} "CI build" - extra-build-deps: devscripts + before-build-hook: debchange --controlmaint -v "$(git describe --tags)~${{ matrix.dist }}" -b --distribution ${{ matrix.dist }} "CI build" + extra-build-deps: devscripts git - uses: actions/upload-artifact@v3 with: name: i2pd_${{ matrix.dist }} From bd63383d7f97cded3c53130be189bb778a3dbba4 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Thu, 23 Feb 2023 14:31:50 +0000 Subject: [PATCH 0020/1171] [gha] update deb build action Signed-off-by: R4SAS --- .github/workflows/build-deb.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 6c659497..4d95b849 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -18,7 +18,7 @@ jobs: with: docker-image: debian:${{ matrix.dist }}-slim buildpackage-opts: --build=binary --no-sign - before-build-hook: debchange --controlmaint -v "$(git describe --tags)~${{ matrix.dist }}" -b --distribution ${{ matrix.dist }} "CI build" + before-build-hook: debchange --controlmaint --local"+$(git rev-parse --short $GITHUB_SHA)~${{ matrix.dist }}" -b --distribution ${{ matrix.dist }} "CI build" extra-build-deps: devscripts git - uses: actions/upload-artifact@v3 with: From 5657079355f306d0f14305203f11f52506abfd14 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Thu, 23 Feb 2023 14:35:38 +0000 Subject: [PATCH 0021/1171] [gha] update deb build action Signed-off-by: R4SAS --- .github/workflows/build-deb.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 4d95b849..f8fd249c 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -18,7 +18,7 @@ jobs: with: docker-image: debian:${{ matrix.dist }}-slim buildpackage-opts: --build=binary --no-sign - before-build-hook: debchange --controlmaint --local"+$(git rev-parse --short $GITHUB_SHA)~${{ matrix.dist }}" -b --distribution ${{ matrix.dist }} "CI build" + before-build-hook: debchange --controlmaint --local "+${{ github.sha }}~${{ matrix.dist }}" -b --distribution ${{ matrix.dist }} "CI build" extra-build-deps: devscripts git - uses: actions/upload-artifact@v3 with: From 2e62f9532f57f75525f6cc8d01f2cb96dbff2b09 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 23 Feb 2023 13:58:06 -0500 Subject: [PATCH 0022/1171] separate thread for processing router's messages --- daemon/Daemon.cpp | 6 +++++- libi2pd/RouterContext.cpp | 40 +++++++++++++++++++++++++-------------- libi2pd/RouterContext.h | 12 +++++++----- libi2pd/api.cpp | 6 +++++- 4 files changed, 43 insertions(+), 21 deletions(-) diff --git a/daemon/Daemon.cpp b/daemon/Daemon.cpp index a0d7cf1a..b6ce396e 100644 --- a/daemon/Daemon.cpp +++ b/daemon/Daemon.cpp @@ -334,10 +334,12 @@ namespace util } } - LogPrint(eLogInfo, "Daemon: Starting Tunnels"); i2p::tunnel::tunnels.Start(); + LogPrint(eLogInfo, "Daemon: Starting Router context"); + i2p::context.Start(); + LogPrint(eLogInfo, "Daemon: Starting Client"); i2p::client::context.Start (); @@ -366,6 +368,8 @@ namespace util LogPrint(eLogInfo, "Daemon: Shutting down"); LogPrint(eLogInfo, "Daemon: Stopping Client"); i2p::client::context.Stop(); + LogPrint(eLogInfo, "Daemon: Stopping Router context"); + i2p::context.Stop(); LogPrint(eLogInfo, "Daemon: Stopping Tunnels"); i2p::tunnel::tunnels.Stop(); diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 72b723ea..088f91d2 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -26,7 +26,7 @@ namespace i2p { RouterContext context; - RouterContext::RouterContext (): + RouterContext::RouterContext (): RunnableServiceWithWork ("Router"), m_LastUpdateTime (0), m_AcceptsTunnels (true), m_IsFloodfill (false), m_ShareRatio (100), m_Status (eRouterStatusUnknown), m_StatusV6 (eRouterStatusUnknown), m_Error (eRouterErrorNone), m_ErrorV6 (eRouterErrorNone), m_NetID (I2PD_NET_ID) @@ -47,6 +47,16 @@ namespace i2p m_ECIESSession = std::make_shared(m_InitialNoiseState); } + void RouterContext::Start () + { + StartIOService (); + } + + void RouterContext::Stop () + { + StopIOService (); + } + void RouterContext::CreateNewRouter () { m_Keys = i2p::data::PrivateKeys::CreateRandomKeys (i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519, @@ -1087,12 +1097,6 @@ namespace i2p bool RouterContext::HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len, uint32_t msgID) { - if (typeID == eI2NPGarlic) - { - // TODO: implement - LogPrint (eLogWarning, "Router: garlic message in garlic clove. Dropped"); - return false; - } auto msg = CreateI2NPMessage (typeID, payload, len, msgID); if (!msg) return false; i2p::HandleI2NPMessage (msg); @@ -1101,7 +1105,11 @@ namespace i2p void RouterContext::ProcessGarlicMessage (std::shared_ptr msg) { - std::unique_lock l(m_GarlicMutex); + GetIOService ().post (std::bind (&RouterContext::PostGarlicMessage, this, msg)); + } + + void RouterContext::PostGarlicMessage (std::shared_ptr msg) + { uint8_t * buf = msg->GetPayload (); uint32_t len = bufbe32toh (buf); if (len > msg->GetLength ()) @@ -1118,23 +1126,27 @@ namespace i2p else LogPrint (eLogError, "Router: Session is not set for ECIES router"); } - } - + } + void RouterContext::ProcessDeliveryStatusMessage (std::shared_ptr msg) { if (i2p::data::netdb.GetPublishReplyToken () == bufbe32toh (msg->GetPayload () + DELIVERY_STATUS_MSGID_OFFSET)) i2p::data::netdb.PostI2NPMsg (msg); else { - std::unique_lock l(m_GarlicMutex); - i2p::garlic::GarlicDestination::ProcessDeliveryStatusMessage (msg); + GetIOService ().post ([msg, this]() + { + this->i2p::garlic::GarlicDestination::ProcessDeliveryStatusMessage (msg); + }); } } void RouterContext::CleanupDestination () { - std::unique_lock l(m_GarlicMutex); - i2p::garlic::GarlicDestination::CleanupExpiredTags (); + GetIOService ().post ([this]() + { + this->i2p::garlic::GarlicDestination::CleanupExpiredTags (); + }); } uint32_t RouterContext::GetUptime () const diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index 9fbbb178..c054bd79 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -12,12 +12,12 @@ #include #include #include -#include #include #include #include "Identity.h" #include "RouterInfo.h" #include "Garlic.h" +#include "util.h" namespace i2p { @@ -52,7 +52,7 @@ namespace garlic eRouterErrorNoDescriptors = 5 }; - class RouterContext: public i2p::garlic::GarlicDestination + class RouterContext: public i2p::garlic::GarlicDestination, private i2p::util::RunnableServiceWithWork { private: @@ -74,7 +74,9 @@ namespace garlic RouterContext (); void Init (); - + void Start (); + void Stop (); + const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; }; i2p::data::LocalRouterInfo& GetRouterInfo () { return m_RouterInfo; }; std::shared_ptr GetSharedRouterInfo () @@ -183,7 +185,8 @@ namespace garlic void PublishNTCP2Address (std::shared_ptr address, int port, bool publish) const; bool DecryptECIESTunnelBuildRecord (const uint8_t * encrypted, uint8_t * data, size_t clearTextSize); - + void PostGarlicMessage (std::shared_ptr msg); + private: i2p::data::LocalRouterInfo m_RouterInfo; @@ -198,7 +201,6 @@ namespace garlic RouterStatus m_Status, m_StatusV6; RouterError m_Error, m_ErrorV6; int m_NetID; - std::mutex m_GarlicMutex; std::unique_ptr m_NTCP2Keys; std::unique_ptr m_SSU2Keys; std::unique_ptr m_NTCP2StaticKeys, m_SSU2StaticKeys; diff --git a/libi2pd/api.cpp b/libi2pd/api.cpp index a298e4b4..3bfb801c 100644 --- a/libi2pd/api.cpp +++ b/libi2pd/api.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -67,11 +67,15 @@ namespace api i2p::transport::transports.Start(); LogPrint(eLogInfo, "API: Starting Tunnels"); i2p::tunnel::tunnels.Start(); + LogPrint(eLogInfo, "API: Starting Router context"); + i2p::context.Start(); } void StopI2P () { LogPrint(eLogInfo, "API: Shutting down"); + LogPrint(eLogInfo, "API: Stopping Router context"); + i2p::context.Stop(); LogPrint(eLogInfo, "API: Stopping Tunnels"); i2p::tunnel::tunnels.Stop(); LogPrint(eLogInfo, "API: Stopping Transports"); From f84d88ac6391cdd830e362d682adaf350968d50b Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 24 Feb 2023 18:28:30 -0500 Subject: [PATCH 0023/1171] publish own RouterInfo in router's thread --- libi2pd/NetDb.cpp | 87 +------------------------- libi2pd/NetDb.hpp | 11 ---- libi2pd/RouterContext.cpp | 128 ++++++++++++++++++++++++++++++++++---- libi2pd/RouterContext.h | 23 ++++++- 4 files changed, 142 insertions(+), 107 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 09d57bac..2302dc86 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -36,7 +36,7 @@ namespace data { NetDb netdb; - NetDb::NetDb (): m_IsRunning (false), m_Thread (nullptr), m_Reseeder (nullptr), m_Storage("netDb", "r", "routerInfo-", "dat"), m_PersistProfiles (true), m_HiddenMode(false) + NetDb::NetDb (): m_IsRunning (false), m_Thread (nullptr), m_Reseeder (nullptr), m_Storage("netDb", "r", "routerInfo-", "dat"), m_PersistProfiles (true) { } @@ -106,7 +106,7 @@ namespace data { i2p::util::SetThreadName("NetDB"); - uint64_t lastSave = 0, lastPublish = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0; + uint64_t lastSave = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0; uint64_t lastProfilesCleanup = i2p::util::GetSecondsSinceEpoch (); int16_t profilesCleanupVariance = 0; @@ -132,9 +132,6 @@ namespace data case eI2NPDatabaseLookup: HandleDatabaseLookupMsg (msg); break; - case eI2NPDeliveryStatus: - HandleDeliveryStatusMsg (msg); - break; case eI2NPDummyMsg: // plain RouterInfo from NTCP2 with flags for now HandleNTCP2RouterInfoMsg (msg); @@ -184,33 +181,6 @@ namespace data profilesCleanupVariance = (rand () % (2 * i2p::data::PEER_PROFILE_AUTOCLEAN_VARIANCE) - i2p::data::PEER_PROFILE_AUTOCLEAN_VARIANCE); } - // publish - if (!m_HiddenMode && i2p::transport::transports.IsOnline ()) - { - bool publish = false; - if (m_PublishReplyToken) - { - // next publishing attempt - if (ts - lastPublish >= NETDB_PUBLISH_CONFIRMATION_TIMEOUT) publish = true; - } - else if (i2p::context.GetLastUpdateTime () > lastPublish || - ts - lastPublish >= NETDB_PUBLISH_INTERVAL || - ts + NETDB_PUBLISH_INTERVAL < lastPublish) - { - // new publish - m_PublishExcluded.clear (); - if (i2p::context.IsFloodfill ()) - m_PublishExcluded.insert (i2p::context.GetIdentHash ()); // do publish to ourselves - publish = true; - } - if (publish) // update timestamp and publish - { - i2p::context.UpdateTimestamp (ts); - Publish (); - lastPublish = ts; - } - } - if (ts - lastExploratory >= 30 || ts + 30 < lastExploratory) // exploratory every 30 seconds { auto numRouters = m_RouterInfos.size (); @@ -224,7 +194,7 @@ namespace data if (numRouters < 1) numRouters = 1; if (numRouters > 9) numRouters = 9; m_Requests.ManageRequests (); - if(!m_HiddenMode) + if(!i2p::context.IsHidden ()) Explore (numRouters); lastExploratory = ts; } @@ -237,12 +207,6 @@ namespace data } } - void NetDb::SetHidden(bool hide) - { - // TODO: remove reachable addresses from router info - m_HiddenMode = hide; - } - std::shared_ptr NetDb::AddRouterInfo (const uint8_t * buf, int len) { bool updated; @@ -1125,16 +1089,6 @@ namespace data } } - void NetDb::HandleDeliveryStatusMsg (std::shared_ptr msg) - { - if (m_PublishReplyToken == bufbe32toh (msg->GetPayload () + DELIVERY_STATUS_MSGID_OFFSET)) - { - LogPrint (eLogInfo, "NetDb: Publishing confirmed. reply token=", m_PublishReplyToken); - m_PublishExcluded.clear (); - m_PublishReplyToken = 0; - } - } - void NetDb::Explore (int numDestinations) { // new requests @@ -1185,41 +1139,6 @@ namespace data outbound->SendTunnelDataMsg (msgs); } - void NetDb::Publish () - { - i2p::context.UpdateStats (); // for floodfill - - if (m_PublishExcluded.size () > NETDB_MAX_PUBLISH_EXCLUDED_FLOODFILLS) - { - LogPrint (eLogError, "NetDb: Couldn't publish our RouterInfo to ", NETDB_MAX_PUBLISH_EXCLUDED_FLOODFILLS, " closest routers. Try again"); - m_PublishExcluded.clear (); - } - - auto floodfill = GetClosestFloodfill (i2p::context.GetIdentHash (), m_PublishExcluded); - if (floodfill) - { - uint32_t replyToken; - RAND_bytes ((uint8_t *)&replyToken, 4); - LogPrint (eLogInfo, "NetDb: Publishing our RouterInfo to ", i2p::data::GetIdentHashAbbreviation(floodfill->GetIdentHash ()), ". reply token=", replyToken); - m_PublishExcluded.insert (floodfill->GetIdentHash ()); - m_PublishReplyToken = replyToken; - if (floodfill->IsReachableFrom (i2p::context.GetRouterInfo ()) || // are we able to connect? - i2p::transport::transports.IsConnected (floodfill->GetIdentHash ())) // already connected ? - // send directly - transports.SendMessage (floodfill->GetIdentHash (), CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken)); - else - { - // otherwise through exploratory - auto exploratoryPool = i2p::tunnel::tunnels.GetExploratoryPool (); - auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel (nullptr, floodfill->GetCompatibleTransports (false)) : nullptr; - auto inbound = exploratoryPool ? exploratoryPool->GetNextInboundTunnel (nullptr, floodfill->GetCompatibleTransports (true)) : nullptr; - if (inbound && outbound) - outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, - CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken, inbound)); - } - } - } - void NetDb::Flood (const IdentHash& ident, std::shared_ptr floodMsg) { std::set excluded; diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index 74774f0d..7958e36d 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -45,9 +45,6 @@ namespace data const int NETDB_MAX_EXPIRATION_TIMEOUT = 27 * 60 * 60; // 27 hours const int NETDB_MAX_OFFLINE_EXPIRATION_TIMEOUT = 180; // in days const int NETDB_EXPIRATION_TIMEOUT_THRESHOLD = 2*60; // 2 minutes - const int NETDB_PUBLISH_INTERVAL = 60 * 40; - const int NETDB_PUBLISH_CONFIRMATION_TIMEOUT = 5; // in seconds - const int NETDB_MAX_PUBLISH_EXCLUDED_FLOODFILLS = 15; const int NETDB_MIN_HIGHBANDWIDTH_VERSION = MAKE_VERSION_NUMBER(0, 9, 51); // 0.9.51 const int NETDB_MIN_FLOODFILL_VERSION = MAKE_VERSION_NUMBER(0, 9, 51); // 0.9.51 const int NETDB_MIN_SHORT_TUNNEL_BUILD_VERSION = MAKE_VERSION_NUMBER(0, 9, 51); // 0.9.51 @@ -86,7 +83,6 @@ namespace data void HandleDatabaseSearchReplyMsg (std::shared_ptr msg); void HandleDatabaseLookupMsg (std::shared_ptr msg); void HandleNTCP2RouterInfoMsg (std::shared_ptr m); - void HandleDeliveryStatusMsg (std::shared_ptr msg); std::shared_ptr GetRandomRouter () const; std::shared_ptr GetRandomRouter (std::shared_ptr compatibleWith, bool reverse) const; @@ -102,9 +98,6 @@ namespace data void PostI2NPMsg (std::shared_ptr msg); - /** set hidden mode, aka don't publish our RI to netdb and don't explore */ - void SetHidden(bool hide); - void Reseed (); Families& GetFamilies () { return m_Families; }; @@ -144,7 +137,6 @@ namespace data void SaveUpdated (); void Run (); // exploratory thread void Explore (int numDestinations); - void Publish (); void Flood (const IdentHash& ident, std::shared_ptr floodMsg); void ManageLeaseSets (); void ManageRequests (); @@ -183,9 +175,6 @@ namespace data /** router info we are bootstrapping from or nullptr if we are not currently doing that*/ std::shared_ptr m_FloodfillBootstrap; - /** true if in hidden mode */ - bool m_HiddenMode; - std::set m_PublishExcluded; uint32_t m_PublishReplyToken = 0; diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 088f91d2..77985a11 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -20,6 +20,8 @@ #include "Log.h" #include "Family.h" #include "ECIESX25519AEADRatchetSession.h" +#include "Transports.h" +#include "Tunnel.h" #include "RouterContext.h" namespace i2p @@ -29,7 +31,8 @@ namespace i2p RouterContext::RouterContext (): RunnableServiceWithWork ("Router"), m_LastUpdateTime (0), m_AcceptsTunnels (true), m_IsFloodfill (false), m_ShareRatio (100), m_Status (eRouterStatusUnknown), m_StatusV6 (eRouterStatusUnknown), - m_Error (eRouterErrorNone), m_ErrorV6 (eRouterErrorNone), m_NetID (I2PD_NET_ID) + m_Error (eRouterErrorNone), m_ErrorV6 (eRouterErrorNone), m_NetID (I2PD_NET_ID), + m_PublishTimer (GetIOService ()), m_PublishReplyToken (0), m_IsHiddenMode (false) { } @@ -49,11 +52,19 @@ namespace i2p void RouterContext::Start () { - StartIOService (); + if (!IsRunning ()) + { + StartIOService (); + if (!m_IsHiddenMode) + ScheduleInitialPublish (); + } } void RouterContext::Stop () { + if (IsRunning ()) + m_PublishTimer.cancel (); + StopIOService (); } @@ -1130,17 +1141,22 @@ namespace i2p void RouterContext::ProcessDeliveryStatusMessage (std::shared_ptr msg) { - if (i2p::data::netdb.GetPublishReplyToken () == bufbe32toh (msg->GetPayload () + DELIVERY_STATUS_MSGID_OFFSET)) - i2p::data::netdb.PostI2NPMsg (msg); - else - { - GetIOService ().post ([msg, this]() - { - this->i2p::garlic::GarlicDestination::ProcessDeliveryStatusMessage (msg); - }); - } + GetIOService ().post (std::bind (&RouterContext::PostDeliveryStatusMessage, this, msg)); } + void RouterContext::PostDeliveryStatusMessage (std::shared_ptr msg) + { + if (m_PublishReplyToken == bufbe32toh (msg->GetPayload () + DELIVERY_STATUS_MSGID_OFFSET)) + { + LogPrint (eLogInfo, "Router: Publishing confirmed. reply token=", m_PublishReplyToken); + m_PublishExcluded.clear (); + m_PublishReplyToken = 0; + SchedulePublish (); + } + else + i2p::garlic::GarlicDestination::ProcessDeliveryStatusMessage (msg); + } + void RouterContext::CleanupDestination () { GetIOService ().post ([this]() @@ -1221,4 +1237,94 @@ namespace i2p } return *m_SSU2StaticKeys; } + + void RouterContext::ScheduleInitialPublish () + { + m_PublishTimer.expires_from_now (boost::posix_time::seconds(ROUTER_INFO_INITIAL_PUBLISH_INTERVAL)); + m_PublishTimer.async_wait (std::bind (&RouterContext::HandlePublishTimer, + this, std::placeholders::_1)); + } + + void RouterContext::SchedulePublish () + { + m_PublishTimer.cancel (); + m_PublishTimer.expires_from_now (boost::posix_time::seconds(ROUTER_INFO_PUBLISH_INTERVAL + + rand () % ROUTER_INFO_PUBLISH_INTERVAL_VARIANCE)); + m_PublishTimer.async_wait (std::bind (&RouterContext::HandlePublishTimer, + this, std::placeholders::_1)); + } + + void RouterContext::HandlePublishTimer (const boost::system::error_code& ecode) + { + if (ecode != boost::asio::error::operation_aborted) + { + m_PublishExcluded.clear (); + m_PublishReplyToken = 0; + if (IsFloodfill ()) + { + UpdateStats (); // for floodfill + m_PublishExcluded.insert (i2p::context.GetIdentHash ()); // don't publish to ourselves + } + UpdateTimestamp (i2p::util::GetSecondsSinceEpoch ()); + Publish (); + SchedulePublishResend (); + } + } + + void RouterContext::Publish () + { + if (!i2p::transport::transports.IsOnline ()) return; + if (m_PublishExcluded.size () > ROUTER_INFO_MAX_PUBLISH_EXCLUDED_FLOODFILLS) + { + LogPrint (eLogError, "Router: Couldn't publish our RouterInfo to ", ROUTER_INFO_MAX_PUBLISH_EXCLUDED_FLOODFILLS, " closest routers. Try again"); + m_PublishExcluded.clear (); + UpdateTimestamp (i2p::util::GetSecondsSinceEpoch ()); + } + + auto floodfill = i2p::data::netdb.GetClosestFloodfill (i2p::context.GetIdentHash (), m_PublishExcluded); + if (floodfill) + { + uint32_t replyToken; + RAND_bytes ((uint8_t *)&replyToken, 4); + LogPrint (eLogInfo, "Router: Publishing our RouterInfo to ", i2p::data::GetIdentHashAbbreviation(floodfill->GetIdentHash ()), ". reply token=", replyToken); + if (floodfill->IsReachableFrom (i2p::context.GetRouterInfo ()) || // are we able to connect? + i2p::transport::transports.IsConnected (floodfill->GetIdentHash ())) // already connected ? + // send directly + i2p::transport::transports.SendMessage (floodfill->GetIdentHash (), CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken)); + else + { + // otherwise through exploratory + auto exploratoryPool = i2p::tunnel::tunnels.GetExploratoryPool (); + auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel (nullptr, floodfill->GetCompatibleTransports (false)) : nullptr; + auto inbound = exploratoryPool ? exploratoryPool->GetNextInboundTunnel (nullptr, floodfill->GetCompatibleTransports (true)) : nullptr; + if (inbound && outbound) + outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, + CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken, inbound)); + else + LogPrint (eLogInfo, "Router: Can't publish our RouterInfo. No tunnles. Try again in ", ROUTER_INFO_CONFIRMATION_TIMEOUT, " seconds"); + } + m_PublishExcluded.insert (floodfill->GetIdentHash ()); + m_PublishReplyToken = replyToken; + } + else + LogPrint (eLogInfo, "Router: Can't find floodfill to publish our RouterInfo"); + } + + void RouterContext::SchedulePublishResend () + { + m_PublishTimer.cancel (); + m_PublishTimer.expires_from_now (boost::posix_time::seconds(ROUTER_INFO_CONFIRMATION_TIMEOUT)); + m_PublishTimer.async_wait (std::bind (&RouterContext::HandlePublishResendTimer, + this, std::placeholders::_1)); + } + + void RouterContext::HandlePublishResendTimer (const boost::system::error_code& ecode) + { + if (ecode != boost::asio::error::operation_aborted) + { + i2p::context.UpdateTimestamp (i2p::util::GetSecondsSinceEpoch ()); + Publish (); + SchedulePublishResend (); + } + } } diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index c054bd79..94b7dcca 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "Identity.h" #include "RouterInfo.h" @@ -30,7 +31,12 @@ namespace garlic const char ROUTER_KEYS[] = "router.keys"; const char NTCP2_KEYS[] = "ntcp2.keys"; const char SSU2_KEYS[] = "ssu2.keys"; - const int ROUTER_INFO_UPDATE_INTERVAL = 1800; // 30 minutes + const int ROUTER_INFO_UPDATE_INTERVAL = 30*60; // 30 minutes + const int ROUTER_INFO_PUBLISH_INTERVAL = 39*60; // in seconds + const int ROUTER_INFO_INITIAL_PUBLISH_INTERVAL = 10; // in seconds + const int ROUTER_INFO_PUBLISH_INTERVAL_VARIANCE = 105;// in seconds + const int ROUTER_INFO_CONFIRMATION_TIMEOUT = 5; // in seconds + const int ROUTER_INFO_MAX_PUBLISH_EXCLUDED_FLOODFILLS = 15; enum RouterStatus { @@ -143,6 +149,8 @@ namespace garlic void SetSupportsV4 (bool supportsV4); void SetSupportsMesh (bool supportsmesh, const boost::asio::ip::address_v6& host); void SetMTU (int mtu, bool v4); + void SetHidden(bool hide) { m_IsHiddenMode = hide; }; + bool IsHidden() const { return m_IsHiddenMode; }; i2p::crypto::NoiseSymmetricState& GetCurrentNoiseState () { return m_CurrentNoiseState; }; void UpdateNTCP2V6Address (const boost::asio::ip::address& host); // called from Daemon. TODO: remove @@ -186,6 +194,14 @@ namespace garlic bool DecryptECIESTunnelBuildRecord (const uint8_t * encrypted, uint8_t * data, size_t clearTextSize); void PostGarlicMessage (std::shared_ptr msg); + void PostDeliveryStatusMessage (std::shared_ptr msg); + + void ScheduleInitialPublish (); + void SchedulePublish (); + void HandlePublishTimer (const boost::system::error_code& ecode); + void Publish (); + void SchedulePublishResend (); + void HandlePublishResendTimer (const boost::system::error_code& ecode); private: @@ -206,6 +222,11 @@ namespace garlic std::unique_ptr m_NTCP2StaticKeys, m_SSU2StaticKeys; // for ECIESx25519 i2p::crypto::NoiseSymmetricState m_InitialNoiseState, m_CurrentNoiseState; + // publish + boost::asio::deadline_timer m_PublishTimer; + std::set m_PublishExcluded; + uint32_t m_PublishReplyToken; + bool m_IsHiddenMode; // not publish }; extern RouterContext context; From 4b421d3feb434dbb38db3e8a6f80f7386a0fb789 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 24 Feb 2023 18:33:33 -0500 Subject: [PATCH 0024/1171] publish own RouterInfo in router's thread --- daemon/Daemon.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemon/Daemon.cpp b/daemon/Daemon.cpp index b6ce396e..2a70dd1f 100644 --- a/daemon/Daemon.cpp +++ b/daemon/Daemon.cpp @@ -269,7 +269,7 @@ namespace util if (hidden) { LogPrint(eLogInfo, "Daemon: Hidden mode enabled"); - i2p::data::netdb.SetHidden(true); + i2p::context.SetHidden(true); } std::string httpLang; i2p::config::GetOption("http.lang", httpLang); From de82b3ae19a82b430544ec6ab82fa9392f10d3c6 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 25 Feb 2023 17:19:14 -0500 Subject: [PATCH 0025/1171] don't publish non-reachable router --- libi2pd/RouterContext.cpp | 25 ++++++++++++++++++++++--- libi2pd/RouterContext.h | 1 + 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 77985a11..e69fb21f 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -1241,9 +1241,22 @@ namespace i2p void RouterContext::ScheduleInitialPublish () { m_PublishTimer.expires_from_now (boost::posix_time::seconds(ROUTER_INFO_INITIAL_PUBLISH_INTERVAL)); - m_PublishTimer.async_wait (std::bind (&RouterContext::HandlePublishTimer, + m_PublishTimer.async_wait (std::bind (&RouterContext::HandleInitialPublishTimer, this, std::placeholders::_1)); } + + void RouterContext::HandleInitialPublishTimer (const boost::system::error_code& ecode) + { + if (ecode != boost::asio::error::operation_aborted) + { + if (m_RouterInfo.IsReachableBy (i2p::data::RouterInfo::eAllTransports)) + HandlePublishTimer (ecode); + else if (!ecode) + ScheduleInitialPublish (); + else + LogPrint (eLogError, "Router: initial publish timer error ", ecode.message ()); + } + } void RouterContext::SchedulePublish () { @@ -1267,7 +1280,10 @@ namespace i2p } UpdateTimestamp (i2p::util::GetSecondsSinceEpoch ()); Publish (); - SchedulePublishResend (); + if (!ecode) + SchedulePublishResend (); + else + LogPrint (eLogError, "Router: publish timer error ", ecode.message ()); } } @@ -1324,7 +1340,10 @@ namespace i2p { i2p::context.UpdateTimestamp (i2p::util::GetSecondsSinceEpoch ()); Publish (); - SchedulePublishResend (); + if (!ecode) + SchedulePublishResend (); + else + LogPrint (eLogError, "Router: publish resend timer error ", ecode.message ()); } } } diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index 94b7dcca..6af5c3de 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -197,6 +197,7 @@ namespace garlic void PostDeliveryStatusMessage (std::shared_ptr msg); void ScheduleInitialPublish (); + void HandleInitialPublishTimer (const boost::system::error_code& ecode); void SchedulePublish (); void HandlePublishTimer (const boost::system::error_code& ecode); void Publish (); From 3c9a574e90c72e901434d74402391b33c15eb508 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 26 Feb 2023 08:46:01 -0500 Subject: [PATCH 0026/1171] create io_service after daemonization --- libi2pd/RouterContext.cpp | 99 ++++++++++++++++++++++++--------------- libi2pd/RouterContext.h | 15 +++++- 2 files changed, 73 insertions(+), 41 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index e69fb21f..5e32d703 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -28,11 +28,11 @@ namespace i2p { RouterContext context; - RouterContext::RouterContext (): RunnableServiceWithWork ("Router"), + RouterContext::RouterContext (): m_LastUpdateTime (0), m_AcceptsTunnels (true), m_IsFloodfill (false), m_ShareRatio (100), m_Status (eRouterStatusUnknown), m_StatusV6 (eRouterStatusUnknown), m_Error (eRouterErrorNone), m_ErrorV6 (eRouterErrorNone), m_NetID (I2PD_NET_ID), - m_PublishTimer (GetIOService ()), m_PublishReplyToken (0), m_IsHiddenMode (false) + m_PublishReplyToken (0), m_IsHiddenMode (false) { } @@ -52,20 +52,26 @@ namespace i2p void RouterContext::Start () { - if (!IsRunning ()) - { - StartIOService (); + if (!m_Service) + { + m_Service.reset (new RouterService); + m_Service->Start (); if (!m_IsHiddenMode) + { + m_PublishTimer.reset (new boost::asio::deadline_timer (m_Service->GetService ())); ScheduleInitialPublish (); + } } } void RouterContext::Stop () { - if (IsRunning ()) - m_PublishTimer.cancel (); - - StopIOService (); + if (m_Service) + { + if (m_PublishTimer) + m_PublishTimer->cancel (); + m_Service->Stop (); + } } void RouterContext::CreateNewRouter () @@ -1116,7 +1122,10 @@ namespace i2p void RouterContext::ProcessGarlicMessage (std::shared_ptr msg) { - GetIOService ().post (std::bind (&RouterContext::PostGarlicMessage, this, msg)); + if (m_Service) + m_Service->GetService ().post (std::bind (&RouterContext::PostGarlicMessage, this, msg)); + else + LogPrint (eLogError, "Router: service is NULL"); } void RouterContext::PostGarlicMessage (std::shared_ptr msg) @@ -1141,7 +1150,10 @@ namespace i2p void RouterContext::ProcessDeliveryStatusMessage (std::shared_ptr msg) { - GetIOService ().post (std::bind (&RouterContext::PostDeliveryStatusMessage, this, msg)); + if (m_Service) + m_Service->GetService ().post (std::bind (&RouterContext::PostDeliveryStatusMessage, this, msg)); + else + LogPrint (eLogError, "Router: service is NULL"); } void RouterContext::PostDeliveryStatusMessage (std::shared_ptr msg) @@ -1159,10 +1171,13 @@ namespace i2p void RouterContext::CleanupDestination () { - GetIOService ().post ([this]() - { - this->i2p::garlic::GarlicDestination::CleanupExpiredTags (); - }); + if (m_Service) + m_Service->GetService ().post ([this]() + { + this->i2p::garlic::GarlicDestination::CleanupExpiredTags (); + }); + else + LogPrint (eLogError, "Router: service is NULL"); } uint32_t RouterContext::GetUptime () const @@ -1240,9 +1255,14 @@ namespace i2p void RouterContext::ScheduleInitialPublish () { - m_PublishTimer.expires_from_now (boost::posix_time::seconds(ROUTER_INFO_INITIAL_PUBLISH_INTERVAL)); - m_PublishTimer.async_wait (std::bind (&RouterContext::HandleInitialPublishTimer, - this, std::placeholders::_1)); + if (m_PublishTimer) + { + m_PublishTimer->expires_from_now (boost::posix_time::seconds(ROUTER_INFO_INITIAL_PUBLISH_INTERVAL)); + m_PublishTimer->async_wait (std::bind (&RouterContext::HandleInitialPublishTimer, + this, std::placeholders::_1)); + } + else + LogPrint (eLogError, "Router: Publish timer is NULL"); } void RouterContext::HandleInitialPublishTimer (const boost::system::error_code& ecode) @@ -1251,20 +1271,22 @@ namespace i2p { if (m_RouterInfo.IsReachableBy (i2p::data::RouterInfo::eAllTransports)) HandlePublishTimer (ecode); - else if (!ecode) - ScheduleInitialPublish (); - else - LogPrint (eLogError, "Router: initial publish timer error ", ecode.message ()); + ScheduleInitialPublish (); } } void RouterContext::SchedulePublish () { - m_PublishTimer.cancel (); - m_PublishTimer.expires_from_now (boost::posix_time::seconds(ROUTER_INFO_PUBLISH_INTERVAL + - rand () % ROUTER_INFO_PUBLISH_INTERVAL_VARIANCE)); - m_PublishTimer.async_wait (std::bind (&RouterContext::HandlePublishTimer, - this, std::placeholders::_1)); + if (m_PublishTimer) + { + m_PublishTimer->cancel (); + m_PublishTimer->expires_from_now (boost::posix_time::seconds(ROUTER_INFO_PUBLISH_INTERVAL + + rand () % ROUTER_INFO_PUBLISH_INTERVAL_VARIANCE)); + m_PublishTimer->async_wait (std::bind (&RouterContext::HandlePublishTimer, + this, std::placeholders::_1)); + } + else + LogPrint (eLogError, "Router: Publish timer is NULL"); } void RouterContext::HandlePublishTimer (const boost::system::error_code& ecode) @@ -1280,10 +1302,7 @@ namespace i2p } UpdateTimestamp (i2p::util::GetSecondsSinceEpoch ()); Publish (); - if (!ecode) - SchedulePublishResend (); - else - LogPrint (eLogError, "Router: publish timer error ", ecode.message ()); + SchedulePublishResend (); } } @@ -1328,10 +1347,15 @@ namespace i2p void RouterContext::SchedulePublishResend () { - m_PublishTimer.cancel (); - m_PublishTimer.expires_from_now (boost::posix_time::seconds(ROUTER_INFO_CONFIRMATION_TIMEOUT)); - m_PublishTimer.async_wait (std::bind (&RouterContext::HandlePublishResendTimer, - this, std::placeholders::_1)); + if (m_PublishTimer) + { + m_PublishTimer->cancel (); + m_PublishTimer->expires_from_now (boost::posix_time::seconds(ROUTER_INFO_CONFIRMATION_TIMEOUT)); + m_PublishTimer->async_wait (std::bind (&RouterContext::HandlePublishResendTimer, + this, std::placeholders::_1)); + } + else + LogPrint (eLogError, "Router: Publish timer is NULL"); } void RouterContext::HandlePublishResendTimer (const boost::system::error_code& ecode) @@ -1340,10 +1364,7 @@ namespace i2p { i2p::context.UpdateTimestamp (i2p::util::GetSecondsSinceEpoch ()); Publish (); - if (!ecode) - SchedulePublishResend (); - else - LogPrint (eLogError, "Router: publish resend timer error ", ecode.message ()); + SchedulePublishResend (); } } } diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index 6af5c3de..4b6d917e 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -58,7 +58,7 @@ namespace garlic eRouterErrorNoDescriptors = 5 }; - class RouterContext: public i2p::garlic::GarlicDestination, private i2p::util::RunnableServiceWithWork + class RouterContext: public i2p::garlic::GarlicDestination { private: @@ -76,6 +76,16 @@ namespace garlic uint8_t intro[32]; }; + class RouterService: public i2p::util::RunnableServiceWithWork + { + public: + + RouterService (): RunnableServiceWithWork ("Router") {}; + boost::asio::io_service& GetService () { return GetIOService (); }; + void Start () { StartIOService (); }; + void Stop () { StopIOService (); }; + }; + public: RouterContext (); @@ -224,7 +234,8 @@ namespace garlic // for ECIESx25519 i2p::crypto::NoiseSymmetricState m_InitialNoiseState, m_CurrentNoiseState; // publish - boost::asio::deadline_timer m_PublishTimer; + std::unique_ptr m_Service; + std::unique_ptr m_PublishTimer; std::set m_PublishExcluded; uint32_t m_PublishReplyToken; bool m_IsHiddenMode; // not publish From 93d89a1fe0e6eeebf5f714e691f112a69fa4378e Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 26 Feb 2023 09:07:53 -0500 Subject: [PATCH 0027/1171] fixed typo --- libi2pd/RouterContext.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 5e32d703..f2b8f4fb 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -1271,7 +1271,8 @@ namespace i2p { if (m_RouterInfo.IsReachableBy (i2p::data::RouterInfo::eAllTransports)) HandlePublishTimer (ecode); - ScheduleInitialPublish (); + else + ScheduleInitialPublish (); } } From 3ff1adf597ed6b29533fb7f3501975e74dc65c0a Mon Sep 17 00:00:00 2001 From: polistern Date: Sun, 26 Feb 2023 16:51:56 +0000 Subject: [PATCH 0028/1171] feat: Added SAM UDP port parameter. --- contrib/i2pd.conf | 3 ++- libi2pd/Config.cpp | 3 ++- libi2pd_client/ClientContext.cpp | 9 +++++---- libi2pd_client/SAM.cpp | 6 +++--- libi2pd_client/SAM.h | 2 +- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/contrib/i2pd.conf b/contrib/i2pd.conf index 84d00347..c6e52c1f 100644 --- a/contrib/i2pd.conf +++ b/contrib/i2pd.conf @@ -168,9 +168,10 @@ port = 4447 [sam] ## Comment or set to 'false' to disable SAM Bridge enabled = true -## Address and port service will listen on +## Address and ports service will listen on # address = 127.0.0.1 # port = 7656 +# portudp = 7655 [bob] ## Uncomment and set to 'true' to enable BOB command channel diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 8df08118..267763a9 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -149,7 +149,8 @@ namespace config { sam.add_options() ("sam.enabled", value()->default_value(true), "Enable or disable SAM Application bridge") ("sam.address", value()->default_value("127.0.0.1"), "SAM listen address") - ("sam.port", value()->default_value(7656), "SAM listen port") + ("sam.port", value()->default_value(7656), "SAM listen TCP port") + ("sam.portudp", value()->default_value(0), "SAM listen UDP port") ("sam.singlethread", value()->default_value(true), "Sessions run in the SAM bridge's thread") ; diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index 3881f2e1..41bd1d49 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -63,18 +63,19 @@ namespace client if (sam) { std::string samAddr; i2p::config::GetOption("sam.address", samAddr); - uint16_t samPort; i2p::config::GetOption("sam.port", samPort); + uint16_t samPortTCP; i2p::config::GetOption("sam.port", samPortTCP); + uint16_t samPortUDP; i2p::config::GetOption("sam.portudp", samPortUDP); bool singleThread; i2p::config::GetOption("sam.singlethread", singleThread); - LogPrint(eLogInfo, "Clients: Starting SAM bridge at ", samAddr, ":", samPort); + LogPrint(eLogInfo, "Clients: Starting SAM bridge at ", samAddr, ":[", samPortTCP, "|", samPortUDP, "]"); try { - m_SamBridge = new SAMBridge (samAddr, samPort, singleThread); + m_SamBridge = new SAMBridge (samAddr, samPortTCP, samPortUDP, singleThread); m_SamBridge->Start (); } catch (std::exception& e) { LogPrint(eLogError, "Clients: Exception in SAM bridge: ", e.what()); - ThrowFatal ("Unable to start SAM bridge at ", samAddr, ":", samPort, ": ", e.what ()); + ThrowFatal ("Unable to start SAM bridge at ", samAddr, ":[", samPortTCP, "|", samPortUDP,"]: ", e.what ()); } } diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 93df59fb..4e19990a 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -1244,10 +1244,10 @@ namespace client // TODO: implement datagrams } - SAMBridge::SAMBridge (const std::string& address, int port, bool singleThread): + SAMBridge::SAMBridge (const std::string& address, int portTCP, int portUDP, bool singleThread): RunnableService ("SAM"), m_IsSingleThread (singleThread), - m_Acceptor (GetIOService (), boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(address), port)), - m_DatagramEndpoint (boost::asio::ip::address::from_string(address), port-1), m_DatagramSocket (GetIOService (), m_DatagramEndpoint), + m_Acceptor (GetIOService (), boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(address), portTCP)), + m_DatagramEndpoint (boost::asio::ip::address::from_string(address), (!portUDP) ? portTCP-1 : portUDP), m_DatagramSocket (GetIOService (), m_DatagramEndpoint), m_SignatureTypes { {"DSA_SHA1", i2p::data::SIGNING_KEY_TYPE_DSA_SHA1}, diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index b6ac23a6..97ac0b8e 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -233,7 +233,7 @@ namespace client { public: - SAMBridge (const std::string& address, int port, bool singleThread); + SAMBridge (const std::string& address, int portTCP, int portUDP, bool singleThread); ~SAMBridge (); void Start (); From b7f0d87dafa8957131b496c38fbe65d8cb378a9d Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sun, 26 Feb 2023 20:38:23 +0000 Subject: [PATCH 0029/1171] GHA and Cmake changes (#1888) Done with Vort's (https://github.com/Vort) cooperation Signed-off-by: R4SAS --- .editorconfig | 4 + .github/workflows/build-deb.yml | 17 ++- .github/workflows/build-freebsd.yml | 10 +- .github/workflows/build-osx.yml | 7 +- .github/workflows/build-windows.yml | 82 +++++++++++++-- .github/workflows/build.yml | 25 +++-- .github/workflows/docker.yml | 155 ++++++++++++++-------------- Makefile | 12 ++- Makefile.bsd | 3 +- Makefile.linux | 5 +- Makefile.mingw | 16 +-- Makefile.osx | 8 +- Win32/Resource.rc | 72 ++++++------- Win32/Resource.rc2 | 4 +- build/.gitignore | 7 +- build/CMakeLists.txt | 110 ++++++++++++++------ build/cmake_modules/Version.cmake | 16 +++ libi2pd/version.h | 4 +- 18 files changed, 369 insertions(+), 188 deletions(-) create mode 100644 build/cmake_modules/Version.cmake diff --git a/.editorconfig b/.editorconfig index ed3973c5..e1f1243a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -30,3 +30,7 @@ indent_size = 4 indent_style = space indent_size = 2 trim_trailing_whitespace = false + +[*.yml] +indent_style = space +indent_size = 2 diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index f8fd249c..ebc3df4d 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -6,25 +6,34 @@ jobs: build: name: ${{ matrix.dist }} runs-on: ubuntu-latest + strategy: fail-fast: false matrix: dist: ['buster', 'bullseye', 'bookworm'] + steps: - - uses: actions/checkout@v2 + - name: Checkout + uses: actions/checkout@v3 with: fetch-depth: 0 - - uses: jtdor/build-deb-action@v1 + + - name: Build package + uses: jtdor/build-deb-action@v1 with: docker-image: debian:${{ matrix.dist }}-slim buildpackage-opts: --build=binary --no-sign before-build-hook: debchange --controlmaint --local "+${{ github.sha }}~${{ matrix.dist }}" -b --distribution ${{ matrix.dist }} "CI build" extra-build-deps: devscripts git - - uses: actions/upload-artifact@v3 + + - name: Upload package + uses: actions/upload-artifact@v3 with: name: i2pd_${{ matrix.dist }} path: debian/artifacts/i2pd_*.deb - - uses: actions/upload-artifact@v3 + + - name: Upload debugging symbols + uses: actions/upload-artifact@v3 with: name: i2pd-dbgsym_${{ matrix.dist }} path: debian/artifacts/i2pd-dbgsym_*.deb diff --git a/.github/workflows/build-freebsd.yml b/.github/workflows/build-freebsd.yml index 557a9b13..76b496ad 100644 --- a/.github/workflows/build-freebsd.yml +++ b/.github/workflows/build-freebsd.yml @@ -6,8 +6,11 @@ jobs: build: runs-on: macos-12 name: with UPnP + steps: - - uses: actions/checkout@v2 + - name: Checkout + uses: actions/checkout@v3 + - name: Test in FreeBSD id: test uses: vmactions/freebsd-vm@v0.3.0 @@ -21,8 +24,9 @@ jobs: cd build cmake -DWITH_UPNP=ON -DCMAKE_BUILD_TYPE=Release . gmake -j2 + - name: Upload artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: i2pd-freebsd - path: build/i2pd \ No newline at end of file + path: build/i2pd diff --git a/.github/workflows/build-osx.yml b/.github/workflows/build-osx.yml index afddb7e9..266f2c54 100644 --- a/.github/workflows/build-osx.yml +++ b/.github/workflows/build-osx.yml @@ -6,16 +6,21 @@ jobs: build: name: With USE_UPNP=${{ matrix.with_upnp }} runs-on: macOS-latest + strategy: fail-fast: true matrix: with_upnp: ['yes', 'no'] + steps: - - uses: actions/checkout@v2 + - name: Checkout + uses: actions/checkout@v3 + - name: install packages run: | find /usr/local/bin -lname '*/Library/Frameworks/Python.framework/*' -delete brew update brew install boost miniupnpc openssl@1.1 + - name: build application run: make HOMEBREW=1 USE_UPNP=${{ matrix.with_upnp }} PREFIX=$GITHUB_WORKSPACE/output -j3 diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index e7752d55..7a9a40c7 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -10,42 +10,104 @@ jobs: build: name: Building using ${{ matrix.arch }} toolchain runs-on: windows-latest + strategy: - fail-fast: true + fail-fast: false matrix: include: [ - { msystem: UCRT64, arch: ucrt-x86_64, arch_short: x64-ucrt }, - { msystem: MINGW64, arch: x86_64, arch_short: x64 }, - { msystem: MINGW32, arch: i686, arch_short: x86 } + { msystem: UCRT64, arch: ucrt-x86_64, arch_short: x64-ucrt, compiler: gcc }, + { msystem: CLANG64, arch: clang-x86_64, arch_short: x64-clang, compiler: clang }, + { msystem: MINGW64, arch: x86_64, arch_short: x64, compiler: gcc }, + { msystem: MINGW32, arch: i686, arch_short: x86, compiler: gcc } ] + steps: - - uses: actions/checkout@v2 + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Setup MSYS2 uses: msys2/setup-msys2@v2 with: msystem: ${{ matrix.msystem }} - install: base-devel mingw-w64-${{ matrix.arch }}-gcc mingw-w64-${{ matrix.arch }}-boost mingw-w64-${{ matrix.arch }}-openssl mingw-w64-${{ matrix.arch }}-miniupnpc + install: base-devel git mingw-w64-${{ matrix.arch }}-${{ matrix.compiler }} mingw-w64-${{ matrix.arch }}-boost mingw-w64-${{ matrix.arch }}-openssl mingw-w64-${{ matrix.arch }}-miniupnpc update: true + + - name: Install additional clang packages + if: ${{ matrix.msystem == 'CLANG64' }} + run: pacman --noconfirm -S mingw-w64-${{ matrix.arch }}-gcc-compat + - name: Build application run: | mkdir -p obj/Win32 obj/libi2pd obj/libi2pd_client obj/daemon make USE_UPNP=yes DEBUG=no USE_GIT_VERSION=yes -j3 + - name: Upload artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: i2pd-${{ matrix.arch_short }}.exe path: i2pd.exe + + build-cmake: + name: Building using ${{ matrix.arch }} toolchain using CMake + runs-on: windows-latest + + strategy: + fail-fast: false + matrix: + include: [ + { msystem: UCRT64, arch: ucrt-x86_64, arch_short: x64-ucrt, compiler: gcc }, + { msystem: CLANG64, arch: clang-x86_64, arch_short: x64-clang, compiler: clang }, + { msystem: MINGW64, arch: x86_64, arch_short: x64, compiler: gcc }, + { msystem: MINGW32, arch: i686, arch_short: x86, compiler: gcc } + ] + + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Setup MSYS2 + uses: msys2/setup-msys2@v2 + with: + msystem: ${{ matrix.msystem }} + install: base-devel git mingw-w64-${{ matrix.arch }}-cmake mingw-w64-${{ matrix.arch }}-ninja mingw-w64-${{ matrix.arch }}-${{ matrix.compiler }} mingw-w64-${{ matrix.arch }}-boost mingw-w64-${{ matrix.arch }}-openssl mingw-w64-${{ matrix.arch }}-miniupnpc + update: true + + - name: Build application + run: | + cd build + cmake -DWITH_GIT_VERSION=ON -DWITH_STATIC=ON -DWITH_UPNP=ON -DCMAKE_BUILD_TYPE=Release . + cmake --build . -- -j3 + + - name: Upload artifacts + uses: actions/upload-artifact@v3 + with: + name: i2pd-cmake-${{ matrix.arch_short }}.exe + path: build/i2pd.exe + build-xp: name: Building for Windows XP runs-on: windows-latest + + strategy: + fail-fast: false + steps: - - uses: actions/checkout@v2 + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Setup MSYS2 uses: msys2/setup-msys2@v2 with: msystem: MINGW32 install: base-devel git mingw-w64-i686-gcc mingw-w64-i686-boost mingw-w64-i686-openssl mingw-w64-i686-miniupnpc update: true + - name: Build WinXP-capable CRT packages run: | git clone https://github.com/msys2/MINGW-packages @@ -64,12 +126,14 @@ jobs: pacman --noconfirm -U mingw-w64-i686-libwinpthread-git-*-any.pkg.tar.zst mingw-w64-i686-winpthreads-git-*-any.pkg.tar.zst popd popd + - name: Build application run: | mkdir -p obj/Win32 obj/libi2pd obj/libi2pd_client obj/daemon make USE_UPNP=yes DEBUG=no USE_GIT_VERSION=yes USE_WINXP_FLAGS=yes -j3 + - name: Upload artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: i2pd-xp.exe path: i2pd.exe diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d8828f61..935c2f93 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,34 +5,43 @@ on: [push, pull_request] jobs: build-make: name: Make with USE_UPNP=${{ matrix.with_upnp }} - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest + strategy: fail-fast: true matrix: with_upnp: ['yes', 'no'] + steps: - - uses: actions/checkout@v2 + - name: Checkout + uses: actions/checkout@v3 + - name: install packages run: | - sudo add-apt-repository ppa:mhier/libboost-latest sudo apt-get update - sudo apt-get install build-essential libboost1.74-dev libminiupnpc-dev libssl-dev zlib1g-dev + sudo apt-get install build-essential libboost-all-dev libminiupnpc-dev libssl-dev zlib1g-dev + - name: build application run: make USE_UPNP=${{ matrix.with_upnp }} -j3 + build-cmake: name: CMake with -DWITH_UPNP=${{ matrix.with_upnp }} - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest + strategy: fail-fast: true matrix: with_upnp: ['ON', 'OFF'] + steps: - - uses: actions/checkout@v2 + - name: Checkout + uses: actions/checkout@v3 + - name: install packages run: | - sudo add-apt-repository ppa:mhier/libboost-latest sudo apt-get update - sudo apt-get install build-essential cmake libboost1.74-dev libminiupnpc-dev libssl-dev zlib1g-dev + sudo apt-get install build-essential cmake libboost-all-dev libminiupnpc-dev libssl-dev zlib1g-dev + - name: build application run: | cd build diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 1f3142e4..28e4e8b0 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -10,6 +10,7 @@ on: jobs: build: + name: Building container for ${{ matrix.platform }} runs-on: ubuntu-latest permissions: packages: write @@ -25,42 +26,44 @@ jobs: ] steps: - - name: Checkout - uses: actions/checkout@v2 + - name: Checkout + uses: actions/checkout@v3 - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 - - name: Login to DockerHub - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Login to DockerHub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Login to GitHub Container registry - uses: docker/login-action@v2 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + - name: Login to GitHub Container registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - - name: Build container for ${{ matrix.archname }} - uses: docker/build-push-action@v3 - with: - context: ./contrib/docker - file: ./contrib/docker/Dockerfile - platforms: ${{ matrix.platform }} - push: true - tags: | - purplei2p/i2pd:latest-${{ matrix.archname }} - ghcr.io/purplei2p/i2pd:latest-${{ matrix.archname }} - provenance: false + - name: Build container for ${{ matrix.archname }} + uses: docker/build-push-action@v3 + with: + context: ./contrib/docker + file: ./contrib/docker/Dockerfile + platforms: ${{ matrix.platform }} + push: true + tags: | + purplei2p/i2pd:latest-${{ matrix.archname }} + ghcr.io/purplei2p/i2pd:latest-${{ matrix.archname }} + provenance: false push: + name: Pushing merged manifest runs-on: ubuntu-latest + permissions: packages: write contents: read @@ -68,60 +71,60 @@ jobs: needs: build steps: - - name: Checkout - uses: actions/checkout@v2 + - name: Checkout + uses: actions/checkout@v3 - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 - - name: Login to DockerHub - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Login to DockerHub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Login to GitHub Container registry - uses: docker/login-action@v2 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + - name: Login to GitHub Container registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - - name: Create and push latest manifest image to Docker Hub - if: ${{ !startsWith(github.ref, 'refs/tags/') }} - uses: Noelware/docker-manifest-action@master - with: - inputs: purplei2p/i2pd:latest - images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7 - push: true + - name: Create and push latest manifest image to Docker Hub + if: ${{ !startsWith(github.ref, 'refs/tags/') }} + uses: Noelware/docker-manifest-action@master + with: + inputs: purplei2p/i2pd:latest + images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7 + push: true - - name: Create and push latest manifest image to GHCR - if: ${{ !startsWith(github.ref, 'refs/tags/') }} - uses: Noelware/docker-manifest-action@master - with: - inputs: ghcr.io/purplei2p/i2pd:latest - images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7 - push: true + - name: Create and push latest manifest image to GHCR + if: ${{ !startsWith(github.ref, 'refs/tags/') }} + uses: Noelware/docker-manifest-action@master + with: + inputs: ghcr.io/purplei2p/i2pd:latest + images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7 + push: true - - name: Store release version to env - if: ${{ startsWith(github.ref, 'refs/tags/') }} - run: echo "RELEASE_VERSION=${GITHUB_REF:10}" >> $GITHUB_ENV + - name: Store release version to env + if: ${{ startsWith(github.ref, 'refs/tags/') }} + run: echo "RELEASE_VERSION=${GITHUB_REF:10}" >> $GITHUB_ENV - - name: Create and push release manifest to Docker Hub - if: ${{ startsWith(github.ref, 'refs/tags/') }} - uses: Noelware/docker-manifest-action@master - with: - inputs: purplei2p/i2pd:latest,purplei2p/i2pd:latest-release,purplei2p/i2pd:release-${{ env.RELEASE_VERSION }} - images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7 - push: true + - name: Create and push release manifest to Docker Hub + if: ${{ startsWith(github.ref, 'refs/tags/') }} + uses: Noelware/docker-manifest-action@master + with: + inputs: purplei2p/i2pd:latest,purplei2p/i2pd:latest-release,purplei2p/i2pd:release-${{ env.RELEASE_VERSION }} + images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7 + push: true - - name: Create and push release manifest to GHCR - if: ${{ startsWith(github.ref, 'refs/tags/') }} - uses: Noelware/docker-manifest-action@master - with: - inputs: ghcr.io/purplei2p/i2pd:latest,ghcr.io/purplei2p/i2pd:latest-release,ghcr.io/purplei2p/i2pd:release-${{ env.RELEASE_VERSION }} - images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7 - push: true + - name: Create and push release manifest to GHCR + if: ${{ startsWith(github.ref, 'refs/tags/') }} + uses: Noelware/docker-manifest-action@master + with: + inputs: ghcr.io/purplei2p/i2pd:latest,ghcr.io/purplei2p/i2pd:latest-release,ghcr.io/purplei2p/i2pd:release-${{ env.RELEASE_VERSION }} + images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7 + push: true diff --git a/Makefile b/Makefile index 520a56ba..0861ec0b 100644 --- a/Makefile +++ b/Makefile @@ -71,13 +71,15 @@ else # not supported $(error Not supported platform) endif +INCFLAGS += -I$(LIB_SRC_DIR) -I$(LIB_CLIENT_SRC_DIR) -I$(LANG_SRC_DIR) +DEFINES += -DOPENSSL_SUPPRESS_DEPRECATED +NEEDED_CXXFLAGS += -MMD -MP + ifeq ($(USE_GIT_VERSION),yes) GIT_VERSION := $(shell git describe --tags) - NEEDED_CXXFLAGS += -DGITVER=\"$(GIT_VERSION)\" + DEFINES += -DGITVER=$(GIT_VERSION) endif -NEEDED_CXXFLAGS += -MMD -MP -I$(LIB_SRC_DIR) -I$(LIB_CLIENT_SRC_DIR) -I$(LANG_SRC_DIR) -DOPENSSL_SUPPRESS_DEPRECATED - LIB_OBJS += $(patsubst %.cpp,obj/%.o,$(LIB_SRC)) LIB_CLIENT_OBJS += $(patsubst %.cpp,obj/%.o,$(LIB_CLIENT_SRC)) LANG_OBJS += $(patsubst %.cpp,obj/%.o,$(LANG_SRC)) @@ -110,13 +112,13 @@ wrapper: api_client $(SHLIB_WRAP) $(ARLIB_WRAP) ## custom FLAGS to work at build-time. obj/%.o: %.cpp | mk_obj_dir - $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -c -o $@ $< + $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(DEFINES) $(INCFLAGS) -c -o $@ $< # '-' is 'ignore if missing' on first run -include $(DEPS) $(I2PD): $(DAEMON_OBJS) $(ARLIB) $(ARLIB_CLIENT) $(ARLIB_LANG) - $(CXX) -o $@ $(LDFLAGS) $^ $(LDLIBS) + $(CXX) -o $@ $(DEFINES) $(LDFLAGS) $^ $(LDLIBS) $(SHLIB): $(LIB_OBJS) ifneq ($(USE_STATIC),yes) diff --git a/Makefile.bsd b/Makefile.bsd index 39e5651a..00543193 100644 --- a/Makefile.bsd +++ b/Makefile.bsd @@ -6,7 +6,8 @@ CXXFLAGS ?= ${CXX_DEBUG} -Wall -Wextra -Wno-unused-parameter -pedantic -Wno-misl ## (e.g. -fstack-protector-strong -Wformat -Werror=format-security), we do not want to remove ## -std=c++11. If you want to remove this variable please do so in a way that allows setting ## custom FLAGS to work at build-time. -NEEDED_CXXFLAGS = -std=c++11 -D_GLIBCXX_USE_NANOSLEEP=1 +NEEDED_CXXFLAGS = -std=c++11 +DEFINES = -D_GLIBCXX_USE_NANOSLEEP=1 INCFLAGS = -I/usr/include/ -I/usr/local/include/ LDFLAGS = ${LD_DEBUG} -Wl,-rpath,/usr/local/lib -L/usr/local/lib LDLIBS = -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread diff --git a/Makefile.linux b/Makefile.linux index d01f2b73..6c7a4619 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -58,12 +58,13 @@ endif # UPNP Support (miniupnpc 1.5 and higher) ifeq ($(USE_UPNP),yes) - NEEDED_CXXFLAGS += -DUSE_UPNP + DEFINES += -DUSE_UPNP endif ifeq ($(USE_AESNI),yes) ifneq (, $(findstring i386, $(SYS))$(findstring i686, $(SYS))$(findstring x86_64, $(SYS))) # only x86-based CPU supports that - NEEDED_CXXFLAGS += -D__AES__ -maes + NEEDED_CXXFLAGS += -maes + DEFINES += -D__AES__ endif endif diff --git a/Makefile.mingw b/Makefile.mingw index a1a861e6..6cd19080 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -4,17 +4,18 @@ USE_WIN32_APP := yes WINDRES = windres CXXFLAGS := $(CXX_DEBUG) -fPIC -msse -INCFLAGS = -I$(DAEMON_SRC_DIR) -IWin32 +INCFLAGS := -I$(DAEMON_SRC_DIR) -IWin32 LDFLAGS := ${LD_DEBUG} -static -NEEDED_CXXFLAGS += -std=c++17 -DWIN32_LEAN_AND_MEAN +NEEDED_CXXFLAGS += -std=c++17 +DEFINES += -DWIN32_LEAN_AND_MEAN # Boost libraries suffix BOOST_SUFFIX = -mt # UPNP Support ifeq ($(USE_UPNP),yes) - CXXFLAGS += -DUSE_UPNP -DMINIUPNP_STATICLIB + DEFINES += -DUSE_UPNP -DMINIUPNP_STATICLIB LDLIBS = -lminiupnpc endif @@ -35,18 +36,19 @@ LDLIBS += \ -lpthread ifeq ($(USE_WIN32_APP), yes) - NEEDED_CXXFLAGS += -DWIN32_APP + DEFINES += -DWIN32_APP LDFLAGS += -mwindows DAEMON_RC += Win32/Resource.rc DAEMON_OBJS += $(patsubst %.rc,obj/%.o,$(DAEMON_RC)) endif ifeq ($(USE_WINXP_FLAGS), yes) - NEEDED_CXXFLAGS += -DWINVER=0x0501 -D_WIN32_WINNT=0x0501 + DEFINES += -DWINVER=0x0501 -D_WIN32_WINNT=0x0501 endif ifeq ($(USE_AESNI),yes) - NEEDED_CXXFLAGS += -D__AES__ -maes + NEEDED_CXXFLAGS += -maes + DEFINES += -D__AES__ endif ifeq ($(USE_ASLR),yes) @@ -54,4 +56,4 @@ ifeq ($(USE_ASLR),yes) endif obj/%.o : %.rc | mk_obj_dir - $(WINDRES) -i $< -o $@ + $(WINDRES) $(DEFINES) $(INCFLAGS) --preprocessor-arg=-MMD --preprocessor-arg=-MP --preprocessor-arg=-MF$@.d -i $< -o $@ diff --git a/Makefile.osx b/Makefile.osx index 2e52585e..b91008d6 100644 --- a/Makefile.osx +++ b/Makefile.osx @@ -1,6 +1,7 @@ CXX = clang++ -CXXFLAGS := ${CXX_DEBUG} -Wall -std=c++11 -DMAC_OSX +CXXFLAGS := ${CXX_DEBUG} -Wall -std=c++11 INCFLAGS = -I/usr/local/include +DEFINES := -DMAC_OSX LDFLAGS := -Wl,-rpath,/usr/local/lib -L/usr/local/lib LDFLAGS += -Wl,-dead_strip LDFLAGS += -Wl,-dead_strip_dylibs @@ -14,7 +15,7 @@ endif ifeq ($(USE_UPNP),yes) LDFLAGS += -ldl - CXXFLAGS += -DUSE_UPNP + DEFINES += -DUSE_UPNP ifeq ($(USE_STATIC),yes) LDLIBS += /usr/local/lib/libminiupnpc.a else @@ -23,7 +24,8 @@ ifeq ($(USE_UPNP),yes) endif ifeq ($(USE_AESNI),yes) - CXXFLAGS += -D__AES__ -maes + CXXFLAGS += -maes + DEFINES += -D__AES__ else CXXFLAGS += -msse endif diff --git a/Win32/Resource.rc b/Win32/Resource.rc index 5d394d1a..c9266b08 100644 --- a/Win32/Resource.rc +++ b/Win32/Resource.rc @@ -1,36 +1,36 @@ -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -#include "winres.h" -#undef APSTUDIO_READONLY_SYMBOLS - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) - -#ifdef APSTUDIO_INVOKED -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END -#endif // APSTUDIO_INVOKED - -MAINICON ICON "mask.ico" -#endif // English (United States) resources - -#ifndef APSTUDIO_INVOKED -#include "Resource.rc2" -#endif // not APSTUDIO_INVOKED - +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +#include "winres.h" +#undef APSTUDIO_READONLY_SYMBOLS + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) + +#ifdef APSTUDIO_INVOKED +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END +#endif // APSTUDIO_INVOKED + +MAINICON ICON "mask.ico" +#endif // English (United States) resources + +#ifndef APSTUDIO_INVOKED +#include "Resource.rc2" +#endif // not APSTUDIO_INVOKED + diff --git a/Win32/Resource.rc2 b/Win32/Resource.rc2 index 873d6402..32744584 100644 --- a/Win32/Resource.rc2 +++ b/Win32/Resource.rc2 @@ -2,7 +2,7 @@ #error this file is not editable by Microsoft Visual C++ #endif //APSTUDIO_INVOKED -#include "../libi2pd/version.h" +#include "version.h" VS_VERSION_INFO VERSIONINFO FILEVERSION I2PD_VERSION_MAJOR,I2PD_VERSION_MINOR,I2PD_VERSION_MICRO,I2PD_VERSION_PATCH @@ -25,7 +25,7 @@ BEGIN VALUE "FileDescription", "C++ I2P daemon" VALUE "FileVersion", I2PD_VERSION VALUE "InternalName", CODENAME - VALUE "LegalCopyright", "Copyright (C) 2013-2022, The PurpleI2P Project" + VALUE "LegalCopyright", "Copyright (C) 2013-2023, The PurpleI2P Project" VALUE "OriginalFilename", "i2pd" VALUE "ProductName", "Purple I2P" VALUE "ProductVersion", I2P_VERSION diff --git a/build/.gitignore b/build/.gitignore index 7689cc88..d51958d6 100644 --- a/build/.gitignore +++ b/build/.gitignore @@ -2,7 +2,12 @@ /CMakeFiles/ /Testing/ /tests/ +/.ninja_* +/arch.c +/build.ninja /i2pd +/i2pd.exe +/i2pd.exe.debug /libi2pd.a /libi2pdclient.a /libi2pdlang.a @@ -12,7 +17,7 @@ /CPackSourceConfig.cmake /CTestTestfile.cmake /install_manifest.txt -/arch.c +/Makefile # windows build script i2pd*.zip build*.log diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index f6f52001..3ac2f61a 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -1,14 +1,32 @@ cmake_minimum_required(VERSION 3.7) -cmake_policy(VERSION 3.7) -project("i2pd") + +if(${CMAKE_VERSION} VERSION_LESS 3.22) + cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) +else() + cmake_policy(VERSION 3.22) +endif() # for debugging #set(CMAKE_VERBOSE_MAKEFILE on) -# Win32 build with cmake is not supported -if(WIN32 OR MSVC OR MSYS OR MINGW) - message(SEND_ERROR "cmake build for windows is not supported. Please use MSYS2 with makefiles in project root.") -endif() +# paths +set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules") +set(CMAKE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/..") + +set(LIBI2PD_SRC_DIR ${CMAKE_SOURCE_DIR}/libi2pd) +set(LIBI2PD_CLIENT_SRC_DIR ${CMAKE_SOURCE_DIR}/libi2pd_client) +set(LANG_SRC_DIR ${CMAKE_SOURCE_DIR}/i18n) +set(DAEMON_SRC_DIR ${CMAKE_SOURCE_DIR}/daemon) + +include(Version) +set_version("${LIBI2PD_SRC_DIR}/version.h" PROJECT_VERSION) + +project( + i2pd + VERSION ${PROJECT_VERSION} + HOMEPAGE_URL "https://i2pd.website/" + LANGUAGES CXX +) # configurable options option(WITH_AESNI "Use AES-NI instructions set" ON) @@ -26,27 +44,16 @@ IF(BUILD_TESTING) enable_testing() ENDIF() -# paths -set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules") -set(CMAKE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/..") - # Handle paths nicely include(GNUInstallDirs) -# architecture +# Architecture include(TargetArch) target_architecture(ARCHITECTURE) -set(LIBI2PD_SRC_DIR ../libi2pd) -set(LIBI2PD_CLIENT_SRC_DIR ../libi2pd_client) -set(LANG_SRC_DIR ../i18n) -set(DAEMON_SRC_DIR ../daemon) +include(CheckAtomic) include_directories(${LIBI2PD_SRC_DIR}) -include_directories(${LIBI2PD_CLIENT_SRC_DIR}) -include_directories(${LANG_SRC_DIR}) -include_directories(${DAEMON_SRC_DIR}) - FILE(GLOB LIBI2PD_SRC ${LIBI2PD_SRC_DIR}/*.cpp) add_library(libi2pd ${LIBI2PD_SRC}) set_target_properties(libi2pd PROPERTIES PREFIX "") @@ -57,11 +64,9 @@ if(WITH_LIBRARY) ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT Libraries) -# TODO Make libi2pd available to 3rd party projects via CMake as imported target -# FIXME This pulls stdafx -# install(EXPORT libi2pd DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif() +include_directories(${LIBI2PD_CLIENT_SRC_DIR}) FILE(GLOB CLIENT_SRC ${LIBI2PD_CLIENT_SRC_DIR}/*.cpp) add_library(libi2pdclient ${CLIENT_SRC}) set_target_properties(libi2pdclient PROPERTIES PREFIX "") @@ -74,6 +79,7 @@ if(WITH_LIBRARY) COMPONENT Libraries) endif() +include_directories(${LANG_SRC_DIR}) FILE(GLOB LANG_SRC ${LANG_SRC_DIR}/*.cpp) add_library(libi2pdlang ${LANG_SRC}) set_target_properties(libi2pdlang PROPERTIES PREFIX "") @@ -86,6 +92,8 @@ if(WITH_LIBRARY) COMPONENT Libraries) endif() +include_directories(${DAEMON_SRC_DIR}) + set(DAEMON_SRC "${DAEMON_SRC_DIR}/Daemon.cpp" "${DAEMON_SRC_DIR}/HTTPServer.cpp" @@ -95,6 +103,22 @@ set(DAEMON_SRC "${DAEMON_SRC_DIR}/UPnP.cpp" ) +if(WIN32) + set(WIN32_SRC_DIR ${CMAKE_SOURCE_DIR}/Win32) + include_directories(${WIN32_SRC_DIR}) + + list(APPEND DAEMON_SRC + "${WIN32_SRC_DIR}/DaemonWin32.cpp" + "${WIN32_SRC_DIR}/Win32App.cpp" + "${WIN32_SRC_DIR}/Win32Service.cpp" + "${WIN32_SRC_DIR}/Win32NetState.cpp" + ) + + file(GLOB WIN32_RC ${WIN32_SRC_DIR}/*.rc) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWIN32_APP -DWIN32_LEAN_AND_MEAN") + +endif() + if(WITH_UPNP) add_definitions(-DUSE_UPNP) endif() @@ -102,14 +126,14 @@ endif() if(WITH_GIT_VERSION) include(GetGitRevisionDescription) git_describe(GIT_VERSION) - add_definitions(-DGITVER="${GIT_VERSION}") + add_definitions(-DGITVER=${GIT_VERSION}) endif() if(APPLE) add_definitions(-DMAC_OSX) endif() -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Winvalid-pch -Wno-unused-parameter") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Winvalid-pch -Wno-unused-parameter -Wno-uninitialized") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pedantic") # TODO: The following is incompatible with static build and enabled hardening for OpenWRT. # Multiple definitions of __stack_chk_fail(libssp & libc) @@ -118,8 +142,10 @@ set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "-Wl,--gc-sections") # -flto is added from # check for c++17 & c++11 support include(CheckCXXCompilerFlag) + CHECK_CXX_COMPILER_FLAG("-std=c++17" CXX17_SUPPORTED) CHECK_CXX_COMPILER_FLAG("-std=c++11" CXX11_SUPPORTED) + if(CXX17_SUPPORTED) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") elseif(CXX11_SUPPORTED) @@ -188,10 +214,23 @@ set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) if(WITH_STATIC) + set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") + set(Boost_USE_STATIC_LIBS ON) - set(Boost_USE_STATIC_RUNTIME ON) + set(Boost_USE_STATIC_RUNTIME OFF) + set(OPENSSL_USE_STATIC_LIBS ON) + + set(ZLIB_USE_STATIC_LIBS ON) + set(ZLIB_NAMES libz zlibstatic zlibstat zlib z) + + if(WITH_UPNP) + set(MINIUPNPC_USE_STATIC_LIBS ON) + add_definitions(-DMINIUPNP_STATICLIB) + endif() + set(BUILD_SHARED_LIBS OFF) + if(${CMAKE_CXX_COMPILER} MATCHES ".*-openwrt-.*") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") # set(CMAKE_THREAD_LIBS_INIT "gcc_eh -Wl,--whole-archive -lpthread -Wl,--no-whole-archive") @@ -236,8 +275,6 @@ endif() # load includes include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR}) -include(CheckAtomic) - # show summary message(STATUS "---------------------------------------") message(STATUS "Build type : ${CMAKE_BUILD_TYPE}") @@ -259,7 +296,15 @@ message(STATUS " THREADSANITIZER : ${WITH_THREADSANITIZER}") message(STATUS "---------------------------------------") if(WITH_BINARY) - add_executable("${PROJECT_NAME}" ${DAEMON_SRC}) + if(WIN32) + add_executable("${PROJECT_NAME}" WIN32 ${DAEMON_SRC} ${WIN32_RC}) + else() + add_executable("${PROJECT_NAME}" ${DAEMON_SRC}) + endif() + + if (WIN32) + set(MINGW_EXTRA "wsock32" "ws2_32" "iphlpapi") + endif () if(WITH_STATIC) set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-static") @@ -275,11 +320,18 @@ if(WITH_BINARY) list(REMOVE_AT Boost_LIBRARIES -1) endif() + # synchronization library is incompatible with Windows 7 + if(WIN32) + get_target_property(BOOSTFSLIBS Boost::filesystem INTERFACE_LINK_LIBRARIES) + list(REMOVE_ITEM BOOSTFSLIBS synchronization) + set_target_properties(Boost::filesystem PROPERTIES INTERFACE_LINK_LIBRARIES "${BOOSTFSLIBS}") + endif() + if(WITH_STATIC) set(DL_LIB ${CMAKE_DL_LIBS}) endif() - target_link_libraries("${PROJECT_NAME}" libi2pd libi2pdclient libi2pdlang ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto ${MINIUPNPC_LIBRARY} ZLIB::ZLIB Threads::Threads ${DL_LIB} ${CMAKE_REQUIRED_LIBRARIES}) + target_link_libraries("${PROJECT_NAME}" libi2pd libi2pdclient libi2pdlang ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto ${MINIUPNPC_LIBRARY} ZLIB::ZLIB Threads::Threads ${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}") diff --git a/build/cmake_modules/Version.cmake b/build/cmake_modules/Version.cmake new file mode 100644 index 00000000..cb9551db --- /dev/null +++ b/build/cmake_modules/Version.cmake @@ -0,0 +1,16 @@ +# read version + +function(set_version version_file output_var) + file(READ "${version_file}" version_data) + + string(REGEX MATCH "I2PD_VERSION_MAJOR ([0-9]*)" _ ${version_data}) + set(version_major ${CMAKE_MATCH_1}) + + string(REGEX MATCH "I2PD_VERSION_MINOR ([0-9]*)" _ ${version_data}) + set(version_minor ${CMAKE_MATCH_1}) + + string(REGEX MATCH "I2PD_VERSION_MICRO ([0-9]*)" _ ${version_data}) + set(version_micro ${CMAKE_MATCH_1}) + + set(${output_var} "${version_major}.${version_minor}.${version_micro}" PARENT_SCOPE) +endfunction() diff --git a/libi2pd/version.h b/libi2pd/version.h index b7de21a8..8d91c5c8 100644 --- a/libi2pd/version.h +++ b/libi2pd/version.h @@ -11,7 +11,9 @@ #define CODENAME "Purple" +#define XSTRINGIZE(x) STRINGIZE(x) #define STRINGIZE(x) #x + #define MAKE_VERSION(a,b,c) STRINGIZE(a) "." STRINGIZE(b) "." STRINGIZE(c) #define MAKE_VERSION_NUMBER(a,b,c) ((a*100+b)*100+c) @@ -20,7 +22,7 @@ #define I2PD_VERSION_MICRO 1 #define I2PD_VERSION_PATCH 0 #ifdef GITVER - #define I2PD_VERSION GITVER + #define I2PD_VERSION XSTRINGIZE(GITVER) #else #define I2PD_VERSION MAKE_VERSION(I2PD_VERSION_MAJOR, I2PD_VERSION_MINOR, I2PD_VERSION_MICRO) #endif From 10dfe39f5fa3ecb78a5b809a4ac30740b1096827 Mon Sep 17 00:00:00 2001 From: Vort Date: Mon, 27 Feb 2023 14:32:42 +0200 Subject: [PATCH 0030/1171] Fix architecture detection in cmake build (#1890) --- build/cmake_modules/TargetArch.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/cmake_modules/TargetArch.cmake b/build/cmake_modules/TargetArch.cmake index d59925c8..e611c4f7 100644 --- a/build/cmake_modules/TargetArch.cmake +++ b/build/cmake_modules/TargetArch.cmake @@ -18,7 +18,7 @@ set(archdetect_c_code " || defined(_M_ARM64) \\ || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 8) #error cmake_ARCH arm64 - #if defined(__ARM_ARCH_7__) \\ + #elif defined(__ARM_ARCH_7__) \\ || defined(__ARM_ARCH_7A__) \\ || defined(__ARM_ARCH_7R__) \\ || defined(__ARM_ARCH_7M__) \\ From 5f8820d9d6412470d1eeeadef9591f4d0db62f74 Mon Sep 17 00:00:00 2001 From: Vort Date: Mon, 27 Feb 2023 21:35:06 +0200 Subject: [PATCH 0031/1171] Silence several compiler warnings --- Win32/Win32Service.cpp | 2 +- libi2pd/util.cpp | 10 +++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/Win32/Win32Service.cpp b/Win32/Win32Service.cpp index d4ba0d76..a9ecf477 100644 --- a/Win32/Win32Service.cpp +++ b/Win32/Win32Service.cpp @@ -21,7 +21,7 @@ BOOL I2PService::isService() HWINSTA hWinStation = GetProcessWindowStation(); if (hWinStation != NULL) { - USEROBJECTFLAGS uof = { 0 }; + USEROBJECTFLAGS uof = { FALSE, FALSE, 0 }; if (GetUserObjectInformation(hWinStation, UOI_FLAGS, &uof, sizeof(USEROBJECTFLAGS), NULL) && ((uof.dwFlags & WSF_VISIBLE) == 0)) { bIsService = TRUE; diff --git a/libi2pd/util.cpp b/libi2pd/util.cpp index 369f999e..6d49c6c9 100644 --- a/libi2pd/util.cpp +++ b/libi2pd/util.cpp @@ -200,13 +200,11 @@ namespace net pCurrAddresses = pAddresses; while(pCurrAddresses) { - PIP_ADAPTER_UNICAST_ADDRESS firstUnicastAddress = pCurrAddresses->FirstUnicastAddress; - pUnicast = pCurrAddresses->FirstUnicastAddress; if(pUnicast == nullptr) LogPrint(eLogError, "NetIface: GetMTU: Not a unicast IPv4 address, this is not supported"); - for(int i = 0; pUnicast != nullptr; ++i) + while(pUnicast != nullptr) { LPSOCKADDR lpAddr = pUnicast->Address.lpSockaddr; sockaddr_in* localInterfaceAddress = (sockaddr_in*) lpAddr; @@ -264,12 +262,11 @@ namespace net pCurrAddresses = pAddresses; while (pCurrAddresses) { - PIP_ADAPTER_UNICAST_ADDRESS firstUnicastAddress = pCurrAddresses->FirstUnicastAddress; pUnicast = pCurrAddresses->FirstUnicastAddress; if (pUnicast == nullptr) LogPrint(eLogError, "NetIface: GetMTU: Not a unicast IPv6 address, this is not supported"); - for (int i = 0; pUnicast != nullptr; ++i) + while (pUnicast != nullptr) { LPSOCKADDR lpAddr = pUnicast->Address.lpSockaddr; sockaddr_in6 *localInterfaceAddress = (sockaddr_in6*) lpAddr; @@ -533,10 +530,9 @@ namespace net pCurrAddresses = pAddresses; while(pCurrAddresses) { - PIP_ADAPTER_UNICAST_ADDRESS firstUnicastAddress = pCurrAddresses->FirstUnicastAddress; pUnicast = pCurrAddresses->FirstUnicastAddress; - for(int i = 0; pUnicast != nullptr; ++i) + while(pUnicast != nullptr) { LPSOCKADDR lpAddr = pUnicast->Address.lpSockaddr; sockaddr_in6 *localInterfaceAddress = (sockaddr_in6*) lpAddr; From 34617bcb442f2b0c246fd94a73ecae0ce29a491d Mon Sep 17 00:00:00 2001 From: Vort Date: Mon, 27 Feb 2023 21:35:23 +0200 Subject: [PATCH 0032/1171] Code style unification across file --- libi2pd/util.cpp | 65 ++++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/libi2pd/util.cpp b/libi2pd/util.cpp index 6d49c6c9..daf7fcbf 100644 --- a/libi2pd/util.cpp +++ b/libi2pd/util.cpp @@ -75,7 +75,8 @@ const char *inet_ntop_xp(int af, const void *src, char *dst, socklen_t size) ZeroMemory(&ss, sizeof(ss)); ss.ss_family = af; - switch(af) { + switch (af) + { case AF_INET: ((struct sockaddr_in *)&ss)->sin_addr = *(struct in_addr *)src; break; @@ -179,7 +180,7 @@ namespace net PIP_ADAPTER_ADDRESSES pCurrAddresses = nullptr; PIP_ADAPTER_UNICAST_ADDRESS pUnicast = nullptr; - if(GetAdaptersAddresses(AF_INET, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen) + if (GetAdaptersAddresses(AF_INET, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen) == ERROR_BUFFER_OVERFLOW) { FREE(pAddresses); @@ -190,7 +191,7 @@ namespace net AF_INET, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen ); - if(dwRetVal != NO_ERROR) + if (dwRetVal != NO_ERROR) { LogPrint(eLogError, "NetIface: GetMTU: Enclosed GetAdaptersAddresses() call has failed"); FREE(pAddresses); @@ -198,17 +199,17 @@ namespace net } pCurrAddresses = pAddresses; - while(pCurrAddresses) + while (pCurrAddresses) { pUnicast = pCurrAddresses->FirstUnicastAddress; - if(pUnicast == nullptr) + if (pUnicast == nullptr) LogPrint(eLogError, "NetIface: GetMTU: Not a unicast IPv4 address, this is not supported"); - while(pUnicast != nullptr) + while (pUnicast != nullptr) { LPSOCKADDR lpAddr = pUnicast->Address.lpSockaddr; sockaddr_in* localInterfaceAddress = (sockaddr_in*) lpAddr; - if(localInterfaceAddress->sin_addr.S_un.S_addr == inputAddress.sin_addr.S_un.S_addr) + if (localInterfaceAddress->sin_addr.S_un.S_addr == inputAddress.sin_addr.S_un.S_addr) { char addr[INET_ADDRSTRLEN]; inetntop(AF_INET, &(((struct sockaddr_in *)localInterfaceAddress)->sin_addr), addr, INET_ADDRSTRLEN); @@ -314,13 +315,13 @@ namespace net IPN inetpton = (IPN)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetPton"); if (!inetpton) inetpton = inet_pton_xp; // use own implementation if not found - if(localAddress.is_v4()) + if (localAddress.is_v4()) { sockaddr_in inputAddress; inetpton(AF_INET, localAddressUniversal.c_str(), &(inputAddress.sin_addr)); return GetMTUWindowsIpv4(inputAddress, fallback); } - else if(localAddress.is_v6()) + else if (localAddress.is_v6()) { sockaddr_in6 inputAddress; inetpton(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr)); @@ -336,7 +337,7 @@ namespace net int GetMTUUnix (const boost::asio::ip::address& localAddress, int fallback) { ifaddrs* ifaddr, *ifa = nullptr; - if(getifaddrs(&ifaddr) == -1) + if (getifaddrs(&ifaddr) == -1) { LogPrint(eLogError, "NetIface: Can't call getifaddrs(): ", strerror(errno)); return fallback; @@ -344,34 +345,34 @@ namespace net int family = 0; // look for interface matching local address - for(ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) + for (ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) { - if(!ifa->ifa_addr) + if (!ifa->ifa_addr) continue; family = ifa->ifa_addr->sa_family; - if(family == AF_INET && localAddress.is_v4()) + if (family == AF_INET && localAddress.is_v4()) { sockaddr_in* sa = (sockaddr_in*) ifa->ifa_addr; - if(!memcmp(&sa->sin_addr, localAddress.to_v4().to_bytes().data(), 4)) + if (!memcmp(&sa->sin_addr, localAddress.to_v4().to_bytes().data(), 4)) break; // address matches } - else if(family == AF_INET6 && localAddress.is_v6()) + else if (family == AF_INET6 && localAddress.is_v6()) { sockaddr_in6* sa = (sockaddr_in6*) ifa->ifa_addr; - if(!memcmp(&sa->sin6_addr, localAddress.to_v6().to_bytes().data(), 16)) + if (!memcmp(&sa->sin6_addr, localAddress.to_v6().to_bytes().data(), 16)) break; // address matches } } int mtu = fallback; - if(ifa && family) + if (ifa && family) { // interface found? int fd = socket(family, SOCK_DGRAM, 0); - if(fd > 0) + if (fd > 0) { ifreq ifr; strncpy(ifr.ifr_name, ifa->ifa_name, IFNAMSIZ-1); // set interface for query - if(ioctl(fd, SIOCGIFMTU, &ifr) >= 0) + if (ioctl(fd, SIOCGIFMTU, &ifr) >= 0) mtu = ifr.ifr_mtu; // MTU else LogPrint (eLogError, "NetIface: Failed to run ioctl: ", strerror(errno)); @@ -404,7 +405,7 @@ namespace net { #ifdef _WIN32 LogPrint(eLogError, "NetIface: Cannot get address by interface name, not implemented on WIN32"); - if(ipv6) + if (ipv6) return boost::asio::ip::address::from_string("::1"); else return boost::asio::ip::address::from_string("127.0.0.1"); @@ -423,7 +424,7 @@ namespace net // match char addr[INET6_ADDRSTRLEN]; memset (addr, 0, INET6_ADDRSTRLEN); - if(af == AF_INET) + if (af == AF_INET) inet_ntop(af, &((sockaddr_in *)cur->ifa_addr)->sin_addr, addr, INET6_ADDRSTRLEN); else inet_ntop(af, &((sockaddr_in6 *)cur->ifa_addr)->sin6_addr, addr, INET6_ADDRSTRLEN); @@ -439,9 +440,9 @@ namespace net LogPrint(eLogError, "NetIface: Exception while searching address using ifaddr: ", ex.what()); } - if(addrs) freeifaddrs(addrs); + if (addrs) freeifaddrs(addrs); std::string fallback; - if(ipv6) + if (ipv6) { fallback = "::1"; LogPrint(eLogWarning, "NetIface: Cannot find IPv6 address for interface ", ifname); @@ -509,7 +510,7 @@ namespace net PIP_ADAPTER_ADDRESSES pCurrAddresses = nullptr; PIP_ADAPTER_UNICAST_ADDRESS pUnicast = nullptr; - if(GetAdaptersAddresses(AF_INET6, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen) + if (GetAdaptersAddresses(AF_INET6, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen) == ERROR_BUFFER_OVERFLOW) { FREE(pAddresses); @@ -520,7 +521,7 @@ namespace net AF_INET6, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen ); - if(dwRetVal != NO_ERROR) + if (dwRetVal != NO_ERROR) { LogPrint(eLogError, "NetIface: GetYggdrasilAddress(): enclosed GetAdaptersAddresses() call has failed"); FREE(pAddresses); @@ -528,11 +529,11 @@ namespace net } pCurrAddresses = pAddresses; - while(pCurrAddresses) + while (pCurrAddresses) { pUnicast = pCurrAddresses->FirstUnicastAddress; - while(pUnicast != nullptr) + while (pUnicast != nullptr) { LPSOCKADDR lpAddr = pUnicast->Address.lpSockaddr; sockaddr_in6 *localInterfaceAddress = (sockaddr_in6*) lpAddr; @@ -576,7 +577,7 @@ namespace net LogPrint(eLogError, "NetIface: Exception while searching Yggdrasill address using ifaddr: ", ex.what()); } LogPrint(eLogWarning, "NetIface: Interface with Yggdrasil network address not found"); - if(addrs) freeifaddrs(addrs); + if (addrs) freeifaddrs(addrs); return boost::asio::ip::address_v6 (); #endif } @@ -596,7 +597,7 @@ namespace net { // https://en.wikipedia.org/wiki/Reserved_IP_addresses if (host.is_unspecified ()) return false; - if(host.is_v4()) + if (host.is_v4()) { static const std::vector< std::pair > reservedIPv4Ranges { address_pair_v4("0.0.0.0", "0.255.255.255"), @@ -616,12 +617,12 @@ namespace net }; uint32_t ipv4_address = host.to_v4 ().to_ulong (); - for(const auto& it : reservedIPv4Ranges) { + for (const auto& it : reservedIPv4Ranges) { if (ipv4_address >= it.first && ipv4_address <= it.second) return true; } } - if(host.is_v6()) + if (host.is_v6()) { static const std::vector< std::pair > reservedIPv6Ranges { address_pair_v6("2001:db8::", "2001:db8:ffff:ffff:ffff:ffff:ffff:ffff"), @@ -633,7 +634,7 @@ namespace net }; boost::asio::ip::address_v6::bytes_type ipv6_address = host.to_v6 ().to_bytes (); - for(const auto& it : reservedIPv6Ranges) { + for (const auto& it : reservedIPv6Ranges) { if (ipv6_address >= it.first && ipv6_address <= it.second) return true; } From 64f0a545fdf99bb1967d99ccd402e28db571d1f7 Mon Sep 17 00:00:00 2001 From: Vort Date: Tue, 28 Feb 2023 19:41:17 +0200 Subject: [PATCH 0033/1171] Improve MSVC 2015 compatibility --- libi2pd/I2PEndian.h | 18 ++++++++++++++++++ libi2pd/Streaming.cpp | 2 +- libi2pd/util.cpp | 31 ++++++++++++++++++++++++++++++- libi2pd_client/HTTPProxy.cpp | 2 +- 4 files changed, 50 insertions(+), 3 deletions(-) diff --git a/libi2pd/I2PEndian.h b/libi2pd/I2PEndian.h index d97bd055..06abf29a 100644 --- a/libi2pd/I2PEndian.h +++ b/libi2pd/I2PEndian.h @@ -36,6 +36,23 @@ #define le64toh(x) OSSwapLittleToHostInt64(x) #elif defined(_WIN32) +#if defined(_MSC_VER) +#include +#define htobe16(x) _byteswap_ushort(x) +#define htole16(x) (x) +#define be16toh(x) _byteswap_ushort(x) +#define le16toh(x) (x) + +#define htobe32(x) _byteswap_ulong(x) +#define htole32(x) (x) +#define be32toh(x) _byteswap_ulong(x) +#define le32toh(x) (x) + +#define htobe64(x) _byteswap_uint64(x) +#define htole64(x) (x) +#define be64toh(x) _byteswap_uint64(x) +#define le64toh(x) (x) +#else #define htobe16(x) __builtin_bswap16(x) #define htole16(x) (x) #define be16toh(x) __builtin_bswap16(x) @@ -50,6 +67,7 @@ #define htole64(x) (x) #define be64toh(x) __builtin_bswap64(x) #define le64toh(x) (x) +#endif #else #define NEEDS_LOCAL_ENDIAN diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 62c4acc7..1049abce 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -384,7 +384,7 @@ namespace stream memset (p.buf, 0, 22); // minimal header all zeroes memcpy (p.buf + 4, packet->buf, 4); // but receiveStreamID is the sendStreamID from the ping htobe16buf (p.buf + 18, PACKET_FLAG_ECHO); // and echo flag - ssize_t payloadLen = packet->len - (packet->GetPayload () - packet->buf); + auto payloadLen = int(packet->len) - (packet->GetPayload () - packet->buf); if (payloadLen > 0) memcpy (p.buf + 22, packet->GetPayload (), payloadLen); else diff --git a/libi2pd/util.cpp b/libi2pd/util.cpp index daf7fcbf..2426f13a 100644 --- a/libi2pd/util.cpp +++ b/libi2pd/util.cpp @@ -15,7 +15,7 @@ #include "Log.h" #include "I2PEndian.h" -#if not defined (__FreeBSD__) +#if !defined (__FreeBSD__) && !defined(_MSC_VER) #include #endif @@ -37,6 +37,19 @@ #include #include +#if defined(_MSC_VER) +const DWORD MS_VC_EXCEPTION = 0x406D1388; +#pragma pack(push,8) +typedef struct tagTHREADNAME_INFO +{ + DWORD dwType; + LPCSTR szName; + DWORD dwThreadID; + DWORD dwFlags; +} THREADNAME_INFO; +#pragma pack(pop) +#endif + #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) #define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) @@ -162,7 +175,23 @@ namespace util #elif defined(__NetBSD__) pthread_setname_np(pthread_self(), "%s", (void *)name); #elif !defined(__gnu_hurd__) + #if defined(_MSC_VER) + THREADNAME_INFO info; + info.dwType = 0x1000; + info.szName = name; + info.dwThreadID = -1; + info.dwFlags = 0; + #pragma warning(push) + #pragma warning(disable: 6320 6322) + __try { + RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info); + } + __except (EXCEPTION_EXECUTE_HANDLER) { + } + #pragma warning(pop) + #else pthread_setname_np(pthread_self(), name); + #endif #endif } diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index 3e5ab595..61930876 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -113,7 +113,7 @@ namespace proxy { i2p::http::URL m_ProxyURL; i2p::http::URL m_RequestURL; uint8_t m_socks_buf[255+8]; // for socks request/response - ssize_t m_req_len; + int m_req_len; i2p::http::URL m_ClientRequestURL; i2p::http::HTTPReq m_ClientRequest; i2p::http::HTTPRes m_ClientResponse; From a199084c99daa963eabfd65d9a9a47b4a57712b6 Mon Sep 17 00:00:00 2001 From: Vort Date: Wed, 1 Mar 2023 08:52:40 +0200 Subject: [PATCH 0034/1171] Add MSVC support to CMake build --- build/CMakeLists.txt | 61 ++++++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 22 deletions(-) diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 3ac2f61a..999e0a76 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -53,6 +53,12 @@ target_architecture(ARCHITECTURE) include(CheckAtomic) +if(WITH_STATIC) + if(MSVC) + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + endif() +endif() + include_directories(${LIBI2PD_SRC_DIR}) FILE(GLOB LIBI2PD_SRC ${LIBI2PD_SRC_DIR}/*.cpp) add_library(libi2pd ${LIBI2PD_SRC}) @@ -133,25 +139,30 @@ if(APPLE) add_definitions(-DMAC_OSX) endif() -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Winvalid-pch -Wno-unused-parameter -Wno-uninitialized") -set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pedantic") -# TODO: The following is incompatible with static build and enabled hardening for OpenWRT. -# Multiple definitions of __stack_chk_fail(libssp & libc) -set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -flto -s -ffunction-sections -fdata-sections") -set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "-Wl,--gc-sections") # -flto is added from above - -# check for c++17 & c++11 support -include(CheckCXXCompilerFlag) - -CHECK_CXX_COMPILER_FLAG("-std=c++17" CXX17_SUPPORTED) -CHECK_CXX_COMPILER_FLAG("-std=c++11" CXX11_SUPPORTED) - -if(CXX17_SUPPORTED) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") -elseif(CXX11_SUPPORTED) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") +if(MSVC) + add_definitions(-DWINVER=0x0501) + add_definitions(-D_WIN32_WINNT=0x0501) else() - message(SEND_ERROR "C++17 nor C++11 standard not seems to be supported by compiler. Too old version?") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Winvalid-pch -Wno-unused-parameter -Wno-uninitialized") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pedantic") + # TODO: The following is incompatible with static build and enabled hardening for OpenWRT. + # Multiple definitions of __stack_chk_fail(libssp & libc) + set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -flto -s -ffunction-sections -fdata-sections") + set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "-Wl,--gc-sections") # -flto is added from above + + # check for c++17 & c++11 support + include(CheckCXXCompilerFlag) + + CHECK_CXX_COMPILER_FLAG("-std=c++17" CXX17_SUPPORTED) + CHECK_CXX_COMPILER_FLAG("-std=c++11" CXX11_SUPPORTED) + + if(CXX17_SUPPORTED) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") + elseif(CXX11_SUPPORTED) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + else() + message(SEND_ERROR "C++17 nor C++11 standard not seems to be supported by compiler. Too old version?") + endif() endif() if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") @@ -217,7 +228,11 @@ if(WITH_STATIC) set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") set(Boost_USE_STATIC_LIBS ON) - set(Boost_USE_STATIC_RUNTIME OFF) + if(MSVC) + set(Boost_USE_STATIC_RUNTIME ON) + else() + set(Boost_USE_STATIC_RUNTIME OFF) + endif() set(OPENSSL_USE_STATIC_LIBS ON) @@ -244,7 +259,7 @@ else() add_definitions(-DBOOST_SYSTEM_DYN_LINK -DBOOST_FILESYSTEM_DYN_LINK -DBOOST_PROGRAM_OPTIONS_DYN_LINK -DBOOST_DATE_TIME_DYN_LINK -DBOOST_REGEX_DYN_LINK) endif() -find_package(Boost COMPONENTS system filesystem program_options date_time REQUIRED) +find_package(Boost REQUIRED COMPONENTS system filesystem program_options date_time OPTIONAL_COMPONENTS atomic) if(NOT DEFINED Boost_INCLUDE_DIRS) message(SEND_ERROR "Boost is not found, or your boost version was below 1.46. Please download Boost!") endif() @@ -307,7 +322,9 @@ if(WITH_BINARY) endif () if(WITH_STATIC) - set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-static") + if(NOT MSVC) + set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-static") + endif() endif() if(WITH_HARDENING AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") @@ -324,7 +341,7 @@ if(WITH_BINARY) if(WIN32) get_target_property(BOOSTFSLIBS Boost::filesystem INTERFACE_LINK_LIBRARIES) list(REMOVE_ITEM BOOSTFSLIBS synchronization) - set_target_properties(Boost::filesystem PROPERTIES INTERFACE_LINK_LIBRARIES "${BOOSTFSLIBS}") + set_target_properties(Boost::filesystem PROPERTIES INTERFACE_LINK_LIBRARIES "${BOOSTFSLIBS}") endif() if(WITH_STATIC) From 231c02c058ee59e26d50ce5873b6919be8d51616 Mon Sep 17 00:00:00 2001 From: Vort Date: Wed, 1 Mar 2023 22:41:31 +0200 Subject: [PATCH 0035/1171] Make Win32NetState compatible with MSVC --- Win32/Win32NetState.cpp | 4 ++++ build/CMakeLists.txt | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Win32/Win32NetState.cpp b/Win32/Win32NetState.cpp index 5c56711d..216c36b6 100644 --- a/Win32/Win32NetState.cpp +++ b/Win32/Win32NetState.cpp @@ -29,7 +29,11 @@ void SubscribeToEvents() if (SUCCEEDED(Result)) { VARIANT_BOOL IsConnect = VARIANT_FALSE; +#if defined(_MSC_VER) + Result = pNetworkListManager->get_IsConnectedToInternet(&IsConnect); +#else Result = pNetworkListManager->IsConnectedToInternet(&IsConnect); +#endif if (SUCCEEDED(Result)) { i2p::transport::transports.SetOnline (true); LogPrint(eLogInfo, "NetState: Current state: ", IsConnect == VARIANT_TRUE ? "connected" : "disconnected"); diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 999e0a76..2379f9cb 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -140,8 +140,8 @@ if(APPLE) endif() if(MSVC) - add_definitions(-DWINVER=0x0501) - add_definitions(-D_WIN32_WINNT=0x0501) + add_definitions(-DWINVER=0x0600) + add_definitions(-D_WIN32_WINNT=0x0600) else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Winvalid-pch -Wno-unused-parameter -Wno-uninitialized") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pedantic") From 1b921a2eac8a297eb266ab6ad1dad153f33a63bb Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 1 Mar 2023 22:05:24 -0500 Subject: [PATCH 0036/1171] removed some SSU1 code --- libi2pd/RouterInfo.cpp | 11 ++--------- libi2pd/RouterInfo.h | 3 +-- libi2pd/SSU2.cpp | 1 - 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 3fb95814..8117b9fb 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -336,11 +336,7 @@ namespace data address->ssu->introducers.resize (index + 1); } Introducer& introducer = address->ssu->introducers.at (index); - if (!strcmp (key, "ihost")) - introducer.isH = false; // SSU1 - else if (!strcmp (key, "iport")) - introducer.isH = false; // SSU1 - else if (!strcmp (key, "itag")) + if (!strcmp (key, "itag")) { try { @@ -352,10 +348,7 @@ namespace data } } else if (!strcmp (key, "ih")) - { Base64ToByteStream (value, strlen (value), introducer.iH, 32); - introducer.isH = true; - } else if (!strcmp (key, "iexp")) { try @@ -411,7 +404,7 @@ namespace data int numValid = 0; for (auto& it: address->ssu->introducers) { - if (it.iTag && ts < it.iExp && it.isH) + if (it.iTag && ts < it.iExp) numValid++; else it.iTag = 0; diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 1024cda8..ffab8e10 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -110,11 +110,10 @@ namespace data struct Introducer { - Introducer (): iTag (0), iExp (0), isH (false) {}; + Introducer (): iTag (0), iExp (0) {}; IdentHash iH; uint32_t iTag; uint32_t iExp; - bool isH; // TODO: remove later }; struct SSUExt diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 3773f03d..4abf0c17 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -1017,7 +1017,6 @@ namespace transport i2p::data::RouterInfo::Introducer introducer; introducer.iTag = it->GetRelayTag (); introducer.iH = it->GetRemoteIdentity ()->GetIdentHash (); - introducer.isH = true; introducer.iExp = it->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION; excluded.insert (it->GetRemoteIdentity ()->GetIdentHash ()); if (i2p::context.AddSSU2Introducer (introducer, v4)) From 9e0389df1bd0671f608ba493a6adc88195da6e9d Mon Sep 17 00:00:00 2001 From: Vort Date: Thu, 2 Mar 2023 12:14:49 +0200 Subject: [PATCH 0037/1171] Fix several warnings --- libi2pd/Gzip.cpp | 2 +- libi2pd/SSU2.cpp | 4 ++-- libi2pd/Streaming.cpp | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libi2pd/Gzip.cpp b/libi2pd/Gzip.cpp index 35676f5c..4be8684c 100644 --- a/libi2pd/Gzip.cpp +++ b/libi2pd/Gzip.cpp @@ -139,7 +139,7 @@ namespace data if (m_IsDirty) deflateReset (&m_Deflator); m_IsDirty = true; size_t offset = 0; - int err; + int err = 0; for (const auto& it: bufs) { m_Deflator.next_in = const_cast(it.first); diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 4abf0c17..b50284a6 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -918,7 +918,7 @@ namespace transport } uint64_t token; RAND_bytes ((uint8_t *)&token, 8); - m_IncomingTokens.emplace (ep, std::make_pair (token, ts + SSU2_TOKEN_EXPIRATION_TIMEOUT)); + m_IncomingTokens.emplace (ep, std::make_pair (token, uint32_t(ts + SSU2_TOKEN_EXPIRATION_TIMEOUT))); return token; } @@ -927,7 +927,7 @@ namespace transport m_IncomingTokens.erase (ep); // drop previous uint64_t token; RAND_bytes ((uint8_t *)&token, 8); - auto ret = std::make_pair (token, i2p::util::GetSecondsSinceEpoch () + SSU2_NEXT_TOKEN_EXPIRATION_TIMEOUT); + auto ret = std::make_pair (token, uint32_t(i2p::util::GetSecondsSinceEpoch () + SSU2_NEXT_TOKEN_EXPIRATION_TIMEOUT)); m_IncomingTokens.emplace (ep, ret); return ret; } diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 1049abce..67ed925d 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -51,8 +51,8 @@ namespace stream { // partially rem = len - offset; - memcpy (buf + offset, nextBuffer->GetRemaningBuffer (), len - offset); - nextBuffer->offset += (len - offset); + memcpy (buf + offset, nextBuffer->GetRemaningBuffer (), rem); + nextBuffer->offset += rem; offset = len; // break } } From 064c013a72da56bd879913aafc74a086eec22cee Mon Sep 17 00:00:00 2001 From: Vort Date: Thu, 2 Mar 2023 21:25:29 +0200 Subject: [PATCH 0038/1171] Remove unreachable reseed --- libi2pd/Config.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 8df08118..f9d894fa 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -215,7 +215,6 @@ namespace config { "https://reseed.onion.im/," "https://i2pseed.creativecowpat.net:8443/," "https://reseed.i2pgit.org/," - "https://i2p.novg.net/," "https://banana.incognet.io/," "https://reseed-pl.i2pd.xyz/," "https://www2.mk16.de/" From 4db643aa8e91d82bf9026391a3bacfb418402f85 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 2 Mar 2023 16:18:25 -0500 Subject: [PATCH 0039/1171] limited number of acked packets to 511 --- libi2pd/SSU2Session.cpp | 2 +- libi2pd/SSU2Session.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index f2b002cd..46acf05b 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1661,7 +1661,7 @@ namespace transport // ranges len -= 5; const uint8_t * ranges = buf + 5; - while (len > 0 && firstPacketNum) + while (len > 0 && firstPacketNum && ackThrough - firstPacketNum < SSU2_MAX_NUM_ACK_PACKETS) { uint32_t lastPacketNum = firstPacketNum - 1; if (*ranges > lastPacketNum) break; diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index 363cb982..304efdab 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -49,10 +49,10 @@ namespace transport const float SSU2_kAPPA = 1.8; const size_t SSU2_MAX_OUTGOING_QUEUE_SIZE = 500; // in messages const int SSU2_MAX_NUM_ACNT = 255; // acnt, acks or nacks - const int SSU2_MAX_NUM_ACK_PACKETS = 510; // 2*255 ack + nack + const int SSU2_MAX_NUM_ACK_PACKETS = 511; // ackthrough + acnt + 1 range const int SSU2_MAX_NUM_ACK_RANGES = 32; // to send const uint8_t SSU2_MAX_NUM_FRAGMENTS = 64; - const int SSU2_SEND_DATETIME_NUM_PACKETS = 250; + const int SSU2_SEND_DATETIME_NUM_PACKETS = 256; // flags const uint8_t SSU2_FLAG_IMMEDIATE_ACK_REQUESTED = 0x01; From 6610af08c28380cafa584cf2e3204dee8d30998d Mon Sep 17 00:00:00 2001 From: Vort Date: Fri, 3 Mar 2023 21:26:38 +0200 Subject: [PATCH 0040/1171] Correct processing of reseed.floodfill option --- libi2pd/NetDb.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 2302dc86..18f948ac 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -431,8 +431,8 @@ namespace data } // try reseeding from floodfill first if specified - std::string riPath; - if(i2p::config::GetOption("reseed.floodfill", riPath)) + std::string riPath; i2p::config::GetOption("reseed.floodfill", riPath); + if (!riPath.empty()) { auto ri = std::make_shared(riPath); if (ri->IsFloodfill()) From a4759694c819a0fa92613813734e31da93ce5514 Mon Sep 17 00:00:00 2001 From: Vort Date: Fri, 3 Mar 2023 21:28:22 +0200 Subject: [PATCH 0041/1171] Prevent out of bounds array access --- libi2pd/Reseed.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Reseed.cpp b/libi2pd/Reseed.cpp index 4c23b4cc..4a6e5a7e 100644 --- a/libi2pd/Reseed.cpp +++ b/libi2pd/Reseed.cpp @@ -320,7 +320,7 @@ namespace data uint16_t fileNameLength, extraFieldLength; s.read ((char *)&fileNameLength, 2); fileNameLength = le16toh (fileNameLength); - if ( fileNameLength > 255 ) { + if ( fileNameLength >= 255 ) { // too big LogPrint(eLogError, "Reseed: SU3 fileNameLength too large: ", fileNameLength); return numFiles; From d50cf0ad83dfea3b00b27dc1789ff6032f985f3f Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 3 Mar 2023 20:21:56 -0500 Subject: [PATCH 0042/1171] recognize congestion caps --- libi2pd/NetDb.cpp | 2 +- libi2pd/RouterInfo.cpp | 38 +++++++++++++++++++++++++++++++++++--- libi2pd/RouterInfo.h | 20 +++++++++++++++++++- 3 files changed, 55 insertions(+), 5 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 18f948ac..5dfb7889 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -1210,7 +1210,7 @@ namespace data router->IsReachableFrom (*compatibleWith)) && (router->GetCaps () & RouterInfo::eHighBandwidth) && router->GetVersion () >= NETDB_MIN_HIGHBANDWIDTH_VERSION && - router->IsECIES (); + router->IsECIES () && !router->IsHighCongestion (); }); } diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 8117b9fb..e6197061 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -43,7 +43,7 @@ namespace data RouterInfo::RouterInfo (const std::string& fullPath): m_FamilyID (0), m_IsUpdated (false), m_IsUnreachable (false), m_SupportedTransports (0),m_ReachableTransports (0), - m_Caps (0), m_Version (0) + m_Caps (0), m_Version (0), m_Congestion (eLowCongestion) { m_Addresses = boost::make_shared(); // create empty list m_Buffer = NewBuffer (); // always RouterInfo's @@ -53,7 +53,7 @@ namespace data RouterInfo::RouterInfo (std::shared_ptr&& buf, size_t len): m_FamilyID (0), m_IsUpdated (true), m_IsUnreachable (false), m_SupportedTransports (0), m_ReachableTransports (0), - m_Caps (0), m_Version (0) + m_Caps (0), m_Version (0), m_Congestion (eLowCongestion) { if (len <= MAX_RI_BUFFER_SIZE) { @@ -202,7 +202,7 @@ namespace data void RouterInfo::ReadFromStream (std::istream& s) { if (!s) return; - m_Caps = 0; + m_Caps = 0; m_Congestion = eLowCongestion; s.read ((char *)&m_Timestamp, sizeof (m_Timestamp)); m_Timestamp = be64toh (m_Timestamp); // read addresses @@ -535,6 +535,15 @@ namespace data case CAPS_FLAG_UNREACHABLE: m_Caps |= Caps::eUnreachable; break; + case CAPS_FLAG_MEDIUM_COGNESTION: + m_Congestion = eMediumCongestion; + break; + case CAPS_FLAG_HIGH_COGNESTION: + m_Congestion = eHighCongestion; + break; + case CAPS_FLAG_REJECT_ALL_COGNESTION: + m_Congestion = eRejectAll; + break; default: ; } cap++; @@ -1057,6 +1066,15 @@ namespace data m_Timestamp = i2p::util::GetMillisecondsSinceEpoch (); } + bool RouterInfo::IsHighCongestion () const + { + if (m_Congestion == eLowCongestion || m_Congestion == eMediumCongestion) return false; + if (m_Congestion == eRejectAll) return true; + if (m_Congestion == eHighCongestion) + return (i2p::util::GetMillisecondsSinceEpoch () < m_Timestamp + HIGH_COGNESION_INTERVAL*1000LL) ? true : false; + return false; + } + void LocalRouterInfo::CreateBuffer (const PrivateKeys& privateKeys) { RefreshTimestamp (); @@ -1108,6 +1126,20 @@ namespace data if (c & eReachable) caps += CAPS_FLAG_REACHABLE; // reachable if (c & eUnreachable) caps += CAPS_FLAG_UNREACHABLE; // unreachable + switch (GetCongestion ()) + { + case eMediumCongestion: + caps += CAPS_FLAG_MEDIUM_COGNESTION; + break; + case eHighCongestion: + caps += CAPS_FLAG_HIGH_COGNESTION; + break; + case eRejectAll: + caps += CAPS_FLAG_REJECT_ALL_COGNESTION; + break; + default: ; + }; + SetProperty ("caps", caps); } diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index ffab8e10..e0ca53e5 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -44,7 +44,11 @@ namespace data const char CAPS_FLAG_HIGH_BANDWIDTH3 = 'O'; /* 128-256 KBps */ const char CAPS_FLAG_EXTRA_BANDWIDTH1 = 'P'; /* 256-2000 KBps */ const char CAPS_FLAG_EXTRA_BANDWIDTH2 = 'X'; /* > 2000 KBps */ - + // congesion flags + const char CAPS_FLAG_MEDIUM_COGNESTION = 'D'; + const char CAPS_FLAG_HIGH_COGNESTION = 'E'; + const char CAPS_FLAG_REJECT_ALL_COGNESTION = 'G'; + const char CAPS_FLAG_V4 = '4'; const char CAPS_FLAG_V6 = '6'; const char CAPS_FLAG_SSU2_TESTING = 'B'; @@ -56,6 +60,8 @@ namespace data const uint8_t COST_SSU2_NON_PUBLISHED = 15; const size_t MAX_RI_BUFFER_SIZE = 3072; // if RouterInfo exceeds 3K we consider it as malformed, might extend later + const int HIGH_COGNESION_INTERVAL = 15*60; // in seconds, 15 minutes + class RouterInfo: public RoutingDestination { public: @@ -93,6 +99,14 @@ namespace data eUnreachable = 0x20 }; + enum Congestion + { + eLowCongestion = 0, + eMediumCongestion, + eHighCongestion, + eRejectAll + }; + enum AddressCaps { eV4 = 0x01, @@ -234,10 +248,13 @@ namespace data bool IsEligibleFloodfill () const; bool IsSSU2PeerTesting (bool v4) const; bool IsSSU2Introducer (bool v4) const; + bool IsHighCongestion () const; uint8_t GetCaps () const { return m_Caps; }; void SetCaps (uint8_t caps) { m_Caps = caps; }; + Congestion GetCongestion () const { return m_Congestion; }; + void SetUnreachable (bool unreachable) { m_IsUnreachable = unreachable; }; bool IsUnreachable () const { return m_IsUnreachable; }; @@ -302,6 +319,7 @@ namespace data CompatibleTransports m_SupportedTransports, m_ReachableTransports; uint8_t m_Caps; int m_Version; + Congestion m_Congestion; mutable std::shared_ptr m_Profile; }; From 3154eda6a648730db30553287037a50f851e9f11 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 4 Mar 2023 15:46:44 -0500 Subject: [PATCH 0043/1171] fixed typos --- libi2pd/RouterInfo.cpp | 14 +++++++------- libi2pd/RouterInfo.h | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index e6197061..e9df01bb 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -535,13 +535,13 @@ namespace data case CAPS_FLAG_UNREACHABLE: m_Caps |= Caps::eUnreachable; break; - case CAPS_FLAG_MEDIUM_COGNESTION: + case CAPS_FLAG_MEDIUM_CONGESTION: m_Congestion = eMediumCongestion; break; - case CAPS_FLAG_HIGH_COGNESTION: + case CAPS_FLAG_HIGH_CONGESTION: m_Congestion = eHighCongestion; break; - case CAPS_FLAG_REJECT_ALL_COGNESTION: + case CAPS_FLAG_REJECT_ALL_CONGESTION: m_Congestion = eRejectAll; break; default: ; @@ -1071,7 +1071,7 @@ namespace data if (m_Congestion == eLowCongestion || m_Congestion == eMediumCongestion) return false; if (m_Congestion == eRejectAll) return true; if (m_Congestion == eHighCongestion) - return (i2p::util::GetMillisecondsSinceEpoch () < m_Timestamp + HIGH_COGNESION_INTERVAL*1000LL) ? true : false; + return (i2p::util::GetMillisecondsSinceEpoch () < m_Timestamp + HIGH_CONGESION_INTERVAL*1000LL) ? true : false; return false; } @@ -1129,13 +1129,13 @@ namespace data switch (GetCongestion ()) { case eMediumCongestion: - caps += CAPS_FLAG_MEDIUM_COGNESTION; + caps += CAPS_FLAG_MEDIUM_CONGESTION; break; case eHighCongestion: - caps += CAPS_FLAG_HIGH_COGNESTION; + caps += CAPS_FLAG_HIGH_CONGESTION; break; case eRejectAll: - caps += CAPS_FLAG_REJECT_ALL_COGNESTION; + caps += CAPS_FLAG_REJECT_ALL_CONGESTION; break; default: ; }; diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index e0ca53e5..3b74eaf3 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -45,9 +45,9 @@ namespace data const char CAPS_FLAG_EXTRA_BANDWIDTH1 = 'P'; /* 256-2000 KBps */ const char CAPS_FLAG_EXTRA_BANDWIDTH2 = 'X'; /* > 2000 KBps */ // congesion flags - const char CAPS_FLAG_MEDIUM_COGNESTION = 'D'; - const char CAPS_FLAG_HIGH_COGNESTION = 'E'; - const char CAPS_FLAG_REJECT_ALL_COGNESTION = 'G'; + const char CAPS_FLAG_MEDIUM_CONGESTION = 'D'; + const char CAPS_FLAG_HIGH_CONGESTION = 'E'; + const char CAPS_FLAG_REJECT_ALL_CONGESTION = 'G'; const char CAPS_FLAG_V4 = '4'; const char CAPS_FLAG_V6 = '6'; @@ -60,7 +60,7 @@ namespace data const uint8_t COST_SSU2_NON_PUBLISHED = 15; const size_t MAX_RI_BUFFER_SIZE = 3072; // if RouterInfo exceeds 3K we consider it as malformed, might extend later - const int HIGH_COGNESION_INTERVAL = 15*60; // in seconds, 15 minutes + const int HIGH_CONGESION_INTERVAL = 15*60; // in seconds, 15 minutes class RouterInfo: public RoutingDestination { From c02c9c3c2448a87ede1527e3d95a9fc52df57580 Mon Sep 17 00:00:00 2001 From: Sergey Fedorov Date: Sun, 5 Mar 2023 23:50:03 +0800 Subject: [PATCH 0044/1171] Makefile.osx: do not use Intel flags on PPC --- Makefile.osx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Makefile.osx b/Makefile.osx index b91008d6..e069aaff 100644 --- a/Makefile.osx +++ b/Makefile.osx @@ -23,9 +23,12 @@ ifeq ($(USE_UPNP),yes) endif endif -ifeq ($(USE_AESNI),yes) - CXXFLAGS += -maes - DEFINES += -D__AES__ -else - CXXFLAGS += -msse +OSARCH = $(shell uname -p) + +ifneq ($(OSARCH),powerpc) + ifeq ($(USE_AESNI),yes) + CXXFLAGS += -D__AES__ -maes + else + CXXFLAGS += -msse + endif endif From 5470a3a4533c8b382fab958bf16fe33942dc24e4 Mon Sep 17 00:00:00 2001 From: Vort Date: Fri, 3 Mar 2023 21:02:54 +0200 Subject: [PATCH 0045/1171] Eliminate memory leak in Win32NetState --- Win32/DaemonWin32.cpp | 2 +- Win32/Win32App.cpp | 11 ++++++++--- Win32/Win32App.h | 2 +- Win32/Win32NetState.cpp | 9 +++++++-- Win32/Win32NetState.h | 7 ++----- 5 files changed, 19 insertions(+), 12 deletions(-) diff --git a/Win32/DaemonWin32.cpp b/Win32/DaemonWin32.cpp index affc301a..e8052f14 100644 --- a/Win32/DaemonWin32.cpp +++ b/Win32/DaemonWin32.cpp @@ -64,7 +64,7 @@ namespace util //setlocale(LC_ALL, "Russian"); setlocale(LC_TIME, "C"); #ifdef WIN32_APP - if (!i2p::win32::StartWin32App ()) return false; + if (!i2p::win32::StartWin32App (isDaemon)) return false; #endif bool ret = Daemon_Singleton::start(); if (ret && i2p::log::Logger().GetLogType() == eLogFile) diff --git a/Win32/Win32App.cpp b/Win32/Win32App.cpp index 37458046..9eae7a95 100644 --- a/Win32/Win32App.cpp +++ b/Win32/Win32App.cpp @@ -45,6 +45,7 @@ namespace i2p namespace win32 { DWORD g_GracefulShutdownEndtime = 0; + bool g_isWinService; static void ShowPopupMenu (HWND hWnd, POINT *curpos, int wDefaultItem) { @@ -416,8 +417,9 @@ namespace win32 return DefWindowProc( hWnd, uMsg, wParam, lParam); } - bool StartWin32App () + bool StartWin32App (bool isWinService) { + g_isWinService = isWinService; if (FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd"))) { MessageBox(NULL, TEXT("I2Pd is running already"), TEXT("Warning"), MB_OK); @@ -446,7 +448,9 @@ namespace win32 MessageBox(NULL, "Failed to create main window", TEXT("Warning!"), MB_ICONERROR | MB_OK | MB_TOPMOST); return false; } - SubscribeToEvents(); + // COM requires message loop to work, which is not implemented in service mode + if (!g_isWinService) + SubscribeToEvents(); return true; } @@ -466,7 +470,8 @@ namespace win32 HWND hWnd = FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd")); if (hWnd) PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_EXIT, 0), 0); - // UnSubscribeFromEvents(); // TODO: understand why unsubscribing crashes app + else if(!g_isWinService) + UnSubscribeFromEvents(); UnregisterClass (I2PD_WIN32_CLASSNAME, GetModuleHandle(NULL)); } diff --git a/Win32/Win32App.h b/Win32/Win32App.h index ebe49efd..614de738 100644 --- a/Win32/Win32App.h +++ b/Win32/Win32App.h @@ -17,7 +17,7 @@ namespace win32 { extern DWORD g_GracefulShutdownEndtime; - bool StartWin32App (); + bool StartWin32App (bool isWinService); void StopWin32App (); int RunWin32App (); bool GracefulShutdown (); diff --git a/Win32/Win32NetState.cpp b/Win32/Win32NetState.cpp index 216c36b6..794dc4b9 100644 --- a/Win32/Win32NetState.cpp +++ b/Win32/Win32NetState.cpp @@ -15,6 +15,7 @@ IUnknown *pUnknown = nullptr; INetworkListManager *pNetworkListManager = nullptr; IConnectionPointContainer *pCPContainer = nullptr; IConnectionPoint *pConnectPoint = nullptr; +CNetworkListManagerEvent *pNetEvent = nullptr; DWORD Cookie = 0; void SubscribeToEvents() @@ -45,8 +46,8 @@ void SubscribeToEvents() Result = pCPContainer->FindConnectionPoint(IID_INetworkListManagerEvents, &pConnectPoint); if(SUCCEEDED(Result)) { - CNetworkListManagerEvent *NetEvent = new CNetworkListManagerEvent; - Result = pConnectPoint->Advise((IUnknown *)NetEvent, &Cookie); + pNetEvent = new CNetworkListManagerEvent; + Result = pConnectPoint->Advise((IUnknown *)pNetEvent, &Cookie); if (SUCCEEDED(Result)) LogPrint(eLogInfo, "NetState: Successfully subscribed to NetworkListManagerEvent messages"); else @@ -63,6 +64,7 @@ void SubscribeToEvents() void UnSubscribeFromEvents() { + LogPrint(eLogInfo, "NetState: Unsubscribing from NetworkListManagerEvents"); try { if (pConnectPoint) { @@ -70,6 +72,9 @@ void UnSubscribeFromEvents() pConnectPoint->Release(); } + if (pNetEvent) + pNetEvent->Release(); + if (pCPContainer) pCPContainer->Release(); diff --git a/Win32/Win32NetState.h b/Win32/Win32NetState.h index c2ddaee4..1414a324 100644 --- a/Win32/Win32NetState.h +++ b/Win32/Win32NetState.h @@ -19,21 +19,18 @@ class CNetworkListManagerEvent : public INetworkListManagerEvents { public: CNetworkListManagerEvent() : m_ref(1) { } - ~CNetworkListManagerEvent() { } HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) { - HRESULT Result = S_OK; if (IsEqualIID(riid, IID_IUnknown)) { *ppvObject = (IUnknown *)this; } else if (IsEqualIID(riid ,IID_INetworkListManagerEvents)) { *ppvObject = (INetworkListManagerEvents *)this; } else { - Result = E_NOINTERFACE; + return E_NOINTERFACE; } AddRef(); - - return Result; + return S_OK; } ULONG STDMETHODCALLTYPE AddRef() From 24a14e3440128fec355b4785d88b899e7d26c210 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 5 Mar 2023 20:08:15 -0500 Subject: [PATCH 0046/1171] moved max num transit tunnels to Tunnels --- daemon/Daemon.cpp | 2 +- daemon/HTTPServer.cpp | 4 ++-- libi2pd/I2NPProtocol.cpp | 19 ++----------------- libi2pd/I2NPProtocol.h | 6 +----- libi2pd/Tunnel.cpp | 11 ++++++++++- libi2pd/Tunnel.h | 8 +++++++- 6 files changed, 23 insertions(+), 27 deletions(-) diff --git a/daemon/Daemon.cpp b/daemon/Daemon.cpp index 2a70dd1f..84f197fb 100644 --- a/daemon/Daemon.cpp +++ b/daemon/Daemon.cpp @@ -179,7 +179,7 @@ namespace util uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels); if (isFloodfill && i2p::config::IsDefault ("limits.transittunnels")) transitTunnels *= 2; // double default number of transit tunnels for floodfill - SetMaxNumTransitTunnels (transitTunnels); + i2p::tunnel::tunnels.SetMaxNumTransitTunnels (transitTunnels); /* this section also honors 'floodfill' flag, if set above */ std::string bandwidth; i2p::config::GetOption("bandwidth", bandwidth); diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index e42efb36..3d5ff1a0 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -754,7 +754,7 @@ namespace http { s << " info \r\n"; s << " debug
\r\n
\r\n"; - uint16_t maxTunnels = GetMaxNumTransitTunnels (); + uint16_t maxTunnels = i2p::tunnel::tunnels.GetMaxNumTransitTunnels (); s << "" << tr("Transit tunnels limit") << "
\r\n"; s << "
\r\n"; s << " \r\n"; @@ -1314,7 +1314,7 @@ namespace http { { uint32_t limit = std::stoul(params["limit"], nullptr); if (limit > 0 && limit <= TRANSIT_TUNNELS_LIMIT) - SetMaxNumTransitTunnels (limit); + i2p::tunnel::tunnels.SetMaxNumTransitTunnels (limit); else { s << "" << tr("ERROR") << ": " << tr("Transit tunnels count must not exceed %d", TRANSIT_TUNNELS_LIMIT) << "\r\n
\r\n
\r\n"; s << "" << tr("Back to commands list") << "\r\n
\r\n"; diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index 4d1ab6d4..c1724b39 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -353,21 +353,6 @@ namespace i2p return !msg->GetPayload ()[DATABASE_STORE_TYPE_OFFSET]; // 0- RouterInfo } - static uint16_t g_MaxNumTransitTunnels = DEFAULT_MAX_NUM_TRANSIT_TUNNELS; // TODO: - void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels) - { - if (maxNumTransitTunnels > 0 && g_MaxNumTransitTunnels != maxNumTransitTunnels) - { - LogPrint (eLogDebug, "I2NP: Max number of transit tunnels set to ", maxNumTransitTunnels); - g_MaxNumTransitTunnels = maxNumTransitTunnels; - } - } - - uint16_t GetMaxNumTransitTunnels () - { - return g_MaxNumTransitTunnels; - } - static bool HandleBuildRequestRecords (int num, uint8_t * records, uint8_t * clearText) { for (int i = 0; i < num; i++) @@ -380,7 +365,7 @@ namespace i2p uint8_t retCode = 0; // replace record to reply if (i2p::context.AcceptsTunnels () && - i2p::tunnel::tunnels.GetTransitTunnels ().size () <= g_MaxNumTransitTunnels && + !i2p::tunnel::tunnels.IsTooManyTransitTunnels () && !i2p::transport::transports.IsBandwidthExceeded () && !i2p::transport::transports.IsTransitBandwidthExceeded ()) { @@ -577,7 +562,7 @@ namespace i2p // check if we accept this tunnel uint8_t retCode = 0; if (!i2p::context.AcceptsTunnels () || - i2p::tunnel::tunnels.GetTransitTunnels ().size () > g_MaxNumTransitTunnels || + i2p::tunnel::tunnels.IsTooManyTransitTunnels () || i2p::transport::transports.IsBandwidthExceeded () || i2p::transport::transports.IsTransitBandwidthExceeded ()) retCode = 30; diff --git a/libi2pd/I2NPProtocol.h b/libi2pd/I2NPProtocol.h index a388dc52..80757501 100644 --- a/libi2pd/I2NPProtocol.h +++ b/libi2pd/I2NPProtocol.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2021, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -308,10 +308,6 @@ namespace tunnel std::vector > m_TunnelMsgs, m_TunnelGatewayMsgs; }; - - const uint16_t DEFAULT_MAX_NUM_TRANSIT_TUNNELS = 5000; - void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels); - uint16_t GetMaxNumTransitTunnels (); } #endif diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 372c3ff9..3e952bbe 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -331,7 +331,7 @@ namespace tunnel Tunnels tunnels; - Tunnels::Tunnels (): m_IsRunning (false), m_Thread (nullptr), + Tunnels::Tunnels (): m_IsRunning (false), m_Thread (nullptr), m_MaxNumTransitTunnels (DEFAULT_MAX_NUM_TRANSIT_TUNNELS), m_TotalNumSuccesiveTunnelCreations (0), m_TotalNumFailedTunnelCreations (0), // for normal avarage m_TunnelCreationSuccessRate (TCSR_START_VALUE), m_TunnelCreationAttemptsNum(0) { @@ -970,5 +970,14 @@ namespace tunnel // TODO: locking return m_OutboundTunnels.size(); } + + void Tunnels::SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels) + { + if (maxNumTransitTunnels > 0 && m_MaxNumTransitTunnels != maxNumTransitTunnels) + { + LogPrint (eLogDebug, "Tunnel: Max number of transit tunnels set to ", maxNumTransitTunnels); + m_MaxNumTransitTunnels = maxNumTransitTunnels; + } + } } } diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index b690d1eb..5ac410ea 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -41,10 +41,11 @@ namespace tunnel const int MAX_NUM_RECORDS = 8; const int HIGH_LATENCY_PER_HOP = 250; // in milliseconds const int MAX_TUNNEL_MSGS_BATCH_SIZE = 100; // handle messages without interrupt + const uint16_t DEFAULT_MAX_NUM_TRANSIT_TUNNELS = 5000; const int TUNNEL_MANAGE_INTERVAL = 15; // in seconds const int TUNNEL_POOLS_MANAGE_INTERVAL = 5; // in seconds const int TUNNEL_MEMORY_POOL_MANAGE_INTERVAL = 120; // in seconds - + const size_t I2NP_TUNNEL_MESSAGE_SIZE = TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + 34; // reserved for alignment and NTCP 16 + 6 + 12 const size_t I2NP_TUNNEL_ENPOINT_MESSAGE_SIZE = 2*TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE + 28; // reserved for alignment and NTCP 16 + 6 + 6 @@ -229,6 +230,10 @@ namespace tunnel std::shared_ptr NewI2NPTunnelMessage (bool endpoint); + void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels); + uint16_t GetMaxNumTransitTunnels () const { return m_MaxNumTransitTunnels; }; + bool IsTooManyTransitTunnels () const { return m_TransitTunnels.size () >= m_MaxNumTransitTunnels; }; + private: template @@ -287,6 +292,7 @@ namespace tunnel i2p::util::Queue > m_Queue; i2p::util::MemoryPoolMt > m_I2NPTunnelEndpointMessagesMemoryPool; i2p::util::MemoryPoolMt > m_I2NPTunnelMessagesMemoryPool; + uint16_t m_MaxNumTransitTunnels; // count of tunnels for total TCSR algorithm int m_TotalNumSuccesiveTunnelCreations, m_TotalNumFailedTunnelCreations; double m_TunnelCreationSuccessRate; From 716926f0d7f22a203c21355e837a2d7e6ed508c3 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 6 Mar 2023 19:48:04 -0500 Subject: [PATCH 0047/1171] publish high congestion cap --- libi2pd/I2NPProtocol.cpp | 12 +++--------- libi2pd/RouterContext.cpp | 33 +++++++++++++++++++++++++++++++++ libi2pd/RouterContext.h | 6 +++++- libi2pd/RouterInfo.cpp | 18 +++++++++++++++++- libi2pd/RouterInfo.h | 8 +++++--- 5 files changed, 63 insertions(+), 14 deletions(-) diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index c1724b39..5ae89c23 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -364,10 +364,7 @@ namespace i2p if (!i2p::context.DecryptTunnelBuildRecord (record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText)) return false; uint8_t retCode = 0; // replace record to reply - if (i2p::context.AcceptsTunnels () && - !i2p::tunnel::tunnels.IsTooManyTransitTunnels () && - !i2p::transport::transports.IsBandwidthExceeded () && - !i2p::transport::transports.IsTransitBandwidthExceeded ()) + if (i2p::context.AcceptsTunnels () && !i2p::context.IsHighCongestion ()) { auto transitTunnel = i2p::tunnel::CreateTransitTunnel ( bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET), @@ -561,11 +558,8 @@ namespace i2p // check if we accept this tunnel uint8_t retCode = 0; - if (!i2p::context.AcceptsTunnels () || - i2p::tunnel::tunnels.IsTooManyTransitTunnels () || - i2p::transport::transports.IsBandwidthExceeded () || - i2p::transport::transports.IsTransitBandwidthExceeded ()) - retCode = 30; + if (!i2p::context.AcceptsTunnels () || i2p::context.IsHighCongestion ()) + retCode = 30; if (!retCode) { // create new transit tunnel diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index f2b8f4fb..b6806fb3 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -60,6 +60,8 @@ namespace i2p { m_PublishTimer.reset (new boost::asio::deadline_timer (m_Service->GetService ())); ScheduleInitialPublish (); + m_CongestionUpdateTimer.reset (new boost::asio::deadline_timer (m_Service->GetService ())); + ScheduleCongestionUpdate (); } } } @@ -70,6 +72,8 @@ namespace i2p { if (m_PublishTimer) m_PublishTimer->cancel (); + if (m_CongestionUpdateTimer) + m_CongestionUpdateTimer->cancel (); m_Service->Stop (); } } @@ -1107,6 +1111,13 @@ namespace i2p return i2p::tunnel::tunnels.GetExploratoryPool (); } + bool RouterContext::IsHighCongestion () const + { + return i2p::tunnel::tunnels.IsTooManyTransitTunnels () || + i2p::transport::transports.IsBandwidthExceeded () || + i2p::transport::transports.IsTransitBandwidthExceeded (); + } + void RouterContext::HandleI2NPMessage (const uint8_t * buf, size_t len) { i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len))); @@ -1368,4 +1379,26 @@ namespace i2p SchedulePublishResend (); } } + + void RouterContext::ScheduleCongestionUpdate () + { + if (m_CongestionUpdateTimer) + { + m_CongestionUpdateTimer->cancel (); + m_CongestionUpdateTimer->expires_from_now (boost::posix_time::seconds(ROUTER_INFO_CONGESTION_UPDATE_INTERVAL)); + m_CongestionUpdateTimer->async_wait (std::bind (&RouterContext::HandleCongestionUpdateTimer, + this, std::placeholders::_1)); + } + else + LogPrint (eLogError, "Router: Congestion update timer is NULL"); + } + + void RouterContext::HandleCongestionUpdateTimer (const boost::system::error_code& ecode) + { + if (ecode != boost::asio::error::operation_aborted) + { + m_RouterInfo.SetHighCongestion (IsHighCongestion ()); + ScheduleCongestionUpdate (); + } + } } diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index 4b6d917e..b8183339 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -37,6 +37,7 @@ namespace garlic const int ROUTER_INFO_PUBLISH_INTERVAL_VARIANCE = 105;// in seconds const int ROUTER_INFO_CONFIRMATION_TIMEOUT = 5; // in seconds const int ROUTER_INFO_MAX_PUBLISH_EXCLUDED_FLOODFILLS = 15; + const int ROUTER_INFO_CONGESTION_UPDATE_INTERVAL = 12*60; // in seconds enum RouterStatus { @@ -152,6 +153,7 @@ namespace garlic void SetShareRatio (int percents); // 0 - 100 bool AcceptsTunnels () const { return m_AcceptsTunnels; }; void SetAcceptsTunnels (bool acceptsTunnels) { m_AcceptsTunnels = acceptsTunnels; }; + bool IsHighCongestion () const; bool SupportsV6 () const { return m_RouterInfo.IsV6 (); }; bool SupportsV4 () const { return m_RouterInfo.IsV4 (); }; bool SupportsMesh () const { return m_RouterInfo.IsMesh (); }; @@ -213,6 +215,8 @@ namespace garlic void Publish (); void SchedulePublishResend (); void HandlePublishResendTimer (const boost::system::error_code& ecode); + void ScheduleCongestionUpdate (); + void HandleCongestionUpdateTimer (const boost::system::error_code& ecode); private: @@ -235,7 +239,7 @@ namespace garlic i2p::crypto::NoiseSymmetricState m_InitialNoiseState, m_CurrentNoiseState; // publish std::unique_ptr m_Service; - std::unique_ptr m_PublishTimer; + std::unique_ptr m_PublishTimer, m_CongestionUpdateTimer; std::set m_PublishExcluded; uint32_t m_PublishReplyToken; bool m_IsHiddenMode; // not publish diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index e9df01bb..41c69b09 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -1071,9 +1071,15 @@ namespace data if (m_Congestion == eLowCongestion || m_Congestion == eMediumCongestion) return false; if (m_Congestion == eRejectAll) return true; if (m_Congestion == eHighCongestion) - return (i2p::util::GetMillisecondsSinceEpoch () < m_Timestamp + HIGH_CONGESION_INTERVAL*1000LL) ? true : false; + return (i2p::util::GetMillisecondsSinceEpoch () < m_Timestamp + HIGH_CONGESTION_INTERVAL*1000LL) ? true : false; return false; } + + LocalRouterInfo::LocalRouterInfo (const std::string& fullPath): + RouterInfo (fullPath) + { + SetHighCongestion (false); // drop congestion + } void LocalRouterInfo::CreateBuffer (const PrivateKeys& privateKeys) { @@ -1143,6 +1149,16 @@ namespace data SetProperty ("caps", caps); } + void LocalRouterInfo::SetHighCongestion (bool highCongestion) + { + Congestion c = highCongestion ? eHighCongestion : eLowCongestion; + if (c != GetCongestion ()) + { + SetCongestion (c); + UpdateCapsProperty (); + } + } + void LocalRouterInfo::WriteToStream (std::ostream& s) const { auto addresses = GetAddresses (); diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 3b74eaf3..2e9e67b5 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -60,7 +60,7 @@ namespace data const uint8_t COST_SSU2_NON_PUBLISHED = 15; const size_t MAX_RI_BUFFER_SIZE = 3072; // if RouterInfo exceeds 3K we consider it as malformed, might extend later - const int HIGH_CONGESION_INTERVAL = 15*60; // in seconds, 15 minutes + const int HIGH_CONGESTION_INTERVAL = 15*60; // in seconds, 15 minutes class RouterInfo: public RoutingDestination { @@ -291,7 +291,8 @@ namespace data void RefreshTimestamp (); CompatibleTransports GetReachableTransports () const { return m_ReachableTransports; }; void SetReachableTransports (CompatibleTransports transports) { m_ReachableTransports = transports; }; - + void SetCongestion (Congestion c) { m_Congestion = c; }; + private: bool LoadFile (const std::string& fullPath); @@ -328,9 +329,10 @@ namespace data public: LocalRouterInfo () = default; - LocalRouterInfo (const std::string& fullPath): RouterInfo (fullPath) {}; + LocalRouterInfo (const std::string& fullPath); void CreateBuffer (const PrivateKeys& privateKeys); void UpdateCaps (uint8_t caps); + void SetHighCongestion (bool highCongestion); void SetProperty (const std::string& key, const std::string& value) override; void DeleteProperty (const std::string& key); From 4b7fcdc7199c987faf52e7d6808a81e71ea9afb0 Mon Sep 17 00:00:00 2001 From: Vort Date: Tue, 7 Mar 2023 12:06:50 +0200 Subject: [PATCH 0048/1171] Prevent leaking of ExploratoryPool --- libi2pd/Tunnel.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 3e952bbe..58e13ad3 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -339,6 +339,7 @@ namespace tunnel Tunnels::~Tunnels () { + DeleteTunnelPool(m_ExploratoryPool); } std::shared_ptr Tunnels::GetTunnel (uint32_t tunnelID) From 46e4f4aea55b57dd653a028e1516f4c58869e90d Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 7 Mar 2023 13:09:07 -0500 Subject: [PATCH 0049/1171] update RouterInfo if congestion cap changed --- libi2pd/RouterContext.cpp | 3 ++- libi2pd/RouterInfo.cpp | 4 +++- libi2pd/RouterInfo.h | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index b6806fb3..084e8c77 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -1397,7 +1397,8 @@ namespace i2p { if (ecode != boost::asio::error::operation_aborted) { - m_RouterInfo.SetHighCongestion (IsHighCongestion ()); + if (m_RouterInfo.SetHighCongestion (IsHighCongestion ())) + UpdateRouterInfo (); ScheduleCongestionUpdate (); } } diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 41c69b09..db0a7de6 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -1149,14 +1149,16 @@ namespace data SetProperty ("caps", caps); } - void LocalRouterInfo::SetHighCongestion (bool highCongestion) + bool LocalRouterInfo::SetHighCongestion (bool highCongestion) { Congestion c = highCongestion ? eHighCongestion : eLowCongestion; if (c != GetCongestion ()) { SetCongestion (c); UpdateCapsProperty (); + return true; } + return false; } void LocalRouterInfo::WriteToStream (std::ostream& s) const diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 2e9e67b5..3e8e0613 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -332,7 +332,7 @@ namespace data LocalRouterInfo (const std::string& fullPath); void CreateBuffer (const PrivateKeys& privateKeys); void UpdateCaps (uint8_t caps); - void SetHighCongestion (bool highCongestion); + bool SetHighCongestion (bool highCongestion); // returns true if updated void SetProperty (const std::string& key, const std::string& value) override; void DeleteProperty (const std::string& key); From 0a8da6bc2f698ee945dd9c2c328e9510cec63124 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Wed, 8 Mar 2023 11:41:01 +0000 Subject: [PATCH 0050/1171] [cmake] msvc build revision Signed-off-by: R4SAS --- build/.gitignore | 4 ++++ build/CMakeLists.txt | 35 ++++++++++++++++++++++++++++------- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/build/.gitignore b/build/.gitignore index d51958d6..39b8094c 100644 --- a/build/.gitignore +++ b/build/.gitignore @@ -21,3 +21,7 @@ # windows build script i2pd*.zip build*.log +# MVS project files +*.vcxproj +*.vcxproj.filters +*.sln diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 2379f9cb..bc65b41e 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -194,6 +194,12 @@ endif() # Note: AES-NI and AVX is available on x86-based CPU's. # Here also ARM64 implementation, but currently we don't support it. +# MSVC is not supported. +if(MSVC) + message(STATUS "AES-NI is not supported on MSVC, option was disabled") + set(WITH_AESNI OFF) +endif() + if(WITH_AESNI AND (ARCHITECTURE MATCHES "x86_64" OR ARCHITECTURE MATCHES "i386")) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes") add_definitions(-D__AES__) @@ -225,7 +231,9 @@ set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) if(WITH_STATIC) - set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") + if(NOT MSVC) + set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") + endif() set(Boost_USE_STATIC_LIBS ON) if(MSVC) @@ -234,10 +242,17 @@ if(WITH_STATIC) set(Boost_USE_STATIC_RUNTIME OFF) endif() + if(MSVC) + set(OPENSSL_MSVC_STATIC_RT ON) + endif() set(OPENSSL_USE_STATIC_LIBS ON) set(ZLIB_USE_STATIC_LIBS ON) - set(ZLIB_NAMES libz zlibstatic zlibstat zlib z) + if(MSVC) + set(ZLIB_NAMES zlibstatic zlibstat) + else() + set(ZLIB_NAMES libz zlibstatic zlibstat zlib z) + endif() if(WITH_UPNP) set(MINIUPNPC_USE_STATIC_LIBS ON) @@ -255,8 +270,10 @@ else() # TODO: Consider separate compilation for LIBI2PD_SRC for library. # No need in -fPIC overhead for binary if not interested in library # HINT: revert c266cff CMakeLists.txt: compilation speed up - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") - add_definitions(-DBOOST_SYSTEM_DYN_LINK -DBOOST_FILESYSTEM_DYN_LINK -DBOOST_PROGRAM_OPTIONS_DYN_LINK -DBOOST_DATE_TIME_DYN_LINK -DBOOST_REGEX_DYN_LINK) + if(NOT MSVC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") + endif() + add_definitions(-DBOOST_ATOMIC_DYN_LINK -DBOOST_SYSTEM_DYN_LINK -DBOOST_FILESYSTEM_DYN_LINK -DBOOST_PROGRAM_OPTIONS_DYN_LINK -DBOOST_DATE_TIME_DYN_LINK -DBOOST_REGEX_DYN_LINK) endif() find_package(Boost REQUIRED COMPONENTS system filesystem program_options date_time OPTIONAL_COMPONENTS atomic) @@ -317,9 +334,13 @@ if(WITH_BINARY) add_executable("${PROJECT_NAME}" ${DAEMON_SRC}) endif() - if (WIN32) - set(MINGW_EXTRA "wsock32" "ws2_32" "iphlpapi") - endif () + if(WIN32) + list(APPEND MINGW_EXTRA "wsock32" "ws2_32" "iphlpapi") + # OpenSSL may require Crypt32 library on MSVC build, which is not added by CMake lesser than 3.21 + if(MSVC AND ${CMAKE_VERSION} VERSION_LESS 3.21) + list(APPEND MINGW_EXTRA "crypt32") + endif() + endif() if(WITH_STATIC) if(NOT MSVC) From 0a564d153ae8719f16066ed764651587ac273e0b Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 8 Mar 2023 18:23:32 -0500 Subject: [PATCH 0051/1171] reseed update --- .../reseed/arnavbhatt288_at_mail.i2p.crt | 34 +++++++++++++++++++ .../certificates/reseed/igor_at_novg.net.crt | 33 ------------------ libi2pd/Config.cpp | 3 +- 3 files changed, 36 insertions(+), 34 deletions(-) create mode 100644 contrib/certificates/reseed/arnavbhatt288_at_mail.i2p.crt delete mode 100644 contrib/certificates/reseed/igor_at_novg.net.crt diff --git a/contrib/certificates/reseed/arnavbhatt288_at_mail.i2p.crt b/contrib/certificates/reseed/arnavbhatt288_at_mail.i2p.crt new file mode 100644 index 00000000..9068afb9 --- /dev/null +++ b/contrib/certificates/reseed/arnavbhatt288_at_mail.i2p.crt @@ -0,0 +1,34 @@ +-----BEGIN CERTIFICATE----- +MIIF2TCCA8GgAwIBAgIQIHQPtSoFU+cUpYD8PZaWZjANBgkqhkiG9w0BAQsFADB2 +MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYDVQQK +ExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEfMB0GA1UEAwwW +YXJuYXZiaGF0dDI4OEBtYWlsLmkycDAeFw0yMzAxMjUxODUzNDFaFw0zMzAxMjUx +ODUzNDFaMHYxCzAJBgNVBAYTAlhYMQswCQYDVQQHEwJYWDELMAkGA1UECRMCWFgx +HjAcBgNVBAoTFUkyUCBBbm9ueW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMR8w +HQYDVQQDDBZhcm5hdmJoYXR0Mjg4QG1haWwuaTJwMIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEAtwG73sC0jYd3fgEzZh0SveAdUd5yD35nINJRrdPSrSwY +n3i1qGe3fNLj877PvUDU+qiHH0fFZfyFkXTaq3TUp1u4YkmvaoPHy6FZlojB08lK +FBm+iJ1hifQ7MFmvIKUGv+cjlN6xSoQ0U6B2QOy6iZnBgFZ/7jbRY4iZOIj7VJtY +aodeHfy0bWe447VJovbkUi7NJPFZQS65LMcAIWcWTxrC0Gj8SmdxL3a5+hxpmmg0 ++KCQvWQDdxAQjsc16sgUCdUc6cWYO4yw9H6fgdq9GJX+LnXR9OB58GsAjjlLlFoI +CZxdARDpoqcIj6AoKIanALf8yfbIyrqqJE47cuaqV9bht5MWKnXbwHplEkT4ZNkh +PnRDia7B5HY3uwbt39CBm264PEWXvWG2sozTWKQqBjmMN2cj/NFDUEqKv6BggMY1 +HcqxWFKRcgKCtRvrmTmfp5l0/ou+OtUaFUg0a6Qhtb93Hj10vK6wZzidBqj0ggzB +eJDI95b89u8JgzRoOBriuMKTc91WTkOvBLkB3dgUbUpx2p8KHjvf/pppBH9u0oxp +qJFFK840DbnJydEvjKezeVe5Ax6YRSRxyEdKzRoWdvKVxb3qBBKMdCKTYEPxHPBu +JMEQVUCXJMti++1KEiQGhcfWvLyT7OewbcIZNk9XWNrxlKcGrTp9AOwaaNC5m1kC +AwEAAaNjMGEwDgYDVR0PAQH/BAQDAgKEMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggr +BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB8GA1UdDgQYBBZhcm5hdmJoYXR0Mjg4 +QG1haWwuaTJwMA0GCSqGSIb3DQEBCwUAA4ICAQAHiK0ld/1PF9DIhutD660/bzBg +mF2Z76hcBqDZ8tnQai/u/RXYrH9wso9BYyrVsvk3fr6tpGT49Ian0MVpPOxMoTU2 +oBEmQlYrfclQLFsOLmA0y2r1ggXzIrt69jB710Vhwdnz09oOE8rS4E2T5oDD8Wvy +Kony+AarRceqtkOlzyquc42KjzdrbHsosF7G2iGhNI6t+T3BfWJ+Q+d5sj3OIh6e +gSfvHL44E4vZt6dtofRN3MAZ60kNLF5YWyaUo3Snv9Lso1IwIz3AVr5ehv+8sFL/ +KxaXdkZ5Yn2YUX7p1t4VQd+eXVPYjf1befg4PvrwSkylu3Jpee3fllZSKXeSVx9x +jpJiq5vIakqk22pnWb1Vn7xzSW1vtEG7QLjobOr1WrcGiwdv+HKiWcXJXDzKoWXs +h3VEfr51Kap8cIJv+D6lJIG9IcIhiQ6CXWBmtjWJvbdVwFBy1/3Fhaou9liHi+gK +4Yh5a5OGCzc7xjtpGaTmoLEz7NzDNOdd/r840qRDOh70izzmFZd5Gwq4hoVcPJcS +EAySwtgqK0/4d0zDd2Wg9ASJV9DnDf8QuSmHZgZ9Efs47XcWz9TvkWUS1E66AJsN +mmI1NDQ3mv3dv5+WPq+dqqYFsnx3xWL1g5Z3buk0opeuXMzoHwM7UfN8h7Q1M5+t ++XBgkaYA4iEwYKqlCQ== +-----END CERTIFICATE----- diff --git a/contrib/certificates/reseed/igor_at_novg.net.crt b/contrib/certificates/reseed/igor_at_novg.net.crt deleted file mode 100644 index 12ce7a61..00000000 --- a/contrib/certificates/reseed/igor_at_novg.net.crt +++ /dev/null @@ -1,33 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFvjCCA6agAwIBAgIQIDtv8tGMh0FyB2w5XjfZxTANBgkqhkiG9w0BAQsFADBt -MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYDVQQK -ExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEWMBQGA1UEAwwN -aWdvckBub3ZnLm5ldDAeFw0xNzA3MjQxODI4NThaFw0yNzA3MjQxODI4NThaMG0x -CzAJBgNVBAYTAlhYMQswCQYDVQQHEwJYWDELMAkGA1UECRMCWFgxHjAcBgNVBAoT -FUkyUCBBbm9ueW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMRYwFAYDVQQDDA1p -Z29yQG5vdmcubmV0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxst4 -cam3YibBtQHGPCPX13uRQti56U3XZytSZntaKrUFmJxjt41Q/mOy3KYo+lBvhfDF -x3tWKjgP9LJOJ28zvddFhZVNxqZRjcnAoPuSOVCw88g01D9OAasKF11hCfdxZP6h -vGm8WCnjD8KPcYFxJC4HJUiFeProAwuTzEAESTRk4CAQe3Ie91JspuqoLUc5Qxlm -w5QpjnjfZY4kaVHmZDKGIZDgNIt5v85bu4pWwZ6O+o90xQqjxvjyz/xccIec3sHw -MHJ8h8ZKMokCKEJTaRWBvdeNXki7nf3gUy/3GjYQlzo0Nxk/Hw4svPcA+eL0AYiy -Jn83bIB5VToW2zYUdV4u3qHeAhEg8Y7HI0kKcSUGm9AQXzbzP8YCHxi0sbb0GAJy -f1Xf3XzoPfT64giD8ReUHhwKpyMB6uvG/NfWSZAzeAO/NT7DAwXpKIVQdkVdqy8b -mvHvjf9/kWKOirA2Nygf3r79Vbg2mqbYC/b63XI9hheU689+O7qyhTEhNz+11X0d -Zax7UPrLrwOeB9TNfEnztsmrHNdv2n+KcOO2o11Wvz2nHP9g+dgwoZSD1ZEpFzWP -0sD5knKLwAL/64qLlAQ1feqW7hMr80IADcKjLSODkIDIIGm0ksXqEzTjz1JzbRDq -jUjq7EAlkw3G69rv1gHxIntllJRQidAqecyWHOMCAwEAAaNaMFgwDgYDVR0PAQH/ -BAQDAgKEMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHRMBAf8E -BTADAQH/MBYGA1UdDgQPBA1pZ29yQG5vdmcubmV0MA0GCSqGSIb3DQEBCwUAA4IC -AQADyPaec28qc1HQtAV5dscJr47k92RTfvan+GEgIwyQDHZQm38eyTb05xipQCdk -5ruUDFXLB5qXXFJKUbQM6IpaktmWDJqk4Zn+1nGbtFEbKgrF55pd63+NQer5QW9o -3+dGj0eZJa3HX5EBkd2r7j2LFuB6uxv3r/xiTeHaaflCnsmyDLfb7axvYhyEzHQS -AUi1bR+ln+dXewdtuojqc1+YmVGDgzWZK2T0oOz2E21CpZUDiP3wv9QfMaotLEal -zECnbhS++q889inN3GB4kIoN6WpPpeYtTV+/r7FLv9+KUOV1s2z6mxIqC5wBFhZs -0Sr1kVo8hB/EW/YYhDp99LoAOjIO6nn1h+qttfzBYr6C16j+8lGK2A12REJ4LiUQ -cQI/0zTjt2C8Ns6ueNzMLQN1Mvmlg1Z8wIB7Az7jsIbY2zFJ0M5qR5VJveTj33K4 -4WSbC/zMWOBYHTVBvGmc6JGhu5ZUTZ+mWP7QfimGu+tdhvtrybFjE9ROIE/4yFr6 -GkxEyt0UY87TeKXJ/3KygvkMwdvqGWiZhItb807iy99+cySujtbGfF2ZXYGjBXVW -dJOVRbyGQkHh6lrWHQM4ntBv4x+5QA+OAan5PBF3tcDx1vefPx+asYslbOXpzII5 -qhvoQxuRs6j5jsVFG6RdsKNeQAt87Mb2u2zK2ZakMdyD1w== ------END CERTIFICATE----- diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index f9d894fa..346fb659 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -217,7 +217,8 @@ namespace config { "https://reseed.i2pgit.org/," "https://banana.incognet.io/," "https://reseed-pl.i2pd.xyz/," - "https://www2.mk16.de/" + "https://www2.mk16.de/", + "https://i2p.ghativega.in/" ), "Reseed URLs, separated by comma") ("reseed.yggurls", value()->default_value( "http://[324:71e:281a:9ed3::ace]:7070/," From ec5c13a95ecd6d31f2a49477d20ae2bca1cf711b Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 8 Mar 2023 18:38:49 -0500 Subject: [PATCH 0052/1171] add back i2p.novg.net with new certificate --- .../certificates/reseed/igor_at_novg.net.crt | 33 +++++++++++++++++++ libi2pd/Config.cpp | 5 +-- 2 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 contrib/certificates/reseed/igor_at_novg.net.crt diff --git a/contrib/certificates/reseed/igor_at_novg.net.crt b/contrib/certificates/reseed/igor_at_novg.net.crt new file mode 100644 index 00000000..c6a05e8b --- /dev/null +++ b/contrib/certificates/reseed/igor_at_novg.net.crt @@ -0,0 +1,33 @@ +-----BEGIN CERTIFICATE----- +MIIFvjCCA6agAwIBAgIQBnsUOmOu2oZZIwHBmQc1BDANBgkqhkiG9w0BAQsFADBt +MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYDVQQK +ExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEWMBQGA1UEAwwN +aWdvckBub3ZnLm5ldDAeFw0yMzAxMjgxNDM4MzFaFw0zMzAxMjgxNDM4MzFaMG0x +CzAJBgNVBAYTAlhYMQswCQYDVQQHEwJYWDELMAkGA1UECRMCWFgxHjAcBgNVBAoT +FUkyUCBBbm9ueW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMRYwFAYDVQQDDA1p +Z29yQG5vdmcubmV0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvLkf +bM3uiYfp9m0vgdoftyXtk2/9bHf3u5iaM0WfoJIsw1iizo/mxJl+Iy7SxLC16nV0 +v5FpncVv+Z8x9dgoAYVuLq9zKfsAbpj6kuxAqw6vJMlD1TiIL3nSODV9BJLk47X5 +tmvoOSj9BgvemYThTE3nj+DbuJRW5q90KyBV/LdLrQJX3k5R3FFL5tTad2LKFNZ4 +vEOcYwwx6mvrkJ2lly6bAQUCtfc648Jyq+NO3Rba1fmn7gcP9zXXc5KYsj/ovyY2 +OaocSF5wMhzBuPxO+M2HqbYLMAkc6/GesGds8Rm8wofuhJoI5YtqJuLKZm6nQXSc +fx6PKgbKcTIUWNFMsxyfghz9hpbg0rkvC7PtfAjtV0yaDtUum1eZeNEx1HbRWN2n +TQNCVuv0yaKC41qxqzhEybkdjL9JlgUh7VuskaCelB0lz+kgYjGu8ezOa0ua2iKq +4FC/1MbPulxN8NOt4pmbGqqoxmCdShp38wdnOBM3DsAS9f0JaQZd4CDyY4DCSfVn +xPdWk31+VXVt3Ixh1EUqZWYTRSsZApkCyYzkiZ/qPGG6FR9Hq2SuhC5o4P44k7eo +6wwBWD8a5RjsZhvr05E5yBrKXh/PjLwmtG73QC+ouR54/5xtedvdTwNS94FnNctX +FT6QGZnRwCkhPaRe1oQMzP+88pGoCfO33GBAuwUCAwEAAaNaMFgwDgYDVR0PAQH/ +BAQDAgKEMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHRMBAf8E +BTADAQH/MBYGA1UdDgQPBA1pZ29yQG5vdmcubmV0MA0GCSqGSIb3DQEBCwUAA4IC +AQCteAb5/bqhHr/i5CJbDzlofprXFC826c19GxQ/9Hw0kA52l0J9Q8Vz8Vy7VQyP +QNa8MCv6FeNy8a/wXp6cafyFsBtvehVQO8lFlpCgMEl2Bma43+GaCwkrM6bFNXeW +iQ9h4e1KjsUZ8cQDNEcamiJ80+xbMhBrj5bAZwKmZs8MoGEMyXKEZmcmwA+/fy1c +cx4izsOsmRXmEHXsvB9ydJHZZeKW8+r0DAtgPslwXuXHG6MuBQo7dKCqn+iMxHXV +Jxriq3yvNffdGx4maSLJrjQ1ealt/UMzql7huVSItnVFWoYf7GAELXNJ/PmqVyaK +q11LQ8W/Aud6s/bblaJrFJnK8PbPpaw4RvHoWVLYaZYmQnV2msWs5EuESBlEADbv +UklQXLMc2f9HKWPA5678nvYPrmu8IL5pMkAxgGRqmd+7vCz4lU9M5z3HObU+WRBt +qEMYyXywV8o3tbmnlDS5S5Xxf+tLZn1cxz3ZrmcHPHDbLBNdvszF3CTJH/R2sQvD +bizvYJM+p5F+GWM5mt6w0HrOut5MRlpOws/NRrkbijuVA/A45nzTtKplIFYE3qe8 +q5SAbwYLc8cJcZCN3PxtWwbEv81V33abMt5QcjnWGLH5t2+1Z2KLCgKLSCQTxM8s +zBPHtUe8qtSQaElnNLILYbtJ1w67dPnGYTphHihC+CXjBg== +-----END CERTIFICATE----- diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 346fb659..a083e0ea 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -217,8 +217,9 @@ namespace config { "https://reseed.i2pgit.org/," "https://banana.incognet.io/," "https://reseed-pl.i2pd.xyz/," - "https://www2.mk16.de/", - "https://i2p.ghativega.in/" + "https://www2.mk16.de/," + "https://i2p.ghativega.in/," + "https://i2p.novg.net/" ), "Reseed URLs, separated by comma") ("reseed.yggurls", value()->default_value( "http://[324:71e:281a:9ed3::ace]:7070/," From 58ef08310d29441db19f7ee4027b4855630dfd94 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Thu, 9 Mar 2023 15:48:15 +0000 Subject: [PATCH 0053/1171] [reseed] skip records in reserved IP ranges, check Yggdrasil avalability if domain resolves in ygg address Signed-off-by: R4SAS --- libi2pd/Reseed.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/libi2pd/Reseed.cpp b/libi2pd/Reseed.cpp index 4a6e5a7e..f0a4cc29 100644 --- a/libi2pd/Reseed.cpp +++ b/libi2pd/Reseed.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -687,8 +687,18 @@ namespace data while (it != end) { boost::asio::ip::tcp::endpoint ep = *it; - if ((ep.address ().is_v4 () && i2p::context.SupportsV4 ()) || - (ep.address ().is_v6 () && i2p::context.SupportsV6 ())) + if ( + ( + !i2p::util::net::IsInReservedRange(ep.address ()) && ( + (ep.address ().is_v4 () && i2p::context.SupportsV4 ()) || + (ep.address ().is_v6 () && i2p::context.SupportsV6 ()) + ) + ) || + ( + i2p::util::net::IsYggdrasilAddress (ep.address ()) && + i2p::context.SupportsMesh () + ) + ) { s.lowest_layer().connect (ep, ecode); if (!ecode) From 7b35c793f303dafe918ddee0e823f5981d24e7a6 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Fri, 10 Mar 2023 01:19:09 +0000 Subject: [PATCH 0054/1171] [reseed] support domains in yggdrasil reseeder, fix IPv6 URL host parsing Signed-off-by: R4SAS --- libi2pd/HTTP.cpp | 34 +++++++++++++++++++++++++++------- libi2pd/HTTP.h | 3 ++- libi2pd/Reseed.cpp | 41 +++++++++++++++++++++++++++++++++++------ 3 files changed, 64 insertions(+), 14 deletions(-) diff --git a/libi2pd/HTTP.cpp b/libi2pd/HTTP.cpp index 7cc87df8..f4c3dcb9 100644 --- a/libi2pd/HTTP.cpp +++ b/libi2pd/HTTP.cpp @@ -93,15 +93,18 @@ namespace http std::size_t pos_c = 0; /* < work position */ if(url.at(0) != '/' || pos_p > 0) { std::size_t pos_s = 0; + /* schema */ pos_c = url.find("://"); if (pos_c != std::string::npos) { schema = url.substr(0, pos_c); pos_p = pos_c + 3; } + /* user[:pass] */ pos_s = url.find('/', pos_p); /* find first slash */ pos_c = url.find('@', pos_p); /* find end of 'user' or 'user:pass' part */ + if (pos_c != std::string::npos && (pos_s == std::string::npos || pos_s > pos_c)) { std::size_t delim = url.find(':', pos_p); if (delim && delim != std::string::npos && delim < pos_c) { @@ -113,21 +116,28 @@ namespace http } pos_p = pos_c + 1; } + /* hostname[:port][/path] */ - if (url[pos_p] == '[') // ipv6 + if (url.at(pos_p) == '[') // ipv6 { auto pos_b = url.find(']', pos_p); if (pos_b == std::string::npos) return false; + ipv6 = true; pos_c = url.find_first_of(":/", pos_b); } else pos_c = url.find_first_of(":/", pos_p); + if (pos_c == std::string::npos) { /* only hostname, without post and path */ - host = url.substr(pos_p, std::string::npos); + host = ipv6 ? + url.substr(pos_p + 1, url.length() - 1) : + url.substr(pos_p, std::string::npos); return true; } else if (url.at(pos_c) == ':') { - host = url.substr(pos_p, pos_c - pos_p); + host = ipv6 ? + url.substr(pos_p + 1, pos_c - pos_p - 2) : + url.substr(pos_p, pos_c - pos_p); /* port[/path] */ pos_p = pos_c + 1; pos_c = url.find('/', pos_p); @@ -147,7 +157,9 @@ namespace http pos_p = pos_c; } else { /* start of path part found */ - host = url.substr(pos_p, pos_c - pos_p); + host = ipv6 ? + url.substr(pos_p + 1, pos_c - pos_p - 2) : + url.substr(pos_p, pos_c - pos_p); pos_p = pos_c; } } @@ -212,10 +224,18 @@ namespace http } else if (user != "") { out += user + "@"; } - if (port) { - out += host + ":" + std::to_string(port); + if (ipv6) { + if (port) { + out += "[" + host + "]:" + std::to_string(port); + } else { + out += "[" + host + "]"; + } } else { - out += host; + if (port) { + out += host + ":" + std::to_string(port); + } else { + out += host; + } } } out += path; diff --git a/libi2pd/HTTP.h b/libi2pd/HTTP.h index f9d5d009..41f0560a 100644 --- a/libi2pd/HTTP.h +++ b/libi2pd/HTTP.h @@ -36,8 +36,9 @@ namespace http bool hasquery; std::string query; std::string frag; + bool ipv6; - URL(): schema(""), user(""), pass(""), host(""), port(0), path(""), hasquery(false), query(""), frag("") {}; + URL(): schema(""), user(""), pass(""), host(""), port(0), path(""), hasquery(false), query(""), frag(""), ipv6(false) {}; /** * @brief Tries to parse url from string diff --git a/libi2pd/Reseed.cpp b/libi2pd/Reseed.cpp index f0a4cc29..dfc10043 100644 --- a/libi2pd/Reseed.cpp +++ b/libi2pd/Reseed.cpp @@ -703,6 +703,7 @@ namespace data s.lowest_layer().connect (ep, ecode); if (!ecode) { + LogPrint (eLogDebug, "Reseed: Resolved to ", ep.address ()); connected = true; break; } @@ -790,17 +791,45 @@ namespace data boost::asio::io_service service; boost::asio::ip::tcp::socket s(service, boost::asio::ip::tcp::v6()); - if (url.host.length () < 2) return ""; // assume [] - auto host = url.host.substr (1, url.host.length () - 2); - LogPrint (eLogDebug, "Reseed: Connecting to Yggdrasil ", url.host, ":", url.port); - s.connect (boost::asio::ip::tcp::endpoint (boost::asio::ip::address_v6::from_string (host), url.port), ecode); + auto it = boost::asio::ip::tcp::resolver(service).resolve ( + boost::asio::ip::tcp::resolver::query (url.host, std::to_string(url.port)), ecode); + if (!ecode) { - LogPrint (eLogDebug, "Reseed: Connected to Yggdrasil ", url.host, ":", url.port); + bool connected = false; + boost::asio::ip::tcp::resolver::iterator end; + while (it != end) + { + boost::asio::ip::tcp::endpoint ep = *it; + if ( + i2p::util::net::IsYggdrasilAddress (ep.address ()) && + i2p::context.SupportsMesh () + ) + { + LogPrint (eLogDebug, "Reseed: Yggdrasil: Resolved to ", ep.address ()); + s.connect (ep, ecode); + if (!ecode) + { + connected = true; + break; + } + } + it++; + } + if (!connected) + { + LogPrint(eLogError, "Reseed: Yggdrasil: Failed to connect to ", url.host); + return ""; + } + } + + if (!ecode) + { + LogPrint (eLogDebug, "Reseed: Yggdrasil: Connected to ", url.host, ":", url.port); return ReseedRequest (s, url.to_string()); } else - LogPrint (eLogError, "Reseed: Couldn't connect to Yggdrasil ", url.host, ": ", ecode.message ()); + LogPrint (eLogError, "Reseed: Yggdrasil: Couldn't connect to ", url.host, ": ", ecode.message ()); return ""; } From b6d1d8117b21485314fd1fd5acc7e45154ad9e31 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Fri, 10 Mar 2023 01:32:07 +0000 Subject: [PATCH 0055/1171] [GHA] Windows MSVC workflow (#1904) --- .github/workflows/build-windows-msvc.yml | 52 ++++++++++++++++++++++++ .github/workflows/build-windows.yml | 6 +-- build/CMakeLists.txt | 5 ++- 3 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/build-windows-msvc.yml diff --git a/.github/workflows/build-windows-msvc.yml b/.github/workflows/build-windows-msvc.yml new file mode 100644 index 00000000..356bb466 --- /dev/null +++ b/.github/workflows/build-windows-msvc.yml @@ -0,0 +1,52 @@ +name: Build on Windows with MSVC + +on: [push, pull_request] + +jobs: + build: + name: Build + runs-on: windows-latest + + strategy: + fail-fast: false + + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Build and install zlib + run: | + powershell -Command "(Invoke-WebRequest -Uri https://raw.githubusercontent.com/r4sas/zlib.install/master/install.bat -OutFile install_zlib.bat)" + powershell -Command "(Get-Content install_zlib.bat) | Set-Content install_zlib.bat" # fixing line endings + set BUILD_TYPE=Debug + ./install_zlib.bat + set BUILD_TYPE=Release + ./install_zlib.bat + del install_zlib.bat + + - name: Install Boost + uses: crazy-max/ghaction-chocolatey@v2 + with: + args: install boost-msvc-14.3 + + - name: Install OpenSSL + uses: crazy-max/ghaction-chocolatey@v2 + with: + args: install openssl + + - name: Configure + working-directory: build + run: cmake -DWITH_STATIC=ON . + + - name: Build + working-directory: build + run: cmake --build . --config Debug -- -m + + - name: Upload artifacts + uses: actions/upload-artifact@v3 + with: + name: i2pd-msvc + path: build/Debug/i2pd.* + diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 7a9a40c7..66c846c1 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -8,7 +8,7 @@ defaults: jobs: build: - name: Building using ${{ matrix.arch }} toolchain + name: ${{ matrix.arch }} runs-on: windows-latest strategy: @@ -50,7 +50,7 @@ jobs: path: i2pd.exe build-cmake: - name: Building using ${{ matrix.arch }} toolchain using CMake + name: CMake ${{ matrix.arch }} runs-on: windows-latest strategy: @@ -89,7 +89,7 @@ jobs: path: build/i2pd.exe build-xp: - name: Building for Windows XP + name: XP runs-on: windows-latest strategy: diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index bc65b41e..4100c23f 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -147,7 +147,10 @@ else() set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pedantic") # TODO: The following is incompatible with static build and enabled hardening for OpenWRT. # Multiple definitions of __stack_chk_fail(libssp & libc) - set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -flto -s -ffunction-sections -fdata-sections") + if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -flto -s") + endif() + set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -ffunction-sections -fdata-sections") set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "-Wl,--gc-sections") # -flto is added from above # check for c++17 & c++11 support From 6f01ebc0a51a04d756371030138e82acd7bd982f Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 11 Mar 2023 08:44:07 -0500 Subject: [PATCH 0056/1171] check target destination --- libi2pd/Streaming.cpp | 26 +++++++++++++++++++++++--- libi2pd/Streaming.h | 3 ++- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 67ed925d..42f71798 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -139,7 +139,16 @@ namespace stream { m_NumReceivedBytes += packet->GetLength (); if (!m_SendStreamID) + { m_SendStreamID = packet->GetReceiveStreamID (); + if (!m_RemoteIdentity && packet->GetNACKCount () == 8 && // first incoming packet + memcmp (packet->GetNACKs (), m_LocalDestination.GetOwner ()->GetIdentHash (), 32)) + { + LogPrint (eLogWarning, "Streaming: Destination mismatch for ", m_LocalDestination.GetOwner ()->GetIdentHash ().ToBase32 ()); + m_LocalDestination.DeletePacket (packet); + return; + } + } if (!packet->IsNoAck ()) // ack received ProcessAck (packet); @@ -560,8 +569,19 @@ namespace stream else htobe32buf (packet + size, m_LastReceivedSequenceNumber); size += 4; // ack Through - packet[size] = 0; - size++; // NACK count + if (m_Status == eStreamStatusNew && !m_SendStreamID && m_RemoteIdentity) + { + // first SYN packet + packet[size] = 8; + size++; // NACK count + memcpy (packet + size, m_RemoteIdentity->GetIdentHash (), 32); + size += 32; + } + else + { + packet[size] = 0; + size++; // NACK count + } packet[size] = m_RTO/1000; size++; // resend delay if (m_Status == eStreamStatusNew) diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 0e1f7e88..dc0ca6db 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -80,6 +80,7 @@ namespace stream uint32_t GetAckThrough () const { return bufbe32toh (buf + 12); }; uint8_t GetNACKCount () const { return buf[16]; }; uint32_t GetNACK (int i) const { return bufbe32toh (buf + 17 + 4 * i); }; + const uint8_t * GetNACKs () const { return buf + 17; }; const uint8_t * GetOption () const { return buf + 17 + GetNACKCount ()*4 + 3; }; // 3 = resendDelay + flags uint16_t GetFlags () const { return bufbe16toh (GetOption () - 2); }; uint16_t GetOptionSize () const { return bufbe16toh (GetOption ()); }; From a6bd8275ca496c75c84d7eb890c0071569d28f55 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 11 Mar 2023 10:35:55 -0500 Subject: [PATCH 0057/1171] 2.47.0 --- ChangeLog | 15 +++++++++++++++ contrib/rpm/i2pd-git.spec | 5 ++++- contrib/rpm/i2pd.spec | 5 ++++- debian/changelog | 6 ++++++ libi2pd/version.h | 6 +++--- 5 files changed, 32 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 385a3545..b6005d4f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,21 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog +## [2.47.0] - 2023-03-11 +### Added +- Congestion caps +- SAM UDP port parameter +- Support domain addresses for yggdrasil reseeds +### Changed +- DHT for floodfills instead plain list +- Process router's messages in separate thread +- Don't publish non-reachable router +- Send and check target destination in first streaming SYN packet +- Reseeds list +### Fixed +- Memory leak in windows network state detection +- Reseed attempts from invalid address + ## [2.46.1] - 2023-02-20 ### Fixed - Race condition while getting router's peer profile diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index e758d42b..4ee7a8df 100644 --- a/contrib/rpm/i2pd-git.spec +++ b/contrib/rpm/i2pd-git.spec @@ -1,7 +1,7 @@ %define git_hash %(git rev-parse HEAD | cut -c -7) Name: i2pd-git -Version: 2.46.1 +Version: 2.47.0 Release: git%{git_hash}%{?dist} Summary: I2P router written in C++ Conflicts: i2pd @@ -158,6 +158,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Sat Mar 11 2023 orignal - 2.47.0 +- update to 2.47.0 + * Mon Feb 20 2023 r4sas - 2.46.1 - update to 2.46.1 diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 32154a9c..e0ac9d03 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,5 +1,5 @@ Name: i2pd -Version: 2.46.1 +Version: 2.47.0 Release: 2%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git @@ -155,6 +155,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Sat Mar 11 2023 orignal - 2.47.0 +- update to 2.47.0 + * Mon Feb 20 2023 r4sas - 2.46.1 - update to 2.46.1 diff --git a/debian/changelog b/debian/changelog index 13691601..44b0b8b5 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i2pd (2.47.0-1) unstable; urgency=high + + * updated to version 2.47.0/0.9.58 + + -- orignal Sat, 11 Mar 2023 16:00:00 +0000 + i2pd (2.46.1-2) unstable; urgency=critical * re-pushed release due to new critical bug diff --git a/libi2pd/version.h b/libi2pd/version.h index 8d91c5c8..7d5e79fb 100644 --- a/libi2pd/version.h +++ b/libi2pd/version.h @@ -18,8 +18,8 @@ #define MAKE_VERSION_NUMBER(a,b,c) ((a*100+b)*100+c) #define I2PD_VERSION_MAJOR 2 -#define I2PD_VERSION_MINOR 46 -#define I2PD_VERSION_MICRO 1 +#define I2PD_VERSION_MINOR 47 +#define I2PD_VERSION_MICRO 0 #define I2PD_VERSION_PATCH 0 #ifdef GITVER #define I2PD_VERSION XSTRINGIZE(GITVER) @@ -33,7 +33,7 @@ #define I2P_VERSION_MAJOR 0 #define I2P_VERSION_MINOR 9 -#define I2P_VERSION_MICRO 57 +#define I2P_VERSION_MICRO 58 #define I2P_VERSION_PATCH 0 #define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO) #define I2P_VERSION_NUMBER MAKE_VERSION_NUMBER(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO) From 227697c388cae57a04d69d6e962ad379e55a3abd Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sat, 11 Mar 2023 21:53:11 +0000 Subject: [PATCH 0058/1171] [i18n] update translations Signed-off-by: R4SAS --- i18n/German.cpp | 14 ++++++++++++++ i18n/Italian.cpp | 10 ++++++++++ i18n/Portuguese.cpp | 8 ++++---- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/i18n/German.cpp b/i18n/German.cpp index 0db3d6be..02662e8e 100644 --- a/i18n/German.cpp +++ b/i18n/German.cpp @@ -61,6 +61,7 @@ namespace german // language namespace {"Clock skew", "Zeitabweichung"}, {"Offline", "Offline"}, {"Symmetric NAT", "Symmetrisches NAT"}, + {"No Descriptors", "Keine Beschreibungen"}, {"Uptime", "Laufzeit"}, {"Network status", "Netzwerkstatus"}, {"Network status v6", "Netzwerkstatus v6"}, @@ -116,8 +117,10 @@ namespace german // language namespace {"Gateway", "Gateway"}, {"TunnelID", "TunnelID"}, {"EndDate", "Enddatum"}, + {"floodfill mode is disabled", "Floodfill Modus ist deaktiviert"}, {"Queue size", "Größe der Warteschlange"}, {"Run peer test", "Peer-Test durchführen"}, + {"Reload tunnels configuration", "Tunnel Konfiguration neu laden"}, {"Decline transit tunnels", "Transittunnel ablehnen"}, {"Accept transit tunnels", "Transittunnel akzeptieren"}, {"Cancel graceful shutdown", "Beende das kontrollierte Herunterfahren"}, @@ -145,6 +148,8 @@ namespace german // language namespace {"Destination not found", "Ziel nicht gefunden"}, {"StreamID can't be null", "StreamID kann nicht null sein"}, {"Return to destination page", "Zurück zur Ziel-Seite"}, + {"You will be redirected in %d seconds", "Du wirst umgeleitet in %d Sekunden"}, + {"Transit tunnels count must not exceed %d", "Die Anzahl der Transittunnel darf nicht über %d gehen"}, {"Back to commands list", "Zurück zur Befehlsliste"}, {"Register at reg.i2p", "Auf reg.i2p registrieren"}, {"Description", "Beschreibung"}, @@ -162,6 +167,15 @@ namespace german // language namespace {"You may try to find this host on jump services below", "Vielleicht kannst du diesen Host auf einem der nachfolgenden Jump-Services finden"}, {"Invalid request", "Ungültige Anfrage"}, {"Proxy unable to parse your request", "Proxy konnte die Anfrage nicht verarbeiten"}, + {"Addresshelper is not supported", "Adresshelfer wird nicht unterstützt"}, + {"Host %s is already in router's addressbook. Be careful: source of this URL may be harmful! Click here to update record: Continue.", "Host %s ist bereits im Adressbuch des Routers. Vorsicht: Die Quelle dieser URL kann schädlich sein! Klicken Sie hier, um den Datensatz zu aktualisieren: Weiter."}, + {"Addresshelper forced update rejected", "Adresshelfer gezwungene Aktualisierung abgelehnt"}, + {"To add host %s in router's addressbook, click here: Continue.", "Um den Host %s im Adressbuch des Routers hinzuzufügen, klicken Sie hier: Weiter."}, + {"Addresshelper request", "Adresshelfer gefunden"}, + {"Host %s added to router's addressbook from helper. Click here to proceed: Continue.", "Host %s wurde vom Helfer zum Adressbuch des Routers hinzugefügt. Klicken Sie hier, um fortzufahren: Weiter."}, + {"Addresshelper adding", "Adresshelfer hinzufügen"}, + {"Host %s is already in router's addressbook. Click here to update record: Continue.", "Host %s ist bereits im Adressbuch des Routers. Klicken Sie hier, um den Eintrag zu aktualisieren: Weiter."}, + {"Addresshelper update", "Adresshelfer aktualisieren"}, {"Invalid request URI", "Ungültige Anfrage-URI"}, {"Can't detect destination host from request", "Kann den Ziel-Host von der Anfrage nicht erkennen"}, {"Outproxy failure", "Outproxy-Fehler"}, diff --git a/i18n/Italian.cpp b/i18n/Italian.cpp index c51e15a5..386372d5 100644 --- a/i18n/Italian.cpp +++ b/i18n/Italian.cpp @@ -61,6 +61,8 @@ namespace italian // language namespace {"Clock skew", "Orologio disallineato"}, {"Offline", "Disconnesso"}, {"Symmetric NAT", "NAT simmetrico"}, + {"Full cone NAT", "Cono completo NAT"}, + {"No Descriptors", "Nessun descrittore"}, {"Uptime", "In funzione da"}, {"Network status", "Stato della rete"}, {"Network status v6", "Stato della rete v6"}, @@ -116,6 +118,7 @@ namespace italian // language namespace {"Gateway", "Gateway"}, {"TunnelID", "TunnelID"}, {"EndDate", "Data di fine"}, + {"floodfill mode is disabled", "la modalità floodfill è disabilitata"}, {"Queue size", "Dimensione della coda"}, {"Run peer test", "Esegui il test dei peer"}, {"Reload tunnels configuration", "Ricarica la configurazione dei tunnel"}, @@ -165,8 +168,15 @@ namespace italian // language namespace {"You may try to find this host on jump services below", "Si può provare a trovare questo host sui servizi di salto qui sotto"}, {"Invalid request", "Richiesta non valida"}, {"Proxy unable to parse your request", "Il proxy non è in grado di elaborare la tua richiesta"}, + {"Addresshelper is not supported", "Addresshelper non è supportato"}, + {"Host %s is already in router's addressbook. Be careful: source of this URL may be harmful! Click here to update record: Continue.", "L'host %s è già nella rubrica del router. Attenzione: la fonte di questo URL potrebbe essere dannosa! Fai clic qui per aggiornare il record: Continua."}, + {"Addresshelper forced update rejected", "Aggiornamento forzato dell'helper degli indirizzi rifiutato"}, {"To add host %s in router's addressbook, click here: Continue.", "Per aggiungere host %s nella rubrica del router, clicca qui: Continua."}, + {"Addresshelper request", "Richiesta di indirizzo helper"}, + {"Host %s added to router's addressbook from helper. Click here to proceed: Continue.", "L'host %s viene aggiunto alla rubrica del router dall'helper. Fai clic qui per procedere: Continua."}, + {"Addresshelper adding", "Aggiunta di Addresshelper"}, {"Host %s is already in router's addressbook. Click here to update record: Continue.", "L'host %s è già nella rubrica del router. Clicca qui per aggiornare il record: Continua."}, + {"Addresshelper update", "Aggiornamento dell'helper degli indirizzi"}, {"Invalid request URI", "URI della richiesta non valido"}, {"Can't detect destination host from request", "Impossibile determinare l'host di destinazione dalla richiesta"}, {"Outproxy failure", "Fallimento del proxy di uscita"}, diff --git a/i18n/Portuguese.cpp b/i18n/Portuguese.cpp index 528be389..8ba7f0cd 100644 --- a/i18n/Portuguese.cpp +++ b/i18n/Portuguese.cpp @@ -73,7 +73,7 @@ namespace portuguese // language namespace {"%.2f KiB/s", "%.2f KiB/s"}, {"Sent", "Enviado"}, {"Transit", "Trânsito"}, - {"Data path", "Caminho dos dados"}, + {"Data path", "Diretório dos dados"}, {"Hidden content. Press on text to see.", "Conteúdo oculto. Clique no texto para revelar."}, {"Router Ident", "Identidade do Roteador"}, {"Router Family", "Família do Roteador"}, @@ -122,15 +122,15 @@ namespace portuguese // language namespace {"Queue size", "Tamanho da fila"}, {"Run peer test", "Executar teste de peers"}, {"Reload tunnels configuration", "Recarregar a configuração dos túneis"}, - {"Decline transit tunnels", "Negar túnel de trânsito"}, - {"Accept transit tunnels", "Aceitar túnel de trânsito"}, + {"Decline transit tunnels", "Negar túneis de trânsito"}, + {"Accept transit tunnels", "Aceitar túneis de trânsito"}, {"Cancel graceful shutdown", "Cancelar desligamento gracioso"}, {"Start graceful shutdown", "Iniciar desligamento gracioso"}, {"Force shutdown", "Forçar desligamento"}, {"Reload external CSS styles", "Recarregar estilos CSS externos"}, {"Note: any action done here are not persistent and not changes your config files.", " Nota: Qualquer ação feita aqui não será permanente e não altera os seus arquivos de configuração."}, {"Logging level", "Nível de registro"}, - {"Transit tunnels limit", "Limite nos túneis de trânsito"}, + {"Transit tunnels limit", "Limite de túneis de trânsito"}, {"Change", "Mudar"}, {"Change language", "Trocar idioma"}, {"no transit tunnels currently built", "Nenhum túnel de trânsito construido no momento"}, From b97ef1af495456484008ff54c1e5594c008dabf3 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sat, 11 Mar 2023 21:54:32 +0000 Subject: [PATCH 0059/1171] 2.47.0 Signed-off-by: R4SAS --- contrib/rpm/i2pd.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index e0ac9d03..407e2d43 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,6 +1,6 @@ Name: i2pd Version: 2.47.0 -Release: 2%{?dist} +Release: 1%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git From 8677cd54bd4d145e3bba7044484dcba4eed73a85 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sun, 12 Mar 2023 21:41:07 +0000 Subject: [PATCH 0060/1171] [cmake] win32: do not use static boost libs without WITH_STATIC Signed-off-by: R4SAS --- build/CMakeLists.txt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 4100c23f..94688761 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -277,15 +277,19 @@ else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") endif() add_definitions(-DBOOST_ATOMIC_DYN_LINK -DBOOST_SYSTEM_DYN_LINK -DBOOST_FILESYSTEM_DYN_LINK -DBOOST_PROGRAM_OPTIONS_DYN_LINK -DBOOST_DATE_TIME_DYN_LINK -DBOOST_REGEX_DYN_LINK) + if(WIN32) + set(Boost_USE_STATIC_LIBS OFF) + set(Boost_USE_STATIC_RUNTIME OFF) + endif() endif() find_package(Boost REQUIRED COMPONENTS system filesystem program_options date_time OPTIONAL_COMPONENTS atomic) -if(NOT DEFINED Boost_INCLUDE_DIRS) +if(NOT DEFINED Boost_FOUND) message(SEND_ERROR "Boost is not found, or your boost version was below 1.46. Please download Boost!") endif() find_package(OpenSSL REQUIRED) -if(NOT DEFINED OPENSSL_INCLUDE_DIR) +if(NOT DEFINED OPENSSL_FOUND) message(SEND_ERROR "Could not find OpenSSL. Please download and install it first!") endif() @@ -372,7 +376,7 @@ if(WITH_BINARY) set(DL_LIB ${CMAKE_DL_LIBS}) endif() - target_link_libraries("${PROJECT_NAME}" libi2pd libi2pdclient libi2pdlang ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto ${MINIUPNPC_LIBRARY} ZLIB::ZLIB Threads::Threads ${MINGW_EXTRA} ${DL_LIB} ${CMAKE_REQUIRED_LIBRARIES}) + target_link_libraries("${PROJECT_NAME}" libi2pd libi2pdclient libi2pdlang Boost::system Boost::filesystem Boost::program_options Boost::date_time OpenSSL::SSL OpenSSL::Crypto ${MINIUPNPC_LIBRARY} ZLIB::ZLIB Threads::Threads ${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 e96f0bfb142a9a252e060aead451166cd335a65e Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 13 Mar 2023 18:34:45 +0000 Subject: [PATCH 0061/1171] [msvc] fix warnings, revert cmake boost libs linking list Signed-off-by: R4SAS --- build/CMakeLists.txt | 2 +- libi2pd/Ed25519.cpp | 4 ++-- libi2pd/Family.cpp | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 94688761..05401b1f 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -376,7 +376,7 @@ if(WITH_BINARY) set(DL_LIB ${CMAKE_DL_LIBS}) endif() - target_link_libraries("${PROJECT_NAME}" libi2pd libi2pdclient libi2pdlang Boost::system Boost::filesystem Boost::program_options Boost::date_time OpenSSL::SSL OpenSSL::Crypto ${MINIUPNPC_LIBRARY} ZLIB::ZLIB Threads::Threads ${MINGW_EXTRA} ${DL_LIB} ${CMAKE_REQUIRED_LIBRARIES}) + target_link_libraries("${PROJECT_NAME}" libi2pd libi2pdclient libi2pdlang ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto ${MINIUPNPC_LIBRARY} ZLIB::ZLIB Threads::Threads ${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}") diff --git a/libi2pd/Ed25519.cpp b/libi2pd/Ed25519.cpp index 0c6eb4f7..3e0795d5 100644 --- a/libi2pd/Ed25519.cpp +++ b/libi2pd/Ed25519.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -413,7 +413,7 @@ namespace crypto BIGNUM * y = BN_new (); BN_bin2bn (buf1, EDDSA25519_PUBLIC_KEY_LENGTH, y); BIGNUM * x = RecoverX (y, ctx); - if (BN_is_bit_set (x, 0) != isHighestBitSet) + if ((bool)BN_is_bit_set (x, 0) != isHighestBitSet) BN_sub (x, q, x); // x = q - x BIGNUM * z = BN_new (), * t = BN_new (); BN_one (z); BN_mod_mul (t, x, y, q, ctx); // pre-calculate t diff --git a/libi2pd/Family.cpp b/libi2pd/Family.cpp index 9a0700d0..8c6d3ba4 100644 --- a/libi2pd/Family.cpp +++ b/libi2pd/Family.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -88,7 +88,7 @@ namespace data } EVP_PKEY_free (pkey); if (verifier && cn) - m_SigningKeys.emplace (cn, std::make_pair(verifier, m_SigningKeys.size () + 1)); + m_SigningKeys.emplace (cn, std::make_pair(verifier, (int)m_SigningKeys.size () + 1)); } SSL_free (ssl); } From 5ad9c8e74097f1ec97476198a31db4397b5f48b0 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 13 Mar 2023 19:19:57 -0400 Subject: [PATCH 0062/1171] create I2NP tunnel message for first fragment --- libi2pd/SSU2Session.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 46acf05b..9a2fea9a 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1766,8 +1766,8 @@ namespace transport void SSU2Session::HandleFirstFragment (const uint8_t * buf, size_t len) { + auto msg = (buf[0] == eI2NPTunnelData) ? NewI2NPTunnelMessage (true) : NewI2NPShortMessage (); uint32_t msgID; memcpy (&msgID, buf + 1, 4); - auto msg = NewI2NPShortMessage (); // same format as I2NP message block msg->len = msg->offset + len + 7; memcpy (msg->GetNTCP2Header (), buf, len); From 55b2f2c625ae3b7de2d6f20716c908bba801c370 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 16 Mar 2023 21:32:53 -0400 Subject: [PATCH 0063/1171] memory pool for IdentityEx --- libi2pd/Identity.cpp | 78 +++++++++++++----------------------------- libi2pd/Identity.h | 13 +++---- libi2pd/LeaseSet.cpp | 4 +-- libi2pd/NetDb.cpp | 1 + libi2pd/NetDb.hpp | 2 ++ libi2pd/RouterInfo.cpp | 13 +++++-- libi2pd/RouterInfo.h | 2 ++ 7 files changed, 46 insertions(+), 67 deletions(-) diff --git a/libi2pd/Identity.cpp b/libi2pd/Identity.cpp index bf9c26c5..073d8c06 100644 --- a/libi2pd/Identity.cpp +++ b/libi2pd/Identity.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -187,7 +187,6 @@ namespace data IdentityEx::~IdentityEx () { - delete m_Verifier; } IdentityEx& IdentityEx::operator=(const IdentityEx& other) @@ -201,9 +200,8 @@ namespace data if (m_ExtendedLen > MAX_EXTENDED_BUFFER_SIZE) m_ExtendedLen = MAX_EXTENDED_BUFFER_SIZE; memcpy (m_ExtendedBuffer, other.m_ExtendedBuffer, m_ExtendedLen); } - - delete m_Verifier; m_Verifier = nullptr; + CreateVerifier (); return *this; } @@ -212,11 +210,10 @@ namespace data { m_StandardIdentity = standard; m_IdentHash = m_StandardIdentity.Hash (); - m_ExtendedLen = 0; - delete m_Verifier; m_Verifier = nullptr; + CreateVerifier (); return *this; } @@ -249,8 +246,8 @@ namespace data m_ExtendedLen = 0; SHA256(buf, GetFullLen (), m_IdentHash); - delete m_Verifier; m_Verifier = nullptr; + CreateVerifier (); return GetFullLen (); } @@ -286,7 +283,6 @@ namespace data size_t IdentityEx::GetSigningPublicKeyLen () const { - if (!m_Verifier) CreateVerifier (); if (m_Verifier) return m_Verifier->GetPublicKeyLen (); return 128; @@ -301,7 +297,6 @@ namespace data size_t IdentityEx::GetSigningPrivateKeyLen () const { - if (!m_Verifier) CreateVerifier (); if (m_Verifier) return m_Verifier->GetPrivateKeyLen (); return GetSignatureLen ()/2; @@ -309,14 +304,12 @@ namespace data size_t IdentityEx::GetSignatureLen () const { - if (!m_Verifier) CreateVerifier (); if (m_Verifier) return m_Verifier->GetSignatureLen (); return i2p::crypto::DSA_SIGNATURE_LENGTH; } bool IdentityEx::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const { - if (!m_Verifier) CreateVerifier (); if (m_Verifier) return m_Verifier->Verify (buf, len, signature); return false; @@ -373,52 +366,29 @@ namespace data return nullptr; } - void IdentityEx::CreateVerifier () const + void IdentityEx::CreateVerifier () { - if (m_Verifier) return; // don't create again - auto verifier = CreateVerifier (GetSigningKeyType ()); - if (verifier) - { - auto keyLen = verifier->GetPublicKeyLen (); - if (keyLen <= 128) - verifier->SetPublicKey (m_StandardIdentity.signingKey + 128 - keyLen); - else + if (!m_Verifier) + { + auto verifier = CreateVerifier (GetSigningKeyType ()); + if (verifier) { - // for P521 - uint8_t * signingKey = new uint8_t[keyLen]; - memcpy (signingKey, m_StandardIdentity.signingKey, 128); - size_t excessLen = keyLen - 128; - memcpy (signingKey + 128, m_ExtendedBuffer + 4, excessLen); // right after signing and crypto key types - verifier->SetPublicKey (signingKey); - delete[] signingKey; + auto keyLen = verifier->GetPublicKeyLen (); + if (keyLen <= 128) + verifier->SetPublicKey (m_StandardIdentity.signingKey + 128 - keyLen); + else + { + // for P521 + uint8_t * signingKey = new uint8_t[keyLen]; + memcpy (signingKey, m_StandardIdentity.signingKey, 128); + size_t excessLen = keyLen - 128; + memcpy (signingKey + 128, m_ExtendedBuffer + 4, excessLen); // right after signing and crypto key types + verifier->SetPublicKey (signingKey); + delete[] signingKey; + } } - } - UpdateVerifier (verifier); - } - - void IdentityEx::UpdateVerifier (i2p::crypto::Verifier * verifier) const - { - bool del = false; - { - std::lock_guard l(m_VerifierMutex); - if (!m_Verifier) - m_Verifier = verifier; - else - del = true; - } - if (del) - delete verifier; - } - - void IdentityEx::DropVerifier () const - { - i2p::crypto::Verifier * verifier; - { - std::lock_guard l(m_VerifierMutex); - verifier = m_Verifier; - m_Verifier = nullptr; - } - delete verifier; + m_Verifier.reset (verifier); + } } std::shared_ptr IdentityEx::CreateEncryptor (CryptoKeyType keyType, const uint8_t * key) diff --git a/libi2pd/Identity.h b/libi2pd/Identity.h index d5a2da21..97d596d8 100644 --- a/libi2pd/Identity.h +++ b/libi2pd/Identity.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -13,9 +13,7 @@ #include #include #include -#include #include -#include #include "Base.h" #include "Signature.h" #include "CryptoKey.h" @@ -118,7 +116,6 @@ namespace data SigningKeyType GetSigningKeyType () const; bool IsRSA () const; // signing key type CryptoKeyType GetCryptoKeyType () const; - void DropVerifier () const; // to save memory bool operator == (const IdentityEx & other) const { return GetIdentHash() == other.GetIdentHash(); } void RecalculateIdentHash(uint8_t * buff=nullptr); @@ -128,15 +125,13 @@ namespace data private: - void CreateVerifier () const; - void UpdateVerifier (i2p::crypto::Verifier * verifier) const; - + void CreateVerifier (); + private: Identity m_StandardIdentity; IdentHash m_IdentHash; - mutable i2p::crypto::Verifier * m_Verifier = nullptr; - mutable std::mutex m_VerifierMutex; + std::unique_ptr m_Verifier; size_t m_ExtendedLen; uint8_t m_ExtendedBuffer[MAX_EXTENDED_BUFFER_SIZE]; }; diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index 4d756bdb..c47f23d8 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -50,7 +50,7 @@ namespace data void LeaseSet::ReadFromBuffer (bool readIdentity, bool verifySignature) { if (readIdentity || !m_Identity) - m_Identity = std::make_shared(m_Buffer, m_BufferLen); + m_Identity = netdb.NewIdentity (m_Buffer, m_BufferLen); size_t size = m_Identity->GetFullLen (); if (size + 256 > m_BufferLen) { @@ -317,7 +317,7 @@ namespace data std::shared_ptr identity; if (readIdentity || !GetIdentity ()) { - identity = std::make_shared(buf, len); + identity = netdb.NewIdentity (buf, len); SetIdentity (identity); } else diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 5dfb7889..82e15304 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -662,6 +662,7 @@ namespace data m_RouterInfoBuffersPool.CleanUpMt (); m_RouterInfoAddressesPool.CleanUpMt (); m_RouterInfoAddressVectorsPool.CleanUpMt (); + m_IdentitiesPool.CleanUpMt (); if (updatedCount > 0) LogPrint (eLogInfo, "NetDb: Saved ", updatedCount, " new/updated routers"); diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index 7958e36d..71694d8d 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -127,6 +127,7 @@ namespace data &m_RouterInfoAddressVectorsPool, std::placeholders::_1)); }; std::shared_ptr NewLease (const Lease& lease) { return m_LeasesPool.AcquireSharedMt (lease); }; + std::shared_ptr NewIdentity (const uint8_t * buf, size_t len) { return m_IdentitiesPool.AcquireSharedMt (buf, len); }; uint32_t GetPublishReplyToken () const { return m_PublishReplyToken; }; @@ -182,6 +183,7 @@ namespace data i2p::util::MemoryPoolMt m_RouterInfoAddressesPool; i2p::util::MemoryPoolMt m_RouterInfoAddressVectorsPool; i2p::util::MemoryPoolMt m_LeasesPool; + i2p::util::MemoryPoolMt m_IdentitiesPool; }; extern NetDb netdb; diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index db0a7de6..b006cdc0 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -161,7 +161,7 @@ namespace data m_IsUnreachable = true; return; } - m_RouterIdentity = std::make_shared(m_Buffer->data (), m_BufferLen); + m_RouterIdentity = NewIdentity (m_Buffer->data (), m_BufferLen); size_t identityLen = m_RouterIdentity->GetFullLen (); if (identityLen >= m_BufferLen) { @@ -186,7 +186,6 @@ namespace data m_IsUnreachable = true; return; } - m_RouterIdentity->DropVerifier (); } // parse RI std::stringstream str; @@ -1061,6 +1060,11 @@ namespace data return netdb.NewRouterInfoAddresses (); } + std::shared_ptr RouterInfo::NewIdentity (const uint8_t * buf, size_t len) const + { + return netdb.NewIdentity (buf, len); + } + void RouterInfo::RefreshTimestamp () { m_Timestamp = i2p::util::GetMillisecondsSinceEpoch (); @@ -1393,6 +1397,11 @@ namespace data return boost::make_shared (); } + std::shared_ptr LocalRouterInfo::NewIdentity (const uint8_t * buf, size_t len) const + { + return std::make_shared (buf, len); + } + bool LocalRouterInfo::AddSSU2Introducer (const Introducer& introducer, bool v4) { auto addresses = GetAddresses (); diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 3e8e0613..ef145496 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -307,6 +307,7 @@ namespace data virtual std::shared_ptr NewBuffer () const; virtual std::shared_ptr
NewAddress () const; virtual boost::shared_ptr NewAddresses () const; + virtual std::shared_ptr NewIdentity (const uint8_t * buf, size_t len) const; private: @@ -350,6 +351,7 @@ namespace data std::shared_ptr NewBuffer () const override; std::shared_ptr
NewAddress () const override; boost::shared_ptr NewAddresses () const override; + std::shared_ptr NewIdentity (const uint8_t * buf, size_t len) const override; private: From 084663d6ead53cb94b2244ef48be28ac0cdd4d3b Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 18 Mar 2023 15:32:05 -0400 Subject: [PATCH 0064/1171] mediam size I2NP messages --- libi2pd/I2NPProtocol.cpp | 10 +++++++++- libi2pd/I2NPProtocol.h | 2 ++ libi2pd/SSU2Session.cpp | 2 +- libi2pd/TunnelEndpoint.cpp | 8 ++++---- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index 5ae89c23..369107b4 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -36,6 +36,11 @@ namespace i2p return std::make_shared >(); } + std::shared_ptr NewI2NPMediumMessage () + { + return std::make_shared >(); + } + std::shared_ptr NewI2NPTunnelMessage (bool endpoint) { return i2p::tunnel::tunnels.NewI2NPTunnelMessage (endpoint); @@ -43,7 +48,10 @@ namespace i2p std::shared_ptr NewI2NPMessage (size_t len) { - return (len < I2NP_MAX_SHORT_MESSAGE_SIZE - I2NP_HEADER_SIZE - 2) ? NewI2NPShortMessage () : NewI2NPMessage (); + len += I2NP_HEADER_SIZE + 2; + if (len <= I2NP_MAX_SHORT_MESSAGE_SIZE) return NewI2NPShortMessage (); + if (len <= I2NP_MAX_MEDIUM_MESSAGE_SIZE) return NewI2NPMediumMessage (); + return NewI2NPMessage (); } void I2NPMessage::FillI2NPMessageHeader (I2NPMessageType msgType, uint32_t replyMsgID, bool checksum) diff --git a/libi2pd/I2NPProtocol.h b/libi2pd/I2NPProtocol.h index 80757501..c0685190 100644 --- a/libi2pd/I2NPProtocol.h +++ b/libi2pd/I2NPProtocol.h @@ -140,6 +140,7 @@ namespace tunnel const size_t I2NP_MAX_MESSAGE_SIZE = 62708; const size_t I2NP_MAX_SHORT_MESSAGE_SIZE = 4096; + const size_t I2NP_MAX_MEDIUM_MESSAGE_SIZE = 16384; const unsigned int I2NP_MESSAGE_EXPIRATION_TIMEOUT = 8000; // in milliseconds (as initial RTT) const unsigned int I2NP_MESSAGE_CLOCK_SKEW = 60*1000; // 1 minute in milliseconds @@ -262,6 +263,7 @@ namespace tunnel std::shared_ptr NewI2NPMessage (); std::shared_ptr NewI2NPShortMessage (); + std::shared_ptr NewI2NPMediumMessage (); std::shared_ptr NewI2NPTunnelMessage (bool endpoint); std::shared_ptr NewI2NPMessage (size_t len); diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 9a2fea9a..4d3a9866 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -23,7 +23,7 @@ namespace transport if (msg->len + fragmentSize > msg->maxLen) { LogPrint (eLogInfo, "SSU2: I2NP message size ", msg->maxLen, " is not enough"); - auto newMsg = NewI2NPMessage (); + auto newMsg = NewI2NPMessage (msg->len + fragmentSize); *newMsg = *msg; msg = newMsg; } diff --git a/libi2pd/TunnelEndpoint.cpp b/libi2pd/TunnelEndpoint.cpp index 9c294374..7d3b3cbe 100644 --- a/libi2pd/TunnelEndpoint.cpp +++ b/libi2pd/TunnelEndpoint.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -208,7 +208,7 @@ namespace tunnel if (msg.data->len + size > msg.data->maxLen) { // LogPrint (eLogWarning, "TunnelMessage: I2NP message size ", msg.data->maxLen, " is not enough"); - auto newMsg = NewI2NPMessage (); + auto newMsg = NewI2NPMessage (msg.data->len + size); *newMsg = *(msg.data); msg.data = newMsg; } @@ -297,11 +297,11 @@ namespace tunnel if (msg.data->len + size > msg.data->maxLen) { LogPrint (eLogWarning, "TunnelMessage: Tunnel endpoint I2NP message size ", msg.data->maxLen, " is not enough"); - auto newMsg = NewI2NPMessage (); + auto newMsg = NewI2NPMessage (msg.data->len + size); *newMsg = *(msg.data); msg.data = newMsg; } - if (msg.data->Concat (it->second->data.data (), 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) // message complete From 32b54fa1f82c2141154dc8f9d5fbae2d565f0cdb Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 19 Mar 2023 15:47:50 -0400 Subject: [PATCH 0065/1171] handle i2p.streaming.answerPings properly --- libi2pd/Destination.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 5d6b71b9..b6dbeaed 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1000,7 +1000,7 @@ namespace client m_StreamingAckDelay = std::stoi(it->second); it = params->find (I2CP_PARAM_STREAMING_ANSWER_PINGS); if (it != params->end ()) - m_IsStreamingAnswerPings = (it->second == "true"); + m_IsStreamingAnswerPings = std::stoi (it->second); // 1 for true if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) { From f41563a7005363bbfea18f9ec38811cb657e1c5a Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 19 Mar 2023 17:42:53 -0400 Subject: [PATCH 0066/1171] check packet number for SessionConfirmed --- libi2pd/SSU2Session.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 4d3a9866..bc8b5486 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -608,7 +608,7 @@ namespace transport * payload = m_SentHandshakePacket->payload; // fill packet header.h.connID = m_DestConnID; // dest id - header.h.packetNum = 0; + RAND_bytes (header.buf + 8, 4); // random packet num header.h.type = eSSU2SessionRequest; header.h.flags[0] = 2; // ver header.h.flags[1] = (uint8_t)i2p::context.GetNetID (); // netID @@ -636,7 +636,7 @@ namespace transport m_EphemeralKeys->Agree (m_Address->s, sharedSecret); m_NoiseState->MixKey (sharedSecret); // encrypt - const uint8_t nonce[12] = {0}; + const uint8_t nonce[12] = {0}; // always 0 i2p::crypto::AEADChaCha20Poly1305 (payload, payloadSize, m_NoiseState->m_H, 32, m_NoiseState->m_CK + 32, nonce, payload, payloadSize + 16, true); payloadSize += 16; header.ll[0] ^= CreateHeaderMask (m_Address->i, payload + (payloadSize - 24)); @@ -721,7 +721,7 @@ namespace transport uint8_t * headerX = m_SentHandshakePacket->headerX, * payload = m_SentHandshakePacket->payload; header.h.connID = m_DestConnID; // dest id - header.h.packetNum = 0; + RAND_bytes (header.buf + 8, 4); // random packet num header.h.type = eSSU2SessionCreated; header.h.flags[0] = 2; // ver header.h.flags[1] = (uint8_t)i2p::context.GetNetID (); // netID @@ -760,7 +760,7 @@ namespace transport m_EphemeralKeys->Agree (X, sharedSecret); m_NoiseState->MixKey (sharedSecret); // encrypt - const uint8_t nonce[12] = {0}; + const uint8_t nonce[12] = {0}; // always zero i2p::crypto::AEADChaCha20Poly1305 (payload, payloadSize, m_NoiseState->m_H, 32, m_NoiseState->m_CK + 32, nonce, payload, payloadSize + 16, true); payloadSize += 16; m_NoiseState->MixHash (payload, payloadSize); // h = SHA256(h || encrypted Noise payload from Session Created) @@ -832,7 +832,7 @@ namespace transport // fill packet Header& header = m_SentHandshakePacket->header; header.h.connID = m_DestConnID; // dest id - header.h.packetNum = 0; + header.h.packetNum = 0; // always zero header.h.type = eSSU2SessionConfirmed; memset (header.h.flags, 0, 3); header.h.flags[0] = 1; // frag, total fragments always 1 @@ -855,7 +855,7 @@ namespace transport // Encrypt part 1 uint8_t * part1 = m_SentHandshakePacket->headerX; uint8_t nonce[12]; - CreateNonce (1, nonce); + CreateNonce (1, nonce); // always one i2p::crypto::AEADChaCha20Poly1305 (i2p::context.GetSSU2StaticPublicKey (), 32, m_NoiseState->m_H, 32, m_NoiseState->m_CK + 32, nonce, part1, 48, true); m_NoiseState->MixHash (part1, 48); // h = SHA256(h || ciphertext); // KDF for Session Confirmed part 2 @@ -863,7 +863,7 @@ namespace transport i2p::context.GetSSU2StaticKeys ().Agree (Y, sharedSecret); m_NoiseState->MixKey (sharedSecret); // Encrypt part2 - memset (nonce, 0, 12); + memset (nonce, 0, 12); // always zero i2p::crypto::AEADChaCha20Poly1305 (payload, payloadSize, m_NoiseState->m_H, 32, m_NoiseState->m_CK + 32, nonce, payload, payloadSize + 16, true); payloadSize += 16; m_NoiseState->MixHash (payload, payloadSize); // h = SHA256(h || ciphertext); @@ -920,6 +920,12 @@ namespace transport // TODO: queue up return true; } + // packet num must be aways zero + if (header.h.packetNum) + { + LogPrint (eLogError, "SSU2: Non zero packet number in SessionConfirmed"); + return false; + } // check if fragmented uint8_t numFragments = header.h.flags[0] & 0x0F; if (numFragments > 1) From 644d65054d5fcafc0a9b4cb36c27b69558f84f45 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 21 Mar 2023 21:25:00 -0400 Subject: [PATCH 0067/1171] create smaller I2NP packets --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 4 ++-- libi2pd/I2NPProtocol.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 7f9fb72d..3b3ed485 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -1150,7 +1150,7 @@ namespace garlic std::shared_ptr WrapECIESX25519Message (std::shared_ptr msg, const uint8_t * key, uint64_t tag) { - auto m = NewI2NPMessage (); + auto m = NewI2NPMessage ((msg ? msg->GetPayloadLength () : 0) + 128); m->Align (12); // in order to get buf aligned to 16 (12 + 4) uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length size_t offset = 0; @@ -1176,7 +1176,7 @@ namespace garlic // Noise_N, we are Alice, routerPublicKey is Bob's i2p::crypto::NoiseSymmetricState noiseState; i2p::crypto::InitNoiseNState (noiseState, routerPublicKey); - auto m = NewI2NPMessage (); + auto m = NewI2NPMessage ((msg ? msg->GetPayloadLength () : 0) + 128); m->Align (12); // in order to get buf aligned to 16 (12 + 4) uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length size_t offset = 0; diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index 369107b4..5303edbf 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -134,7 +134,8 @@ namespace i2p std::shared_ptr CreateRouterInfoDatabaseLookupMsg (const uint8_t * key, const uint8_t * from, uint32_t replyTunnelID, bool exploratory, std::set * excludedPeers) { - auto m = excludedPeers ? NewI2NPMessage () : NewI2NPShortMessage (); + int cnt = excludedPeers ? excludedPeers->size () : 0; + auto m = cnt > 7 ? NewI2NPMessage () : NewI2NPShortMessage (); uint8_t * buf = m->GetPayload (); memcpy (buf, key, 32); // key buf += 32; @@ -155,7 +156,6 @@ namespace i2p if (excludedPeers) { - int cnt = excludedPeers->size (); htobe16buf (buf, cnt); buf += 2; for (auto& it: *excludedPeers) From 5fee6df87af09566f72d975593b001fd3b4ddd14 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 23 Mar 2023 19:52:39 -0400 Subject: [PATCH 0068/1171] handle reset in reposnse to SYN --- libi2pd/Streaming.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 42f71798..785ab6bb 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -154,8 +154,7 @@ namespace stream ProcessAck (packet); int32_t receivedSeqn = packet->GetSeqn (); - bool isSyn = packet->IsSYN (); - if (!receivedSeqn && !isSyn) + if (!receivedSeqn && !packet->GetFlags ()) { // plain ack LogPrint (eLogDebug, "Streaming: Plain ACK received"); @@ -197,7 +196,7 @@ namespace stream shared_from_this (), std::placeholders::_1)); } } - else if (isSyn) + else if (packet->IsSYN ()) // we have to send SYN back to incoming connection SendBuffer (); // also sets m_IsOpen } From d91d734b5c43f174038a5ca2bdad7fb929ba5a7f Mon Sep 17 00:00:00 2001 From: Dimitris Apostolou Date: Fri, 24 Mar 2023 22:15:47 +0200 Subject: [PATCH 0069/1171] Fix typos --- libi2pd/KadDHT.cpp | 4 ++-- libi2pd/SSU2Session.cpp | 2 +- libi2pd/Tunnel.cpp | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libi2pd/KadDHT.cpp b/libi2pd/KadDHT.cpp index b171cdbc..0f9df8e4 100644 --- a/libi2pd/KadDHT.cpp +++ b/libi2pd/KadDHT.cpp @@ -81,13 +81,13 @@ namespace data { if (bit1) { - if (root->one) return; // someting wrong + if (root->one) return; // something wrong root->one = new DHTNode; root = root->one; } else { - if (root->zero) return; // someting wrong + if (root->zero) return; // something wrong root->zero = new DHTNode; root = root->zero; } diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index bc8b5486..c492279d 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -920,7 +920,7 @@ namespace transport // TODO: queue up return true; } - // packet num must be aways zero + // packet num must be always zero if (header.h.packetNum) { LogPrint (eLogError, "SSU2: Non zero packet number in SessionConfirmed"); diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 58e13ad3..09358179 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -332,7 +332,7 @@ namespace tunnel Tunnels tunnels; Tunnels::Tunnels (): m_IsRunning (false), m_Thread (nullptr), m_MaxNumTransitTunnels (DEFAULT_MAX_NUM_TRANSIT_TUNNELS), - m_TotalNumSuccesiveTunnelCreations (0), m_TotalNumFailedTunnelCreations (0), // for normal avarage + m_TotalNumSuccesiveTunnelCreations (0), m_TotalNumFailedTunnelCreations (0), // for normal average m_TunnelCreationSuccessRate (TCSR_START_VALUE), m_TunnelCreationAttemptsNum(0) { } @@ -544,7 +544,7 @@ namespace tunnel ManageTunnels (ts); lastTs = ts; } - if (ts - lastPoolsTs >= TUNNEL_POOLS_MANAGE_INTERVAL || // manage pools every 5 secondsts + if (ts - lastPoolsTs >= TUNNEL_POOLS_MANAGE_INTERVAL || // manage pools every 5 seconds ts + TUNNEL_POOLS_MANAGE_INTERVAL < lastPoolsTs) { ManageTunnelPools (ts); @@ -698,7 +698,7 @@ namespace tunnel if (m_OutboundTunnels.size () < 3) { - // trying to create one more oubound tunnel + // trying to create one more outbound tunnel auto inboundTunnel = GetNextInboundTunnel (); auto router = i2p::transport::transports.RoutesRestricted() ? i2p::transport::transports.GetRestrictedPeer() : From 71bad23906f47113b8cfb9f906e0d76cc8d6c3b5 Mon Sep 17 00:00:00 2001 From: ralsei Date: Sun, 26 Mar 2023 05:41:56 +0000 Subject: [PATCH 0070/1171] add dinit service Signed-off-by: R4SAS --- contrib/dinit/i2pd | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 contrib/dinit/i2pd diff --git a/contrib/dinit/i2pd b/contrib/dinit/i2pd new file mode 100644 index 00000000..63d877c1 --- /dev/null +++ b/contrib/dinit/i2pd @@ -0,0 +1,8 @@ +type = bgprocess +run-as = i2pd +command = /usr/bin/i2pd --conf=/var/lib/i2pd/i2pd.conf --pidfile=/var/lib/i2pd/i2pd.pid --daemon --service +smooth-recovery = true +depends-on = ntpd +# uncomment if you want to use i2pd with yggdrasil +# depends-on = yggdrasil +pid-file = /var/lib/i2pd/i2pd.pid From 6d204b4d7b9083512a571c329d6be855c8f15451 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 26 Mar 2023 22:12:43 -0400 Subject: [PATCH 0071/1171] shorter streaming I2NP data messages --- libi2pd/Streaming.cpp | 2 +- libi2pd/Streaming.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 785ab6bb..1deca8a6 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -1447,7 +1447,7 @@ namespace stream const uint8_t * payload, size_t len, uint16_t toPort, bool checksum, bool gzip) { size_t size; - auto msg = m_I2NPMsgsPool.AcquireShared (); + auto msg = (len <= STREAMING_MTU_RATCHETS) ? m_I2NPMsgsPool.AcquireShared () : NewI2NPMessage (); uint8_t * buf = msg->GetPayload (); buf += 4; // reserve for lengthlength msg->len += 4; diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index dc0ca6db..3609df92 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -313,7 +313,7 @@ namespace stream std::unordered_map > m_SavedPackets; // receiveStreamID->packets, arrived before SYN i2p::util::MemoryPool m_PacketsPool; - i2p::util::MemoryPool > m_I2NPMsgsPool; + i2p::util::MemoryPool > m_I2NPMsgsPool; public: From c45e31b1b27cfac3f9c164bbe64c9e60d0a7a9fb Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 28 Mar 2023 22:00:17 -0400 Subject: [PATCH 0072/1171] validate new router --- libi2pd/RouterContext.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 084e8c77..20ac589b 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -229,6 +229,7 @@ namespace i2p routerInfo.CreateBuffer (m_Keys); m_RouterInfo.SetRouterIdentity (GetIdentity ()); m_RouterInfo.Update (routerInfo.GetBuffer (), routerInfo.GetBufferLen ()); + m_RouterInfo.SetUnreachable (false); } uint16_t RouterContext::SelectRandomPort () const From 60e648bf9a8c0caedaab74e184211c6a34032cad Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 29 Mar 2023 13:40:12 -0400 Subject: [PATCH 0073/1171] set cap 6 for unspecified ipv6 address --- libi2pd/RouterInfo.cpp | 35 ++++++++++++++--------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index b006cdc0..7462ef0e 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -1201,44 +1201,37 @@ namespace data s.write ((const char *)&cost, sizeof (cost)); s.write ((const char *)&address.date, sizeof (address.date)); std::stringstream properties; - bool isPublished = false; + bool isPublished = address.published && !address.host.is_unspecified () && address.port; if (address.transportStyle == eTransportNTCP2) { - if (address.IsNTCP2 ()) + WriteString ("NTCP2", s); + // caps + if (!isPublished) { - WriteString ("NTCP2", s); - if (address.IsPublishedNTCP2 () && !address.host.is_unspecified () && address.port) - isPublished = true; - else - { - WriteString ("caps", properties); - properties << '='; - std::string caps; - if (address.IsV4 ()) caps += CAPS_FLAG_V4; - if (address.IsV6 ()) caps += CAPS_FLAG_V6; - if (caps.empty ()) caps += CAPS_FLAG_V4; - WriteString (caps, properties); - properties << ';'; - } + WriteString ("caps", properties); + properties << '='; + std::string caps; + if (address.IsV4 ()) caps += CAPS_FLAG_V4; + if (address.IsV6 () || address.host.is_v6 ()) caps += CAPS_FLAG_V6; // we set 6 for unspecified ipv6 + if (caps.empty ()) caps += CAPS_FLAG_V4; + WriteString (caps, properties); + properties << ';'; } - else - continue; // don't write NTCP address } else if (address.transportStyle == eTransportSSU2) { WriteString ("SSU2", s); // caps std::string caps; - if (address.published) + if (isPublished) { - isPublished = true; if (address.IsPeerTesting ()) caps += CAPS_FLAG_SSU2_TESTING; if (address.IsIntroducer ()) caps += CAPS_FLAG_SSU2_INTRODUCER; } else { if (address.IsV4 ()) caps += CAPS_FLAG_V4; - if (address.IsV6 ()) caps += CAPS_FLAG_V6; + if (address.IsV6 () || address.host.is_v6 ()) caps += CAPS_FLAG_V6; // we set 6 for unspecified ipv6 if (caps.empty ()) caps += CAPS_FLAG_V4; } if (!caps.empty ()) From cd1af85e39e0e683af0ea74980d6bb3874bead71 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 29 Mar 2023 15:54:53 -0400 Subject: [PATCH 0074/1171] bypass slow transport sessions --- daemon/HTTPServer.cpp | 1 + libi2pd/NTCP2.cpp | 4 ++++ libi2pd/SSU2Session.cpp | 4 ++++ libi2pd/TransportSession.h | 10 ++++++++-- libi2pd/Transports.cpp | 5 +++-- libi2pd/Transports.h | 10 ++++++++-- 6 files changed, 28 insertions(+), 6 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 3d5ff1a0..29f3f569 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -838,6 +838,7 @@ namespace http { tmp_s << " [itag:" << it->GetRelayTag () << "]"; if (it->GetSendQueueSize () > 0) tmp_s << " [queue:" << it->GetSendQueueSize () << "]"; + if (it->IsSlow ()) tmp_s << " [slow]"; tmp_s << "
\r\n" << std::endl; cnt++; } diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index eaa186f8..48c905ca 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -452,6 +452,7 @@ namespace transport { m_Establisher->CreateSessionRequestMessage (); // send message + m_HandshakeInterval = i2p::util::GetMillisecondsSinceEpoch (); boost::asio::async_write (m_Socket, boost::asio::buffer (m_Establisher->m_SessionRequestBuffer, m_Establisher->m_SessionRequestBufferLen), boost::asio::transfer_all (), std::bind(&NTCP2Session::HandleSessionRequestSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); } @@ -529,6 +530,7 @@ namespace transport { m_Establisher->CreateSessionCreatedMessage (); // send message + m_HandshakeInterval = i2p::util::GetMillisecondsSinceEpoch (); boost::asio::async_write (m_Socket, boost::asio::buffer (m_Establisher->m_SessionCreatedBuffer, m_Establisher->m_SessionCreatedBufferLen), boost::asio::transfer_all (), std::bind(&NTCP2Session::HandleSessionCreatedSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); } @@ -542,6 +544,7 @@ namespace transport } else { + m_HandshakeInterval = i2p::util::GetMillisecondsSinceEpoch () - m_HandshakeInterval; LogPrint (eLogDebug, "NTCP2: SessionCreated received ", bytes_transferred); uint16_t paddingLen = 0; if (m_Establisher->ProcessSessionCreatedMessage (paddingLen)) @@ -646,6 +649,7 @@ namespace transport } else { + m_HandshakeInterval = i2p::util::GetMillisecondsSinceEpoch () - m_HandshakeInterval; LogPrint (eLogDebug, "NTCP2: SessionConfirmed received"); // part 1 uint8_t nonce[12]; diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index c492279d..c618d136 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -648,6 +648,7 @@ namespace transport if (m_State == eSSU2SessionStateTokenReceived || m_Server.AddPendingOutgoingSession (shared_from_this ())) { m_State = eSSU2SessionStateSessionRequestSent; + m_HandshakeInterval = ts; m_Server.Send (header.buf, 16, headerX, 48, payload, payloadSize, m_RemoteEndpoint); } else @@ -770,6 +771,7 @@ namespace transport m_State = eSSU2SessionStateSessionCreatedSent; m_SentHandshakePacket->payloadSize = payloadSize; // send + m_HandshakeInterval = ts; m_Server.Send (header.buf, 16, headerX, 48, payload, payloadSize, m_RemoteEndpoint); } @@ -790,6 +792,7 @@ namespace transport LogPrint (eLogWarning, "SSU2: SessionCreated message too short ", len); return false; } + m_HandshakeInterval = i2p::util::GetMillisecondsSinceEpoch () - m_HandshakeInterval; const uint8_t nonce[12] = {0}; uint8_t headerX[48]; i2p::crypto::ChaCha20 (buf + 16, 48, kh2, nonce, headerX); @@ -995,6 +998,7 @@ namespace transport if (m_SessionConfirmedFragment) m_SessionConfirmedFragment.reset (nullptr); return false; } + m_HandshakeInterval = i2p::util::GetMillisecondsSinceEpoch () - m_HandshakeInterval; // KDF for Session Confirmed part 1 m_NoiseState->MixHash (header.buf, 16); // h = SHA256(h || header) // decrypt part1 diff --git a/libi2pd/TransportSession.h b/libi2pd/TransportSession.h index 83b6cacd..7d2f2653 100644 --- a/libi2pd/TransportSession.h +++ b/libi2pd/TransportSession.h @@ -69,6 +69,8 @@ namespace transport std::stringstream m_Stream; }; + const int64_t TRANSPORT_SESSION_SLOWNESS_THRESHOLD = 500; // in milliseconds + const int64_t TRANSPORT_SESSION_MAX_HANDSHAKE_INTERVAL = 10000; // in milliseconds class TransportSession { public: @@ -76,7 +78,8 @@ namespace transport TransportSession (std::shared_ptr router, int terminationTimeout): m_NumSentBytes (0), m_NumReceivedBytes (0), m_SendQueueSize (0), m_IsOutgoing (router), m_TerminationTimeout (terminationTimeout), - m_LastActivityTimestamp (i2p::util::GetSecondsSinceEpoch ()) + m_LastActivityTimestamp (i2p::util::GetSecondsSinceEpoch ()), + m_HandshakeInterval (0) { if (router) m_RemoteIdentity = router->GetRouterIdentity (); @@ -103,7 +106,9 @@ namespace transport size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; }; size_t GetSendQueueSize () const { return m_SendQueueSize; }; bool IsOutgoing () const { return m_IsOutgoing; }; - + bool IsSlow () const { return m_HandshakeInterval > TRANSPORT_SESSION_SLOWNESS_THRESHOLD && + m_HandshakeInterval < TRANSPORT_SESSION_MAX_HANDSHAKE_INTERVAL; }; + int GetTerminationTimeout () const { return m_TerminationTimeout; }; void SetTerminationTimeout (int terminationTimeout) { m_TerminationTimeout = terminationTimeout; }; bool IsTerminationTimeoutExpired (uint64_t ts) const @@ -129,6 +134,7 @@ namespace transport int m_TerminationTimeout; uint64_t m_LastActivityTimestamp; uint32_t m_CreationTime; // seconds since epoch + int64_t m_HandshakeInterval; // in milliseconds between SessionRequest->SessionCreated or SessionCreated->SessionConfirmed }; // SOCKS5 proxy diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index aa326a92..4e97bb26 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -906,9 +906,10 @@ namespace transport return GetRandomPeer ( [isHighBandwidth](const Peer& peer)->bool { - // connected and not overloaded - return !peer.router && !peer.sessions.empty () && + // connected, not overloaded and not slow + return !peer.router && !peer.sessions.empty () && peer.isReachable && peer.sessions.front ()->GetSendQueueSize () <= PEER_ROUTER_INFO_OVERLOAD_QUEUE_SIZE && + !peer.sessions.front ()->IsSlow () && (!isHighBandwidth || peer.isHighBandwidth); }); } diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index dc97a952..1058d31b 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -72,15 +72,18 @@ namespace transport uint64_t creationTime, nextRouterInfoUpdateTime; std::vector > delayedMessages; std::vector priority; - bool isHighBandwidth; + bool isHighBandwidth, isReachable; Peer (std::shared_ptr r, uint64_t ts): numAttempts (0), router (r), creationTime (ts), nextRouterInfoUpdateTime (ts + PEER_ROUTER_INFO_UPDATE_INTERVAL), - isHighBandwidth (false) + isHighBandwidth (false), isReachable (false) { if (router) + { isHighBandwidth = router->IsHighBandwidth (); + isReachable = (bool)router->GetCompatibleTransports (true); + } } void Done () @@ -93,7 +96,10 @@ namespace transport { router = r; if (router) + { isHighBandwidth = router->IsHighBandwidth (); + isReachable = (bool)router->GetCompatibleTransports (true); + } } }; From a80aeb67155f73bc408f6960358a4632e30a4725 Mon Sep 17 00:00:00 2001 From: weko Date: Thu, 30 Mar 2023 21:31:12 +0000 Subject: [PATCH 0075/1171] add critical log level --- contrib/i2pd.conf | 2 +- libi2pd/Log.cpp | 26 +++++++++++++++----------- libi2pd/Log.h | 1 + 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/contrib/i2pd.conf b/contrib/i2pd.conf index c6e52c1f..5d09c90a 100644 --- a/contrib/i2pd.conf +++ b/contrib/i2pd.conf @@ -33,7 +33,7 @@ # log = file ## Path to logfile (default - autodetect) # logfile = /var/log/i2pd/i2pd.log -## Log messages above this level (debug, info, *warn, error, none) +## Log messages above this level (debug, info, *warn, error, critical, none) ## If you set it to none, logging will be disabled # loglevel = warn ## Write full CLF-formatted date and time to log (default: write only time) diff --git a/libi2pd/Log.cpp b/libi2pd/Log.cpp index 65b00e10..dfb507c9 100644 --- a/libi2pd/Log.cpp +++ b/libi2pd/Log.cpp @@ -20,11 +20,12 @@ namespace log { */ static const char *g_LogLevelStr[eNumLogLevels] = { - "none", // eLogNone - "error", // eLogError - "warn", // eLogWarning - "info", // eLogInfo - "debug" // eLogDebug + "none", // eLogNone + "critical", // eLogCritical + "error", // eLogError + "warn", // eLogWarning + "info", // eLogInfo + "debug" // eLogDebug }; /** @@ -32,10 +33,11 @@ namespace log { * @note Using ISO 6429 (ANSI) color sequences */ #ifdef _WIN32 - static const char *LogMsgColors[] = { "", "", "", "", "", "" }; + static const char *LogMsgColors[] = { "", "", "", "", "", "", "" }; #else /* UNIX */ static const char *LogMsgColors[] = { "\033[1;32m", /* none: green */ + "\033[1;41m", /* critical: red background */ "\033[1;31m", /* error: red */ "\033[1;33m", /* warning: yellow */ "\033[1;36m", /* info: cyan */ @@ -53,6 +55,7 @@ namespace log { int priority = LOG_DEBUG; switch (l) { case eLogNone : priority = LOG_CRIT; break; + case eLogCritical: priority = LOG_CRIT; break; case eLogError : priority = LOG_ERR; break; case eLogWarning : priority = LOG_WARNING; break; case eLogInfo : priority = LOG_INFO; break; @@ -123,11 +126,12 @@ namespace log { void Log::SetLogLevel (const std::string& level_) { std::string level=str_tolower(level_); - if (level == "none") { m_MinLevel = eLogNone; } - else if (level == "error") { m_MinLevel = eLogError; } - else if (level == "warn") { m_MinLevel = eLogWarning; } - else if (level == "info") { m_MinLevel = eLogInfo; } - else if (level == "debug") { m_MinLevel = eLogDebug; } + if (level == "none") { m_MinLevel = eLogNone; } + else if (level == "critical") { m_MinLevel = eLogCritical} + else if (level == "error") { m_MinLevel = eLogError; } + else if (level == "warn") { m_MinLevel = eLogWarning; } + else if (level == "info") { m_MinLevel = eLogInfo; } + else if (level == "debug") { m_MinLevel = eLogDebug; } else { LogPrint(eLogError, "Log: Unknown loglevel: ", level); return; diff --git a/libi2pd/Log.h b/libi2pd/Log.h index 465e10bc..1ec0c5fe 100644 --- a/libi2pd/Log.h +++ b/libi2pd/Log.h @@ -27,6 +27,7 @@ enum LogLevel { eLogNone = 0, + eLogCritical, eLogError, eLogWarning, eLogInfo, From 354a04f0f6f03478518148c7172cc37e18470afa Mon Sep 17 00:00:00 2001 From: weko Date: Fri, 31 Mar 2023 11:29:04 +0000 Subject: [PATCH 0076/1171] Up level for some logs to critical --- Win32/DaemonWin32.cpp | 2 +- Win32/Win32Service.cpp | 18 +++++++++--------- daemon/Daemon.cpp | 12 ++++++------ daemon/HTTPServer.cpp | 19 ++++++++++--------- daemon/I2PControl.cpp | 2 +- daemon/UPnP.cpp | 2 +- daemon/UnixDaemon.cpp | 18 +++++++++--------- libi2pd/Blinding.cpp | 4 ++-- libi2pd/Destination.cpp | 16 ++++++++-------- libi2pd/Family.cpp | 12 ++++++------ libi2pd/Identity.cpp | 6 +++--- libi2pd/LeaseSet.cpp | 2 +- libi2pd/Log.cpp | 6 +++--- libi2pd/NTCP2.cpp | 6 +++--- libi2pd/Reseed.cpp | 14 +++++++------- libi2pd/SSU2.cpp | 4 ++-- libi2pd/SSU2Session.cpp | 10 +++++----- libi2pd/Transports.cpp | 8 ++++---- libi2pd_client/AddressBook.cpp | 2 +- libi2pd_client/ClientContext.cpp | 24 ++++++++++++------------ libi2pd_client/SAM.cpp | 2 +- 21 files changed, 95 insertions(+), 94 deletions(-) diff --git a/Win32/DaemonWin32.cpp b/Win32/DaemonWin32.cpp index e8052f14..48f65c27 100644 --- a/Win32/DaemonWin32.cpp +++ b/Win32/DaemonWin32.cpp @@ -47,7 +47,7 @@ namespace util I2PService service((PSTR)SERVICE_NAME); if (!I2PService::Run(service)) { - LogPrint(eLogError, "Daemon: Service failed to run w/err 0x%08lx\n", GetLastError()); + LogPrint(eLogCritical, "Daemon: Service failed to run w/err 0x%08lx\n", GetLastError()); return false; } return false; diff --git a/Win32/Win32Service.cpp b/Win32/Win32Service.cpp index a9ecf477..057a1edd 100644 --- a/Win32/Win32Service.cpp +++ b/Win32/Win32Service.cpp @@ -119,12 +119,12 @@ void I2PService::Start(DWORD dwArgc, PSTR *pszArgv) } catch (DWORD dwError) { - LogPrint(eLogError, "Win32Service: Start error: ", dwError); + LogPrint(eLogCritical, "Win32Service: Start error: ", dwError); SetServiceStatus(SERVICE_STOPPED, dwError); } catch (...) { - LogPrint(eLogError, "Win32Service: failed to start: ", EVENTLOG_ERROR_TYPE); + LogPrint(eLogCritical, "Win32Service: failed to start: ", EVENTLOG_ERROR_TYPE); SetServiceStatus(SERVICE_STOPPED); } } @@ -162,7 +162,7 @@ void I2PService::Stop() } catch (...) { - LogPrint(eLogError, "Win32Service: Failed to stop: ", EVENTLOG_ERROR_TYPE); + LogPrint(eLogCritical, "Win32Service: Failed to stop: ", EVENTLOG_ERROR_TYPE); SetServiceStatus(dwOriginalState); } } @@ -191,12 +191,12 @@ void I2PService::Pause() } catch (DWORD dwError) { - LogPrint(eLogError, "Win32Service: Pause error: ", dwError); + LogPrint(eLogCritical, "Win32Service: Pause error: ", dwError); SetServiceStatus(SERVICE_RUNNING); } catch (...) { - LogPrint(eLogError, "Win32Service: Failed to pause: ", EVENTLOG_ERROR_TYPE); + LogPrint(eLogCritical, "Win32Service: Failed to pause: ", EVENTLOG_ERROR_TYPE); SetServiceStatus(SERVICE_RUNNING); } } @@ -215,12 +215,12 @@ void I2PService::Continue() } catch (DWORD dwError) { - LogPrint(eLogError, "Win32Service: Continue error: ", dwError); + LogPrint(eLogCritical, "Win32Service: Continue error: ", dwError); SetServiceStatus(SERVICE_PAUSED); } catch (...) { - LogPrint(eLogError, "Win32Service: Failed to resume: ", EVENTLOG_ERROR_TYPE); + LogPrint(eLogCritical, "Win32Service: Failed to resume: ", EVENTLOG_ERROR_TYPE); SetServiceStatus(SERVICE_PAUSED); } } @@ -238,11 +238,11 @@ void I2PService::Shutdown() } catch (DWORD dwError) { - LogPrint(eLogError, "Win32Service: Shutdown error: ", dwError); + LogPrint(eLogCritical, "Win32Service: Shutdown error: ", dwError); } catch (...) { - LogPrint(eLogError, "Win32Service: Failed to shut down: ", EVENTLOG_ERROR_TYPE); + LogPrint(eLogCritical, "Win32Service: Failed to shut down: ", EVENTLOG_ERROR_TYPE); } } diff --git a/daemon/Daemon.cpp b/daemon/Daemon.cpp index 84f197fb..02aee72d 100644 --- a/daemon/Daemon.cpp +++ b/daemon/Daemon.cpp @@ -262,7 +262,7 @@ namespace util restricted = idents.size() > 0; } if(!restricted) - LogPrint(eLogError, "Daemon: No trusted routers of families specified"); + LogPrint(eLogCritical, "Daemon: No trusted routers of families specified"); } bool hidden; i2p::config::GetOption("trust.hidden", hidden); @@ -310,7 +310,7 @@ namespace util LogPrint(eLogInfo, "Daemon: Transports started"); else { - LogPrint(eLogError, "Daemon: Failed to start Transports"); + LogPrint(eLogCritical, "Daemon: Failed to start Transports"); /** shut down netdb right away */ i2p::transport::transports.Stop(); i2p::data::netdb.Stop(); @@ -329,7 +329,7 @@ namespace util } catch (std::exception& ex) { - LogPrint (eLogError, "Daemon: Failed to start Webconsole: ", ex.what ()); + LogPrint (eLogCritical, "Daemon: Failed to start Webconsole: ", ex.what ()); ThrowFatal ("Unable to start webconsole at ", httpAddr, ":", httpPort, ": ", ex.what ()); } } @@ -338,8 +338,8 @@ namespace util i2p::tunnel::tunnels.Start(); LogPrint(eLogInfo, "Daemon: Starting Router context"); - i2p::context.Start(); - + i2p::context.Start(); + LogPrint(eLogInfo, "Daemon: Starting Client"); i2p::client::context.Start (); @@ -356,7 +356,7 @@ namespace util } catch (std::exception& ex) { - LogPrint (eLogError, "Daemon: Failed to start I2PControl: ", ex.what ()); + LogPrint (eLogCritical, "Daemon: Failed to start I2PControl: ", ex.what ()); ThrowFatal ("Unable to start I2PControl service at ", i2pcpAddr, ":", i2pcpPort, ": ", ex.what ()); } } diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 29f3f569..8b034332 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -156,7 +156,7 @@ namespace http { static void SetLogLevel (const std::string& level) { - if (level == "none" || level == "error" || level == "warn" || level == "info" || level == "debug") + if (level == "none" || level == "critical" || level == "error" || level == "warn" || level == "info" || level == "debug") i2p::log::Logger().SetLogLevel(level); else { LogPrint(eLogError, "HTTPServer: Unknown loglevel set attempted"); @@ -625,10 +625,10 @@ namespace http { if (storeType == i2p::data::NETDB_STORE_TYPE_LEASESET) ls.reset (new i2p::data::LeaseSet (leaseSet->GetBuffer(), leaseSet->GetBufferLen())); else - { + { ls.reset (new i2p::data::LeaseSet2 (storeType)); ls->Update (leaseSet->GetBuffer(), leaseSet->GetBufferLen(), false); - } + } if (!ls) return; s << "
IsExpired()) @@ -748,11 +748,12 @@ namespace http { auto loglevel = i2p::log::Logger().GetLogLevel(); s << "" << tr("Logging level") << "
\r\n"; - s << " none \r\n"; - s << " error \r\n"; - s << " warn \r\n"; - s << " info \r\n"; - s << " debug
\r\n
\r\n"; + s << " none \r\n"; + s << " none \r\n"; + s << " error \r\n"; + s << " warn \r\n"; + s << " info \r\n"; + s << " debug
\r\n
\r\n"; uint16_t maxTunnels = i2p::tunnel::tunnels.GetMaxNumTransitTunnels (); s << "" << tr("Transit tunnels limit") << "
\r\n"; @@ -1481,7 +1482,7 @@ namespace http { } catch (std::exception& ex) { - LogPrint (eLogError, "HTTPServer: Runtime exception: ", ex.what ()); + LogPrint (eLogCritical, "HTTPServer: Runtime exception: ", ex.what ()); } } } diff --git a/daemon/I2PControl.cpp b/daemon/I2PControl.cpp index da2443fd..354c19d4 100644 --- a/daemon/I2PControl.cpp +++ b/daemon/I2PControl.cpp @@ -115,7 +115,7 @@ namespace client try { m_Service.run (); } catch (std::exception& ex) { - LogPrint (eLogError, "I2PControl: Runtime exception: ", ex.what ()); + LogPrint (eLogCritical, "I2PControl: Runtime exception: ", ex.what ()); } } } diff --git a/daemon/UPnP.cpp b/daemon/UPnP.cpp index dbaf864a..2c915024 100644 --- a/daemon/UPnP.cpp +++ b/daemon/UPnP.cpp @@ -72,7 +72,7 @@ namespace transport } catch (std::exception& ex) { - LogPrint (eLogError, "UPnP: Runtime exception: ", ex.what ()); + LogPrint (eLogCritical, "UPnP: Runtime exception: ", ex.what ()); PortMapping (); } } diff --git a/daemon/UnixDaemon.cpp b/daemon/UnixDaemon.cpp index e6bad5a0..3c17fd14 100644 --- a/daemon/UnixDaemon.cpp +++ b/daemon/UnixDaemon.cpp @@ -81,7 +81,7 @@ namespace i2p if (pid < 0) // error { - LogPrint(eLogError, "Daemon: Could not fork: ", strerror(errno)); + LogPrint(eLogCritical, "Daemon: Could not fork: ", strerror(errno)); std::cerr << "i2pd: Could not fork: " << strerror(errno) << std::endl; return false; } @@ -91,7 +91,7 @@ namespace i2p int sid = setsid(); if (sid < 0) { - LogPrint(eLogError, "Daemon: Could not create process group."); + LogPrint(eLogCritical, "Daemon: Could not create process group."); std::cerr << "i2pd: Could not create process group." << std::endl; return false; } @@ -121,10 +121,10 @@ namespace i2p LogPrint(eLogInfo, "Daemon: Set max number of open files to ", nfiles, " (system limit is ", limit.rlim_max, ")"); } else { - LogPrint(eLogError, "Daemon: Can't set max number of open files: ", strerror(errno)); + LogPrint(eLogCritical, "Daemon: Can't set max number of open files: ", strerror(errno)); } } else { - LogPrint(eLogError, "Daemon: limits.openfiles exceeds system limit: ", limit.rlim_max); + LogPrint(eLogCritical, "Daemon: limits.openfiles exceeds system limit: ", limit.rlim_max); } uint32_t cfsize; i2p::config::GetOption("limits.coresize", cfsize); if (cfsize) // core file size set @@ -134,14 +134,14 @@ namespace i2p if (cfsize <= limit.rlim_max) { limit.rlim_cur = cfsize; if (setrlimit(RLIMIT_CORE, &limit) != 0) { - LogPrint(eLogError, "Daemon: Can't set max size of coredump: ", strerror(errno)); + LogPrint(eLogCritical, "Daemon: Can't set max size of coredump: ", strerror(errno)); } else if (cfsize == 0) { LogPrint(eLogInfo, "Daemon: coredumps disabled"); } else { LogPrint(eLogInfo, "Daemon: Set max size of core files to ", cfsize / 1024, "Kb"); } } else { - LogPrint(eLogError, "Daemon: limits.coresize exceeds system limit: ", limit.rlim_max); + LogPrint(eLogCritical, "Daemon: limits.coresize exceeds system limit: ", limit.rlim_max); } } @@ -155,7 +155,7 @@ namespace i2p pidFH = open(pidfile.c_str(), O_RDWR | O_CREAT, 0600); if (pidFH < 0) { - LogPrint(eLogError, "Daemon: Could not create pid file ", pidfile, ": ", strerror(errno)); + LogPrint(eLogCritical, "Daemon: Could not create pid file ", pidfile, ": ", strerror(errno)); std::cerr << "i2pd: Could not create pid file " << pidfile << ": " << strerror(errno) << std::endl; return false; } @@ -163,7 +163,7 @@ namespace i2p #ifndef ANDROID if (lockf(pidFH, F_TLOCK, 0) != 0) { - LogPrint(eLogError, "Daemon: Could not lock pid file ", pidfile, ": ", strerror(errno)); + LogPrint(eLogCritical, "Daemon: Could not lock pid file ", pidfile, ": ", strerror(errno)); std::cerr << "i2pd: Could not lock pid file " << pidfile << ": " << strerror(errno) << std::endl; return false; } @@ -173,7 +173,7 @@ namespace i2p ftruncate(pidFH, 0); if (write(pidFH, pid, strlen(pid)) < 0) { - LogPrint(eLogError, "Daemon: Could not write pidfile ", pidfile, ": ", strerror(errno)); + LogPrint(eLogCritical, "Daemon: Could not write pidfile ", pidfile, ": ", strerror(errno)); std::cerr << "i2pd: Could not write pidfile " << pidfile << ": " << strerror(errno) << std::endl; return false; } diff --git a/libi2pd/Blinding.cpp b/libi2pd/Blinding.cpp index ced086e1..1f15cf14 100644 --- a/libi2pd/Blinding.cpp +++ b/libi2pd/Blinding.cpp @@ -259,7 +259,7 @@ namespace data publicKeyLength = i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; break; default: - LogPrint (eLogError, "Blinding: Can't blind signature type ", (int)m_SigType); + LogPrint (eLogCritical, "Blinding: Can't blind signature type ", (int)m_SigType); } return publicKeyLength; } @@ -289,7 +289,7 @@ namespace data break; } default: - LogPrint (eLogError, "Blinding: Can't blind signature type ", (int)m_SigType); + LogPrint (eLogCritical, "Blinding: Can't blind signature type ", (int)m_SigType); } return publicKeyLength; } diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index b6dbeaed..0be25512 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -108,7 +108,7 @@ namespace client if (authType >= i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_NONE && authType <= i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_PSK) m_AuthType = authType; else - LogPrint (eLogError, "Destination: Unknown auth type ", authType); + LogPrint (eLogCritical, "Destination: Unknown auth type ", authType); } } it = params->find (I2CP_PARAM_LEASESET_PRIV_KEY); @@ -117,7 +117,7 @@ namespace client m_LeaseSetPrivKey.reset (new i2p::data::Tag<32>()); if (m_LeaseSetPrivKey->FromBase64 (it->second) != 32) { - LogPrint(eLogError, "Destination: Invalid value i2cp.leaseSetPrivKey ", it->second); + LogPrint(eLogCritical, "Destination: Invalid value i2cp.leaseSetPrivKey ", it->second); m_LeaseSetPrivKey.reset (nullptr); } } @@ -125,7 +125,7 @@ namespace client } catch (std::exception & ex) { - LogPrint(eLogError, "Destination: Unable to parse parameters for destination: ", ex.what()); + LogPrint(eLogCritical, "Destination: Unable to parse parameters for destination: ", ex.what()); } SetNumTags (numTags); m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (inLen, outLen, inQty, outQty, inVar, outVar); @@ -1014,12 +1014,12 @@ namespace client else if (authType == i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_PSK) ReadAuthKey (I2CP_PARAM_LEASESET_CLIENT_PSK, params); else - LogPrint (eLogError, "Destination: Unexpected auth type ", authType); + LogPrint (eLogCritical, "Destination: Unexpected auth type ", authType); if (m_AuthKeys->size ()) LogPrint (eLogInfo, "Destination: ", m_AuthKeys->size (), " auth keys read"); else { - LogPrint (eLogError, "Destination: No auth keys read for auth type ", authType); + LogPrint (eLogCritical, "Destination: No auth keys read for auth type ", authType); m_AuthKeys = nullptr; } } @@ -1028,7 +1028,7 @@ namespace client } catch (std::exception & ex) { - LogPrint(eLogError, "Destination: Unable to parse parameters for destination: ", ex.what()); + LogPrint(eLogCritical, "Destination: Unable to parse parameters for destination: ", ex.what()); } } @@ -1336,7 +1336,7 @@ namespace client f1.write ((char *)keys->priv, 256); return; } - LogPrint(eLogError, "Destinations: Can't save keys to ", path); + LogPrint(eLogCritical, "Destinations: Can't save keys to ", path); } void ClientDestination::CreateNewLeaseSet (const std::vector >& tunnels) @@ -1413,7 +1413,7 @@ namespace client if (pubKey.FromBase64 (it.second.substr (pos+1))) m_AuthKeys->push_back (pubKey); else - LogPrint (eLogError, "Destination: Unexpected auth key ", it.second.substr (pos+1)); + LogPrint (eLogCritical, "Destination: Unexpected auth key ", it.second.substr (pos+1)); } } } diff --git a/libi2pd/Family.cpp b/libi2pd/Family.cpp index 8c6d3ba4..bca9e231 100644 --- a/libi2pd/Family.cpp +++ b/libi2pd/Family.cpp @@ -77,14 +77,14 @@ namespace data verifier->SetPublicKey (signingKey); } else - LogPrint (eLogWarning, "Family: elliptic curve ", curve, " is not supported"); + LogPrint (eLogCritical, "Family: elliptic curve ", curve, " is not supported"); } EC_KEY_free (ecKey); } break; } default: - LogPrint (eLogWarning, "Family: Certificate key type ", keyType, " is not supported"); + LogPrint (eLogCritical, "Family: Certificate key type ", keyType, " is not supported"); } EVP_PKEY_free (pkey); if (verifier && cn) @@ -93,7 +93,7 @@ namespace data SSL_free (ssl); } else - LogPrint (eLogError, "Family: Can't open certificate file ", filename); + LogPrint (eLogCritical, "Family: Can't open certificate file ", filename); SSL_CTX_free (ctx); } @@ -105,7 +105,7 @@ namespace data int numCertificates = 0; if (!i2p::fs::ReadDir(certDir, files)) { - LogPrint(eLogWarning, "Family: Can't load family certificates from ", certDir); + LogPrint(eLogError, "Family: Can't load family certificates from ", certDir); return; } @@ -185,13 +185,13 @@ namespace data delete[] b64; } else - LogPrint (eLogWarning, "Family: elliptic curve ", curve, " is not supported"); + LogPrint (eLogCritical, "Family: elliptic curve ", curve, " is not supported"); } } SSL_free (ssl); } else - LogPrint (eLogError, "Family: Can't open keys file: ", filename); + LogPrint (eLogCritical, "Family: Can't open keys file: ", filename); SSL_CTX_free (ctx); return sig; } diff --git a/libi2pd/Identity.cpp b/libi2pd/Identity.cpp index 073d8c06..7a73f02a 100644 --- a/libi2pd/Identity.cpp +++ b/libi2pd/Identity.cpp @@ -369,7 +369,7 @@ namespace data void IdentityEx::CreateVerifier () { if (!m_Verifier) - { + { auto verifier = CreateVerifier (GetSigningKeyType ()); if (verifier) { @@ -388,7 +388,7 @@ namespace data } } m_Verifier.reset (verifier); - } + } } std::shared_ptr IdentityEx::CreateEncryptor (CryptoKeyType keyType, const uint8_t * key) @@ -755,7 +755,7 @@ namespace data i2p::crypto::CreateECIESX25519AEADRatchetRandomKeys (priv, pub); break; default: - LogPrint (eLogError, "Identity: Crypto key type ", (int)type, " is not supported"); + LogPrint (eLogCritical, "Identity: Crypto key type ", (int)type, " is not supported"); } } diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index c47f23d8..675f6503 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -76,7 +76,7 @@ namespace data LogPrint (eLogDebug, "LeaseSet: Read num=", (int)num); if (!num || num > MAX_NUM_LEASES) { - LogPrint (eLogError, "LeaseSet: Rncorrect number of leases", (int)num); + LogPrint (eLogError, "LeaseSet: Incorrect number of leases", (int)num); m_IsValid = false; return; } diff --git a/libi2pd/Log.cpp b/libi2pd/Log.cpp index dfb507c9..76e85d4a 100644 --- a/libi2pd/Log.cpp +++ b/libi2pd/Log.cpp @@ -127,13 +127,13 @@ namespace log { void Log::SetLogLevel (const std::string& level_) { std::string level=str_tolower(level_); if (level == "none") { m_MinLevel = eLogNone; } - else if (level == "critical") { m_MinLevel = eLogCritical} + else if (level == "critical") { m_MinLevel = eLogCritical; } else if (level == "error") { m_MinLevel = eLogError; } else if (level == "warn") { m_MinLevel = eLogWarning; } else if (level == "info") { m_MinLevel = eLogInfo; } else if (level == "debug") { m_MinLevel = eLogDebug; } else { - LogPrint(eLogError, "Log: Unknown loglevel: ", level); + LogPrint(eLogCritical, "Log: Unknown loglevel: ", level); return; } LogPrint(eLogInfo, "Log: Logging level set to ", level); @@ -216,7 +216,7 @@ namespace log { m_LogStream = os; return; } - LogPrint(eLogError, "Log: Can't open file ", path); + LogPrint(eLogCritical, "Log: Can't open file ", path); } void Log::SendTo (std::shared_ptr os) { diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 48c905ca..91bc9b3d 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1242,7 +1242,7 @@ namespace transport boost::system::error_code e; auto itr = m_Resolver.resolve(q, e); if(e) - LogPrint(eLogError, "NTCP2: Failed to resolve proxy ", e.message()); + LogPrint(eLogCritical, "NTCP2: Failed to resolve proxy ", e.message()); else { m_ProxyEndpoint.reset (new boost::asio::ip::tcp::endpoint(*itr)); @@ -1270,7 +1270,7 @@ namespace transport } catch ( std::exception & ex ) { - LogPrint(eLogError, "NTCP2: Failed to bind to v4 port ", address->port, ex.what()); + LogPrint(eLogCritical, "NTCP2: Failed to bind to v4 port ", address->port, ex.what()); ThrowFatal ("Unable to start IPv4 NTCP2 transport at port ", address->port, ": ", ex.what ()); continue; } @@ -1313,7 +1313,7 @@ namespace transport } catch ( std::exception & ex ) { - LogPrint(eLogError, "NTCP2: Failed to bind to v6 port ", address->port, ": ", ex.what()); + LogPrint(eLogCritical, "NTCP2: Failed to bind to v6 port ", address->port, ": ", ex.what()); ThrowFatal ("Unable to start IPv6 NTCP2 transport at port ", address->port, ": ", ex.what ()); continue; } diff --git a/libi2pd/Reseed.cpp b/libi2pd/Reseed.cpp index dfc10043..28e4db24 100644 --- a/libi2pd/Reseed.cpp +++ b/libi2pd/Reseed.cpp @@ -153,7 +153,7 @@ namespace data return ProcessSU3Stream (s); else { - LogPrint (eLogError, "Reseed: Can't open file ", filename); + LogPrint (eLogCritical, "Reseed: Can't open file ", filename); return 0; } } @@ -170,7 +170,7 @@ namespace data } else { - LogPrint (eLogError, "Reseed: Can't open file ", filename); + LogPrint (eLogCritical, "Reseed: Can't open file ", filename); return 0; } } @@ -278,7 +278,7 @@ namespace data if (verify) // not verified { - LogPrint (eLogError, "Reseed: SU3 verification failed"); + LogPrint (eLogCritical, "Reseed: SU3 verification failed"); return 0; } @@ -492,7 +492,7 @@ namespace data SSL_free (ssl); } else - LogPrint (eLogError, "Reseed: Can't open certificate file ", filename); + LogPrint (eLogCritical, "Reseed: Can't open certificate file ", filename); SSL_CTX_free (ctx); } @@ -534,17 +534,17 @@ namespace data } // check for valid proxy url schema if (proxyUrl.schema != "http" && proxyUrl.schema != "socks") { - LogPrint(eLogError, "Reseed: Bad proxy url: ", proxy); + LogPrint(eLogCritical, "Reseed: Bad proxy url: ", proxy); return ""; } } else { - LogPrint(eLogError, "Reseed: Bad proxy url: ", proxy); + LogPrint(eLogCritical, "Reseed: Bad proxy url: ", proxy); return ""; } } i2p::http::URL url; if (!url.parse(address)) { - LogPrint(eLogError, "Reseed: Failed to parse url: ", address); + LogPrint(eLogCritical, "Reseed: Failed to parse url: ", address); return ""; } url.schema = "https"; diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index b50284a6..5df4d33a 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -99,7 +99,7 @@ namespace transport } } else - LogPrint (eLogError, "SSU2: Can't start server because port not specified"); + LogPrint (eLogCritical, "SSU2: Can't start server because port not specified"); } } if (found) @@ -224,7 +224,7 @@ namespace transport } catch (std::exception& ex ) { - LogPrint (eLogError, "SSU2: Failed to bind to ", localEndpoint, ": ", ex.what()); + LogPrint (eLogCritical, "SSU2: Failed to bind to ", localEndpoint, ": ", ex.what()); ThrowFatal ("Unable to start SSU2 transport on ", localEndpoint, ": ", ex.what ()); } return socket; diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index c618d136..47d59ea4 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -84,7 +84,7 @@ namespace transport m_Server (server), m_Address (addr), m_RemoteTransports (0), m_DestConnID (0), m_SourceConnID (0), m_State (eSSU2SessionStateUnknown), m_SendPacketNum (0), m_ReceivePacketNum (0), m_LastDatetimeSentPacketNum (0), - m_IsDataReceived (false), m_WindowSize (SSU2_MIN_WINDOW_SIZE), + m_IsDataReceived (false), m_WindowSize (SSU2_MIN_WINDOW_SIZE), m_RTT (SSU2_RESEND_INTERVAL), m_RTO (SSU2_RESEND_INTERVAL*SSU2_kAPPA), m_RelayTag (0), m_ConnectTimer (server.GetService ()), m_TerminationReason (eSSU2TerminationReasonNormalClose), m_MaxPayloadSize (SSU2_MIN_PACKET_SIZE - IPV6_HEADER_SIZE - UDP_HEADER_SIZE - 32) // min size @@ -928,7 +928,7 @@ namespace transport { LogPrint (eLogError, "SSU2: Non zero packet number in SessionConfirmed"); return false; - } + } // check if fragmented uint8_t numFragments = header.h.flags[0] & 0x0F; if (numFragments > 1) @@ -1884,7 +1884,7 @@ namespace transport auto r = i2p::data::netdb.FindRouter (GetRemoteIdentity ()->GetIdentHash ()); // Alice's RI if (r && (r->IsUnreachable () || !i2p::data::netdb.PopulateRouterInfoBuffer (r))) r = nullptr; if (!r) LogPrint (eLogWarning, "SSU2: RelayRequest Alice's router info not found"); - + uint8_t payload[SSU2_MAX_PACKET_SIZE]; size_t payloadSize = r ? CreateRouterInfoBlock (payload, m_MaxPayloadSize - len - 32, r) : 0; if (!payloadSize && r) @@ -2817,13 +2817,13 @@ namespace transport uint8_t payload[SSU2_MAX_PACKET_SIZE]; size_t payloadSize = 0; if (m_SendPacketNum > m_LastDatetimeSentPacketNum + SSU2_SEND_DATETIME_NUM_PACKETS) - { + { payload[0] = eSSU2BlkDateTime; htobe16buf (payload + 1, 4); htobe32buf (payload + 3, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); payloadSize += 7; m_LastDatetimeSentPacketNum = m_SendPacketNum; - } + } payloadSize += CreateAckBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); SendData (payload, payloadSize); diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 4e97bb26..c2aeb964 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -200,10 +200,10 @@ namespace transport i2p::context.SetStatusV6 (eRouterStatusProxy); } else - LogPrint(eLogError, "Transports: Unsupported NTCP2 proxy URL ", ntcp2proxy); + LogPrint(eLogCritical, "Transports: Unsupported NTCP2 proxy URL ", ntcp2proxy); } else - LogPrint(eLogError, "Transports: Invalid NTCP2 proxy URL ", ntcp2proxy); + LogPrint(eLogCritical, "Transports: Invalid NTCP2 proxy URL ", ntcp2proxy); } else m_NTCP2Server = new NTCP2Server (); @@ -225,10 +225,10 @@ namespace transport i2p::context.SetStatusV6 (eRouterStatusProxy); } else - LogPrint(eLogError, "Transports: Can't set SSU2 proxy ", ssu2proxy); + LogPrint(eLogCritical, "Transports: Can't set SSU2 proxy ", ssu2proxy); } else - LogPrint(eLogError, "Transports: Invalid SSU2 proxy URL ", ssu2proxy); + LogPrint(eLogCritical, "Transports: Invalid SSU2 proxy URL ", ssu2proxy); } } diff --git a/libi2pd_client/AddressBook.cpp b/libi2pd_client/AddressBook.cpp index 652dfb8d..055311a9 100644 --- a/libi2pd_client/AddressBook.cpp +++ b/libi2pd_client/AddressBook.cpp @@ -661,7 +661,7 @@ namespace client this, std::placeholders::_1)); } else - LogPrint (eLogError, "Addressbook: Can't start subscriptions: missing shared local destination"); + LogPrint (eLogCritical, "Addressbook: Can't start subscriptions: missing shared local destination"); } void AddressBook::StopSubscriptions () diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index 41bd1d49..b90386db 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -74,7 +74,7 @@ namespace client } catch (std::exception& e) { - LogPrint(eLogError, "Clients: Exception in SAM bridge: ", e.what()); + LogPrint(eLogCritical, "Clients: Exception in SAM bridge: ", e.what()); ThrowFatal ("Unable to start SAM bridge at ", samAddr, ":[", samPortTCP, "|", samPortUDP,"]: ", e.what ()); } } @@ -92,7 +92,7 @@ namespace client } catch (std::exception& e) { - LogPrint(eLogError, "Clients: Exception in BOB bridge: ", e.what()); + LogPrint(eLogCritical, "Clients: Exception in BOB bridge: ", e.what()); ThrowFatal ("Unable to start BOB bridge at ", bobAddr, ":", bobPort, ": ", e.what ()); } } @@ -112,7 +112,7 @@ namespace client } catch (std::exception& e) { - LogPrint(eLogError, "Clients: Exception in I2CP: ", e.what()); + LogPrint(eLogCritical, "Clients: Exception in I2CP: ", e.what()); ThrowFatal ("Unable to start I2CP at ", i2cpAddr, ":", i2cpPort, ": ", e.what ()); } } @@ -279,7 +279,7 @@ namespace client s.read ((char *)buf, len); if(!keys.FromBuffer (buf, len)) { - LogPrint (eLogError, "Clients: Failed to load keyfile ", filename); + LogPrint (eLogCritical, "Clients: Failed to load keyfile ", filename); success = false; } else @@ -288,7 +288,7 @@ namespace client } else { - LogPrint (eLogError, "Clients: Can't open file ", fullPath, " Creating new one with signature type ", sigType, " crypto type ", cryptoType); + LogPrint (eLogCritical, "Clients: Can't open file ", fullPath, " Creating new one with signature type ", sigType, " crypto type ", cryptoType); keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType, cryptoType, true); std::ofstream f (fullPath, std::ofstream::binary | std::ofstream::out); size_t len = keys.GetFullLen (); @@ -633,7 +633,7 @@ namespace client ins.first->second->Start (); } ins.first->second->isUpdated = true; - LogPrint(eLogError, "Clients: I2P Client forward for endpoint ", end, " already exists"); + LogPrint(eLogCritical, "Clients: I2P Client forward for endpoint ", end, " already exists"); } } else { @@ -785,7 +785,7 @@ namespace client else { ins.first->second->isUpdated = true; - LogPrint(eLogError, "Clients: I2P Server Forward for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash()), "/", port, " already exists"); + LogPrint(eLogCritical, "Clients: I2P Server Forward for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash()), "/", port, " already exists"); } continue; @@ -851,7 +851,7 @@ namespace client } catch (std::exception& ex) { - LogPrint (eLogError, "Clients: Can't read tunnel ", name, " params: ", ex.what ()); + LogPrint (eLogCritical, "Clients: Can't read tunnel ", name, " params: ", ex.what ()); ThrowFatal ("Unable to start tunnel ", name, ": ", ex.what ()); } } @@ -883,7 +883,7 @@ namespace client if (localDestination) localDestination->Acquire (); } else - LogPrint(eLogError, "Clients: Failed to load HTTP Proxy key"); + LogPrint(eLogCritical, "Clients: Failed to load HTTP Proxy key"); } try { @@ -892,7 +892,7 @@ namespace client } catch (std::exception& e) { - LogPrint(eLogError, "Clients: Exception in HTTP Proxy: ", e.what()); + LogPrint(eLogCritical, "Clients: Exception in HTTP Proxy: ", e.what()); ThrowFatal ("Unable to start HTTP Proxy at ", httpProxyAddr, ":", httpProxyPort, ": ", e.what ()); } } @@ -930,7 +930,7 @@ namespace client if (localDestination) localDestination->Acquire (); } else - LogPrint(eLogError, "Clients: Failed to load SOCKS Proxy key"); + LogPrint(eLogCritical, "Clients: Failed to load SOCKS Proxy key"); } try { @@ -940,7 +940,7 @@ namespace client } catch (std::exception& e) { - LogPrint(eLogError, "Clients: Exception in SOCKS Proxy: ", e.what()); + LogPrint(eLogCritical, "Clients: Exception in SOCKS Proxy: ", e.what()); ThrowFatal ("Unable to start SOCKS Proxy at ", socksProxyAddr, ":", socksProxyPort, ": ", e.what ()); } } diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 4e19990a..37577fcc 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -1283,7 +1283,7 @@ namespace client } catch (const std::exception& ex) { - LogPrint (eLogError, "SAM: Runtime exception: ", ex.what ()); + LogPrint (eLogCritical, "SAM: Runtime exception: ", ex.what ()); } { From e36d5634e7f7ac7e36e4ef9d5297d43c5dca290b Mon Sep 17 00:00:00 2001 From: weko Date: Fri, 31 Mar 2023 11:40:07 +0000 Subject: [PATCH 0077/1171] fix log level show in webconsole --- daemon/HTTPServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 8b034332..edfa80df 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -749,7 +749,7 @@ namespace http { auto loglevel = i2p::log::Logger().GetLogLevel(); s << "" << tr("Logging level") << "
\r\n"; s << " none \r\n"; - s << " none \r\n"; + s << " critical \r\n"; s << " error \r\n"; s << " warn \r\n"; s << " info \r\n"; From 710a35993db02644f7f28dbee739fe1e7a68a5a5 Mon Sep 17 00:00:00 2001 From: weko Date: Fri, 31 Mar 2023 12:16:32 +0000 Subject: [PATCH 0078/1171] change some log level to error back --- daemon/Daemon.cpp | 2 +- daemon/HTTPServer.cpp | 2 +- daemon/I2PControl.cpp | 2 +- daemon/UPnP.cpp | 2 +- daemon/UnixDaemon.cpp | 16 ++++++++-------- libi2pd/Blinding.cpp | 4 ++-- libi2pd/Destination.cpp | 12 ++++++------ libi2pd/Family.cpp | 10 +++++----- libi2pd/Identity.cpp | 2 +- libi2pd_client/ClientContext.cpp | 4 ++-- 10 files changed, 28 insertions(+), 28 deletions(-) diff --git a/daemon/Daemon.cpp b/daemon/Daemon.cpp index 02aee72d..8e9721db 100644 --- a/daemon/Daemon.cpp +++ b/daemon/Daemon.cpp @@ -262,7 +262,7 @@ namespace util restricted = idents.size() > 0; } if(!restricted) - LogPrint(eLogCritical, "Daemon: No trusted routers of families specified"); + LogPrint(eLogError, "Daemon: No trusted routers of families specified"); } bool hidden; i2p::config::GetOption("trust.hidden", hidden); diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index edfa80df..dceee06a 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -1482,7 +1482,7 @@ namespace http { } catch (std::exception& ex) { - LogPrint (eLogCritical, "HTTPServer: Runtime exception: ", ex.what ()); + LogPrint (eLogError, "HTTPServer: Runtime exception: ", ex.what ()); } } } diff --git a/daemon/I2PControl.cpp b/daemon/I2PControl.cpp index 354c19d4..da2443fd 100644 --- a/daemon/I2PControl.cpp +++ b/daemon/I2PControl.cpp @@ -115,7 +115,7 @@ namespace client try { m_Service.run (); } catch (std::exception& ex) { - LogPrint (eLogCritical, "I2PControl: Runtime exception: ", ex.what ()); + LogPrint (eLogError, "I2PControl: Runtime exception: ", ex.what ()); } } } diff --git a/daemon/UPnP.cpp b/daemon/UPnP.cpp index 2c915024..dbaf864a 100644 --- a/daemon/UPnP.cpp +++ b/daemon/UPnP.cpp @@ -72,7 +72,7 @@ namespace transport } catch (std::exception& ex) { - LogPrint (eLogCritical, "UPnP: Runtime exception: ", ex.what ()); + LogPrint (eLogError, "UPnP: Runtime exception: ", ex.what ()); PortMapping (); } } diff --git a/daemon/UnixDaemon.cpp b/daemon/UnixDaemon.cpp index 3c17fd14..bf4a7662 100644 --- a/daemon/UnixDaemon.cpp +++ b/daemon/UnixDaemon.cpp @@ -81,7 +81,7 @@ namespace i2p if (pid < 0) // error { - LogPrint(eLogCritical, "Daemon: Could not fork: ", strerror(errno)); + LogPrint(eLogError, "Daemon: Could not fork: ", strerror(errno)); std::cerr << "i2pd: Could not fork: " << strerror(errno) << std::endl; return false; } @@ -91,7 +91,7 @@ namespace i2p int sid = setsid(); if (sid < 0) { - LogPrint(eLogCritical, "Daemon: Could not create process group."); + LogPrint(eLogError, "Daemon: Could not create process group."); std::cerr << "i2pd: Could not create process group." << std::endl; return false; } @@ -121,10 +121,10 @@ namespace i2p LogPrint(eLogInfo, "Daemon: Set max number of open files to ", nfiles, " (system limit is ", limit.rlim_max, ")"); } else { - LogPrint(eLogCritical, "Daemon: Can't set max number of open files: ", strerror(errno)); + LogPrint(eLogError, "Daemon: Can't set max number of open files: ", strerror(errno)); } } else { - LogPrint(eLogCritical, "Daemon: limits.openfiles exceeds system limit: ", limit.rlim_max); + LogPrint(eLogError, "Daemon: limits.openfiles exceeds system limit: ", limit.rlim_max); } uint32_t cfsize; i2p::config::GetOption("limits.coresize", cfsize); if (cfsize) // core file size set @@ -134,14 +134,14 @@ namespace i2p if (cfsize <= limit.rlim_max) { limit.rlim_cur = cfsize; if (setrlimit(RLIMIT_CORE, &limit) != 0) { - LogPrint(eLogCritical, "Daemon: Can't set max size of coredump: ", strerror(errno)); + LogPrint(eLogError, "Daemon: Can't set max size of coredump: ", strerror(errno)); } else if (cfsize == 0) { LogPrint(eLogInfo, "Daemon: coredumps disabled"); } else { LogPrint(eLogInfo, "Daemon: Set max size of core files to ", cfsize / 1024, "Kb"); } } else { - LogPrint(eLogCritical, "Daemon: limits.coresize exceeds system limit: ", limit.rlim_max); + LogPrint(eLogError, "Daemon: limits.coresize exceeds system limit: ", limit.rlim_max); } } @@ -155,7 +155,7 @@ namespace i2p pidFH = open(pidfile.c_str(), O_RDWR | O_CREAT, 0600); if (pidFH < 0) { - LogPrint(eLogCritical, "Daemon: Could not create pid file ", pidfile, ": ", strerror(errno)); + LogPrint(eLogError, "Daemon: Could not create pid file ", pidfile, ": ", strerror(errno)); std::cerr << "i2pd: Could not create pid file " << pidfile << ": " << strerror(errno) << std::endl; return false; } @@ -163,7 +163,7 @@ namespace i2p #ifndef ANDROID if (lockf(pidFH, F_TLOCK, 0) != 0) { - LogPrint(eLogCritical, "Daemon: Could not lock pid file ", pidfile, ": ", strerror(errno)); + LogPrint(eLogError, "Daemon: Could not lock pid file ", pidfile, ": ", strerror(errno)); std::cerr << "i2pd: Could not lock pid file " << pidfile << ": " << strerror(errno) << std::endl; return false; } diff --git a/libi2pd/Blinding.cpp b/libi2pd/Blinding.cpp index 1f15cf14..ced086e1 100644 --- a/libi2pd/Blinding.cpp +++ b/libi2pd/Blinding.cpp @@ -259,7 +259,7 @@ namespace data publicKeyLength = i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; break; default: - LogPrint (eLogCritical, "Blinding: Can't blind signature type ", (int)m_SigType); + LogPrint (eLogError, "Blinding: Can't blind signature type ", (int)m_SigType); } return publicKeyLength; } @@ -289,7 +289,7 @@ namespace data break; } default: - LogPrint (eLogCritical, "Blinding: Can't blind signature type ", (int)m_SigType); + LogPrint (eLogError, "Blinding: Can't blind signature type ", (int)m_SigType); } return publicKeyLength; } diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 0be25512..4175f54c 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -108,7 +108,7 @@ namespace client if (authType >= i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_NONE && authType <= i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_PSK) m_AuthType = authType; else - LogPrint (eLogCritical, "Destination: Unknown auth type ", authType); + LogPrint (eLogCritical, "Destination: Unknown auth type: ", authType); } } it = params->find (I2CP_PARAM_LEASESET_PRIV_KEY); @@ -117,7 +117,7 @@ namespace client m_LeaseSetPrivKey.reset (new i2p::data::Tag<32>()); if (m_LeaseSetPrivKey->FromBase64 (it->second) != 32) { - LogPrint(eLogCritical, "Destination: Invalid value i2cp.leaseSetPrivKey ", it->second); + LogPrint(eLogCritical, "Destination: Invalid value i2cp.leaseSetPrivKey: ", it->second); m_LeaseSetPrivKey.reset (nullptr); } } @@ -125,7 +125,7 @@ namespace client } catch (std::exception & ex) { - LogPrint(eLogCritical, "Destination: Unable to parse parameters for destination: ", ex.what()); + LogPrint(eLogError, "Destination: Unable to parse parameters for destination: ", ex.what()); } SetNumTags (numTags); m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (inLen, outLen, inQty, outQty, inVar, outVar); @@ -1014,12 +1014,12 @@ namespace client else if (authType == i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_PSK) ReadAuthKey (I2CP_PARAM_LEASESET_CLIENT_PSK, params); else - LogPrint (eLogCritical, "Destination: Unexpected auth type ", authType); + LogPrint (eLogCritical, "Destination: Unexpected auth type: ", authType); if (m_AuthKeys->size ()) LogPrint (eLogInfo, "Destination: ", m_AuthKeys->size (), " auth keys read"); else { - LogPrint (eLogCritical, "Destination: No auth keys read for auth type ", authType); + LogPrint (eLogCritical, "Destination: No auth keys read for auth type: ", authType); m_AuthKeys = nullptr; } } @@ -1413,7 +1413,7 @@ namespace client if (pubKey.FromBase64 (it.second.substr (pos+1))) m_AuthKeys->push_back (pubKey); else - LogPrint (eLogCritical, "Destination: Unexpected auth key ", it.second.substr (pos+1)); + LogPrint (eLogCritical, "Destination: Unexpected auth key: ", it.second.substr (pos+1)); } } } diff --git a/libi2pd/Family.cpp b/libi2pd/Family.cpp index bca9e231..6564901e 100644 --- a/libi2pd/Family.cpp +++ b/libi2pd/Family.cpp @@ -77,14 +77,14 @@ namespace data verifier->SetPublicKey (signingKey); } else - LogPrint (eLogCritical, "Family: elliptic curve ", curve, " is not supported"); + LogPrint (eLogError, "Family: elliptic curve ", curve, " is not supported"); } EC_KEY_free (ecKey); } break; } default: - LogPrint (eLogCritical, "Family: Certificate key type ", keyType, " is not supported"); + LogPrint (eLogError, "Family: Certificate key type ", keyType, " is not supported"); } EVP_PKEY_free (pkey); if (verifier && cn) @@ -93,7 +93,7 @@ namespace data SSL_free (ssl); } else - LogPrint (eLogCritical, "Family: Can't open certificate file ", filename); + LogPrint (eLogError, "Family: Can't open certificate file ", filename); SSL_CTX_free (ctx); } @@ -185,13 +185,13 @@ namespace data delete[] b64; } else - LogPrint (eLogCritical, "Family: elliptic curve ", curve, " is not supported"); + LogPrint (eLogError, "Family: elliptic curve ", curve, " is not supported"); } } SSL_free (ssl); } else - LogPrint (eLogCritical, "Family: Can't open keys file: ", filename); + LogPrint (eLogError, "Family: Can't open keys file: ", filename); SSL_CTX_free (ctx); return sig; } diff --git a/libi2pd/Identity.cpp b/libi2pd/Identity.cpp index 7a73f02a..ca47e797 100644 --- a/libi2pd/Identity.cpp +++ b/libi2pd/Identity.cpp @@ -755,7 +755,7 @@ namespace data i2p::crypto::CreateECIESX25519AEADRatchetRandomKeys (priv, pub); break; default: - LogPrint (eLogCritical, "Identity: Crypto key type ", (int)type, " is not supported"); + LogPrint (eLogError, "Identity: Crypto key type ", (int)type, " is not supported"); } } diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index b90386db..dadb9ae5 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -633,7 +633,7 @@ namespace client ins.first->second->Start (); } ins.first->second->isUpdated = true; - LogPrint(eLogCritical, "Clients: I2P Client forward for endpoint ", end, " already exists"); + LogPrint(eLogError, "Clients: I2P Client forward for endpoint ", end, " already exists"); } } else { @@ -785,7 +785,7 @@ namespace client else { ins.first->second->isUpdated = true; - LogPrint(eLogCritical, "Clients: I2P Server Forward for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash()), "/", port, " already exists"); + LogPrint(eLogError, "Clients: I2P Server Forward for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash()), "/", port, " already exists"); } continue; From 2abc997af8785229450cee88dbf594c37afb7da3 Mon Sep 17 00:00:00 2001 From: weko Date: Fri, 31 Mar 2023 12:29:13 +0000 Subject: [PATCH 0079/1171] change some log levels back --- libi2pd/Family.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libi2pd/Family.cpp b/libi2pd/Family.cpp index 6564901e..8c6d3ba4 100644 --- a/libi2pd/Family.cpp +++ b/libi2pd/Family.cpp @@ -77,14 +77,14 @@ namespace data verifier->SetPublicKey (signingKey); } else - LogPrint (eLogError, "Family: elliptic curve ", curve, " is not supported"); + LogPrint (eLogWarning, "Family: elliptic curve ", curve, " is not supported"); } EC_KEY_free (ecKey); } break; } default: - LogPrint (eLogError, "Family: Certificate key type ", keyType, " is not supported"); + LogPrint (eLogWarning, "Family: Certificate key type ", keyType, " is not supported"); } EVP_PKEY_free (pkey); if (verifier && cn) @@ -105,7 +105,7 @@ namespace data int numCertificates = 0; if (!i2p::fs::ReadDir(certDir, files)) { - LogPrint(eLogError, "Family: Can't load family certificates from ", certDir); + LogPrint(eLogWarning, "Family: Can't load family certificates from ", certDir); return; } @@ -185,7 +185,7 @@ namespace data delete[] b64; } else - LogPrint (eLogError, "Family: elliptic curve ", curve, " is not supported"); + LogPrint (eLogWarning, "Family: elliptic curve ", curve, " is not supported"); } } SSL_free (ssl); From a3bdc4ddc1142b60da03e6f01d2a7766e96312dc Mon Sep 17 00:00:00 2001 From: weko Date: Fri, 31 Mar 2023 12:40:38 +0000 Subject: [PATCH 0080/1171] change some log levels back --- libi2pd/Destination.cpp | 4 ++-- libi2pd_client/SAM.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 4175f54c..8002e6f9 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -108,7 +108,7 @@ namespace client if (authType >= i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_NONE && authType <= i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_PSK) m_AuthType = authType; else - LogPrint (eLogCritical, "Destination: Unknown auth type: ", authType); + LogPrint (eLogError, "Destination: Unknown auth type: ", authType); } } it = params->find (I2CP_PARAM_LEASESET_PRIV_KEY); @@ -1014,7 +1014,7 @@ namespace client else if (authType == i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_PSK) ReadAuthKey (I2CP_PARAM_LEASESET_CLIENT_PSK, params); else - LogPrint (eLogCritical, "Destination: Unexpected auth type: ", authType); + LogPrint (eLogError, "Destination: Unexpected auth type: ", authType); if (m_AuthKeys->size ()) LogPrint (eLogInfo, "Destination: ", m_AuthKeys->size (), " auth keys read"); else diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 37577fcc..4e19990a 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -1283,7 +1283,7 @@ namespace client } catch (const std::exception& ex) { - LogPrint (eLogCritical, "SAM: Runtime exception: ", ex.what ()); + LogPrint (eLogError, "SAM: Runtime exception: ", ex.what ()); } { From b8032e7fbfd6cf2a91bf8fee0b970dd4ede767a7 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 2 Apr 2023 11:27:51 -0400 Subject: [PATCH 0081/1171] publish congestion cap G --- libi2pd/RouterContext.cpp | 9 ++++++++- libi2pd/RouterInfo.cpp | 9 +-------- libi2pd/RouterInfo.h | 3 +-- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 20ac589b..de103910 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -1090,6 +1090,8 @@ namespace i2p UpdateSSU2Keys (); updated = true; } + if (m_RouterInfo.UpdateCongestion (i2p::data::RouterInfo::eLowCongestion)) + updated = true; if (updated) UpdateRouterInfo (); @@ -1398,7 +1400,12 @@ namespace i2p { if (ecode != boost::asio::error::operation_aborted) { - if (m_RouterInfo.SetHighCongestion (IsHighCongestion ())) + auto c = i2p::data::RouterInfo::eLowCongestion; + if (!AcceptsTunnels ()) + c = i2p::data::RouterInfo::eRejectAll; + else if (IsHighCongestion ()) + c = i2p::data::RouterInfo::eHighCongestion; + if (m_RouterInfo.UpdateCongestion (c)) UpdateRouterInfo (); ScheduleCongestionUpdate (); } diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 7462ef0e..3ae5abd9 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -1077,12 +1077,6 @@ namespace data if (m_Congestion == eHighCongestion) return (i2p::util::GetMillisecondsSinceEpoch () < m_Timestamp + HIGH_CONGESTION_INTERVAL*1000LL) ? true : false; return false; - } - - LocalRouterInfo::LocalRouterInfo (const std::string& fullPath): - RouterInfo (fullPath) - { - SetHighCongestion (false); // drop congestion } void LocalRouterInfo::CreateBuffer (const PrivateKeys& privateKeys) @@ -1153,9 +1147,8 @@ namespace data SetProperty ("caps", caps); } - bool LocalRouterInfo::SetHighCongestion (bool highCongestion) + bool LocalRouterInfo::UpdateCongestion (Congestion c) { - Congestion c = highCongestion ? eHighCongestion : eLowCongestion; if (c != GetCongestion ()) { SetCongestion (c); diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index ef145496..f258b018 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -330,10 +330,9 @@ namespace data public: LocalRouterInfo () = default; - LocalRouterInfo (const std::string& fullPath); void CreateBuffer (const PrivateKeys& privateKeys); void UpdateCaps (uint8_t caps); - bool SetHighCongestion (bool highCongestion); // returns true if updated + bool UpdateCongestion (Congestion c); // returns true if updated void SetProperty (const std::string& key, const std::string& value) override; void DeleteProperty (const std::string& key); From 7c2da75197deebee232090d80e5d177a6eb438d1 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 3 Apr 2023 19:05:35 -0400 Subject: [PATCH 0082/1171] don't recreate existing streaming destination --- libi2pd_client/I2PTunnel.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index 5558cd8d..db0d0c04 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -691,7 +691,10 @@ namespace client int port, std::shared_ptr localDestination, int inport, bool gzip): I2PService (localDestination), m_IsUniqueLocal(true), m_Name (name), m_Address (address), m_Port (port), m_IsAccessList (false) { - m_PortDestination = localDestination->CreateStreamingDestination (inport > 0 ? inport : port, gzip); + if (!inport) inport = port; + m_PortDestination = localDestination->GetStreamingDestination (inport); + if (!m_PortDestination) + m_PortDestination = localDestination->CreateStreamingDestination (inport, gzip); } void I2PServerTunnel::Start () From 0c8a80b6f8179e84a910d8cb5926f0282d5ea120 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 3 Apr 2023 21:35:10 -0400 Subject: [PATCH 0083/1171] fixed warnings --- libi2pd/TransitTunnel.h | 18 +++++++++--------- libi2pd/Tunnel.h | 20 ++++++++++---------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/libi2pd/TransitTunnel.h b/libi2pd/TransitTunnel.h index 60e2f450..fb2dad21 100644 --- a/libi2pd/TransitTunnel.h +++ b/libi2pd/TransitTunnel.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -34,9 +34,9 @@ namespace tunnel virtual size_t GetNumTransmittedBytes () const { return 0; }; // implements TunnelBase - void SendTunnelDataMsg (std::shared_ptr msg); - void HandleTunnelDataMsg (std::shared_ptr&& tunnelMsg); - void EncryptTunnelMsg (std::shared_ptr in, std::shared_ptr out); + void SendTunnelDataMsg (std::shared_ptr msg) override; + void HandleTunnelDataMsg (std::shared_ptr&& tunnelMsg) override; + void EncryptTunnelMsg (std::shared_ptr in, std::shared_ptr out) override; private: i2p::crypto::AESKey m_LayerKey, m_IVKey; @@ -55,8 +55,8 @@ namespace tunnel ~TransitTunnelParticipant (); size_t GetNumTransmittedBytes () const { return m_NumTransmittedBytes; }; - void HandleTunnelDataMsg (std::shared_ptr&& tunnelMsg); - void FlushTunnelDataMsgs (); + void HandleTunnelDataMsg (std::shared_ptr&& tunnelMsg) override; + void FlushTunnelDataMsgs () override; private: @@ -74,8 +74,8 @@ namespace tunnel TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey), m_Gateway(this) {}; - void SendTunnelDataMsg (std::shared_ptr msg); - void FlushTunnelDataMsgs (); + void SendTunnelDataMsg (std::shared_ptr msg) override; + void FlushTunnelDataMsgs () override; size_t GetNumTransmittedBytes () const { return m_Gateway.GetNumSentBytes (); }; private: @@ -96,7 +96,7 @@ namespace tunnel void Cleanup () { m_Endpoint.Cleanup (); } - void HandleTunnelDataMsg (std::shared_ptr&& tunnelMsg); + void HandleTunnelDataMsg (std::shared_ptr&& tunnelMsg) override; size_t GetNumTransmittedBytes () const { return m_Endpoint.GetNumReceivedBytes (); } private: diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index 5ac410ea..561b81a3 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -103,8 +103,8 @@ namespace tunnel bool HandleTunnelBuildResponse (uint8_t * msg, size_t len); // implements TunnelBase - void SendTunnelDataMsg (std::shared_ptr msg); - void EncryptTunnelMsg (std::shared_ptr in, std::shared_ptr out); + void SendTunnelDataMsg (std::shared_ptr msg) override; + void EncryptTunnelMsg (std::shared_ptr in, std::shared_ptr out) override; /** @brief add latency sample */ void AddLatencySample(const uint64_t ms) { m_Latency = (m_Latency + ms) >> 1; } @@ -144,9 +144,9 @@ namespace tunnel virtual size_t GetNumSentBytes () const { return m_Gateway.GetNumSentBytes (); }; // implements TunnelBase - void HandleTunnelDataMsg (std::shared_ptr&& tunnelMsg); + void HandleTunnelDataMsg (std::shared_ptr&& tunnelMsg) override; - bool IsInbound() const { return false; } + bool IsInbound() const override { return false; } private: @@ -160,9 +160,9 @@ namespace tunnel public: InboundTunnel (std::shared_ptr config): Tunnel (config), m_Endpoint (true) {}; - void HandleTunnelDataMsg (std::shared_ptr&& msg); + void HandleTunnelDataMsg (std::shared_ptr&& msg) override; virtual size_t GetNumReceivedBytes () const { return m_Endpoint.GetNumReceivedBytes (); }; - bool IsInbound() const { return true; } + bool IsInbound() const override { return true; } // override TunnelBase void Cleanup () { m_Endpoint.Cleanup (); }; @@ -177,8 +177,8 @@ namespace tunnel public: ZeroHopsInboundTunnel (); - void SendTunnelDataMsg (std::shared_ptr msg); - size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; }; + void SendTunnelDataMsg (std::shared_ptr msg) override; + size_t GetNumReceivedBytes () const override { return m_NumReceivedBytes; }; private: @@ -190,8 +190,8 @@ namespace tunnel public: ZeroHopsOutboundTunnel (); - void SendTunnelDataMsg (const std::vector& msgs); - size_t GetNumSentBytes () const { return m_NumSentBytes; }; + void SendTunnelDataMsg (const std::vector& msgs) override; + size_t GetNumSentBytes () const override { return m_NumSentBytes; }; private: From dc6499aa981bdb4c475ac9e0ca93590150b59366 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 3 Apr 2023 22:50:31 -0400 Subject: [PATCH 0084/1171] fixed warnings --- libi2pd/TransitTunnel.h | 2 +- libi2pd/Tunnel.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/TransitTunnel.h b/libi2pd/TransitTunnel.h index fb2dad21..20aff500 100644 --- a/libi2pd/TransitTunnel.h +++ b/libi2pd/TransitTunnel.h @@ -94,7 +94,7 @@ namespace tunnel TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey), m_Endpoint (false) {}; // transit endpoint is always outbound - void Cleanup () { m_Endpoint.Cleanup (); } + void Cleanup () override { m_Endpoint.Cleanup (); } void HandleTunnelDataMsg (std::shared_ptr&& tunnelMsg) override; size_t GetNumTransmittedBytes () const { return m_Endpoint.GetNumReceivedBytes (); } diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index 561b81a3..cd12369e 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -165,7 +165,7 @@ namespace tunnel bool IsInbound() const override { return true; } // override TunnelBase - void Cleanup () { m_Endpoint.Cleanup (); }; + void Cleanup () override { m_Endpoint.Cleanup (); }; private: From 922e5915b16f07b6dea56704f660cb1237c2efa1 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 4 Apr 2023 13:19:08 -0400 Subject: [PATCH 0085/1171] rename SendTunnelDataMsg to SendTunnelDataMsgs for multiple messages --- libi2pd/Datagram.cpp | 4 ++-- libi2pd/Destination.cpp | 2 +- libi2pd/NetDb.cpp | 2 +- libi2pd/Streaming.cpp | 2 +- libi2pd/Tunnel.cpp | 6 +++--- libi2pd/Tunnel.h | 4 ++-- libi2pd_client/I2CP.cpp | 4 ++-- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp index 30635b09..64738ebe 100644 --- a/libi2pd/Datagram.cpp +++ b/libi2pd/Datagram.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2021, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -425,7 +425,7 @@ namespace datagram if (m) send.push_back(i2p::tunnel::TunnelMessageBlock{i2p::tunnel::eDeliveryTypeTunnel,routingPath->remoteLease->tunnelGateway, routingPath->remoteLease->tunnelID, m}); } - routingPath->outboundTunnel->SendTunnelDataMsg(send); + routingPath->outboundTunnel->SendTunnelDataMsgs(send); } m_SendQueue.clear(); } diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 8002e6f9..efda499f 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -835,7 +835,7 @@ namespace client AddSessionKey (replyKey, replyTag); auto msg = WrapMessageForRouter (nextFloodfill, CreateLeaseSetDatabaseLookupMsg (dest, request->excluded, request->replyTunnel, replyKey, replyTag, isECIES)); - request->outboundTunnel->SendTunnelDataMsg ( + request->outboundTunnel->SendTunnelDataMsgs ( { i2p::tunnel::TunnelMessageBlock { diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 82e15304..ecae4f24 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -1137,7 +1137,7 @@ namespace data m_Requests.RequestComplete (randomHash, nullptr); } if (throughTunnels && msgs.size () > 0) - outbound->SendTunnelDataMsg (msgs); + outbound->SendTunnelDataMsgs (msgs); } void NetDb::Flood (const IdentHash& ident, std::shared_ptr floodMsg) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 1deca8a6..c2cf3a0a 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -925,7 +925,7 @@ namespace stream }); m_NumSentBytes += it->GetLength (); } - m_CurrentOutboundTunnel->SendTunnelDataMsg (msgs); + m_CurrentOutboundTunnel->SendTunnelDataMsgs (msgs); } else { diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 09358179..9c880378 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -284,10 +284,10 @@ namespace tunnel block.deliveryType = eDeliveryTypeLocal; block.data = msg; - SendTunnelDataMsg ({block}); + SendTunnelDataMsgs ({block}); } - void OutboundTunnel::SendTunnelDataMsg (const std::vector& msgs) + void OutboundTunnel::SendTunnelDataMsgs (const std::vector& msgs) { std::unique_lock l(m_SendMutex); for (auto& it : msgs) @@ -306,7 +306,7 @@ namespace tunnel { } - void ZeroHopsOutboundTunnel::SendTunnelDataMsg (const std::vector& msgs) + void ZeroHopsOutboundTunnel::SendTunnelDataMsgs (const std::vector& msgs) { for (auto& msg : msgs) { diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index cd12369e..bf0274db 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -139,7 +139,7 @@ namespace tunnel Tunnel (config), m_Gateway (this), m_EndpointIdentHash (config->GetLastIdentHash ()) {}; void SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, std::shared_ptr msg); - virtual void SendTunnelDataMsg (const std::vector& msgs); // multiple messages + virtual void SendTunnelDataMsgs (const std::vector& msgs); // multiple messages const i2p::data::IdentHash& GetEndpointIdentHash () const { return m_EndpointIdentHash; }; virtual size_t GetNumSentBytes () const { return m_Gateway.GetNumSentBytes (); }; @@ -190,7 +190,7 @@ namespace tunnel public: ZeroHopsOutboundTunnel (); - void SendTunnelDataMsg (const std::vector& msgs) override; + void SendTunnelDataMsgs (const std::vector& msgs) override; size_t GetNumSentBytes () const override { return m_NumSentBytes; }; private: diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index cc0837b7..87f37e5e 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -230,7 +230,7 @@ namespace client remoteLease->tunnelGateway, remoteLease->tunnelID, garlic }); - outboundTunnel->SendTunnelDataMsg (msgs); + outboundTunnel->SendTunnelDataMsgs (msgs); return true; } else From 8178df752b1432de7b45c72820b56694b4f526c7 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 4 Apr 2023 13:42:54 -0400 Subject: [PATCH 0086/1171] fixed warning --- libi2pd/TransitTunnel.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/TransitTunnel.h b/libi2pd/TransitTunnel.h index 20aff500..cbab8d5b 100644 --- a/libi2pd/TransitTunnel.h +++ b/libi2pd/TransitTunnel.h @@ -54,7 +54,7 @@ namespace tunnel layerKey, ivKey), m_NumTransmittedBytes (0) {}; ~TransitTunnelParticipant (); - size_t GetNumTransmittedBytes () const { return m_NumTransmittedBytes; }; + size_t GetNumTransmittedBytes () const override { return m_NumTransmittedBytes; }; void HandleTunnelDataMsg (std::shared_ptr&& tunnelMsg) override; void FlushTunnelDataMsgs () override; @@ -76,7 +76,7 @@ namespace tunnel void SendTunnelDataMsg (std::shared_ptr msg) override; void FlushTunnelDataMsgs () override; - size_t GetNumTransmittedBytes () const { return m_Gateway.GetNumSentBytes (); }; + size_t GetNumTransmittedBytes () const override { return m_Gateway.GetNumSentBytes (); }; private: From 220ef283dea2af174c1fb62aa501d5752c6910dd Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 4 Apr 2023 13:48:00 -0400 Subject: [PATCH 0087/1171] rename SendTunnelDataMsg to SendTunnelDataMsgTo for router tunnel delivery types --- libi2pd/Destination.cpp | 2 +- libi2pd/Garlic.cpp | 6 +++--- libi2pd/NetDb.cpp | 8 ++++---- libi2pd/NetDbRequests.cpp | 4 ++-- libi2pd/RouterContext.cpp | 2 +- libi2pd/Tunnel.cpp | 4 ++-- libi2pd/Tunnel.h | 2 +- libi2pd/TunnelPool.cpp | 2 +- 8 files changed, 15 insertions(+), 15 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index efda499f..9e5fbe20 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -635,7 +635,7 @@ namespace client m_PublishConfirmationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT)); m_PublishConfirmationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishConfirmationTimer, shared_from_this (), std::placeholders::_1)); - outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, msg); + outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0, msg); m_LastSubmissionTime = ts; } diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 9daea1f0..c351f6d6 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -709,7 +709,7 @@ namespace garlic else LogPrint (eLogError, "Garlic: Tunnel pool is not set for inbound tunnel"); if (tunnel) // we have sent it through an outbound tunnel - tunnel->SendTunnelDataMsg (gwHash, gwTunnel, msg); + tunnel->SendTunnelDataMsgTo (gwHash, gwTunnel, msg); else LogPrint (eLogWarning, "Garlic: No outbound tunnels available for garlic clove"); } @@ -1075,7 +1075,7 @@ namespace garlic { auto tunnel = GetTunnelPool ()->GetNextOutboundTunnel (); if (tunnel) - tunnel->SendTunnelDataMsg (gwHash, gwTunnel, CreateI2NPMessage (typeID, buf, len - offset, msgID)); + tunnel->SendTunnelDataMsgTo (gwHash, gwTunnel, CreateI2NPMessage (typeID, buf, len - offset, msgID)); else LogPrint (eLogWarning, "Garlic: No outbound tunnels available for garlic clove"); } diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index ecae4f24..447eb873 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -717,7 +717,7 @@ namespace data auto outbound = pool ? pool->GetNextOutboundTunnel (nullptr, floodfill->GetCompatibleTransports (false)) : nullptr; auto inbound = pool ? pool->GetNextInboundTunnel (nullptr, floodfill->GetCompatibleTransports (true)) : nullptr; if (outbound && inbound) - outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, dest->CreateRequestMessage (floodfill, inbound)); + outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0, dest->CreateRequestMessage (floodfill, inbound)); else { LogPrint (eLogError, "NetDb: ", destination.ToBase64(), " destination requested, but no tunnels found"); @@ -792,7 +792,7 @@ namespace data auto pool = i2p::tunnel::tunnels.GetExploratoryPool (); auto outbound = pool ? pool->GetNextOutboundTunnel () : nullptr; if (outbound) - outbound->SendTunnelDataMsg (buf + offset, tunnelID, deliveryStatus); + outbound->SendTunnelDataMsgTo (buf + offset, tunnelID, deliveryStatus); else LogPrint (eLogWarning, "NetDb: No outbound tunnels for DatabaseStore reply found"); } @@ -901,7 +901,7 @@ namespace data { // request destination LogPrint (eLogDebug, "NetDb: Try ", key, " at ", count, " floodfill ", nextFloodfill->GetIdentHash ().ToBase64 ()); - outbound->SendTunnelDataMsg (nextFloodfill->GetIdentHash (), 0, + outbound->SendTunnelDataMsgTo (nextFloodfill->GetIdentHash (), 0, dest->CreateRequestMessage (nextFloodfill, inbound)); deleteDest = false; } @@ -1081,7 +1081,7 @@ namespace data auto exploratoryPool = i2p::tunnel::tunnels.GetExploratoryPool (); auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel () : nullptr; if (outbound) - outbound->SendTunnelDataMsg (replyIdent, replyTunnelID, replyMsg); + outbound->SendTunnelDataMsgTo (replyIdent, replyTunnelID, replyMsg); else transports.SendMessage (replyIdent, i2p::CreateTunnelGatewayMsg (replyTunnelID, replyMsg)); } diff --git a/libi2pd/NetDbRequests.cpp b/libi2pd/NetDbRequests.cpp index e7aab34c..4011b8aa 100644 --- a/libi2pd/NetDbRequests.cpp +++ b/libi2pd/NetDbRequests.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -137,7 +137,7 @@ namespace data auto inbound = pool->GetNextInboundTunnel (); auto nextFloodfill = netdb.GetClosestFloodfill (dest->GetDestination (), dest->GetExcludedPeers ()); if (nextFloodfill && outbound && inbound) - outbound->SendTunnelDataMsg (nextFloodfill->GetIdentHash (), 0, + outbound->SendTunnelDataMsgTo (nextFloodfill->GetIdentHash (), 0, dest->CreateRequestMessage (nextFloodfill, inbound)); else { diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index de103910..d6c3c57b 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -1348,7 +1348,7 @@ namespace i2p auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel (nullptr, floodfill->GetCompatibleTransports (false)) : nullptr; auto inbound = exploratoryPool ? exploratoryPool->GetNextInboundTunnel (nullptr, floodfill->GetCompatibleTransports (true)) : nullptr; if (inbound && outbound) - outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, + outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0, CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken, inbound)); else LogPrint (eLogInfo, "Router: Can't publish our RouterInfo. No tunnles. Try again in ", ROUTER_INFO_CONFIRMATION_TIMEOUT, " seconds"); diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 9c880378..05359390 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -103,7 +103,7 @@ namespace tunnel if (msg1) msg = msg1; } } - outboundTunnel->SendTunnelDataMsg (GetNextIdentHash (), 0, msg); + outboundTunnel->SendTunnelDataMsgTo (GetNextIdentHash (), 0, msg); } else { @@ -266,7 +266,7 @@ namespace tunnel } } - void OutboundTunnel::SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, std::shared_ptr msg) + void OutboundTunnel::SendTunnelDataMsgTo (const uint8_t * gwHash, uint32_t gwTunnel, std::shared_ptr msg) { TunnelMessageBlock block; if (gwHash) diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index bf0274db..5810a7a8 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -138,7 +138,7 @@ namespace tunnel OutboundTunnel (std::shared_ptr config): Tunnel (config), m_Gateway (this), m_EndpointIdentHash (config->GetLastIdentHash ()) {}; - void SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, std::shared_ptr msg); + void SendTunnelDataMsgTo (const uint8_t * gwHash, uint32_t gwTunnel, std::shared_ptr msg); virtual void SendTunnelDataMsgs (const std::vector& msgs); // multiple messages const i2p::data::IdentHash& GetEndpointIdentHash () const { return m_EndpointIdentHash; }; virtual size_t GetNumSentBytes () const { return m_Gateway.GetNumSentBytes (); }; diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index bafc1c2d..cf146218 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -383,7 +383,7 @@ namespace tunnel std::unique_lock l(m_TestsMutex); m_Tests[msgID] = std::make_pair (*it1, *it2); } - (*it1)->SendTunnelDataMsg ((*it2)->GetNextIdentHash (), (*it2)->GetNextTunnelID (), + (*it1)->SendTunnelDataMsgTo ((*it2)->GetNextIdentHash (), (*it2)->GetNextTunnelID (), CreateDeliveryStatusMsg (msgID)); ++it1; ++it2; } From e3fb9d84835cc95092b5cea998d8d543dcb42a9b Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 4 Apr 2023 13:57:46 -0400 Subject: [PATCH 0088/1171] fixed warning --- libi2pd/TransitTunnel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/TransitTunnel.h b/libi2pd/TransitTunnel.h index cbab8d5b..f83007a9 100644 --- a/libi2pd/TransitTunnel.h +++ b/libi2pd/TransitTunnel.h @@ -97,7 +97,7 @@ namespace tunnel void Cleanup () override { m_Endpoint.Cleanup (); } void HandleTunnelDataMsg (std::shared_ptr&& tunnelMsg) override; - size_t GetNumTransmittedBytes () const { return m_Endpoint.GetNumReceivedBytes (); } + size_t GetNumTransmittedBytes () const override { return m_Endpoint.GetNumReceivedBytes (); } private: From 9475a2272830fd98ec22675076e9864845026a6a Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 5 Apr 2023 21:30:36 -0400 Subject: [PATCH 0089/1171] update introducers. cleanup unreachable routers --- libi2pd/NetDb.cpp | 30 ++++++++++++++---------- libi2pd/NetDb.hpp | 2 +- libi2pd/RouterInfo.cpp | 53 +++++++++++++++++++++++++++++++++--------- libi2pd/RouterInfo.h | 6 +++-- libi2pd/TunnelPool.cpp | 7 +++--- 5 files changed, 69 insertions(+), 29 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 447eb873..9fd9923a 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -106,7 +106,7 @@ namespace data { i2p::util::SetThreadName("NetDB"); - uint64_t lastSave = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0; + uint64_t lastManage = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0; uint64_t lastProfilesCleanup = i2p::util::GetSecondsSinceEpoch (); int16_t profilesCleanupVariance = 0; @@ -155,14 +155,14 @@ namespace data lastManageRequest = ts; } - if (ts - lastSave >= 60 || ts + 60 < lastSave) // save routers, manage leasesets and validate subscriptions every minute + if (ts - lastManage >= 60 || ts + 60 < lastManage) // manage routers and leasesets every minute { - if (lastSave) + if (lastManage) { - SaveUpdated (); + ManageRouterInfos (); ManageLeaseSets (); } - lastSave = ts; + lastManage = ts; } if (ts - lastDestinationCleanup >= i2p::garlic::INCOMING_TAGS_EXPIRATION_TIMEOUT || @@ -631,13 +631,8 @@ namespace data if (!it.second->IsUnreachable ()) { // find & mark expired routers - if (!it.second->IsReachable () && (it.second->GetCompatibleTransports (true) & RouterInfo::eSSU2V4)) - // non-reachable router, but reachable by ipv4 SSU2 means introducers - { - if (ts > it.second->GetTimestamp () + NETDB_INTRODUCEE_EXPIRATION_TIMEOUT*1000LL) - // RouterInfo expires after 1 hour if uses introducer - it.second->SetUnreachable (true); - } + if (it.second->GetCompatibleTransports (true)) // non reachable by any transport + it.second->SetUnreachable (true); else if (checkForExpiration && ts > it.second->GetTimestamp () + expirationTimeout) it.second->SetUnreachable (true); else if (ts + NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < it.second->GetTimestamp ()) @@ -1348,6 +1343,17 @@ namespace data return r; } + void NetDb::ManageRouterInfos () + { + auto ts = i2p::util::GetSecondsSinceEpoch (); + { + std::unique_lock l(m_RouterInfosMutex); + for (auto& it: m_RouterInfos) + it.second->UpdateIntroducers (ts); + } + SaveUpdated (); + } + void NetDb::ManageLeaseSets () { auto ts = i2p::util::GetMillisecondsSinceEpoch (); diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index 71694d8d..d98d487e 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -40,7 +40,6 @@ namespace data const int NETDB_MIN_FLOODFILLS = 5; const int NETDB_MIN_TUNNEL_CREATION_SUCCESS_RATE = 8; // in percents const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60 * 60; // 1 hour, in seconds - const int NETDB_INTRODUCEE_EXPIRATION_TIMEOUT = 65 * 60; const int NETDB_MIN_EXPIRATION_TIMEOUT = 90 * 60; // 1.5 hours const int NETDB_MAX_EXPIRATION_TIMEOUT = 27 * 60 * 60; // 27 hours const int NETDB_MAX_OFFLINE_EXPIRATION_TIMEOUT = 180; // in days @@ -139,6 +138,7 @@ namespace data void Run (); // exploratory thread void Explore (int numDestinations); void Flood (const IdentHash& ident, std::shared_ptr floodMsg); + void ManageRouterInfos (); void ManageLeaseSets (); void ManageRequests (); diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 3ae5abd9..eb186ec9 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -400,18 +400,9 @@ namespace data { // exclude invalid introducers uint32_t ts = i2p::util::GetSecondsSinceEpoch (); - int numValid = 0; - for (auto& it: address->ssu->introducers) - { - if (it.iTag && ts < it.iExp) - numValid++; - else - it.iTag = 0; - } - if (numValid) + UpdateIntroducers (address, ts); + if (!address->ssu->introducers.empty ()) // still has something m_ReachableTransports |= supportedTransports; - else - address->ssu->introducers.resize (0); } } if (supportedTransports) @@ -576,6 +567,21 @@ namespace data return caps; } + void RouterInfo::UpdateIntroducers (std::shared_ptr
address, uint64_t ts) + { + if (!address || !address->ssu) return; + int numValid = 0; + for (auto& it: address->ssu->introducers) + { + if (it.iTag && ts < it.iExp) + numValid++; + else + it.iTag = 0; + } + if (!numValid) + address->ssu->introducers.resize (0); + } + bool RouterInfo::IsNewer (const uint8_t * buf, size_t len) const { if (!m_RouterIdentity) return false; @@ -1036,6 +1042,31 @@ namespace data } } + void RouterInfo::UpdateIntroducers (uint64_t ts) + { + if (ts*1000 < m_Timestamp + INTRODUCER_UPDATE_INTERVAL) return; + if (m_ReachableTransports & eSSU2V4) + { + auto addr = (*GetAddresses ())[eSSU2V4Idx]; + if (addr && addr->UsesIntroducer ()) + { + UpdateIntroducers (addr, ts); + if (!addr->UsesIntroducer ()) // no more valid introducers + m_ReachableTransports &= ~eSSU2V4; + } + } + if (m_ReachableTransports & eSSU2V6) + { + auto addr = (*GetAddresses ())[eSSU2V6Idx]; + if (addr && addr->UsesIntroducer ()) + { + UpdateIntroducers (addr, ts); + if (!addr->UsesIntroducer ()) // no more valid introducers + m_ReachableTransports &= ~eSSU2V6; + } + } + } + void RouterInfo::UpdateBuffer (const uint8_t * buf, size_t len) { if (!m_Buffer) diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index f258b018..273e7a75 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -61,6 +61,7 @@ namespace data const size_t MAX_RI_BUFFER_SIZE = 3072; // if RouterInfo exceeds 3K we consider it as malformed, might extend later const int HIGH_CONGESTION_INTERVAL = 15*60; // in seconds, 15 minutes + const int INTRODUCER_UPDATE_INTERVAL = 20*60*1000; // in milliseconds, 20 minutes class RouterInfo: public RoutingDestination { @@ -221,8 +222,8 @@ namespace data void RemoveSSU2Address (bool v4); void SetUnreachableAddressesTransportCaps (uint8_t transports); // bitmask of AddressCaps void UpdateSupportedTransports (); + void UpdateIntroducers (uint64_t ts); // ts in seconds bool IsFloodfill () const { return m_Caps & Caps::eFloodfill; }; - bool IsReachable () const { return m_Caps & Caps::eReachable; }; bool IsECIES () const { return m_RouterIdentity->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD; }; bool IsNTCP2 (bool v4only = true) const; bool IsNTCP2V6 () const { return m_SupportedTransports & eNTCP2V6; }; @@ -302,6 +303,7 @@ namespace data size_t ReadString (char* str, size_t len, std::istream& s) const; void ExtractCaps (const char * value); uint8_t ExtractAddressCaps (const char * value) const; + void UpdateIntroducers (std::shared_ptr
address, uint64_t ts); template std::shared_ptr GetAddress (Filter filter) const; virtual std::shared_ptr NewBuffer () const; @@ -315,7 +317,7 @@ namespace data std::shared_ptr m_RouterIdentity; std::shared_ptr m_Buffer; size_t m_BufferLen; - uint64_t m_Timestamp; + uint64_t m_Timestamp; // in milliseconds boost::shared_ptr m_Addresses; // TODO: use std::shared_ptr and std::atomic_store for gcc >= 4.9 bool m_IsUpdated, m_IsUnreachable; CompatibleTransports m_SupportedTransports, m_ReachableTransports; diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index cf146218..c1102d25 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -498,7 +498,8 @@ namespace tunnel { auto r = i2p::transport::transports.GetRandomPeer (!IsExploratory ()); if (r && r->IsECIES () && !r->GetProfile ()->IsBad () && - (numHops > 1 || (r->IsV4 () && (!inbound || r->IsReachable ())))) // first inbound must be reachable + (numHops > 1 || (r->IsV4 () && (!inbound || + r->IsReachableBy (i2p::data::RouterInfo::eNTCP2V4 | i2p::data::RouterInfo::eSSU2V4))))) // first inbound must be reachable { prevHop = r; path.Add (r); @@ -520,8 +521,8 @@ namespace tunnel LogPrint (eLogError, "Tunnels: Can't select next hop for ", prevHop->GetIdentHashBase64 ()); return false; } - if ((i == numHops - 1) && (!hop->IsV4 () || // doesn't support ipv4 - (inbound && !hop->IsReachable ()))) // IBGW is not reachable + if ((i == numHops - 1) && (!hop->IsV4 () || (inbound && // doesn't support ipv4 + !hop->IsReachableBy (i2p::data::RouterInfo::eNTCP2V4 | i2p::data::RouterInfo::eSSU2V4)))) // IBGW is not reachable { auto hop1 = nextHop (prevHop, true); if (hop1) hop = hop1; From d580c0155ac8ff31f26ac0378719b63750f555e5 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 5 Apr 2023 21:49:49 -0400 Subject: [PATCH 0090/1171] fixed typo --- libi2pd/NetDb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 9fd9923a..3847f24f 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -631,7 +631,7 @@ namespace data if (!it.second->IsUnreachable ()) { // find & mark expired routers - if (it.second->GetCompatibleTransports (true)) // non reachable by any transport + if (!it.second->GetCompatibleTransports (true)) // non reachable by any transport it.second->SetUnreachable (true); else if (checkForExpiration && ts > it.second->GetTimestamp () + expirationTimeout) it.second->SetUnreachable (true); From caff003a85c0cfbd807d7c71333ac9ac34f1eba7 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 6 Apr 2023 16:03:15 -0400 Subject: [PATCH 0091/1171] check for published ipv4 addresses for floodfills and IBGW --- libi2pd/RouterInfo.cpp | 20 ++++++++++++++++---- libi2pd/RouterInfo.h | 1 + libi2pd/TunnelPool.cpp | 6 ++---- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index eb186ec9..ad1de04a 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -366,7 +366,7 @@ namespace data { if (isStaticKey) { - if (isHost) + if (isHost && address->port) { if (address->host.is_v6 ()) supportedTransports |= (i2p::util::net::IsYggdrasilAddress (address->host) ? eNTCP2V6Mesh : eNTCP2V6); @@ -374,8 +374,9 @@ namespace data supportedTransports |= eNTCP2V4; m_ReachableTransports |= supportedTransports; } - else if (!address->published) + else { + address->published = false; if (address->caps) { if (address->caps & AddressCaps::eV4) supportedTransports |= eNTCP2V4; @@ -982,11 +983,22 @@ namespace data bool RouterInfo::IsEligibleFloodfill () const { - // floodfill must be reachable by ipv4, >= 0.9.38 and not DSA - return IsReachableBy (eNTCP2V4 | eSSU2V4) && m_Version >= NETDB_MIN_FLOODFILL_VERSION && + // floodfill must have published ipv4, >= 0.9.38 and not DSA + return m_Version >= NETDB_MIN_FLOODFILL_VERSION && IsPublished (true) && GetIdentity ()->GetSigningKeyType () != SIGNING_KEY_TYPE_DSA_SHA1; } + bool RouterInfo::IsPublished (bool v4) const + { + auto addr = GetAddresses (); + if (v4) + return ((*addr)[eNTCP2V4] && ((*addr)[eNTCP2V4])->published) || + ((*addr)[eSSU2V4] && ((*addr)[eSSU2V4])->published); + else + return ((*addr)[eNTCP2V6] && ((*addr)[eNTCP2V6])->published) || + ((*addr)[eSSU2V6] && ((*addr)[eSSU2V6])->published); + } + bool RouterInfo::IsSSU2PeerTesting (bool v4) const { if (!(m_SupportedTransports & (v4 ? eSSU2V4 : eSSU2V6))) return false; diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 273e7a75..3789438d 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -247,6 +247,7 @@ namespace data bool IsHighBandwidth () const { return m_Caps & RouterInfo::eHighBandwidth; }; bool IsExtraBandwidth () const { return m_Caps & RouterInfo::eExtraBandwidth; }; bool IsEligibleFloodfill () const; + bool IsPublished (bool v4) const; bool IsSSU2PeerTesting (bool v4) const; bool IsSSU2Introducer (bool v4) const; bool IsHighCongestion () const; diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index c1102d25..aee466a1 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -498,8 +498,7 @@ namespace tunnel { auto r = i2p::transport::transports.GetRandomPeer (!IsExploratory ()); if (r && r->IsECIES () && !r->GetProfile ()->IsBad () && - (numHops > 1 || (r->IsV4 () && (!inbound || - r->IsReachableBy (i2p::data::RouterInfo::eNTCP2V4 | i2p::data::RouterInfo::eSSU2V4))))) // first inbound must be reachable + (numHops > 1 || (r->IsV4 () && (!inbound || r->IsPublished (true))))) // first inbound must be published ipv4 { prevHop = r; path.Add (r); @@ -521,8 +520,7 @@ namespace tunnel LogPrint (eLogError, "Tunnels: Can't select next hop for ", prevHop->GetIdentHashBase64 ()); return false; } - if ((i == numHops - 1) && (!hop->IsV4 () || (inbound && // doesn't support ipv4 - !hop->IsReachableBy (i2p::data::RouterInfo::eNTCP2V4 | i2p::data::RouterInfo::eSSU2V4)))) // IBGW is not reachable + if ((i == numHops - 1) && (!hop->IsV4 () || (inbound && !hop->IsPublished (true)))) // IBGW is not published ipv4 { auto hop1 = nextHop (prevHop, true); if (hop1) hop = hop1; From c1f19cb2582bb51d1fe1c9b49459557da1e45ab3 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 6 Apr 2023 16:19:56 -0400 Subject: [PATCH 0092/1171] fixed typo --- libi2pd/RouterInfo.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index ad1de04a..34bd705d 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -992,11 +992,11 @@ namespace data { auto addr = GetAddresses (); if (v4) - return ((*addr)[eNTCP2V4] && ((*addr)[eNTCP2V4])->published) || - ((*addr)[eSSU2V4] && ((*addr)[eSSU2V4])->published); + return ((*addr)[eNTCP2V4Idx] && ((*addr)[eNTCP2V4Idx])->published) || + ((*addr)[eSSU2V4Idx] && ((*addr)[eSSU2V4Idx])->published); else - return ((*addr)[eNTCP2V6] && ((*addr)[eNTCP2V6])->published) || - ((*addr)[eSSU2V6] && ((*addr)[eSSU2V6])->published); + return ((*addr)[eNTCP2V6Idx] && ((*addr)[eNTCP2V6Idx])->published) || + ((*addr)[eSSU2V6Idx] && ((*addr)[eSSU2V6Idx])->published); } bool RouterInfo::IsSSU2PeerTesting (bool v4) const From 572694b141720183ff65bdb5e081ff60772c224e Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 9 Apr 2023 21:32:44 -0400 Subject: [PATCH 0093/1171] check routers' congestion before recreating a tunnel --- libi2pd/TunnelPool.cpp | 31 ++++++++++++++++++++++++++----- libi2pd/TunnelPool.h | 1 + 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index aee466a1..d21347e6 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -637,8 +637,13 @@ namespace tunnel outboundTunnel = tunnels.GetNextOutboundTunnel (); LogPrint (eLogDebug, "Tunnels: Re-creating destination inbound tunnel..."); std::shared_ptr config; - if (m_NumInboundHops > 0 && tunnel->GetPeers().size()) - config = std::make_shared(tunnel->GetPeers (), tunnel->IsShortBuildMessage (), tunnel->GetFarEndTransports ()); + if (m_NumInboundHops > 0) + { + auto peers = tunnel->GetPeers(); + if (peers.size ()&& ValidatePeers (peers)) + config = std::make_shared(tunnel->GetPeers (), + tunnel->IsShortBuildMessage (), tunnel->GetFarEndTransports ()); + } if (!m_NumInboundHops || config) { auto newTunnel = tunnels.CreateInboundTunnel (config, shared_from_this(), outboundTunnel); @@ -702,10 +707,12 @@ namespace tunnel { LogPrint (eLogDebug, "Tunnels: Re-creating destination outbound tunnel..."); std::shared_ptr config; - if (m_NumOutboundHops > 0 && tunnel->GetPeers().size()) + if (m_NumOutboundHops > 0) { - config = std::make_shared(tunnel->GetPeers (), inboundTunnel->GetNextTunnelID (), - inboundTunnel->GetNextIdentHash (), inboundTunnel->IsShortBuildMessage (), tunnel->GetFarEndTransports ()); + auto peers = tunnel->GetPeers(); + if (peers.size () && ValidatePeers (peers)) + config = std::make_shared(peers, inboundTunnel->GetNextTunnelID (), + inboundTunnel->GetNextIdentHash (), inboundTunnel->IsShortBuildMessage (), tunnel->GetFarEndTransports ()); } if (!m_NumOutboundHops || config) { @@ -746,6 +753,20 @@ namespace tunnel return m_CustomPeerSelector != nullptr; } + bool TunnelPool::ValidatePeers (std::vector >& peers) + { + for (auto it: peers) + { + auto r = i2p::data::netdb.FindRouter (it->GetIdentHash ()); + if (r) + { + if (r->IsHighCongestion ()) return false; + it = r->GetIdentity (); // use identity from updated RouterInfo + } + } + return true; + } + std::shared_ptr TunnelPool::GetLowestLatencyInboundTunnel(std::shared_ptr exclude) const { std::shared_ptr tun = nullptr; diff --git a/libi2pd/TunnelPool.h b/libi2pd/TunnelPool.h index 7d952559..f49ce309 100644 --- a/libi2pd/TunnelPool.h +++ b/libi2pd/TunnelPool.h @@ -126,6 +126,7 @@ namespace tunnel typename TTunnels::value_type excluded, i2p::data::RouterInfo::CompatibleTransports compatible) const; bool SelectPeers (Path& path, bool isInbound); bool SelectExplicitPeers (Path& path, bool isInbound); + static bool ValidatePeers (std::vector >& peers); private: From 4ebc7c970a168257c21f823b9fff792458a1ab25 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 10 Apr 2023 23:04:38 -0400 Subject: [PATCH 0094/1171] bypass medium congestion(D) routers for client tunnels --- libi2pd/NetDb.cpp | 4 ++-- libi2pd/RouterInfo.cpp | 24 ++++++++++++++++++------ libi2pd/RouterInfo.h | 2 +- libi2pd/TunnelPool.cpp | 5 +++-- libi2pd/TunnelPool.h | 2 +- 5 files changed, 25 insertions(+), 12 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 3847f24f..c9c92b64 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -1172,7 +1172,7 @@ namespace data return !router->IsHidden () && router != compatibleWith && (reverse ? compatibleWith->IsReachableFrom (*router) : router->IsReachableFrom (*compatibleWith)) && - router->IsECIES (); + router->IsECIES () && !router->IsHighCongestion (false); }); } @@ -1206,7 +1206,7 @@ namespace data router->IsReachableFrom (*compatibleWith)) && (router->GetCaps () & RouterInfo::eHighBandwidth) && router->GetVersion () >= NETDB_MIN_HIGHBANDWIDTH_VERSION && - router->IsECIES () && !router->IsHighCongestion (); + router->IsECIES () && !router->IsHighCongestion (true); }); } diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 34bd705d..c18e0521 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -1113,13 +1113,25 @@ namespace data m_Timestamp = i2p::util::GetMillisecondsSinceEpoch (); } - bool RouterInfo::IsHighCongestion () const + bool RouterInfo::IsHighCongestion (bool highBandwidth) const { - if (m_Congestion == eLowCongestion || m_Congestion == eMediumCongestion) return false; - if (m_Congestion == eRejectAll) return true; - if (m_Congestion == eHighCongestion) - return (i2p::util::GetMillisecondsSinceEpoch () < m_Timestamp + HIGH_CONGESTION_INTERVAL*1000LL) ? true : false; - return false; + switch (m_Congestion) + { + case eLowCongestion: + return false; + break; + case eMediumCongestion: + return highBandwidth; + break; + case eHighCongestion: + return i2p::util::GetMillisecondsSinceEpoch () < m_Timestamp + HIGH_CONGESTION_INTERVAL*1000LL; + break; + case eRejectAll: + return true; + break; + default: + return false; + } } void LocalRouterInfo::CreateBuffer (const PrivateKeys& privateKeys) diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 3789438d..070737e8 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -250,7 +250,7 @@ namespace data bool IsPublished (bool v4) const; bool IsSSU2PeerTesting (bool v4) const; bool IsSSU2Introducer (bool v4) const; - bool IsHighCongestion () const; + bool IsHighCongestion (bool highBandwidth) const; uint8_t GetCaps () const { return m_Caps; }; void SetCaps (uint8_t caps) { m_Caps = caps; }; diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index d21347e6..3dc0256e 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -753,14 +753,15 @@ namespace tunnel return m_CustomPeerSelector != nullptr; } - bool TunnelPool::ValidatePeers (std::vector >& peers) + bool TunnelPool::ValidatePeers (std::vector >& peers) const { + bool highBandwidth = !IsExploratory (); for (auto it: peers) { auto r = i2p::data::netdb.FindRouter (it->GetIdentHash ()); if (r) { - if (r->IsHighCongestion ()) return false; + if (r->IsHighCongestion (highBandwidth)) return false; it = r->GetIdentity (); // use identity from updated RouterInfo } } diff --git a/libi2pd/TunnelPool.h b/libi2pd/TunnelPool.h index f49ce309..e9dd142e 100644 --- a/libi2pd/TunnelPool.h +++ b/libi2pd/TunnelPool.h @@ -126,7 +126,7 @@ namespace tunnel typename TTunnels::value_type excluded, i2p::data::RouterInfo::CompatibleTransports compatible) const; bool SelectPeers (Path& path, bool isInbound); bool SelectExplicitPeers (Path& path, bool isInbound); - static bool ValidatePeers (std::vector >& peers); + bool ValidatePeers (std::vector >& peers) const; private: From b8d21a1282cc00f4808cedbf3442b42eac820002 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 12 Apr 2023 07:46:50 -0400 Subject: [PATCH 0095/1171] create non-default port destination explicitly --- libi2pd_client/I2PTunnel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index db0d0c04..07cb0224 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -693,7 +693,7 @@ namespace client { if (!inport) inport = port; m_PortDestination = localDestination->GetStreamingDestination (inport); - if (!m_PortDestination) + if (!m_PortDestination || (inport && (m_PortDestination == localDestination->GetStreamingDestination ()))) // default destination m_PortDestination = localDestination->CreateStreamingDestination (inport, gzip); } From 132557f941eded30e5e3a21df1c9c7cf5ab3d4ab Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 12 Apr 2023 13:33:20 -0400 Subject: [PATCH 0096/1171] don't return default destination if port is specified explicitly --- libi2pd/Destination.cpp | 6 ++++-- libi2pd_client/I2PTunnel.cpp | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 9e5fbe20..1a93f163 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1083,6 +1083,7 @@ namespace client { // streaming protocol auto dest = GetStreamingDestination (toPort); + if (!dest) dest = m_StreamingDestination; // if no destination on port use default if (dest) dest->HandleDataMessagePayload (buf, length); else @@ -1236,8 +1237,9 @@ namespace client if (it != m_StreamingDestinationsByPorts.end ()) return it->second; } - // if port is zero or not found, use default destination - return m_StreamingDestination; + else // if port is zero, use default destination + return m_StreamingDestination; + return nullptr; } void ClientDestination::AcceptStreams (const i2p::stream::StreamingDestination::Acceptor& acceptor) diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index 07cb0224..78634b7e 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -693,7 +693,7 @@ namespace client { if (!inport) inport = port; m_PortDestination = localDestination->GetStreamingDestination (inport); - if (!m_PortDestination || (inport && (m_PortDestination == localDestination->GetStreamingDestination ()))) // default destination + if (!m_PortDestination) // default destination m_PortDestination = localDestination->CreateStreamingDestination (inport, gzip); } From e20acb93cfdb7880ad200fe55b6d5d58a07093a0 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 12 Apr 2023 15:28:15 -0400 Subject: [PATCH 0097/1171] don't lookup streaming destination for each message --- libi2pd/Destination.cpp | 16 +++++++++++----- libi2pd/Destination.h | 3 ++- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 1a93f163..7b878fbe 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -930,7 +930,7 @@ namespace client bool isPublic, const std::map * params): LeaseSetDestination (service, isPublic, params), m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY), - m_IsStreamingAnswerPings (DEFAULT_ANSWER_PINGS), + m_IsStreamingAnswerPings (DEFAULT_ANSWER_PINGS), m_LastPort (0), m_DatagramDestination (nullptr), m_RefCounter (0), m_ReadyChecker(service) { @@ -1058,6 +1058,7 @@ namespace client //it.second->SetOwner (nullptr); } m_StreamingDestinationsByPorts.clear (); + m_LastStreamingDestination = nullptr; if (m_DatagramDestination) { delete m_DatagramDestination; @@ -1082,10 +1083,15 @@ namespace client case PROTOCOL_TYPE_STREAMING: { // streaming protocol - auto dest = GetStreamingDestination (toPort); - if (!dest) dest = m_StreamingDestination; // if no destination on port use default - if (dest) - dest->HandleDataMessagePayload (buf, length); + if (toPort != m_LastPort || !m_LastStreamingDestination) + { + m_LastStreamingDestination = GetStreamingDestination (toPort); + if (!m_LastStreamingDestination) + m_LastStreamingDestination = m_StreamingDestination; // if no destination on port use default + m_LastPort = toPort; + } + if (m_LastStreamingDestination) + m_LastStreamingDestination->HandleDataMessagePayload (buf, length); else LogPrint (eLogError, "Destination: Missing streaming destination"); } diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 9e2d171f..96b20a54 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -297,6 +297,7 @@ namespace client bool m_IsStreamingAnswerPings; std::shared_ptr m_StreamingDestination; // default std::map > m_StreamingDestinationsByPorts; + std::shared_ptr m_LastStreamingDestination; uint16_t m_LastPort; // for server tunnels i2p::datagram::DatagramDestination * m_DatagramDestination; int m_RefCounter; // how many clients(tunnels) use this destination From cd5bfaabb5b209f3d7239568e5e2d975a1d9bc16 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 15 Apr 2023 22:16:31 -0400 Subject: [PATCH 0098/1171] mark and check unreachable ident hashes --- libi2pd/Transports.cpp | 21 +++++++++++++++------ libi2pd/Transports.h | 1 + 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index c2aeb964..940e17d8 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -458,8 +458,20 @@ namespace transport it->second.sessions.front ()->SendI2NPMessages (msgs); else { - if (it->second.delayedMessages.size () < MAX_NUM_DELAYED_MESSAGES) + auto sz = it->second.delayedMessages.size (); + if (sz < MAX_NUM_DELAYED_MESSAGES) { + if (sz > CHECK_PROFILE_NUM_DELAYED_MESSAGES) + { + auto profile = i2p::data::GetRouterProfile (ident); + if (profile && profile->IsUnreachable ()) + { + LogPrint (eLogWarning, "Transports: Peer profile for ", ident.ToBase64 (), "reports unreachable. Dropped"); + std::unique_lock l(m_PeersMutex); + m_Peers.erase (it); + return; + } + } for (auto& it1: msgs) it->second.delayedMessages.push_back (it1); } @@ -775,11 +787,8 @@ namespace transport if (it->second.sessions.empty () && ts > it->second.creationTime + SESSION_CREATION_TIMEOUT) { LogPrint (eLogWarning, "Transports: Session to peer ", it->first.ToBase64 (), " has not been created in ", SESSION_CREATION_TIMEOUT, " seconds"); - auto profile = i2p::data::GetRouterProfile(it->first); - if (profile) - { - profile->TunnelNonReplied(); - } + auto profile = i2p::data::GetRouterProfile (it->first); + if (profile) profile->Unreachable (); std::unique_lock l(m_PeersMutex); it = m_Peers.erase (it); } diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index 1058d31b..a8f2a16a 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -106,6 +106,7 @@ namespace transport const uint64_t SESSION_CREATION_TIMEOUT = 15; // in seconds const int PEER_TEST_INTERVAL = 71; // in minutes const int MAX_NUM_DELAYED_MESSAGES = 150; + const int CHECK_PROFILE_NUM_DELAYED_MESSAGES = 15; // check profile after class Transports { public: From 527ee3b3c5435553e3172fdcfe44f8c941a7bf01 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 16 Apr 2023 08:18:41 -0400 Subject: [PATCH 0099/1171] check if ident is unrechable only once --- libi2pd/Transports.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 940e17d8..fcdfc105 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -461,7 +461,7 @@ namespace transport auto sz = it->second.delayedMessages.size (); if (sz < MAX_NUM_DELAYED_MESSAGES) { - if (sz > CHECK_PROFILE_NUM_DELAYED_MESSAGES) + if (sz < CHECK_PROFILE_NUM_DELAYED_MESSAGES && sz + msgs.size () >= CHECK_PROFILE_NUM_DELAYED_MESSAGES) { auto profile = i2p::data::GetRouterProfile (ident); if (profile && profile->IsUnreachable ()) From b77ae0838859505182f99a80a8a12d575f49cb10 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 18 Apr 2023 14:35:13 -0400 Subject: [PATCH 0100/1171] exclude previously non-reachable transports --- libi2pd/NetDb.cpp | 20 +++++++++++++++----- libi2pd/NetDb.hpp | 1 + libi2pd/RouterInfo.h | 1 + libi2pd/Transports.cpp | 11 +++++++++++ 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index c9c92b64..1f9797f2 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -409,19 +409,29 @@ namespace data void NetDb::SetUnreachable (const IdentHash& ident, bool unreachable) { - auto it = m_RouterInfos.find (ident); - if (it != m_RouterInfos.end ()) + auto r = FindRouter (ident); + if (r) { - it->second->SetUnreachable (unreachable); + r->SetUnreachable (unreachable); if (unreachable) { - auto profile = it->second->GetProfile (); + auto profile = r->GetProfile (); if (profile) profile->Unreachable (); } - } + } } + void NetDb::ExcludeReachableTransports (const IdentHash& ident, RouterInfo::CompatibleTransports transports) + { + auto r = FindRouter (ident); + if (r) + { + std::unique_lock l(m_RouterInfosMutex); + r->ExcludeReachableTransports (transports); + } + } + void NetDb::Reseed () { if (!m_Reseeder) diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index d98d487e..b6dc8ce7 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -94,6 +94,7 @@ namespace data std::shared_ptr GetClosestNonFloodfill (const IdentHash& destination, const std::set& excluded) const; std::shared_ptr GetRandomRouterInFamily (FamilyID fam) const; void SetUnreachable (const IdentHash& ident, bool unreachable); + void ExcludeReachableTransports (const IdentHash& ident, RouterInfo::CompatibleTransports transports); void PostI2NPMsg (std::shared_ptr msg); diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 070737e8..35737c9b 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -259,6 +259,7 @@ namespace data void SetUnreachable (bool unreachable) { m_IsUnreachable = unreachable; }; bool IsUnreachable () const { return m_IsUnreachable; }; + void ExcludeReachableTransports (CompatibleTransports transports) { m_ReachableTransports &= ~transports; }; const uint8_t * GetBuffer () const { return m_Buffer ? m_Buffer->data () : nullptr; }; const uint8_t * LoadBuffer (const std::string& fullPath); // load if necessary diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index fcdfc105..258ceca3 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -700,6 +700,17 @@ namespace transport auto it = m_Peers.find (ident); if (it != m_Peers.end ()) { + if (it->second.numAttempts > 1) + { + // exclude failed transports + i2p::data::RouterInfo::CompatibleTransports transports = 0; + int numExcluded = it->second.numAttempts - 1; + if (numExcluded > (int)it->second.priority.size ()) numExcluded = it->second.priority.size (); + for (int i = 0; i < numExcluded; i++) + transports |= it->second.priority[i]; + i2p::data::netdb.ExcludeReachableTransports (ident, transports); + } + it->second.numAttempts = 0; it->second.router = nullptr; // we don't need RouterInfo after successive connect bool sendDatabaseStore = true; if (it->second.delayedMessages.size () > 0) From 7a12b5ca4beb13dbc4f8a6c7148f94f927eb47ed Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 18 Apr 2023 19:25:15 -0400 Subject: [PATCH 0101/1171] handle incomplete HTTP header lines --- libi2pd_client/I2PTunnel.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index 78634b7e..23a3ad52 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -346,7 +346,12 @@ namespace client } } else + { + // insert incomplete line back + m_InHeader.clear (); + m_InHeader << line; break; + } } if (endOfHeader) @@ -409,7 +414,7 @@ namespace client matched = true; break; } - if (matched) break; + if (matched) continue; // replace some headers if (!m_Host.empty () && boost::iequals (line.substr (0, 5), "Host:")) @@ -428,7 +433,12 @@ namespace client } } else + { + // insert incomplete line back + m_InHeader.clear (); + m_InHeader << line; break; + } } if (endOfHeader) @@ -496,7 +506,12 @@ namespace client } } else + { + // insert incomplete line back + m_InHeader.clear (); + m_InHeader << line; break; + } } if (endOfHeader) From 6206616347f36f099c5b146cac6febfa1cbe7d67 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 18 Apr 2023 20:21:22 -0400 Subject: [PATCH 0102/1171] don't set unreachable twice --- libi2pd/Transports.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 258ceca3..304081ba 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -466,7 +466,7 @@ namespace transport auto profile = i2p::data::GetRouterProfile (ident); if (profile && profile->IsUnreachable ()) { - LogPrint (eLogWarning, "Transports: Peer profile for ", ident.ToBase64 (), "reports unreachable. Dropped"); + LogPrint (eLogWarning, "Transports: Peer profile for ", ident.ToBase64 (), " reports unreachable. Dropped"); std::unique_lock l(m_PeersMutex); m_Peers.erase (it); return; @@ -798,8 +798,12 @@ namespace transport if (it->second.sessions.empty () && ts > it->second.creationTime + SESSION_CREATION_TIMEOUT) { LogPrint (eLogWarning, "Transports: Session to peer ", it->first.ToBase64 (), " has not been created in ", SESSION_CREATION_TIMEOUT, " seconds"); - auto profile = i2p::data::GetRouterProfile (it->first); - if (profile) profile->Unreachable (); + if (!it->second.router) + { + // if router for ident not found mark it unreachable + auto profile = i2p::data::GetRouterProfile (it->first); + if (profile) profile->Unreachable (); + } std::unique_lock l(m_PeersMutex); it = m_Peers.erase (it); } From c22fc7537052260b11f9f1c3015b0600cc846975 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 19 Apr 2023 19:48:09 -0400 Subject: [PATCH 0103/1171] set router properties from incoming connections --- libi2pd/Transports.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 304081ba..e66a831c 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -729,7 +729,7 @@ namespace transport session->SendI2NPMessages (it->second.delayedMessages); it->second.delayedMessages.clear (); } - else // incoming connection + else // incoming connection or peer test { if(RoutesRestricted() && ! IsRestrictedPeer(ident)) { // not trusted @@ -737,11 +737,14 @@ namespace transport session->Done(); return; } - session->SendI2NPMessages ({ CreateDatabaseStoreMsg () }); // send DatabaseStore + if (!session->IsOutgoing ()) // incoming + session->SendI2NPMessages ({ CreateDatabaseStoreMsg () }); // send DatabaseStore + auto r = i2p::data::netdb.FindRouter (ident); // router should be in netdb after SessionConfirmed auto ts = i2p::util::GetSecondsSinceEpoch (); std::unique_lock l(m_PeersMutex); - auto it = m_Peers.insert (std::make_pair (ident, Peer{ nullptr, ts })).first; + auto it = m_Peers.insert (std::make_pair (ident, Peer{ r, ts })).first; it->second.sessions.push_back (session); + it->second.router = nullptr; } }); } From dc265367dcb33c54480389972ea08b5afb9fdabe Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 20 Apr 2023 14:23:41 -0400 Subject: [PATCH 0104/1171] drop unexpected I2NP messages --- libi2pd/I2NPProtocol.cpp | 24 +++++++++++++++++++----- libi2pd/Transports.cpp | 4 ++-- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index 5303edbf..1a5b1cde 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -785,10 +785,12 @@ namespace i2p switch (typeID) { case eI2NPTunnelData: - i2p::tunnel::tunnels.PostTunnelData (msg); + if (!msg->from) + i2p::tunnel::tunnels.PostTunnelData (msg); break; case eI2NPTunnelGateway: - i2p::tunnel::tunnels.PostTunnelData (msg); + if (!msg->from) + i2p::tunnel::tunnels.PostTunnelData (msg); break; case eI2NPGarlic: { @@ -799,11 +801,19 @@ namespace i2p break; } case eI2NPDatabaseStore: + // forward to netDb if came directly or through exploratory tunnel as response to our request + if (!msg->from || !msg->from->GetTunnelPool () || msg->from->GetTunnelPool ()->IsExploratory ()) + i2p::data::netdb.PostI2NPMsg (msg); + break; case eI2NPDatabaseSearchReply: - case eI2NPDatabaseLookup: // forward to netDb i2p::data::netdb.PostI2NPMsg (msg); break; + case eI2NPDatabaseLookup: + // forward to netDb if floodfill and came directly + if (!msg->from && i2p::context.IsFloodfill ()) + i2p::data::netdb.PostI2NPMsg (msg); + break; case eI2NPDeliveryStatus: { if (msg->from && msg->from->GetTunnelPool ()) @@ -813,10 +823,14 @@ namespace i2p break; } case eI2NPVariableTunnelBuild: - case eI2NPVariableTunnelBuildReply: case eI2NPTunnelBuild: - case eI2NPTunnelBuildReply: case eI2NPShortTunnelBuild: + // forward to tunnel thread + if (!msg->from) + i2p::tunnel::tunnels.PostTunnelData (msg); + break; + case eI2NPVariableTunnelBuildReply: + case eI2NPTunnelBuildReply: case eI2NPShortTunnelBuildReply: // forward to tunnel thread i2p::tunnel::tunnels.PostTunnelData (msg); diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index e66a831c..c6e9f372 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -801,12 +801,12 @@ namespace transport if (it->second.sessions.empty () && ts > it->second.creationTime + SESSION_CREATION_TIMEOUT) { LogPrint (eLogWarning, "Transports: Session to peer ", it->first.ToBase64 (), " has not been created in ", SESSION_CREATION_TIMEOUT, " seconds"); - if (!it->second.router) + /* if (!it->second.router) { // if router for ident not found mark it unreachable auto profile = i2p::data::GetRouterProfile (it->first); if (profile) profile->Unreachable (); - } + } */ std::unique_lock l(m_PeersMutex); it = m_Peers.erase (it); } From 5769a41208dc696fb64ea519bfbceb9c2b7e46ff Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 21 Apr 2023 14:54:54 -0400 Subject: [PATCH 0105/1171] use unordered_map for LeaseSets --- libi2pd/Destination.cpp | 11 ----------- libi2pd/Destination.h | 5 +++-- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 7b878fbe..6bcedb4e 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -262,17 +262,6 @@ namespace client return nullptr; } } - else - { - auto ls = i2p::data::netdb.FindLeaseSet (ident); - if (ls && !ls->IsExpired ()) - { - ls->PopulateLeases (); // since we don't store them in netdb - std::lock_guard _lock(m_RemoteLeaseSetsMutex); - m_RemoteLeaseSets[ident] = ls; - return ls; - } - } return nullptr; } diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 96b20a54..76508e49 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -184,8 +185,8 @@ namespace client boost::asio::io_service& m_Service; mutable std::mutex m_RemoteLeaseSetsMutex; - std::map > m_RemoteLeaseSets; - std::map > m_LeaseSetRequests; + std::unordered_map > m_RemoteLeaseSets; + std::unordered_map > m_LeaseSetRequests; std::shared_ptr m_Pool; std::mutex m_LeaseSetMutex; From c34df2090cc2921736d0667bb635a53183844bbe Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 21 Apr 2023 21:31:14 -0400 Subject: [PATCH 0106/1171] don't reply to DatabaseStore messages extracted from transit --- libi2pd/Tunnel.cpp | 12 +++++++++--- libi2pd/TunnelEndpoint.cpp | 14 +++++++++++--- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 05359390..76bdb4c7 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -586,10 +586,16 @@ namespace tunnel auto typeID = msg->GetTypeID (); LogPrint (eLogDebug, "Tunnel: Gateway of ", (int) len, " bytes for tunnel ", tunnel->GetTunnelID (), ", msg type ", (int)typeID); - if (IsRouterInfoMsg (msg) || typeID == eI2NPDatabaseSearchReply) - // transit DatabaseStore my contain new/updated RI - // or DatabaseSearchReply with new routers + if (typeID == eI2NPDatabaseSearchReply) + // DatabaseSearchReply with new routers i2p::data::netdb.PostI2NPMsg (CopyI2NPMessage (msg)); + else if (IsRouterInfoMsg (msg)) + { + // transit DatabaseStore might contain new/updated RI + auto m = CopyI2NPMessage (msg); + memset (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0, 4); // no reply + i2p::data::netdb.PostI2NPMsg (m); + } tunnel->SendTunnelDataMsg (msg); } diff --git a/libi2pd/TunnelEndpoint.cpp b/libi2pd/TunnelEndpoint.cpp index 7d3b3cbe..f2d8a085 100644 --- a/libi2pd/TunnelEndpoint.cpp +++ b/libi2pd/TunnelEndpoint.cpp @@ -324,9 +324,17 @@ namespace tunnel uint8_t typeID = msg.data->GetTypeID (); LogPrint (eLogDebug, "TunnelMessage: Handle fragment of ", msg.data->GetLength (), " bytes, msg type ", (int)typeID); // catch RI or reply with new list of routers - if ((IsRouterInfoMsg (msg.data) || typeID == eI2NPDatabaseSearchReply) && - !m_IsInbound && msg.deliveryType != eDeliveryTypeLocal) - i2p::data::netdb.PostI2NPMsg (CopyI2NPMessage (msg.data)); + if (!m_IsInbound && msg.deliveryType != eDeliveryTypeLocal) + { + if (typeID == eI2NPDatabaseSearchReply) + i2p::data::netdb.PostI2NPMsg (CopyI2NPMessage (msg.data)); + else if (IsRouterInfoMsg (msg.data)) + { + auto m = CopyI2NPMessage (msg.data); + memset (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0, 4); // no reply + i2p::data::netdb.PostI2NPMsg (m); + } + } switch (msg.deliveryType) { From 786c27c8eca566bdbd57c429f1c1ad57a2147108 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 21 Apr 2023 22:27:55 -0400 Subject: [PATCH 0107/1171] publish encrypted RouterInfo --- libi2pd/RouterContext.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index d6c3c57b..3e7d7a2c 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -1348,8 +1348,12 @@ namespace i2p auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel (nullptr, floodfill->GetCompatibleTransports (false)) : nullptr; auto inbound = exploratoryPool ? exploratoryPool->GetNextInboundTunnel (nullptr, floodfill->GetCompatibleTransports (true)) : nullptr; if (inbound && outbound) - outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0, - CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken, inbound)); + { + // encrypt for floodfill + auto msg = CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken, inbound); + outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0, + i2p::garlic::WrapECIESX25519MessageForRouter (msg, floodfill->GetIdentity ()->GetEncryptionPublicKey ())); + } else LogPrint (eLogInfo, "Router: Can't publish our RouterInfo. No tunnles. Try again in ", ROUTER_INFO_CONFIRMATION_TIMEOUT, " seconds"); } From f21e1c75d571d52a1a880116d3c3f8e1501c9d59 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 23 Apr 2023 15:31:24 -0400 Subject: [PATCH 0108/1171] check tagset for null --- libi2pd/Garlic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index c351f6d6..3f885186 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -588,7 +588,7 @@ namespace garlic auto it = m_ECIESx25519Tags.find (tag); if (it != m_ECIESx25519Tags.end ()) { - if (it->second.tagset->HandleNextMessage (buf, len, it->second.index)) + if (it->second.tagset && it->second.tagset->HandleNextMessage (buf, len, it->second.index)) m_LastTagset = it->second.tagset; else LogPrint (eLogError, "Garlic: Can't handle ECIES-X25519-AEAD-Ratchet message"); From edfcd23b01c04b6b7cb1b29fd7cfe26acd13002c Mon Sep 17 00:00:00 2001 From: r4sas Date: Mon, 24 Apr 2023 14:01:21 +0300 Subject: [PATCH 0109/1171] [webconsole] added a button to prematurely release a leaseset Signed-off-by: r4sas --- daemon/HTTPServer.cpp | 52 +++++++++++++++++++++++++++++++++++++++---- libi2pd/LeaseSet.h | 3 +++ 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index dceee06a..f9b034ae 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -87,6 +87,7 @@ namespace http { const char HTTP_COMMAND_GET_REG_STRING[] = "get_reg_string"; const char HTTP_COMMAND_SETLANGUAGE[] = "setlanguage"; const char HTTP_COMMAND_RELOAD_CSS[] = "reload_css"; + const char HTTP_COMMAND_EXPIRELEASE[] = "expirelease"; static std::string ConvertTime (uint64_t time) { @@ -434,12 +435,11 @@ namespace http { if (dest->IsPublic() && token && !dest->IsEncryptedLeaseSet ()) { std::string webroot; i2p::config::GetOption("http.webroot", webroot); - auto base32 = dest->GetIdentHash ().ToBase32 (); s << "
\r\n\r\n
\r\n" "\r\n" " \r\n" " \r\n" - " \r\n" + " GetIdentHash ().ToBase32 () << "\">\r\n" " " << tr("Domain") << ":\r\n\r\n" " \r\n" "\r\n" << tr("Note: result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.") << "\r\n
\r\n
\r\n
\r\n"; @@ -448,9 +448,23 @@ namespace http { if (dest->GetNumRemoteLeaseSets()) { s << "
\r\n\r\n
\r\n"; + << "\r\n\r\n
\r\n" + << "
"<< tr("Address") << "" << tr("Type") << "" << tr("EncType") << "
" + << "" + << "" // LeaseSet expiration button column + << "" + << "" + << ""; for(auto& it: dest->GetLeaseSets ()) - s << "\r\n"; + { + s << "" + << "" + << "" + << "" + << "" + << "\r\n"; + } s << "
" << tr("Address") << " " << tr("Type") << "" << tr("EncType") << "
" << it.first.ToBase32 () << "" << (int)it.second->GetStoreType () << "" << (int)it.second->GetEncryptionType () <<"
" << it.first.ToBase32 () << "" << (int)it.second->GetStoreType () << "" << (int)it.second->GetEncryptionType () <<"
\r\n
\r\n
\r\n
\r\n"; } else s << "" << tr("LeaseSets") << ": 0
\r\n
\r\n"; @@ -1312,6 +1326,36 @@ namespace http { res.add_header("Refresh", redirect.c_str()); return; } + else if (cmd == HTTP_COMMAND_EXPIRELEASE) + { + std::string b32 = params["b32"]; + std::string lease = params["lease"]; + + i2p::data::IdentHash ident, leaseident; + ident.FromBase32 (b32); + leaseident.FromBase32 (lease); + auto dest = i2p::client::context.FindLocalDestination (ident); + + if (dest) + { + auto leaseset = dest->FindLeaseSet (leaseident); + if (leaseset) + { + leaseset->ExpireLease (); + s << "" << tr("SUCCESS") << ": " << tr("LeaseSet expiration time updated") << "
\r\n
\r\n"; + } + else + s << "" << tr("ERROR") << ": " << tr("LeaseSet is not found or already expired") << "
\r\n
\r\n"; + } + else + s << "" << tr("ERROR") << ": " << tr("Destination not found") << "
\r\n
\r\n"; + + s << "" << tr("Return to destination page") << "
\r\n"; + s << "

" << tr("You will be redirected in %d seconds", COMMAND_REDIRECT_TIMEOUT) << ""; + redirect = std::to_string(COMMAND_REDIRECT_TIMEOUT) + "; url=" + webroot + "?page=local_destination&b32=" + b32; + res.add_header("Refresh", redirect.c_str()); + return; + } else if (cmd == HTTP_COMMAND_LIMITTRANSIT) { uint32_t limit = std::stoul(params["limit"], nullptr); diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index 566c4655..4b1311a5 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -96,6 +96,9 @@ namespace data void Encrypt (const uint8_t * data, uint8_t * encrypted) const; bool IsDestination () const { return true; }; + // used in webconsole + void ExpireLease () { m_ExpirationTime = i2p::util::GetSecondsSinceEpoch (); }; + protected: void UpdateLeasesBegin (); From 76adac31c3b8f717622e3b2d00bbc6cff90b1aa9 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 24 Apr 2023 19:25:26 -0400 Subject: [PATCH 0110/1171] enrcrypt lookup if being sent through a tunnel --- libi2pd/NetDb.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 1f9797f2..1abe9748 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -722,7 +722,11 @@ namespace data auto outbound = pool ? pool->GetNextOutboundTunnel (nullptr, floodfill->GetCompatibleTransports (false)) : nullptr; auto inbound = pool ? pool->GetNextInboundTunnel (nullptr, floodfill->GetCompatibleTransports (true)) : nullptr; if (outbound && inbound) - outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0, dest->CreateRequestMessage (floodfill, inbound)); + { + auto msg = dest->CreateRequestMessage (floodfill, inbound); + outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0, + i2p::garlic::WrapECIESX25519MessageForRouter (msg, floodfill->GetIdentity ()->GetEncryptionPublicKey ())); + } else { LogPrint (eLogError, "NetDb: ", destination.ToBase64(), " destination requested, but no tunnels found"); From 0ce15ffc91971a21bcf73adaf7c2f906a097a38f Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 26 Apr 2023 21:34:22 -0400 Subject: [PATCH 0111/1171] check for incomplete HTTP header --- libi2pd_client/I2PTunnel.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index 23a3ad52..d1006f26 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -397,7 +397,8 @@ namespace client while (!endOfHeader) { std::getline(m_InHeader, line); - if (!m_InHeader.fail ()) + if (m_InHeader.fail ()) break; + if (!m_InHeader.eof ()) { if (line == "\r") endOfHeader = true; else @@ -485,7 +486,8 @@ namespace client while (!endOfHeader) { std::getline(m_InHeader, line); - if (!m_InHeader.fail ()) + if (m_InHeader.fail ()) break; + if (!m_InHeader.eof ()) { if (line == "\r") endOfHeader = true; else From ead6a6dca35c7a4036bc775f1bfe215f6a866583 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 27 Apr 2023 21:37:30 -0400 Subject: [PATCH 0112/1171] correct parsing of caught RouterInfo at IBGW and OBEP --- libi2pd/NetDb.cpp | 25 ++++++++++++++----------- libi2pd/Tunnel.cpp | 2 +- libi2pd/TunnelEndpoint.cpp | 2 +- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 1abe9748..a271d459 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -791,20 +791,23 @@ namespace data LogPrint (eLogError, "NetDb: Database store msg with reply token is too short ", len, ". Dropped"); return; } - auto deliveryStatus = CreateDeliveryStatusMsg (replyToken); uint32_t tunnelID = bufbe32toh (buf + offset); offset += 4; - if (!tunnelID) // send response directly - transports.SendMessage (buf + offset, deliveryStatus); - else - { - auto pool = i2p::tunnel::tunnels.GetExploratoryPool (); - auto outbound = pool ? pool->GetNextOutboundTunnel () : nullptr; - if (outbound) - outbound->SendTunnelDataMsgTo (buf + offset, tunnelID, deliveryStatus); + if (replyToken != 0xFFFFFFFFU) // if not caught on OBEP or IBGW + { + auto deliveryStatus = CreateDeliveryStatusMsg (replyToken); + if (!tunnelID) // send response directly + transports.SendMessage (buf + offset, deliveryStatus); else - LogPrint (eLogWarning, "NetDb: No outbound tunnels for DatabaseStore reply found"); - } + { + auto pool = i2p::tunnel::tunnels.GetExploratoryPool (); + auto outbound = pool ? pool->GetNextOutboundTunnel () : nullptr; + if (outbound) + outbound->SendTunnelDataMsgTo (buf + offset, tunnelID, deliveryStatus); + else + LogPrint (eLogWarning, "NetDb: No outbound tunnels for DatabaseStore reply found"); + } + } offset += 32; } // we must send reply back before this check diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 76bdb4c7..bf1bad46 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -593,7 +593,7 @@ namespace tunnel { // transit DatabaseStore might contain new/updated RI auto m = CopyI2NPMessage (msg); - memset (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0, 4); // no reply + memset (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0xFF, 4); // fake replyToken meaning no reply i2p::data::netdb.PostI2NPMsg (m); } tunnel->SendTunnelDataMsg (msg); diff --git a/libi2pd/TunnelEndpoint.cpp b/libi2pd/TunnelEndpoint.cpp index f2d8a085..fe90da60 100644 --- a/libi2pd/TunnelEndpoint.cpp +++ b/libi2pd/TunnelEndpoint.cpp @@ -331,7 +331,7 @@ namespace tunnel else if (IsRouterInfoMsg (msg.data)) { auto m = CopyI2NPMessage (msg.data); - memset (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0, 4); // no reply + memset (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0xFF, 4); // fake replyToken meaning no reply i2p::data::netdb.PostI2NPMsg (m); } } From 2af4a2b58dcf39f26bcf775d1494e3ec350e1eaa Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 28 Apr 2023 08:01:02 -0400 Subject: [PATCH 0113/1171] override reply token only if non-zero --- libi2pd/Tunnel.cpp | 3 ++- libi2pd/TunnelEndpoint.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index bf1bad46..249f0a31 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -593,7 +593,8 @@ namespace tunnel { // transit DatabaseStore might contain new/updated RI auto m = CopyI2NPMessage (msg); - memset (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0xFF, 4); // fake replyToken meaning no reply + if (bufbe32toh (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET)) + memset (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0xFF, 4); // fake replyToken meaning no reply i2p::data::netdb.PostI2NPMsg (m); } tunnel->SendTunnelDataMsg (msg); diff --git a/libi2pd/TunnelEndpoint.cpp b/libi2pd/TunnelEndpoint.cpp index fe90da60..b2a0c837 100644 --- a/libi2pd/TunnelEndpoint.cpp +++ b/libi2pd/TunnelEndpoint.cpp @@ -331,7 +331,8 @@ namespace tunnel else if (IsRouterInfoMsg (msg.data)) { auto m = CopyI2NPMessage (msg.data); - memset (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0xFF, 4); // fake replyToken meaning no reply + if (bufbe32toh (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET)) + memset (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0xFF, 4); // fake replyToken meaning no reply i2p::data::netdb.PostI2NPMsg (m); } } From 7c535159bc442b2ad539c4eb22eda00b018cc47d Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 30 Apr 2023 20:05:35 -0400 Subject: [PATCH 0114/1171] static keys table --- libi2pd/NTCP2.cpp | 1 + libi2pd/Profiling.cpp | 28 ++++++++++++++++++++++++++++ libi2pd/Profiling.h | 4 ++++ libi2pd/SSU2Session.cpp | 1 + libi2pd/Transports.cpp | 15 +++++++++++++++ 5 files changed, 49 insertions(+) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 91bc9b3d..aceef0f5 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -714,6 +714,7 @@ namespace transport Terminate (); return; } + i2p::data::UpdateStaticKey (addr->s, ri.GetIdentHash ()); // good static key i2p::data::netdb.PostI2NPMsg (CreateI2NPMessage (eI2NPDummyMsg, buf.data () + 3, size)); // TODO: should insert ri and not parse it twice // TODO: process options diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index 311d1c86..3144bd9c 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -301,5 +301,33 @@ namespace data } } } + +// static keys + + struct StaticKeyProfile + { + i2p::data::IdentHash ident; + boost::posix_time::ptime lastUpdateTime; + }; + //static i2p::fs::HashedStorage g_StaticKeysProfilesStorage("statickeysProfiles", "s", "statickey-", "txt"); + static std::unordered_map, std::shared_ptr > g_StaticKeysProfiles; + static std::mutex g_StaticKeysProfilesMutex; + + bool CheckStaticKey (const i2p::data::Tag<32>& staticKey, const i2p::data::IdentHash& ident) + { + std::unique_lock l(g_StaticKeysProfilesMutex); + auto it = g_StaticKeysProfiles.find (staticKey); + if (it != g_StaticKeysProfiles.end ()) + return it->second->ident == ident; + return true; + } + + void UpdateStaticKey (const i2p::data::Tag<32>& staticKey, const i2p::data::IdentHash& ident) + { + std::unique_lock l(g_StaticKeysProfilesMutex); + auto res = g_StaticKeysProfiles.emplace (staticKey, std::make_shared(StaticKeyProfile{ident, GetTime ()})); + if (!res.second) + res.first->second->lastUpdateTime = GetTime (); + } } } diff --git a/libi2pd/Profiling.h b/libi2pd/Profiling.h index 752d6190..2f60f961 100644 --- a/libi2pd/Profiling.h +++ b/libi2pd/Profiling.h @@ -85,6 +85,10 @@ namespace data void DeleteObsoleteProfiles (); void SaveProfiles (); void PersistProfiles (); + + // static keys + bool CheckStaticKey (const i2p::data::Tag<32>& staticKey, const i2p::data::IdentHash& ident); + void UpdateStaticKey (const i2p::data::Tag<32>& staticKey, const i2p::data::IdentHash& ident); } } diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 47d59ea4..46319bd9 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1073,6 +1073,7 @@ namespace transport return false; } SetRemoteIdentity (ri->GetRouterIdentity ()); + i2p::data::UpdateStaticKey (m_Address->s, ri->GetIdentHash ()); // good static key AdjustMaxPayloadSize (); m_Server.AddSessionByRouterHash (shared_from_this ()); // we know remote router now m_RemoteTransports = ri->GetCompatibleTransports (false); diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index c6e9f372..5693719c 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -507,6 +507,11 @@ namespace transport peer.router->GetPublishedNTCP2V6Address () : peer.router->GetPublishedNTCP2V4Address (); if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host)) address = nullptr; + if (address && !i2p::data::CheckStaticKey (address->s, ident)) + { + LogPrint (eLogWarning, "Transports: NTCP2 address static key router mismatch ", ident.ToBase64 ()); + address = nullptr; + } if (address) { auto s = std::make_shared (*m_NTCP2Server, peer.router, address); @@ -526,6 +531,11 @@ namespace transport peer.router->GetSSU2V6Address () : peer.router->GetSSU2V4Address (); if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host)) address = nullptr; + if (address && !i2p::data::CheckStaticKey (address->s, ident)) + { + LogPrint (eLogWarning, "Transports: SSU2 address static key router mismatch ", ident.ToBase64 ()); + address = nullptr; + } if (address && address->IsReachableSSU ()) { if (m_SSU2Server->CreateSession (peer.router, address)) @@ -537,6 +547,11 @@ namespace transport { if (!m_NTCP2Server) continue; auto address = peer.router->GetYggdrasilAddress (); + if (address && !i2p::data::CheckStaticKey (address->s, ident)) + { + LogPrint (eLogWarning, "Transports: Yggdrasil address static key router mismatch ", ident.ToBase64 ()); + address = nullptr; + } if (address) { auto s = std::make_shared (*m_NTCP2Server, peer.router, address); From ec2297ed9dd87c1690ff0bce3565fbeee173b35f Mon Sep 17 00:00:00 2001 From: weko Date: Mon, 1 May 2023 19:28:32 +0000 Subject: [PATCH 0115/1171] Recognize invalid static key --- libi2pd/RouterInfo.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index c18e0521..9334ed60 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -362,6 +362,10 @@ namespace data } if (!s) return; } + + if (!i2p::data::CheckStaticKey(address->s, (*m_RouterIdentity).GetIdentHash())) + continue; // skip address + if (address->transportStyle == eTransportNTCP2) { if (isStaticKey) From dab34e90519062a0cc91e0ea5a0433e131d6acbd Mon Sep 17 00:00:00 2001 From: weko Date: Mon, 1 May 2023 20:08:08 +0000 Subject: [PATCH 0116/1171] get indent hash directly --- libi2pd/RouterInfo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 9334ed60..f72c3322 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -363,7 +363,7 @@ namespace data if (!s) return; } - if (!i2p::data::CheckStaticKey(address->s, (*m_RouterIdentity).GetIdentHash())) + if (!i2p::data::CheckStaticKey(address->s, GetIdentHash())) continue; // skip address if (address->transportStyle == eTransportNTCP2) From 7418f11651c9673b98bf5cc0b27301de08094a10 Mon Sep 17 00:00:00 2001 From: contextswap Date: Wed, 3 May 2023 19:04:16 +0900 Subject: [PATCH 0117/1171] limit aesni inline asm to x86 Signed-off-by: contextswap --- libi2pd/Crypto.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index c9670f6c..4a4d5ef4 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -555,7 +555,7 @@ namespace crypto } // AES -#ifdef __AES__ +#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) #define KeyExpansion256(round0,round1) \ "pshufd $0xff, %%xmm2, %%xmm2 \n" \ "movaps %%xmm1, %%xmm4 \n" \ @@ -580,7 +580,7 @@ namespace crypto "movaps %%xmm3, "#round1"(%[sched]) \n" #endif -#ifdef __AES__ +#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) void ECBCryptoAESNI::ExpandKey (const AESKey& key) { __asm__ @@ -621,7 +621,7 @@ namespace crypto #endif -#ifdef __AES__ +#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) #define EncryptAES256(sched) \ "pxor (%["#sched"]), %%xmm0 \n" \ "aesenc 16(%["#sched"]), %%xmm0 \n" \ @@ -642,7 +642,7 @@ namespace crypto void ECBEncryption::Encrypt (const ChipherBlock * in, ChipherBlock * out) { -#ifdef __AES__ +#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ @@ -660,7 +660,7 @@ namespace crypto } } -#ifdef __AES__ +#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) #define DecryptAES256(sched) \ "pxor 224(%["#sched"]), %%xmm0 \n" \ "aesdec 208(%["#sched"]), %%xmm0 \n" \ @@ -681,7 +681,7 @@ namespace crypto void ECBDecryption::Decrypt (const ChipherBlock * in, ChipherBlock * out) { -#ifdef __AES__ +#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ @@ -699,7 +699,7 @@ namespace crypto } } -#ifdef __AES__ +#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) #define CallAESIMC(offset) \ "movaps "#offset"(%[shed]), %%xmm0 \n" \ "aesimc %%xmm0, %%xmm0 \n" \ @@ -708,7 +708,7 @@ namespace crypto void ECBEncryption::SetKey (const AESKey& key) { -#ifdef __AES__ +#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { ExpandKey (key); @@ -722,7 +722,7 @@ namespace crypto void ECBDecryption::SetKey (const AESKey& key) { -#ifdef __AES__ +#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { ExpandKey (key); // expand encryption key first @@ -754,7 +754,7 @@ namespace crypto void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out) { -#ifdef __AES__ +#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ @@ -799,7 +799,7 @@ namespace crypto void CBCEncryption::Encrypt (const uint8_t * in, uint8_t * out) { -#ifdef __AES__ +#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ @@ -823,7 +823,7 @@ namespace crypto void CBCDecryption::Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out) { -#ifdef __AES__ +#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ @@ -869,7 +869,7 @@ namespace crypto void CBCDecryption::Decrypt (const uint8_t * in, uint8_t * out) { -#ifdef __AES__ +#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ @@ -893,7 +893,7 @@ namespace crypto void TunnelEncryption::Encrypt (const uint8_t * in, uint8_t * out) { -#ifdef __AES__ +#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ @@ -934,7 +934,7 @@ namespace crypto void TunnelDecryption::Decrypt (const uint8_t * in, uint8_t * out) { -#ifdef __AES__ +#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ From 12d0abda55d19ce87e6eedbb402961ba8b1c7fb6 Mon Sep 17 00:00:00 2001 From: contextswap Date: Wed, 3 May 2023 19:10:16 +0900 Subject: [PATCH 0118/1171] [ Signed-off-by: contextswap --- libi2pd/Crypto.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index 4a4d5ef4..4a78f2b1 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -555,7 +555,7 @@ namespace crypto } // AES -#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) +#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) #define KeyExpansion256(round0,round1) \ "pshufd $0xff, %%xmm2, %%xmm2 \n" \ "movaps %%xmm1, %%xmm4 \n" \ @@ -580,7 +580,7 @@ namespace crypto "movaps %%xmm3, "#round1"(%[sched]) \n" #endif -#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) +#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) void ECBCryptoAESNI::ExpandKey (const AESKey& key) { __asm__ @@ -621,7 +621,7 @@ namespace crypto #endif -#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) +#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) #define EncryptAES256(sched) \ "pxor (%["#sched"]), %%xmm0 \n" \ "aesenc 16(%["#sched"]), %%xmm0 \n" \ @@ -642,7 +642,7 @@ namespace crypto void ECBEncryption::Encrypt (const ChipherBlock * in, ChipherBlock * out) { -#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) +#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ @@ -660,7 +660,7 @@ namespace crypto } } -#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) +#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) #define DecryptAES256(sched) \ "pxor 224(%["#sched"]), %%xmm0 \n" \ "aesdec 208(%["#sched"]), %%xmm0 \n" \ @@ -681,7 +681,7 @@ namespace crypto void ECBDecryption::Decrypt (const ChipherBlock * in, ChipherBlock * out) { -#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) +#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ @@ -699,7 +699,7 @@ namespace crypto } } -#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) +#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) #define CallAESIMC(offset) \ "movaps "#offset"(%[shed]), %%xmm0 \n" \ "aesimc %%xmm0, %%xmm0 \n" \ @@ -708,7 +708,7 @@ namespace crypto void ECBEncryption::SetKey (const AESKey& key) { -#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) +#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { ExpandKey (key); @@ -722,7 +722,7 @@ namespace crypto void ECBDecryption::SetKey (const AESKey& key) { -#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) +#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { ExpandKey (key); // expand encryption key first @@ -754,7 +754,7 @@ namespace crypto void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out) { -#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) +#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ @@ -799,7 +799,7 @@ namespace crypto void CBCEncryption::Encrypt (const uint8_t * in, uint8_t * out) { -#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) +#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ @@ -823,7 +823,7 @@ namespace crypto void CBCDecryption::Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out) { -#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) +#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ @@ -869,7 +869,7 @@ namespace crypto void CBCDecryption::Decrypt (const uint8_t * in, uint8_t * out) { -#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) +#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ @@ -893,7 +893,7 @@ namespace crypto void TunnelEncryption::Encrypt (const uint8_t * in, uint8_t * out) { -#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) +#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ @@ -934,7 +934,7 @@ namespace crypto void TunnelDecryption::Decrypt (const uint8_t * in, uint8_t * out) { -#ifdef __AES__ && (defined(__x86_64__) || defined(__i386__)) +#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) if(i2p::cpu::aesni) { __asm__ From 4ce2ef1d8381c2d93ebcdd77e8017123ae3a23c3 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 3 May 2023 07:43:28 -0400 Subject: [PATCH 0119/1171] make router unreachable if AEAD fails in SessionCreated --- libi2pd/NTCP2.cpp | 4 ++++ libi2pd/NetDb.cpp | 2 +- libi2pd/SSU2Session.cpp | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index aceef0f5..3f80bcd2 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -566,7 +566,11 @@ namespace transport SendSessionConfirmed (); } else + { + if (GetRemoteIdentity ()) + i2p::data::netdb.SetUnreachable (GetRemoteIdentity ()->GetIdentHash (), true); // assume wrong s key Terminate (); + } } } diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index a271d459..d3346236 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -607,7 +607,7 @@ namespace data uint64_t expirationTimeout = NETDB_MAX_EXPIRATION_TIMEOUT*1000LL; uint64_t ts = i2p::util::GetMillisecondsSinceEpoch(); auto uptime = i2p::context.GetUptime (); - bool isLowRate = i2p::tunnel::tunnels.GetTunnelCreationSuccessRate () < NETDB_MIN_TUNNEL_CREATION_SUCCESS_RATE; + bool isLowRate = false; // i2p::tunnel::tunnels.GetTunnelCreationSuccessRate () < NETDB_MIN_TUNNEL_CREATION_SUCCESS_RATE; // routers don't expire if less than 90 or uptime is less than 1 hour bool checkForExpiration = total > NETDB_MIN_ROUTERS && uptime > 600; // 10 minutes if (checkForExpiration && uptime > 3600) // 1 hour diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 46319bd9..9bfa4ce0 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -809,6 +809,8 @@ namespace transport m_NoiseState->m_CK + 32, nonce, decryptedPayload.data (), decryptedPayload.size (), false)) { LogPrint (eLogWarning, "SSU2: SessionCreated AEAD verification failed "); + if (GetRemoteIdentity ()) + i2p::data::netdb.SetUnreachable (GetRemoteIdentity ()->GetIdentHash (), true); // assume wrong s key return false; } m_NoiseState->MixHash (payload, len - 64); // h = SHA256(h || encrypted payload from SessionCreated) for SessionConfirmed From 3b13a3f2a1f177f1caf0614c574c5d4c3936df39 Mon Sep 17 00:00:00 2001 From: SidorKozlov Date: Wed, 3 May 2023 15:59:35 +0200 Subject: [PATCH 0120/1171] Configurable minimum successful tunnels --- libi2pd/Config.cpp | 1 + libi2pd/NetDb.cpp | 56 ++++++++++++++++++++++++---------------------- libi2pd/NetDb.hpp | 1 - libi2pd/Tunnel.h | 9 ++++---- 4 files changed, 35 insertions(+), 32 deletions(-) diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 39af997b..6b515ef9 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -78,6 +78,7 @@ namespace config { ("limits.coresize", value()->default_value(0), "Maximum size of corefile in Kb (0 - use system limit)") ("limits.openfiles", value()->default_value(0), "Maximum number of open files (0 - use system default)") ("limits.transittunnels", value()->default_value(5000), "Maximum active transit tunnels (default:5000)") + ("limits.zombies", value()->default_value(0), "Minimum percentage of successfully created tunnels under which tunnel cleanup is paused (default [%]: 0.00)") ("limits.ntcpsoft", value()->default_value(0), "Ignored") ("limits.ntcphard", value()->default_value(0), "Ignored") ("limits.ntcpthreads", value()->default_value(1), "Ignored") diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index d3346236..aea97adc 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -245,19 +245,19 @@ namespace data updated = false; m_Requests.RequestComplete (ident, r); return r; - } + } if (r->IsUnreachable ()) { // delete router as invalid after update m_RouterInfos.erase (ident); if (wasFloodfill) - { + { std::unique_lock l(m_FloodfillsMutex); m_Floodfills.Remove (r->GetIdentHash ()); - } + } m_Requests.RequestComplete (ident, nullptr); - return nullptr; - } + return nullptr; + } } LogPrint (eLogInfo, "NetDb: RouterInfo updated: ", ident.ToBase64()); if (wasFloodfill != r->IsFloodfill ()) // if floodfill status updated @@ -419,7 +419,7 @@ namespace data if (profile) profile->Unreachable (); } - } + } } void NetDb::ExcludeReachableTransports (const IdentHash& ident, RouterInfo::CompatibleTransports transports) @@ -429,9 +429,9 @@ namespace data { std::unique_lock l(m_RouterInfosMutex); r->ExcludeReachableTransports (transports); - } - } - + } + } + void NetDb::Reseed () { if (!m_Reseeder) @@ -607,7 +607,9 @@ namespace data uint64_t expirationTimeout = NETDB_MAX_EXPIRATION_TIMEOUT*1000LL; uint64_t ts = i2p::util::GetMillisecondsSinceEpoch(); auto uptime = i2p::context.GetUptime (); - bool isLowRate = false; // i2p::tunnel::tunnels.GetTunnelCreationSuccessRate () < NETDB_MIN_TUNNEL_CREATION_SUCCESS_RATE; + double minTunnelCreationSuccessRate; + i2p::config::GetOption("limits.zombies", minTunnelCreationSuccessRate); + bool isLowRate = i2p::tunnel::tunnels.GetPreciseTunnelCreationSuccessRate () < minTunnelCreationSuccessRate; // routers don't expire if less than 90 or uptime is less than 1 hour bool checkForExpiration = total > NETDB_MIN_ROUTERS && uptime > 600; // 10 minutes if (checkForExpiration && uptime > 3600) // 1 hour @@ -622,12 +624,12 @@ namespace data if (it.second->IsUpdated ()) { if (it.second->GetBuffer ()) - { + { // we have something to save it.second->SaveToFile (m_Storage.Path(ident)); it.second->SetUnreachable (false); it.second->DeleteBuffer (); - } + } it.second->SetUpdated (false); updatedCount++; continue; @@ -639,7 +641,7 @@ namespace data (it.second->IsFloodfill () && totalFloodfills - deletedFloodfillsCount < NETDB_MIN_FLOODFILLS))) it.second->SetUnreachable (false); if (!it.second->IsUnreachable ()) - { + { // find & mark expired routers if (!it.second->GetCompatibleTransports (true)) // non reachable by any transport it.second->SetUnreachable (true); @@ -652,7 +654,7 @@ namespace data } if (it.second->IsUnreachable () && i2p::transport::transports.IsConnected (it.second->GetIdentHash ())) it.second->SetUnreachable (false); // don't expire connected router - } + } if (it.second->IsUnreachable ()) { @@ -667,7 +669,7 @@ namespace data m_RouterInfoBuffersPool.CleanUpMt (); m_RouterInfoAddressesPool.CleanUpMt (); m_RouterInfoAddressVectorsPool.CleanUpMt (); - m_IdentitiesPool.CleanUpMt (); + m_IdentitiesPool.CleanUpMt (); if (updatedCount > 0) LogPrint (eLogInfo, "NetDb: Saved ", updatedCount, " new/updated routers"); @@ -682,10 +684,10 @@ namespace data if (it->second->IsUnreachable ()) it = m_RouterInfos.erase (it); else - { + { it->second->DropProfile (); it++; - } + } } } // clean up expired floodfills or not floodfills anymore @@ -724,9 +726,9 @@ namespace data if (outbound && inbound) { auto msg = dest->CreateRequestMessage (floodfill, inbound); - outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0, + outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0, i2p::garlic::WrapECIESX25519MessageForRouter (msg, floodfill->GetIdentity ()->GetEncryptionPublicKey ())); - } + } else { LogPrint (eLogError, "NetDb: ", destination.ToBase64(), " destination requested, but no tunnels found"); @@ -794,7 +796,7 @@ namespace data uint32_t tunnelID = bufbe32toh (buf + offset); offset += 4; if (replyToken != 0xFFFFFFFFU) // if not caught on OBEP or IBGW - { + { auto deliveryStatus = CreateDeliveryStatusMsg (replyToken); if (!tunnelID) // send response directly transports.SendMessage (buf + offset, deliveryStatus); @@ -807,7 +809,7 @@ namespace data else LogPrint (eLogWarning, "NetDb: No outbound tunnels for DatabaseStore reply found"); } - } + } offset += 32; } // we must send reply back before this check @@ -1315,16 +1317,16 @@ namespace data return r && !r->IsUnreachable () && !r->GetProfile ()->IsUnreachable () && !excluded.count (r->GetIdentHash ()); }); - } + } if (v.empty ()) return res; - + XORMetric ourMetric; if (closeThanUsOnly) ourMetric = destKey ^ i2p::context.GetIdentHash (); for (auto& it: v) { if (closeThanUsOnly && ourMetric < (destKey ^ it->GetIdentHash ())) break; res.push_back (it->GetIdentHash ()); - } + } return res; } @@ -1367,10 +1369,10 @@ namespace data std::unique_lock l(m_RouterInfosMutex); for (auto& it: m_RouterInfos) it.second->UpdateIntroducers (ts); - } + } SaveUpdated (); - } - + } + void NetDb::ManageLeaseSets () { auto ts = i2p::util::GetMillisecondsSinceEpoch (); diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index b6dc8ce7..0222de0d 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -38,7 +38,6 @@ namespace data { const int NETDB_MIN_ROUTERS = 90; const int NETDB_MIN_FLOODFILLS = 5; - const int NETDB_MIN_TUNNEL_CREATION_SUCCESS_RATE = 8; // in percents const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60 * 60; // 1 hour, in seconds const int NETDB_MIN_EXPIRATION_TIMEOUT = 90 * 60; // 1.5 hours const int NETDB_MAX_EXPIRATION_TIMEOUT = 27 * 60 * 60; // 27 hours diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index 5810a7a8..e6e3c3a5 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -45,7 +45,7 @@ namespace tunnel const int TUNNEL_MANAGE_INTERVAL = 15; // in seconds const int TUNNEL_POOLS_MANAGE_INTERVAL = 5; // in seconds const int TUNNEL_MEMORY_POOL_MANAGE_INTERVAL = 120; // in seconds - + const size_t I2NP_TUNNEL_MESSAGE_SIZE = TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + 34; // reserved for alignment and NTCP 16 + 6 + 12 const size_t I2NP_TUNNEL_ENPOINT_MESSAGE_SIZE = 2*TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE + 28; // reserved for alignment and NTCP 16 + 6 + 6 @@ -232,8 +232,8 @@ namespace tunnel void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels); uint16_t GetMaxNumTransitTunnels () const { return m_MaxNumTransitTunnels; }; - bool IsTooManyTransitTunnels () const { return m_TransitTunnels.size () >= m_MaxNumTransitTunnels; }; - + bool IsTooManyTransitTunnels () const { return m_TransitTunnels.size () >= m_MaxNumTransitTunnels; }; + private: template @@ -292,7 +292,7 @@ namespace tunnel i2p::util::Queue > m_Queue; i2p::util::MemoryPoolMt > m_I2NPTunnelEndpointMessagesMemoryPool; i2p::util::MemoryPoolMt > m_I2NPTunnelMessagesMemoryPool; - uint16_t m_MaxNumTransitTunnels; + uint16_t m_MaxNumTransitTunnels; // count of tunnels for total TCSR algorithm int m_TotalNumSuccesiveTunnelCreations, m_TotalNumFailedTunnelCreations; double m_TunnelCreationSuccessRate; @@ -311,6 +311,7 @@ namespace tunnel int GetQueueSize () { return m_Queue.GetSize (); }; int GetTunnelCreationSuccessRate () const { return std::round(m_TunnelCreationSuccessRate * 100); } // in percents + double GetPreciseTunnelCreationSuccessRate () const { return m_TunnelCreationSuccessRate * 100; } // in percents int GetTotalTunnelCreationSuccessRate () const // in percents { int totalNum = m_TotalNumSuccesiveTunnelCreations + m_TotalNumFailedTunnelCreations; From 1bd6390f7801addfa9e4d2a80c864afa8c9e0b03 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 4 May 2023 08:20:38 -0400 Subject: [PATCH 0121/1171] check if s is x25519 public key --- libi2pd/RouterInfo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index f72c3322..7f8abec3 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -363,7 +363,7 @@ namespace data if (!s) return; } - if (!i2p::data::CheckStaticKey(address->s, GetIdentHash())) + if ((address->s[31] & 0x80) || !i2p::data::CheckStaticKey(address->s, GetIdentHash())) continue; // skip address if (address->transportStyle == eTransportNTCP2) From c1168c2aa0f3dec34aa2a1c35d9bf45e0d14443e Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 4 May 2023 09:39:37 -0400 Subject: [PATCH 0122/1171] don't catch RouterInfo at OBEP --- libi2pd/TunnelEndpoint.cpp | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/libi2pd/TunnelEndpoint.cpp b/libi2pd/TunnelEndpoint.cpp index b2a0c837..3dc0dc07 100644 --- a/libi2pd/TunnelEndpoint.cpp +++ b/libi2pd/TunnelEndpoint.cpp @@ -323,20 +323,7 @@ namespace tunnel } uint8_t typeID = msg.data->GetTypeID (); LogPrint (eLogDebug, "TunnelMessage: Handle fragment of ", msg.data->GetLength (), " bytes, msg type ", (int)typeID); - // catch RI or reply with new list of routers - if (!m_IsInbound && msg.deliveryType != eDeliveryTypeLocal) - { - if (typeID == eI2NPDatabaseSearchReply) - i2p::data::netdb.PostI2NPMsg (CopyI2NPMessage (msg.data)); - else if (IsRouterInfoMsg (msg.data)) - { - auto m = CopyI2NPMessage (msg.data); - if (bufbe32toh (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET)) - memset (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0xFF, 4); // fake replyToken meaning no reply - i2p::data::netdb.PostI2NPMsg (m); - } - } - + switch (msg.deliveryType) { case eDeliveryTypeLocal: From 2f74e670a5948c6318c685d62fed2fcc9b53ed46 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 4 May 2023 15:32:19 -0400 Subject: [PATCH 0123/1171] invalidate routers with incorrect family signature --- libi2pd/RouterInfo.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 7f8abec3..0cf5a0c5 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -487,7 +487,10 @@ namespace data if (netdb.GetFamilies ().VerifyFamily (family, GetIdentHash (), value)) m_FamilyID = netdb.GetFamilies ().GetFamilyID (family); else + { LogPrint (eLogWarning, "RouterInfo: Family ", family, " signature verification failed"); + SetUnreachable (true); + } } if (!s) return; From b6de474fdafbfffe020852d4db95a1aaf81885f8 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 5 May 2023 16:14:54 -0400 Subject: [PATCH 0124/1171] don't include unconfirmed floodfill to the list if we have enough floodfills already --- libi2pd/NTCP2.cpp | 1 + libi2pd/NetDb.cpp | 6 ++++-- libi2pd/NetDb.hpp | 1 + libi2pd/Profiling.cpp | 10 +++++++++- libi2pd/Profiling.h | 6 +++++- libi2pd/SSU2Session.cpp | 1 + 6 files changed, 21 insertions(+), 4 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 3f80bcd2..be584eb1 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -718,6 +718,7 @@ namespace transport Terminate (); return; } + ri.GetProfile ()->Connected (); i2p::data::UpdateStaticKey (addr->s, ri.GetIdentHash ()); // good static key i2p::data::netdb.PostI2NPMsg (CreateI2NPMessage (eI2NPDummyMsg, buf.data () + 3, size)); // TODO: should insert ri and not parse it twice // TODO: process options diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index aea97adc..3575b052 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -290,8 +290,10 @@ namespace data if (inserted) { LogPrint (eLogInfo, "NetDb: RouterInfo added: ", ident.ToBase64()); - if (r->IsFloodfill () && r->IsEligibleFloodfill ()) - { + if (r->IsFloodfill () && r->IsEligibleFloodfill () && + (m_Floodfills.GetSize () < NETDB_NUM_FLOODFILLS_THRESHOLD || + r->GetProfile ()->IsReal ())) // don't insert floodfill until it's known real if we have enough + { std::unique_lock l(m_FloodfillsMutex); m_Floodfills.Insert (r); } diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index 0222de0d..4aa69d59 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -38,6 +38,7 @@ namespace data { const int NETDB_MIN_ROUTERS = 90; const int NETDB_MIN_FLOODFILLS = 5; + const int NETDB_NUM_FLOODFILLS_THRESHOLD = 1000; const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60 * 60; // 1 hour, in seconds const int NETDB_MIN_EXPIRATION_TIMEOUT = 90 * 60; // 1.5 hours const int NETDB_MAX_EXPIRATION_TIMEOUT = 27 * 60 * 60; // 27 hours diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index 3144bd9c..d20e48b9 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -35,7 +35,7 @@ namespace data m_LastUpdateTime (GetTime ()), m_IsUpdated (false), m_LastDeclineTime (0), m_LastUnreachableTime (0), m_NumTunnelsAgreed (0), m_NumTunnelsDeclined (0), m_NumTunnelsNonReplied (0), - m_NumTimesTaken (0), m_NumTimesRejected (0) + m_NumTimesTaken (0), m_NumTimesRejected (0), m_HasConnected (false) { } @@ -52,6 +52,7 @@ namespace data participation.put (PEER_PROFILE_PARTICIPATION_AGREED, m_NumTunnelsAgreed); participation.put (PEER_PROFILE_PARTICIPATION_DECLINED, m_NumTunnelsDeclined); participation.put (PEER_PROFILE_PARTICIPATION_NON_REPLIED, m_NumTunnelsNonReplied); + participation.put (PEER_PROFILE_USAGE_CONNECTED, m_HasConnected); boost::property_tree::ptree usage; usage.put (PEER_PROFILE_USAGE_TAKEN, m_NumTimesTaken); usage.put (PEER_PROFILE_USAGE_REJECTED, m_NumTimesRejected); @@ -112,6 +113,7 @@ namespace data m_NumTunnelsAgreed = participations.get (PEER_PROFILE_PARTICIPATION_AGREED, 0); m_NumTunnelsDeclined = participations.get (PEER_PROFILE_PARTICIPATION_DECLINED, 0); m_NumTunnelsNonReplied = participations.get (PEER_PROFILE_PARTICIPATION_NON_REPLIED, 0); + m_HasConnected = participations.get (PEER_PROFILE_USAGE_CONNECTED, false); } catch (boost::property_tree::ptree_bad_path& ex) { @@ -167,6 +169,12 @@ namespace data UpdateTime (); } + void RouterProfile::Connected () + { + m_HasConnected = true; + UpdateTime (); + } + bool RouterProfile::IsLowPartcipationRate () const { return 4*m_NumTunnelsAgreed < m_NumTunnelsDeclined; // < 20% rate diff --git a/libi2pd/Profiling.h b/libi2pd/Profiling.h index 2f60f961..08721bec 100644 --- a/libi2pd/Profiling.h +++ b/libi2pd/Profiling.h @@ -28,7 +28,8 @@ namespace data const char PEER_PROFILE_PARTICIPATION_NON_REPLIED[] = "nonreplied"; const char PEER_PROFILE_USAGE_TAKEN[] = "taken"; const char PEER_PROFILE_USAGE_REJECTED[] = "rejected"; - + const char PEER_PROFILE_USAGE_CONNECTED[] = "connected"; + const int PEER_PROFILE_EXPIRATION_TIMEOUT = 36; // in hours (1.5 days) const int PEER_PROFILE_AUTOCLEAN_TIMEOUT = 6 * 3600; // in seconds (6 hours) const int PEER_PROFILE_AUTOCLEAN_VARIANCE = 3600; // in seconds (1 hour) @@ -48,11 +49,13 @@ namespace data bool IsBad (); bool IsUnreachable (); + bool IsReal () const { return m_HasConnected || m_NumTunnelsAgreed > 0 || m_NumTunnelsDeclined > 0; } void TunnelBuildResponse (uint8_t ret); void TunnelNonReplied (); void Unreachable (); + void Connected (); boost::posix_time::ptime GetLastUpdateTime () const { return m_LastUpdateTime; }; bool IsUpdated () const { return m_IsUpdated; }; @@ -78,6 +81,7 @@ namespace data // usage uint32_t m_NumTimesTaken; uint32_t m_NumTimesRejected; + bool m_HasConnected; // incoming connection received }; std::shared_ptr GetRouterProfile (const IdentHash& identHash); diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 9bfa4ce0..efe7117d 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1075,6 +1075,7 @@ namespace transport return false; } SetRemoteIdentity (ri->GetRouterIdentity ()); + ri->GetProfile ()->Connected (); i2p::data::UpdateStaticKey (m_Address->s, ri->GetIdentHash ()); // good static key AdjustMaxPayloadSize (); m_Server.AddSessionByRouterHash (shared_from_this ()); // we know remote router now From 7646147ed26319e6dd64697f6fd7663921cfefc9 Mon Sep 17 00:00:00 2001 From: weko Date: Fri, 5 May 2023 21:30:44 +0000 Subject: [PATCH 0125/1171] save only non-default peer profile --- libi2pd/Profiling.cpp | 14 +++++++++----- libi2pd/Profiling.h | 4 ++++ libi2pd/RouterInfo.cpp | 4 ++++ 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index d20e48b9..63d39004 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -35,7 +35,7 @@ namespace data m_LastUpdateTime (GetTime ()), m_IsUpdated (false), m_LastDeclineTime (0), m_LastUnreachableTime (0), m_NumTunnelsAgreed (0), m_NumTunnelsDeclined (0), m_NumTunnelsNonReplied (0), - m_NumTimesTaken (0), m_NumTimesRejected (0), m_HasConnected (false) + m_NumTimesTaken (0), m_NumTimesRejected (0), m_HasConnected (false), m_IsUseful (0) { } @@ -145,22 +145,25 @@ namespace data UpdateTime (); if (ret > 0) { - m_NumTunnelsDeclined++; + if (++m_NumTunnelsDeclined > PEER_PROFILE_USEFUL_THRESHOLD) m_IsUseful = true; m_LastDeclineTime = i2p::util::GetSecondsSinceEpoch (); } else { - m_NumTunnelsAgreed++; + if (++m_NumTunnelsAgreed > PEER_PROFILE_USEFUL_THRESHOLD) m_IsUseful = true; m_LastDeclineTime = 0; } } void RouterProfile::TunnelNonReplied () { - m_NumTunnelsNonReplied++; + if (++m_NumTunnelsNonReplied > PEER_PROFILE_USEFUL_THRESHOLD) m_IsUseful = true; UpdateTime (); if (m_NumTunnelsNonReplied > 2*m_NumTunnelsAgreed && m_NumTunnelsNonReplied > 3) + { m_LastDeclineTime = i2p::util::GetSecondsSinceEpoch (); + m_IsUseful = true; + } } void RouterProfile::Unreachable () @@ -206,6 +209,7 @@ namespace data m_NumTunnelsAgreed = 0; m_NumTunnelsDeclined = 0; m_NumTunnelsNonReplied = 0; + m_IsUseful = false; isBad = false; } if (isBad) m_NumTimesRejected++; else m_NumTimesTaken++; @@ -275,7 +279,7 @@ namespace data } auto ts = GetTime (); for (auto& it: tmp) - if (it.second->IsUpdated () && (ts - it.second->GetLastUpdateTime ()).total_seconds () < PEER_PROFILE_EXPIRATION_TIMEOUT*3600) + if (it.second->IsUseful() && it.second->IsUpdated () && (ts - it.second->GetLastUpdateTime ()).total_seconds () < PEER_PROFILE_EXPIRATION_TIMEOUT*3600) it.second->Save (it.first); } diff --git a/libi2pd/Profiling.h b/libi2pd/Profiling.h index 08721bec..c8654805 100644 --- a/libi2pd/Profiling.h +++ b/libi2pd/Profiling.h @@ -36,6 +36,7 @@ namespace data const int PEER_PROFILE_DECLINED_RECENTLY_INTERVAL = 150; // in seconds (2.5 minutes) const int PEER_PROFILE_PERSIST_INTERVAL = 3300; // in seconds (55 minutes) const int PEER_PROFILE_UNREACHABLE_INTERVAL = 2*3600; // on seconds (2 hours) + const int PEER_PROFILE_USEFUL_THRESHOLD = 3; class RouterProfile { @@ -59,6 +60,7 @@ namespace data boost::posix_time::ptime GetLastUpdateTime () const { return m_LastUpdateTime; }; bool IsUpdated () const { return m_IsUpdated; }; + bool IsUseful() const { return m_IsUseful; }; private: @@ -82,6 +84,8 @@ namespace data uint32_t m_NumTimesTaken; uint32_t m_NumTimesRejected; bool m_HasConnected; // incoming connection received + // is need to be saved + bool m_IsUseful; }; std::shared_ptr GetRouterProfile (const IdentHash& identHash); diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 0cf5a0c5..3352f262 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -363,7 +363,11 @@ namespace data if (!s) return; } +<<<<<<< HEAD if ((address->s[31] & 0x80) || !i2p::data::CheckStaticKey(address->s, GetIdentHash())) +======= + if (!i2p::data::CheckStaticKey(address->s, GetIdentHash())) +>>>>>>> 146e446b (save only non-default peer profile) continue; // skip address if (address->transportStyle == eTransportNTCP2) From 8fcab7b0c1c832d2c5dabce6b272cf3048d9ce8a Mon Sep 17 00:00:00 2001 From: weko Date: Fri, 5 May 2023 21:55:31 +0000 Subject: [PATCH 0126/1171] fix incorrect merge conflict resolve --- libi2pd/RouterInfo.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 3352f262..0cf5a0c5 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -363,11 +363,7 @@ namespace data if (!s) return; } -<<<<<<< HEAD if ((address->s[31] & 0x80) || !i2p::data::CheckStaticKey(address->s, GetIdentHash())) -======= - if (!i2p::data::CheckStaticKey(address->s, GetIdentHash())) ->>>>>>> 146e446b (save only non-default peer profile) continue; // skip address if (address->transportStyle == eTransportNTCP2) From c757b6d0201f7353807136f7ff07dde070c34c89 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 5 May 2023 18:22:11 -0400 Subject: [PATCH 0127/1171] reset floodfill cap for unknown floodfills --- libi2pd/NetDb.cpp | 21 +++++++++++++++------ libi2pd/RouterInfo.h | 1 + 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 3575b052..18b6694b 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -267,7 +267,12 @@ namespace data if (wasFloodfill) m_Floodfills.Remove (r->GetIdentHash ()); else if (r->IsEligibleFloodfill ()) - m_Floodfills.Insert (r); + { + if (m_Floodfills.GetSize () < NETDB_NUM_FLOODFILLS_THRESHOLD || r->GetProfile ()->IsReal ()) + m_Floodfills.Insert (r); + else + r->ResetFlooldFill (); + } } } else @@ -290,12 +295,16 @@ namespace data if (inserted) { LogPrint (eLogInfo, "NetDb: RouterInfo added: ", ident.ToBase64()); - if (r->IsFloodfill () && r->IsEligibleFloodfill () && - (m_Floodfills.GetSize () < NETDB_NUM_FLOODFILLS_THRESHOLD || - r->GetProfile ()->IsReal ())) // don't insert floodfill until it's known real if we have enough + if (r->IsFloodfill () && r->IsEligibleFloodfill ()) { - std::unique_lock l(m_FloodfillsMutex); - m_Floodfills.Insert (r); + if (m_Floodfills.GetSize () < NETDB_NUM_FLOODFILLS_THRESHOLD || + r->GetProfile ()->IsReal ()) // don't insert floodfill until it's known real if we have enough + { + std::unique_lock l(m_FloodfillsMutex); + m_Floodfills.Insert (r); + } + else + r->ResetFlooldFill (); } } else diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 35737c9b..47ee1dae 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -224,6 +224,7 @@ namespace data void UpdateSupportedTransports (); void UpdateIntroducers (uint64_t ts); // ts in seconds bool IsFloodfill () const { return m_Caps & Caps::eFloodfill; }; + void ResetFlooldFill () { m_Caps &= ~Caps::eFloodfill; }; bool IsECIES () const { return m_RouterIdentity->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD; }; bool IsNTCP2 (bool v4only = true) const; bool IsNTCP2V6 () const { return m_SupportedTransports & eNTCP2V6; }; From 2e2cbe7803d2e324d882fba4aa55a9557feadc3b Mon Sep 17 00:00:00 2001 From: weko Date: Fri, 5 May 2023 22:46:48 +0000 Subject: [PATCH 0128/1171] save profile if has connected --- libi2pd/Profiling.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index 63d39004..a290aa0a 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -175,6 +175,7 @@ namespace data void RouterProfile::Connected () { m_HasConnected = true; + m_IsUseful = true; UpdateTime (); } @@ -209,7 +210,8 @@ namespace data m_NumTunnelsAgreed = 0; m_NumTunnelsDeclined = 0; m_NumTunnelsNonReplied = 0; - m_IsUseful = false; + // we do not reset m_HasConnected here + // m_IsUseful = false; isBad = false; } if (isBad) m_NumTimesRejected++; else m_NumTimesTaken++; From e068a3cf22089484cff82af0649cf9dad4d3edd8 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 5 May 2023 19:58:58 -0400 Subject: [PATCH 0129/1171] store 'connected' in 'usage' section --- libi2pd/Profiling.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index d20e48b9..b3617db5 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -52,10 +52,10 @@ namespace data participation.put (PEER_PROFILE_PARTICIPATION_AGREED, m_NumTunnelsAgreed); participation.put (PEER_PROFILE_PARTICIPATION_DECLINED, m_NumTunnelsDeclined); participation.put (PEER_PROFILE_PARTICIPATION_NON_REPLIED, m_NumTunnelsNonReplied); - participation.put (PEER_PROFILE_USAGE_CONNECTED, m_HasConnected); boost::property_tree::ptree usage; usage.put (PEER_PROFILE_USAGE_TAKEN, m_NumTimesTaken); usage.put (PEER_PROFILE_USAGE_REJECTED, m_NumTimesRejected); + usage.put (PEER_PROFILE_USAGE_CONNECTED, m_HasConnected); // fill property tree boost::property_tree::ptree pt; pt.put (PEER_PROFILE_LAST_UPDATE_TIME, boost::posix_time::to_simple_string (m_LastUpdateTime)); @@ -113,7 +113,6 @@ namespace data m_NumTunnelsAgreed = participations.get (PEER_PROFILE_PARTICIPATION_AGREED, 0); m_NumTunnelsDeclined = participations.get (PEER_PROFILE_PARTICIPATION_DECLINED, 0); m_NumTunnelsNonReplied = participations.get (PEER_PROFILE_PARTICIPATION_NON_REPLIED, 0); - m_HasConnected = participations.get (PEER_PROFILE_USAGE_CONNECTED, false); } catch (boost::property_tree::ptree_bad_path& ex) { @@ -125,6 +124,7 @@ namespace data auto usage = pt.get_child (PEER_PROFILE_SECTION_USAGE); m_NumTimesTaken = usage.get (PEER_PROFILE_USAGE_TAKEN, 0); m_NumTimesRejected = usage.get (PEER_PROFILE_USAGE_REJECTED, 0); + m_HasConnected = usage.get (PEER_PROFILE_USAGE_CONNECTED, false); } catch (boost::property_tree::ptree_bad_path& ex) { From 3bc56ba4238e458889860c4f7a7b256e6f300312 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 5 May 2023 19:58:58 -0400 Subject: [PATCH 0130/1171] store 'connected' in 'usage' section --- libi2pd/Profiling.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index a290aa0a..dc11df4a 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -52,10 +52,10 @@ namespace data participation.put (PEER_PROFILE_PARTICIPATION_AGREED, m_NumTunnelsAgreed); participation.put (PEER_PROFILE_PARTICIPATION_DECLINED, m_NumTunnelsDeclined); participation.put (PEER_PROFILE_PARTICIPATION_NON_REPLIED, m_NumTunnelsNonReplied); - participation.put (PEER_PROFILE_USAGE_CONNECTED, m_HasConnected); boost::property_tree::ptree usage; usage.put (PEER_PROFILE_USAGE_TAKEN, m_NumTimesTaken); usage.put (PEER_PROFILE_USAGE_REJECTED, m_NumTimesRejected); + usage.put (PEER_PROFILE_USAGE_CONNECTED, m_HasConnected); // fill property tree boost::property_tree::ptree pt; pt.put (PEER_PROFILE_LAST_UPDATE_TIME, boost::posix_time::to_simple_string (m_LastUpdateTime)); @@ -113,7 +113,6 @@ namespace data m_NumTunnelsAgreed = participations.get (PEER_PROFILE_PARTICIPATION_AGREED, 0); m_NumTunnelsDeclined = participations.get (PEER_PROFILE_PARTICIPATION_DECLINED, 0); m_NumTunnelsNonReplied = participations.get (PEER_PROFILE_PARTICIPATION_NON_REPLIED, 0); - m_HasConnected = participations.get (PEER_PROFILE_USAGE_CONNECTED, false); } catch (boost::property_tree::ptree_bad_path& ex) { @@ -125,6 +124,7 @@ namespace data auto usage = pt.get_child (PEER_PROFILE_SECTION_USAGE); m_NumTimesTaken = usage.get (PEER_PROFILE_USAGE_TAKEN, 0); m_NumTimesRejected = usage.get (PEER_PROFILE_USAGE_REJECTED, 0); + m_HasConnected = usage.get (PEER_PROFILE_USAGE_CONNECTED, false); } catch (boost::property_tree::ptree_bad_path& ex) { From 1d8a91c5cccdbb0134d2cf8a1eb182e48a272e0a Mon Sep 17 00:00:00 2001 From: weko Date: Sat, 6 May 2023 07:59:40 +0000 Subject: [PATCH 0131/1171] redo no save useless profiles --- libi2pd/Profiling.cpp | 25 +++++++++++++++---------- libi2pd/Profiling.h | 5 ++--- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index dc11df4a..9d795451 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -35,7 +35,7 @@ namespace data m_LastUpdateTime (GetTime ()), m_IsUpdated (false), m_LastDeclineTime (0), m_LastUnreachableTime (0), m_NumTunnelsAgreed (0), m_NumTunnelsDeclined (0), m_NumTunnelsNonReplied (0), - m_NumTimesTaken (0), m_NumTimesRejected (0), m_HasConnected (false), m_IsUseful (0) + m_NumTimesTaken (0), m_NumTimesRejected (0), m_HasConnected (false) { } @@ -52,10 +52,10 @@ namespace data participation.put (PEER_PROFILE_PARTICIPATION_AGREED, m_NumTunnelsAgreed); participation.put (PEER_PROFILE_PARTICIPATION_DECLINED, m_NumTunnelsDeclined); participation.put (PEER_PROFILE_PARTICIPATION_NON_REPLIED, m_NumTunnelsNonReplied); + participation.put (PEER_PROFILE_USAGE_CONNECTED, m_HasConnected); boost::property_tree::ptree usage; usage.put (PEER_PROFILE_USAGE_TAKEN, m_NumTimesTaken); usage.put (PEER_PROFILE_USAGE_REJECTED, m_NumTimesRejected); - usage.put (PEER_PROFILE_USAGE_CONNECTED, m_HasConnected); // fill property tree boost::property_tree::ptree pt; pt.put (PEER_PROFILE_LAST_UPDATE_TIME, boost::posix_time::to_simple_string (m_LastUpdateTime)); @@ -113,6 +113,7 @@ namespace data m_NumTunnelsAgreed = participations.get (PEER_PROFILE_PARTICIPATION_AGREED, 0); m_NumTunnelsDeclined = participations.get (PEER_PROFILE_PARTICIPATION_DECLINED, 0); m_NumTunnelsNonReplied = participations.get (PEER_PROFILE_PARTICIPATION_NON_REPLIED, 0); + m_HasConnected = participations.get (PEER_PROFILE_USAGE_CONNECTED, false); } catch (boost::property_tree::ptree_bad_path& ex) { @@ -124,7 +125,6 @@ namespace data auto usage = pt.get_child (PEER_PROFILE_SECTION_USAGE); m_NumTimesTaken = usage.get (PEER_PROFILE_USAGE_TAKEN, 0); m_NumTimesRejected = usage.get (PEER_PROFILE_USAGE_REJECTED, 0); - m_HasConnected = usage.get (PEER_PROFILE_USAGE_CONNECTED, false); } catch (boost::property_tree::ptree_bad_path& ex) { @@ -145,24 +145,23 @@ namespace data UpdateTime (); if (ret > 0) { - if (++m_NumTunnelsDeclined > PEER_PROFILE_USEFUL_THRESHOLD) m_IsUseful = true; + m_NumTunnelsDeclined++; m_LastDeclineTime = i2p::util::GetSecondsSinceEpoch (); } else { - if (++m_NumTunnelsAgreed > PEER_PROFILE_USEFUL_THRESHOLD) m_IsUseful = true; + m_NumTunnelsAgreed++; m_LastDeclineTime = 0; } } void RouterProfile::TunnelNonReplied () { - if (++m_NumTunnelsNonReplied > PEER_PROFILE_USEFUL_THRESHOLD) m_IsUseful = true; + m_NumTunnelsNonReplied++; UpdateTime (); if (m_NumTunnelsNonReplied > 2*m_NumTunnelsAgreed && m_NumTunnelsNonReplied > 3) { m_LastDeclineTime = i2p::util::GetSecondsSinceEpoch (); - m_IsUseful = true; } } @@ -175,7 +174,6 @@ namespace data void RouterProfile::Connected () { m_HasConnected = true; - m_IsUseful = true; UpdateTime (); } @@ -210,8 +208,6 @@ namespace data m_NumTunnelsAgreed = 0; m_NumTunnelsDeclined = 0; m_NumTunnelsNonReplied = 0; - // we do not reset m_HasConnected here - // m_IsUseful = false; isBad = false; } if (isBad) m_NumTimesRejected++; else m_NumTimesTaken++; @@ -227,6 +223,15 @@ namespace data m_LastUnreachableTime = 0; return (bool)m_LastUnreachableTime; } + + bool RouterProfile::IsUseful() const { + return + m_NumTunnelsAgreed >= PEER_PROFILE_USEFUL_THRESHOLD || + m_NumTunnelsDeclined >= PEER_PROFILE_USEFUL_THRESHOLD || + m_NumTunnelsNonReplied >= PEER_PROFILE_USEFUL_THRESHOLD || + m_HasConnected; + } + std::shared_ptr GetRouterProfile (const IdentHash& identHash) { diff --git a/libi2pd/Profiling.h b/libi2pd/Profiling.h index c8654805..2520a6af 100644 --- a/libi2pd/Profiling.h +++ b/libi2pd/Profiling.h @@ -60,7 +60,8 @@ namespace data boost::posix_time::ptime GetLastUpdateTime () const { return m_LastUpdateTime; }; bool IsUpdated () const { return m_IsUpdated; }; - bool IsUseful() const { return m_IsUseful; }; + + bool IsUseful() const; private: @@ -84,8 +85,6 @@ namespace data uint32_t m_NumTimesTaken; uint32_t m_NumTimesRejected; bool m_HasConnected; // incoming connection received - // is need to be saved - bool m_IsUseful; }; std::shared_ptr GetRouterProfile (const IdentHash& identHash); From 8a52295882ced0e7080dda57e6c0f2456f937d00 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 6 May 2023 16:43:09 -0400 Subject: [PATCH 0132/1171] make router real upon successive outgoing NTCP2 session. Eliminate static keys table --- libi2pd/NTCP2.cpp | 2 -- libi2pd/Profiling.cpp | 28 ---------------------------- libi2pd/Profiling.h | 6 +----- libi2pd/RouterInfo.cpp | 8 +++----- libi2pd/SSU2Session.cpp | 2 -- libi2pd/Transports.cpp | 25 +++++++++---------------- 6 files changed, 13 insertions(+), 58 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index be584eb1..5e1cbaf6 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -718,8 +718,6 @@ namespace transport Terminate (); return; } - ri.GetProfile ()->Connected (); - i2p::data::UpdateStaticKey (addr->s, ri.GetIdentHash ()); // good static key i2p::data::netdb.PostI2NPMsg (CreateI2NPMessage (eI2NPDummyMsg, buf.data () + 3, size)); // TODO: should insert ri and not parse it twice // TODO: process options diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index 45e4ae22..754a2ce3 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -320,33 +320,5 @@ namespace data } } } - -// static keys - - struct StaticKeyProfile - { - i2p::data::IdentHash ident; - boost::posix_time::ptime lastUpdateTime; - }; - //static i2p::fs::HashedStorage g_StaticKeysProfilesStorage("statickeysProfiles", "s", "statickey-", "txt"); - static std::unordered_map, std::shared_ptr > g_StaticKeysProfiles; - static std::mutex g_StaticKeysProfilesMutex; - - bool CheckStaticKey (const i2p::data::Tag<32>& staticKey, const i2p::data::IdentHash& ident) - { - std::unique_lock l(g_StaticKeysProfilesMutex); - auto it = g_StaticKeysProfiles.find (staticKey); - if (it != g_StaticKeysProfiles.end ()) - return it->second->ident == ident; - return true; - } - - void UpdateStaticKey (const i2p::data::Tag<32>& staticKey, const i2p::data::IdentHash& ident) - { - std::unique_lock l(g_StaticKeysProfilesMutex); - auto res = g_StaticKeysProfiles.emplace (staticKey, std::make_shared(StaticKeyProfile{ident, GetTime ()})); - if (!res.second) - res.first->second->lastUpdateTime = GetTime (); - } } } diff --git a/libi2pd/Profiling.h b/libi2pd/Profiling.h index 2520a6af..6b814893 100644 --- a/libi2pd/Profiling.h +++ b/libi2pd/Profiling.h @@ -84,7 +84,7 @@ namespace data // usage uint32_t m_NumTimesTaken; uint32_t m_NumTimesRejected; - bool m_HasConnected; // incoming connection received + bool m_HasConnected; // successful trusted(incoming or NTCP2) connection }; std::shared_ptr GetRouterProfile (const IdentHash& identHash); @@ -92,10 +92,6 @@ namespace data void DeleteObsoleteProfiles (); void SaveProfiles (); void PersistProfiles (); - - // static keys - bool CheckStaticKey (const i2p::data::Tag<32>& staticKey, const i2p::data::IdentHash& ident); - void UpdateStaticKey (const i2p::data::Tag<32>& staticKey, const i2p::data::IdentHash& ident); } } diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 0cf5a0c5..5ba8a5b1 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -293,7 +293,8 @@ namespace data else if (!strcmp (key, "s")) // ntcp2 or ssu2 static key { Base64ToByteStream (value, strlen (value), address->s, 32); - isStaticKey = true; + if (!(address->s[31] & 0x80)) // check if x25519 public key + isStaticKey = true; } else if (!strcmp (key, "i")) // ntcp2 iv or ssu2 intro { @@ -363,9 +364,6 @@ namespace data if (!s) return; } - if ((address->s[31] & 0x80) || !i2p::data::CheckStaticKey(address->s, GetIdentHash())) - continue; // skip address - if (address->transportStyle == eTransportNTCP2) { if (isStaticKey) @@ -391,7 +389,7 @@ namespace data } } } - else if (address->transportStyle == eTransportSSU2 && isV2) + else if (address->transportStyle == eTransportSSU2 && isV2 && isStaticKey) { if (address->IsV4 ()) supportedTransports |= eSSU2V4; if (address->IsV6 ()) supportedTransports |= eSSU2V6; diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index efe7117d..49004437 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1075,8 +1075,6 @@ namespace transport return false; } SetRemoteIdentity (ri->GetRouterIdentity ()); - ri->GetProfile ()->Connected (); - i2p::data::UpdateStaticKey (m_Address->s, ri->GetIdentHash ()); // good static key AdjustMaxPayloadSize (); m_Server.AddSessionByRouterHash (shared_from_this ()); // we know remote router now m_RemoteTransports = ri->GetCompatibleTransports (false); diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 5693719c..f66a8f96 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -507,11 +507,6 @@ namespace transport peer.router->GetPublishedNTCP2V6Address () : peer.router->GetPublishedNTCP2V4Address (); if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host)) address = nullptr; - if (address && !i2p::data::CheckStaticKey (address->s, ident)) - { - LogPrint (eLogWarning, "Transports: NTCP2 address static key router mismatch ", ident.ToBase64 ()); - address = nullptr; - } if (address) { auto s = std::make_shared (*m_NTCP2Server, peer.router, address); @@ -531,11 +526,6 @@ namespace transport peer.router->GetSSU2V6Address () : peer.router->GetSSU2V4Address (); if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host)) address = nullptr; - if (address && !i2p::data::CheckStaticKey (address->s, ident)) - { - LogPrint (eLogWarning, "Transports: SSU2 address static key router mismatch ", ident.ToBase64 ()); - address = nullptr; - } if (address && address->IsReachableSSU ()) { if (m_SSU2Server->CreateSession (peer.router, address)) @@ -547,11 +537,6 @@ namespace transport { if (!m_NTCP2Server) continue; auto address = peer.router->GetYggdrasilAddress (); - if (address && !i2p::data::CheckStaticKey (address->s, ident)) - { - LogPrint (eLogWarning, "Transports: Yggdrasil address static key router mismatch ", ident.ToBase64 ()); - address = nullptr; - } if (address) { auto s = std::make_shared (*m_NTCP2Server, peer.router, address); @@ -606,7 +591,7 @@ namespace transport peer.router->GetCompatibleTransports (true); peer.numAttempts = 0; peer.priority.clear (); - bool ssu2 = rand () & 1; + bool ssu2 = peer.router->GetProfile ()->IsReal () ? (rand () & 1) : false; // try NTCP2 if router is not confirmed real const auto& priority = ssu2 ? ssu2Priority : ntcp2Priority; for (auto transport: priority) if (transport & compatibleTransports) @@ -724,6 +709,13 @@ namespace transport for (int i = 0; i < numExcluded; i++) transports |= it->second.priority[i]; i2p::data::netdb.ExcludeReachableTransports (ident, transports); + } + if (it->second.router) + { + auto transport = it->second.priority[it->second.numAttempts]; + if (transport == i2p::data::RouterInfo::eNTCP2V4 || + transport == i2p::data::RouterInfo::eNTCP2V6 || transport == i2p::data::RouterInfo::eNTCP2V6Mesh) + it->second.router->GetProfile ()->Connected (); // outgoing NTCP2 connection if always real } it->second.numAttempts = 0; it->second.router = nullptr; // we don't need RouterInfo after successive connect @@ -755,6 +747,7 @@ namespace transport if (!session->IsOutgoing ()) // incoming session->SendI2NPMessages ({ CreateDatabaseStoreMsg () }); // send DatabaseStore auto r = i2p::data::netdb.FindRouter (ident); // router should be in netdb after SessionConfirmed + if (r) r->GetProfile ()->Connected (); auto ts = i2p::util::GetSecondsSinceEpoch (); std::unique_lock l(m_PeersMutex); auto it = m_Peers.insert (std::make_pair (ident, Peer{ r, ts })).first; From 623c3f4605b805fdc6b4c5e90d8735eae72107c1 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 6 May 2023 18:07:21 -0400 Subject: [PATCH 0133/1171] check for max number of records in tunnel build and tunnel build reply messages --- libi2pd/I2NPProtocol.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index 1a5b1cde..f100c6e5 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -424,6 +424,11 @@ namespace i2p { int num = buf[0]; LogPrint (eLogDebug, "I2NP: VariableTunnelBuild ", num, " records"); + if (num > i2p::tunnel::MAX_NUM_RECORDS) + { + LogPrint (eLogError, "I2NP: Too many records in VaribleTunnelBuild message ", num); + return; + } if (len < num*TUNNEL_BUILD_RECORD_SIZE + 1) { LogPrint (eLogError, "I2NP: VaribleTunnelBuild message of ", num, " records is too short ", len); @@ -477,6 +482,11 @@ namespace i2p { int num = buf[0]; LogPrint (eLogDebug, "I2NP: TunnelBuildReplyMsg of ", num, " records replyMsgID=", replyMsgID); + if (num > i2p::tunnel::MAX_NUM_RECORDS) + { + LogPrint (eLogError, "I2NP: Too many records in TunnelBuildReply message ", num); + return; + } size_t recordSize = isShort ? SHORT_TUNNEL_BUILD_RECORD_SIZE : TUNNEL_BUILD_RECORD_SIZE; if (len < num*recordSize + 1) { @@ -508,6 +518,11 @@ namespace i2p { int num = buf[0]; LogPrint (eLogDebug, "I2NP: ShortTunnelBuild ", num, " records"); + if (num > i2p::tunnel::MAX_NUM_RECORDS) + { + LogPrint (eLogError, "I2NP: Too many records in ShortTunnelBuild message ", num); + return; + } if (len < num*SHORT_TUNNEL_BUILD_RECORD_SIZE + 1) { LogPrint (eLogError, "I2NP: ShortTunnelBuild message of ", num, " records is too short ", len); From a15864715390e33f566b1133ed69edf05004e7dc Mon Sep 17 00:00:00 2001 From: weko Date: Mon, 8 May 2023 14:50:27 +0000 Subject: [PATCH 0134/1171] refactor TBM hadling --- libi2pd/I2NPProtocol.cpp | 74 ++++++++++++++++++---------------------- libi2pd/I2NPProtocol.h | 2 +- libi2pd/Tunnel.cpp | 8 ++--- 3 files changed, 38 insertions(+), 46 deletions(-) diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index f100c6e5..623132ea 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -40,7 +40,7 @@ namespace i2p { return std::make_shared >(); } - + std::shared_ptr NewI2NPTunnelMessage (bool endpoint) { return i2p::tunnel::tunnels.NewI2NPTunnelMessage (endpoint); @@ -51,7 +51,7 @@ namespace i2p len += I2NP_HEADER_SIZE + 2; if (len <= I2NP_MAX_SHORT_MESSAGE_SIZE) return NewI2NPShortMessage (); if (len <= I2NP_MAX_MEDIUM_MESSAGE_SIZE) return NewI2NPMediumMessage (); - return NewI2NPMessage (); + return NewI2NPMessage (); } void I2NPMessage::FillI2NPMessageHeader (I2NPMessageType msgType, uint32_t replyMsgID, bool checksum) @@ -748,46 +748,38 @@ namespace i2p return l; } - void HandleI2NPMessage (uint8_t * msg, size_t len) + void HandleTunnlBuildI2NPMessage (std::shared_ptr msg) { - if (len < I2NP_HEADER_SIZE) + if (msg) { - LogPrint (eLogError, "I2NP: Message length ", len, " is smaller than header"); - return; - } - uint8_t typeID = msg[I2NP_HEADER_TYPEID_OFFSET]; - uint32_t msgID = bufbe32toh (msg + I2NP_HEADER_MSGID_OFFSET); - LogPrint (eLogDebug, "I2NP: Msg received len=", len,", type=", (int)typeID, ", msgID=", (unsigned int)msgID); - uint8_t * buf = msg + I2NP_HEADER_SIZE; - auto size = bufbe16toh (msg + I2NP_HEADER_SIZE_OFFSET); - len -= I2NP_HEADER_SIZE; - if (size > len) - { - LogPrint (eLogError, "I2NP: Payload size ", size, " exceeds buffer length ", len); - size = len; - } - switch (typeID) - { - case eI2NPVariableTunnelBuild: - HandleVariableTunnelBuildMsg (msgID, buf, size); - break; - case eI2NPShortTunnelBuild: - HandleShortTunnelBuildMsg (msgID, buf, size); - break; - case eI2NPVariableTunnelBuildReply: - HandleTunnelBuildReplyMsg (msgID, buf, size, false); - break; - case eI2NPShortTunnelBuildReply: - HandleTunnelBuildReplyMsg (msgID, buf, size, true); - break; - case eI2NPTunnelBuild: - HandleTunnelBuildMsg (buf, size); - break; - case eI2NPTunnelBuildReply: - // TODO: - break; - default: - LogPrint (eLogWarning, "I2NP: Unexpected message ", (int)typeID); + uint8_t typeID = msg->GetTypeID(); + uint32_t msgID = msg->GetMsgID(); + LogPrint (eLogDebug, "I2NP: Handling tunnel build message with len=", msg->GetLength(),", type=", (int)typeID, ", msgID=", (unsigned int)msgID); + uint8_t * payload = msg->GetPayload(); + auto size = msg->GetPayloadLength(); + switch (typeID) + { + case eI2NPVariableTunnelBuild: + HandleVariableTunnelBuildMsg (msgID, payload, size); + break; + case eI2NPShortTunnelBuild: + HandleShortTunnelBuildMsg (msgID, payload, size); + break; + case eI2NPVariableTunnelBuildReply: + HandleTunnelBuildReplyMsg (msgID, payload, size, false); + break; + case eI2NPShortTunnelBuildReply: + HandleTunnelBuildReplyMsg (msgID, payload, size, true); + break; + case eI2NPTunnelBuild: + HandleTunnelBuildMsg (payload, size); + break; + case eI2NPTunnelBuildReply: + // TODO: + break; + default: + LogPrint (eLogError, "I2NP: Unexpected message with type", (int)typeID, " during handling TBM; skipping"); + } } } @@ -851,7 +843,7 @@ namespace i2p i2p::tunnel::tunnels.PostTunnelData (msg); break; default: - HandleI2NPMessage (msg->GetBuffer (), msg->GetLength ()); + LogPrint(eLogError, "I2NP: Unexpected I2NP message with type ", int(typeID), " during handling; skipping"); } } } diff --git a/libi2pd/I2NPProtocol.h b/libi2pd/I2NPProtocol.h index c0685190..5efd8f70 100644 --- a/libi2pd/I2NPProtocol.h +++ b/libi2pd/I2NPProtocol.h @@ -295,7 +295,7 @@ namespace tunnel std::shared_ptr CreateTunnelGatewayMsg (uint32_t tunnelID, std::shared_ptr msg); size_t GetI2NPMessageLength (const uint8_t * msg, size_t len); - void HandleI2NPMessage (uint8_t * msg, size_t len); + void HandleTunnlBuildI2NPMessage (std::shared_ptr msg); void HandleI2NPMessage (std::shared_ptr msg); class I2NPMessagesHandler diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 249f0a31..99824ab7 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -516,7 +516,7 @@ namespace tunnel case eI2NPShortTunnelBuildReply: case eI2NPTunnelBuild: case eI2NPTunnelBuildReply: - HandleI2NPMessage (msg->GetBuffer (), msg->GetLength ()); + HandleTunnlBuildI2NPMessage (msg); break; default: LogPrint (eLogWarning, "Tunnel: Unexpected message type ", (int) typeID); @@ -590,13 +590,13 @@ namespace tunnel // DatabaseSearchReply with new routers i2p::data::netdb.PostI2NPMsg (CopyI2NPMessage (msg)); else if (IsRouterInfoMsg (msg)) - { + { // transit DatabaseStore might contain new/updated RI auto m = CopyI2NPMessage (msg); if (bufbe32toh (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET)) memset (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0xFF, 4); // fake replyToken meaning no reply i2p::data::netdb.PostI2NPMsg (m); - } + } tunnel->SendTunnelDataMsg (msg); } @@ -986,6 +986,6 @@ namespace tunnel LogPrint (eLogDebug, "Tunnel: Max number of transit tunnels set to ", maxNumTransitTunnels); m_MaxNumTransitTunnels = maxNumTransitTunnels; } - } + } } } From d44be2fd73269d256295ede9b0637f33f27a7b85 Mon Sep 17 00:00:00 2001 From: weko Date: Mon, 8 May 2023 15:33:40 +0000 Subject: [PATCH 0135/1171] fix typo --- libi2pd/I2NPProtocol.cpp | 8 ++++---- libi2pd/I2NPProtocol.h | 2 +- libi2pd/Tunnel.cpp | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index 623132ea..8a6f443c 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -428,7 +428,7 @@ namespace i2p { LogPrint (eLogError, "I2NP: Too many records in VaribleTunnelBuild message ", num); return; - } + } if (len < num*TUNNEL_BUILD_RECORD_SIZE + 1) { LogPrint (eLogError, "I2NP: VaribleTunnelBuild message of ", num, " records is too short ", len); @@ -486,7 +486,7 @@ namespace i2p { LogPrint (eLogError, "I2NP: Too many records in TunnelBuildReply message ", num); return; - } + } size_t recordSize = isShort ? SHORT_TUNNEL_BUILD_RECORD_SIZE : TUNNEL_BUILD_RECORD_SIZE; if (len < num*recordSize + 1) { @@ -522,7 +522,7 @@ namespace i2p { LogPrint (eLogError, "I2NP: Too many records in ShortTunnelBuild message ", num); return; - } + } if (len < num*SHORT_TUNNEL_BUILD_RECORD_SIZE + 1) { LogPrint (eLogError, "I2NP: ShortTunnelBuild message of ", num, " records is too short ", len); @@ -748,7 +748,7 @@ namespace i2p return l; } - void HandleTunnlBuildI2NPMessage (std::shared_ptr msg) + void HandleTunnelBuildI2NPMessage (std::shared_ptr msg) { if (msg) { diff --git a/libi2pd/I2NPProtocol.h b/libi2pd/I2NPProtocol.h index 5efd8f70..6c64f2ab 100644 --- a/libi2pd/I2NPProtocol.h +++ b/libi2pd/I2NPProtocol.h @@ -295,7 +295,7 @@ namespace tunnel std::shared_ptr CreateTunnelGatewayMsg (uint32_t tunnelID, std::shared_ptr msg); size_t GetI2NPMessageLength (const uint8_t * msg, size_t len); - void HandleTunnlBuildI2NPMessage (std::shared_ptr msg); + void HandleTunnelBuildI2NPMessage (std::shared_ptr msg); void HandleI2NPMessage (std::shared_ptr msg); class I2NPMessagesHandler diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 99824ab7..db6f74f9 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -516,7 +516,7 @@ namespace tunnel case eI2NPShortTunnelBuildReply: case eI2NPTunnelBuild: case eI2NPTunnelBuildReply: - HandleTunnlBuildI2NPMessage (msg); + HandleTunnelBuildI2NPMessage (msg); break; default: LogPrint (eLogWarning, "Tunnel: Unexpected message type ", (int) typeID); From c984f89dfb721a90dbb31f4c3bb169f6721fc82b Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 21 May 2023 18:43:58 -0400 Subject: [PATCH 0136/1171] don't handle unecnrypted DatabaseSearchReply msg if came throug client tunnel --- libi2pd/I2NPProtocol.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index 8a6f443c..b8147555 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -808,14 +808,12 @@ namespace i2p break; } case eI2NPDatabaseStore: + case eI2NPDatabaseSearchReply: // forward to netDb if came directly or through exploratory tunnel as response to our request if (!msg->from || !msg->from->GetTunnelPool () || msg->from->GetTunnelPool ()->IsExploratory ()) i2p::data::netdb.PostI2NPMsg (msg); break; - case eI2NPDatabaseSearchReply: - // forward to netDb - i2p::data::netdb.PostI2NPMsg (msg); - break; + case eI2NPDatabaseLookup: // forward to netDb if floodfill and came directly if (!msg->from && i2p::context.IsFloodfill ()) From e95fb3ab8941ae9e651bfc06b4e810b840c9460d Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 22 May 2023 08:58:04 -0400 Subject: [PATCH 0137/1171] allow user/password authentication --- libi2pd_client/SOCKS.cpp | 53 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/libi2pd_client/SOCKS.cpp b/libi2pd_client/SOCKS.cpp index ca87e22a..c40cb479 100644 --- a/libi2pd_client/SOCKS.cpp +++ b/libi2pd_client/SOCKS.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -66,6 +66,11 @@ namespace proxy GET5_IPV6, GET5_HOST_SIZE, GET5_HOST, + GET5_USERPASSWD, + GET5_USER_SIZE, + GET5_USER, + GET5_PASSWD_SIZE, + GET5_PASSWD, READY, UPSTREAM_RESOLVE, UPSTREAM_CONNECT, @@ -129,6 +134,7 @@ namespace proxy boost::asio::const_buffers_1 GenerateSOCKS5Response(errTypes error, addrTypes type, const address &addr, uint16_t port); boost::asio::const_buffers_1 GenerateUpstreamRequest(); bool Socks5ChooseAuth(); + void Socks5UserPasswdResponse (); void SocksRequestFailed(errTypes error); void SocksRequestSuccess(); void SentSocksFailed(const boost::system::error_code & ecode); @@ -324,6 +330,15 @@ namespace proxy } } + void SOCKSHandler::Socks5UserPasswdResponse () + { + m_response[0] = 5; // Version + m_response[1] = 0; // Response code + LogPrint(eLogDebug, "SOCKS: v5 user/password response"); + boost::asio::async_write(*m_sock, boost::asio::const_buffers_1(m_response, 2), + std::bind(&SOCKSHandler::SentSocksResponse, shared_from_this(), std::placeholders::_1)); + } + /* All hope is lost beyond this point */ void SOCKSHandler::SocksRequestFailed(SOCKSHandler::errTypes error) { @@ -438,10 +453,15 @@ namespace proxy m_parseleft --; if (*sock_buff == AUTH_NONE) m_authchosen = AUTH_NONE; + else if (*sock_buff == AUTH_USERPASSWD) + m_authchosen = AUTH_USERPASSWD; if ( m_parseleft == 0 ) { if (!Socks5ChooseAuth()) return false; - EnterState(GET5_REQUESTV); + if (m_authchosen == AUTH_USERPASSWD) + EnterState(GET5_USERPASSWD); + else + EnterState(GET5_REQUESTV); } break; case GET_COMMAND: @@ -557,6 +577,35 @@ namespace proxy m_parseleft--; if (m_parseleft == 0) EnterState(GET_PORT); break; + case GET5_USERPASSWD: + if (*sock_buff != 1) + { + LogPrint(eLogError,"SOCKS: v5 rejected invalid username/password subnegotiation: ", ((int)*sock_buff)); + SocksRequestFailed(SOCKS5_GEN_FAIL); + return false; + } + EnterState(GET5_USER_SIZE); + break; + case GET5_USER_SIZE: + EnterState(GET5_USER, *sock_buff); + break; + case GET5_USER: + // skip user for now + m_parseleft--; + if (m_parseleft == 0) EnterState(GET5_PASSWD_SIZE); + break; + case GET5_PASSWD_SIZE: + EnterState(GET5_PASSWD, *sock_buff); + break; + case GET5_PASSWD: + // skip passwd for now + m_parseleft--; + if (m_parseleft == 0) + { + Socks5UserPasswdResponse (); + EnterState(GET5_REQUESTV); + } + break; default: LogPrint(eLogError, "SOCKS: Parse state?? ", m_state); Terminate(); From e56d243c3f883c3ba7addf1c5bc769ed9ebeef8a Mon Sep 17 00:00:00 2001 From: r4sas Date: Mon, 24 Apr 2023 14:04:56 +0300 Subject: [PATCH 0138/1171] [win32] suppress fallthrough warning Signed-off-by: r4sas --- Win32/Win32App.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Win32/Win32App.cpp b/Win32/Win32App.cpp index 9eae7a95..fc61a8ac 100644 --- a/Win32/Win32App.cpp +++ b/Win32/Win32App.cpp @@ -348,6 +348,9 @@ namespace win32 } } } +#if (__cplusplus >= 201703L) // C++ 17 or higher + [[fallthrough]]; +#endif } case WM_TRAYICON: { From a2726cf206a52360ab9798c1666059d5360a4cba Mon Sep 17 00:00:00 2001 From: r4sas Date: Mon, 24 Apr 2023 14:07:12 +0300 Subject: [PATCH 0139/1171] [cmake] print commit-based version if option is used Signed-off-by: r4sas --- build/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 05401b1f..f5d01a0b 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -329,7 +329,11 @@ message(STATUS " LIBRARY : ${WITH_LIBRARY}") message(STATUS " BINARY : ${WITH_BINARY}") message(STATUS " STATIC BUILD : ${WITH_STATIC}") message(STATUS " UPnP : ${WITH_UPNP}") +if(WITH_GIT_VERSION) +message(STATUS " GIT VERSION : ${WITH_GIT_VERSION} (${GIT_VERSION})") +else() message(STATUS " GIT VERSION : ${WITH_GIT_VERSION}") +endif() message(STATUS " ADDRSANITIZER : ${WITH_ADDRSANITIZER}") message(STATUS " THREADSANITIZER : ${WITH_THREADSANITIZER}") message(STATUS "---------------------------------------") From fdf38f45d966454ee0d7eb9092de7809bce2677d Mon Sep 17 00:00:00 2001 From: r4sas Date: Sat, 29 Apr 2023 22:00:13 +0300 Subject: [PATCH 0140/1171] more debug messages at destinations stop Signed-off-by: r4sas --- libi2pd/Destination.cpp | 11 +++++++++-- libi2pd_client/ClientContext.cpp | 14 +++++++++++--- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 6bcedb4e..a755347d 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1036,11 +1036,15 @@ namespace client void ClientDestination::Stop () { + LogPrint(eLogDebug, "Destination: Stopping destination ", GetIdentHash().ToBase32(), ".b32.i2p"); LeaseSetDestination::Stop (); m_ReadyChecker.cancel(); + LogPrint(eLogDebug, "Destination: -> Stopping Streaming Destination"); m_StreamingDestination->Stop (); //m_StreamingDestination->SetOwner (nullptr); m_StreamingDestination = nullptr; + + LogPrint(eLogDebug, "Destination: -> Stopping Streaming Destination by ports"); for (auto& it: m_StreamingDestinationsByPorts) { it.second->Stop (); @@ -1048,11 +1052,14 @@ namespace client } m_StreamingDestinationsByPorts.clear (); m_LastStreamingDestination = nullptr; + if (m_DatagramDestination) { + LogPrint(eLogDebug, "Destination: -> Stopping Datagram Destination"); delete m_DatagramDestination; m_DatagramDestination = nullptr; } + LogPrint(eLogDebug, "Destination: -> Stopping done"); } void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len) @@ -1075,10 +1082,10 @@ namespace client if (toPort != m_LastPort || !m_LastStreamingDestination) { m_LastStreamingDestination = GetStreamingDestination (toPort); - if (!m_LastStreamingDestination) + if (!m_LastStreamingDestination) m_LastStreamingDestination = m_StreamingDestination; // if no destination on port use default m_LastPort = toPort; - } + } if (m_LastStreamingDestination) m_LastStreamingDestination->HandleDataMessagePayload (buf, length); else diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index dadb9ae5..afb34c2a 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -186,22 +186,30 @@ namespace client LogPrint(eLogInfo, "Clients: Stopping AddressBook"); m_AddressBook.Stop (); + LogPrint(eLogInfo, "Clients: Stopping UDP Tunnels"); { std::lock_guard lock(m_ForwardsMutex); m_ServerForwards.clear(); m_ClientForwards.clear(); } + LogPrint(eLogInfo, "Clients: Stopping UDP Tunnels timers"); if (m_CleanupUDPTimer) { m_CleanupUDPTimer->cancel (); m_CleanupUDPTimer = nullptr; } - for (auto& it: m_Destinations) - it.second->Stop (); - m_Destinations.clear (); + { + LogPrint(eLogInfo, "Clients: Stopping Destinations"); + std::lock_guard lock(m_DestinationsMutex); + for (auto& it: m_Destinations) + it.second->Stop (); + LogPrint(eLogInfo, "Clients: Stopping Destinations - Clear"); + m_Destinations.clear (); + } + LogPrint(eLogInfo, "Clients: Stopping SharedLocalDestination"); m_SharedLocalDestination->Release (); m_SharedLocalDestination = nullptr; } From dc6a42c26ff1572b97b59d64a2fd86bf5383053c Mon Sep 17 00:00:00 2001 From: r4sas Date: Mon, 8 May 2023 22:49:12 +0300 Subject: [PATCH 0141/1171] [contrib] update example config file comments, remove ssu option Signed-off-by: r4sas --- contrib/i2pd.conf | 109 ++++++++++++++++++++++++---------------------- 1 file changed, 56 insertions(+), 53 deletions(-) diff --git a/contrib/i2pd.conf b/contrib/i2pd.conf index 5d09c90a..5facbbd5 100644 --- a/contrib/i2pd.conf +++ b/contrib/i2pd.conf @@ -19,7 +19,7 @@ ## Default: ~/.i2pd/certificates or /var/lib/i2pd/certificates # certsdir = /var/lib/i2pd/certificates -## Where to write pidfile (default: i2pd.pid, not used in Windows) +## Where to write pidfile (default: /run/i2pd.pid, not used in Windows) # pidfile = /run/i2pd.pid ## Logging configuration section @@ -31,7 +31,7 @@ ## * file - log entries to a file ## * syslog - use syslog, see man 3 syslog # log = file -## Path to logfile (default - autodetect) +## Path to logfile (default: autodetect) # logfile = /var/log/i2pd/i2pd.log ## Log messages above this level (debug, info, *warn, error, critical, none) ## If you set it to none, logging will be disabled @@ -40,6 +40,7 @@ # logclftime = true ## Daemon mode. Router will go to background after start. Ignored on Windows +## (default: true) # daemon = true ## Specify a family, router belongs to (default - none) @@ -70,58 +71,60 @@ ## don't just uncomment this # port = 4567 -## Enable communication through ipv4 +## Enable communication through ipv4 (default: true) ipv4 = true -## Enable communication through ipv6 +## Enable communication through ipv6 (default: false) ipv6 = false -## Enable SSU transport -ssu = false - ## Bandwidth configuration -## L limit bandwidth to 32KBs/sec, O - to 256KBs/sec, P - to 2048KBs/sec, +## L limit bandwidth to 32 KB/sec, O - to 256 KB/sec, P - to 2048 KB/sec, ## X - unlimited -## Default is L (regular node) and X if floodfill mode enabled. If you want to -## share more bandwidth without floodfill mode, uncomment that line and adjust -## value to your possibilities +## Default is L (regular node) and X if floodfill mode enabled. +## If you want to share more bandwidth without floodfill mode, uncomment +## that line and adjust value to your possibilities. Value can be set to +## integer in kilobytes, it will apply that limit and flag will be used +## from next upper limit (example: if you set 4096 flag will be X, but real +## limit will be 4096 KB/s). Same can be done when floodfill mode is used, +## but keep in mind that low values may be negatively evaluated by Java +## router algorithms. # bandwidth = L -## Max % of bandwidth limit for transit. 0-100. 100 by default +## Max % of bandwidth limit for transit. 0-100 (default: 100) # share = 100 ## Router will not accept transit tunnels, disabling transit traffic completely -## (default = false) +## (default: false) # notransit = true -## Router will be floodfill +## Router will be floodfill (default: false) ## Note: that mode uses much more network connections and CPU! # floodfill = true [ntcp2] -## Enable NTCP2 transport (default = true) +## Enable NTCP2 transport (default: true) # enabled = true -## Publish address in RouterInfo (default = true) +## Publish address in RouterInfo (default: true) # published = true ## Port for incoming connections (default is global port option value) # port = 4567 [ssu2] -## Enable SSU2 transport +## Enable SSU2 transport (default: true) # enabled = true -## Publish address in RouterInfo +## Publish address in RouterInfo (default: true) # published = true -## Port for incoming connections (default is global port option value or port + 1 if SSU is enabled) +## Port for incoming connections (default is global port option value) # port = 4567 [http] ## Web Console settings -## Uncomment and set to 'false' to disable Web Console +## Enable the Web Console (default: true) # enabled = true -## Address and port service will listen on -address = 127.0.0.1 -port = 7070 -## Path to web console, default "/" +## Address and port service will listen on (default: 127.0.0.1:7070) +# address = 127.0.0.1 +# port = 7070 +## Path to web console (default: /) # webroot = / -## Uncomment following lines to enable Web Console authentication +## Enable Web Console authentication (default: false) ## You should not use Web Console via public networks without additional encryption. ## HTTP authentication is not encryption layer! # auth = true @@ -134,12 +137,12 @@ port = 7070 # lang = english [httpproxy] -## Uncomment and set to 'false' to disable HTTP Proxy +## Enable the HTTP proxy (default: true) # enabled = true -## Address and port service will listen on -address = 127.0.0.1 -port = 4444 -## Optional keys file for proxy local destination +## Address and port service will listen on (default: 127.0.0.1:4444) +# address = 127.0.0.1 +# port = 4444 +## Optional keys file for proxy local destination (default: http-proxy-keys.dat) # keys = http-proxy-keys.dat ## Enable address helper for adding .i2p domains with "jump URLs" (default: true) ## You should disable this feature if your i2pd HTTP Proxy is public, @@ -150,15 +153,15 @@ port = 4444 ## httpproxy section also accepts I2CP parameters, like "inbound.length" etc. [socksproxy] -## Uncomment and set to 'false' to disable SOCKS Proxy +## Enable the SOCKS proxy (default: true) # enabled = true -## Address and port service will listen on -address = 127.0.0.1 -port = 4447 -## Optional keys file for proxy local destination +## Address and port service will listen on (default: 127.0.0.1:4447) +# address = 127.0.0.1 +# port = 4447 +## Optional keys file for proxy local destination (default: socks-proxy-keys.dat) # keys = socks-proxy-keys.dat ## Socks outproxy. Example below is set to use Tor for all connections except i2p -## Uncomment and set to 'true' to enable using of SOCKS outproxy +## Enable using of SOCKS outproxy (works only with SOCKS4, default: false) # outproxy.enabled = false ## Address and port of outproxy # outproxy = 127.0.0.1 @@ -166,34 +169,34 @@ port = 4447 ## socksproxy section also accepts I2CP parameters, like "inbound.length" etc. [sam] -## Comment or set to 'false' to disable SAM Bridge -enabled = true -## Address and ports service will listen on +## Enable the SAM bridge (default: true) +# enabled = false +## Address and ports service will listen on (default: 127.0.0.1:7656, udp: 7655) # address = 127.0.0.1 # port = 7656 # portudp = 7655 [bob] -## Uncomment and set to 'true' to enable BOB command channel +## Enable the BOB command channel (default: false) # enabled = false -## Address and port service will listen on +## Address and port service will listen on (default: 127.0.0.1:2827) # address = 127.0.0.1 # port = 2827 [i2cp] -## Uncomment and set to 'true' to enable I2CP protocol +## Enable the I2CP protocol (default: false) # enabled = false -## Address and port service will listen on +## Address and port service will listen on (default: 127.0.0.1:7654) # address = 127.0.0.1 # port = 7654 [i2pcontrol] -## Uncomment and set to 'true' to enable I2PControl protocol +## Enable the I2PControl protocol (default: false) # enabled = false -## Address and port service will listen on +## Address and port service will listen on (default: 127.0.0.1:7650) # address = 127.0.0.1 # port = 7650 -## Authentication password. "itoopie" by default +## Authentication password (default: itoopie) # password = itoopie [precomputation] @@ -204,11 +207,11 @@ enabled = true [upnp] ## Enable or disable UPnP: automatic port forwarding (enabled by default in WINDOWS, ANDROID) # enabled = false -## Name i2pd appears in UPnP forwardings list (default = I2Pd) +## Name i2pd appears in UPnP forwardings list (default: I2Pd) # name = I2Pd [meshnets] -## Enable connectivity over the Yggdrasil network +## Enable connectivity over the Yggdrasil network (default: false) # yggdrasil = false ## You can bind address from your Yggdrasil subnet 300::/64 ## The address must first be added to the network interface @@ -216,7 +219,7 @@ enabled = true [reseed] ## Options for bootstrapping into I2P network, aka reseeding -## Enable or disable reseed data verification. +## Enable reseed data verification (default: true) verify = true ## URLs to request reseed data from, separated by comma ## Default: "mainline" I2P Network reseeds @@ -232,7 +235,7 @@ verify = true ## If you run i2pd behind a proxy server, set proxy server for reseeding here ## Should be http://address:port or socks://address:port # proxy = http://127.0.0.1:8118 -## Minimum number of known routers, below which i2pd triggers reseeding. 25 by default +## Minimum number of known routers, below which i2pd triggers reseeding (default: 25) # threshold = 25 [addressbook] @@ -252,13 +255,13 @@ verify = true # coresize = 0 [trust] -## Enable explicit trust options. false by default +## Enable explicit trust options. (default: false) # enabled = true ## Make direct I2P connections only to routers in specified Family. # family = MyFamily ## Make direct I2P connections only to routers specified here. Comma separated list of base64 identities. # routers = -## Should we hide our router from other routers? false by default +## Should we hide our router from other routers? (default: false) # hidden = true [exploratory] @@ -279,6 +282,6 @@ verify = true # aesni = true ## Use CPU AVX instructions set when work with cryptography when available (default: true) # avx = true -## Force usage of CPU instructions set, even if they not found +## Force usage of CPU instructions set, even if they not found (default: false) ## DO NOT TOUCH that option if you really don't know what are you doing! # force = false From ae439b5385944215ce9cba75eba55a2789b9989e Mon Sep 17 00:00:00 2001 From: r4sas Date: Sat, 27 May 2023 01:00:19 +0300 Subject: [PATCH 0142/1171] SSU2: check if socket is opened before sending data, handle network_reset error Signed-off-by: r4sas --- libi2pd/Profiling.cpp | 24 ++++++++++++------------ libi2pd/SSU2.cpp | 23 ++++++++++++++++++++++- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index 754a2ce3..4fbf0fa2 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -30,7 +30,7 @@ namespace data { return boost::posix_time::second_clock::local_time(); } - + RouterProfile::RouterProfile (): m_LastUpdateTime (GetTime ()), m_IsUpdated (false), m_LastDeclineTime (0), m_LastUnreachableTime (0), @@ -175,8 +175,8 @@ namespace data { m_HasConnected = true; UpdateTime (); - } - + } + bool RouterProfile::IsLowPartcipationRate () const { return 4*m_NumTunnelsAgreed < m_NumTunnelsDeclined; // < 20% rate @@ -223,7 +223,7 @@ namespace data m_LastUnreachableTime = 0; return (bool)m_LastUnreachableTime; } - + bool RouterProfile::IsUseful() const { return m_NumTunnelsAgreed >= PEER_PROFILE_USEFUL_THRESHOLD || @@ -240,7 +240,7 @@ namespace data auto it = g_Profiles.find (identHash); if (it != g_Profiles.end ()) return it->second; - } + } auto profile = std::make_shared (); profile->Load (identHash); // if possible std::unique_lock l(g_ProfilesMutex); @@ -261,7 +261,7 @@ namespace data { std::unique_lock l(g_ProfilesMutex); for (auto it = g_Profiles.begin (); it != g_Profiles.end ();) - { + { if ((ts - it->second->GetLastUpdateTime ()).total_seconds () > PEER_PROFILE_PERSIST_INTERVAL) { if (it->second->IsUpdated ()) @@ -270,11 +270,11 @@ namespace data } else it++; - } + } } for (auto& it: tmp) if (it.second) it.second->Save (it.first); - } + } void SaveProfiles () { @@ -288,22 +288,22 @@ namespace data for (auto& it: tmp) if (it.second->IsUseful() && it.second->IsUpdated () && (ts - it.second->GetLastUpdateTime ()).total_seconds () < PEER_PROFILE_EXPIRATION_TIMEOUT*3600) it.second->Save (it.first); - } - + } + void DeleteObsoleteProfiles () { { auto ts = GetTime (); std::unique_lock l(g_ProfilesMutex); for (auto it = g_Profiles.begin (); it != g_Profiles.end ();) - { + { if ((ts - it->second->GetLastUpdateTime ()).total_seconds () >= PEER_PROFILE_EXPIRATION_TIMEOUT*3600) it = g_Profiles.erase (it); else it++; } } - + struct stat st; std::time_t now = std::time(nullptr); diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 5df4d33a..a9e04790 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -78,6 +78,7 @@ namespace transport if (address->IsV4 ()) { found = true; + LogPrint (eLogDebug, "SSU2: Opening IPv4 socket at Start"); OpenSocket (boost::asio::ip::udp::endpoint (m_AddressV4, port)); m_ReceiveService.GetService ().post( [this]() @@ -89,6 +90,7 @@ namespace transport if (address->IsV6 ()) { found = true; + LogPrint (eLogDebug, "SSU2: Opening IPv6 socket at Start"); OpenSocket (boost::asio::ip::udp::endpoint (m_AddressV6, port)); m_ReceiveService.GetService ().post( [this]() @@ -243,10 +245,12 @@ namespace transport if (!ecode || ecode == boost::asio::error::connection_refused || ecode == boost::asio::error::connection_reset + || ecode == boost::asio::error::network_reset || ecode == boost::asio::error::network_unreachable || ecode == boost::asio::error::host_unreachable #ifdef _WIN32 // windows can throw WinAPI error, which is not handled by ASIO || ecode.value() == boost::winapi::ERROR_CONNECTION_REFUSED_ + || ecode.value() == boost::winapi::WSAENETRESET_ // 10052 || ecode.value() == boost::winapi::ERROR_NETWORK_UNREACHABLE_ || ecode.value() == boost::winapi::ERROR_HOST_UNREACHABLE_ #endif @@ -303,7 +307,7 @@ namespace transport else { auto ep = socket.local_endpoint (); - socket.close (); + LogPrint (eLogCritical, "SSU2: Reopening socket in HandleReceivedFrom: code ", ecode.value(), ": ", ecode.message ()); OpenSocket (ep); Receive (socket); } @@ -558,16 +562,25 @@ namespace transport SendThroughProxy (header, headerLen, nullptr, 0, payload, payloadLen, to); return; } + std::vector bufs { boost::asio::buffer (header, headerLen), boost::asio::buffer (payload, payloadLen) }; + boost::system::error_code ec; if (to.address ().is_v6 ()) + { + if (!m_SocketV6.is_open ()) return; m_SocketV6.send_to (bufs, to, 0, ec); + } else + { + if (!m_SocketV4.is_open ()) return; m_SocketV4.send_to (bufs, to, 0, ec); + } + if (!ec) i2p::transport::transports.UpdateSentBytes (headerLen + payloadLen); else @@ -582,17 +595,25 @@ namespace transport SendThroughProxy (header, headerLen, headerX, headerXLen, payload, payloadLen, to); return; } + std::vector bufs { boost::asio::buffer (header, headerLen), boost::asio::buffer (headerX, headerXLen), boost::asio::buffer (payload, payloadLen) }; + boost::system::error_code ec; if (to.address ().is_v6 ()) + { + if (!m_SocketV6.is_open ()) return; m_SocketV6.send_to (bufs, to, 0, ec); + } else + { + if (!m_SocketV4.is_open ()) return; m_SocketV4.send_to (bufs, to, 0, ec); + } if (!ec) i2p::transport::transports.UpdateSentBytes (headerLen + headerXLen + payloadLen); From 86173400d5dda64da4a9c30bd4bd851d6bac7bcb Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 29 May 2023 08:49:45 -0400 Subject: [PATCH 0143/1171] don't drop profile of real router too early --- libi2pd/NetDb.hpp | 2 +- libi2pd/Profiling.cpp | 12 ++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index 4aa69d59..adfdcde7 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -38,7 +38,7 @@ namespace data { const int NETDB_MIN_ROUTERS = 90; const int NETDB_MIN_FLOODFILLS = 5; - const int NETDB_NUM_FLOODFILLS_THRESHOLD = 1000; + const int NETDB_NUM_FLOODFILLS_THRESHOLD = 1500; const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60 * 60; // 1 hour, in seconds const int NETDB_MIN_EXPIRATION_TIMEOUT = 90 * 60; // 1.5 hours const int NETDB_MAX_EXPIRATION_TIMEOUT = 27 * 60 * 60; // 27 hours diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index 4fbf0fa2..47fc15e7 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -224,15 +224,11 @@ namespace data return (bool)m_LastUnreachableTime; } - bool RouterProfile::IsUseful() const { - return - m_NumTunnelsAgreed >= PEER_PROFILE_USEFUL_THRESHOLD || - m_NumTunnelsDeclined >= PEER_PROFILE_USEFUL_THRESHOLD || - m_NumTunnelsNonReplied >= PEER_PROFILE_USEFUL_THRESHOLD || - m_HasConnected; + bool RouterProfile::IsUseful() const + { + return IsReal () || m_NumTunnelsNonReplied >= PEER_PROFILE_USEFUL_THRESHOLD; } - std::shared_ptr GetRouterProfile (const IdentHash& identHash) { { @@ -286,7 +282,7 @@ namespace data } auto ts = GetTime (); for (auto& it: tmp) - if (it.second->IsUseful() && it.second->IsUpdated () && (ts - it.second->GetLastUpdateTime ()).total_seconds () < PEER_PROFILE_EXPIRATION_TIMEOUT*3600) + if (it.second->IsUseful() && (it.second->IsUpdated () || (ts - it.second->GetLastUpdateTime ()).total_seconds () < PEER_PROFILE_EXPIRATION_TIMEOUT*3600)) it.second->Save (it.first); } From d5ee1f602fdc7a47ccc9a4e239ea720dd63f123a Mon Sep 17 00:00:00 2001 From: AsciiMoth Date: Tue, 30 May 2023 18:27:40 +0400 Subject: [PATCH 0144/1171] Update dates in license (#1934) Update copyright timestamp in LICENSE file from 2020 to actual 2023 --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 9a1e4527..93280084 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2013-2020, The PurpleI2P Project +Copyright (c) 2013-2023, The PurpleI2P Project All rights reserved. From dfe5df29e18afa7f93fa3c452ebe12398178ad6b Mon Sep 17 00:00:00 2001 From: r4sas Date: Tue, 30 May 2023 21:05:15 +0300 Subject: [PATCH 0145/1171] suppress build warnings on windows Signed-off-by: r4sas --- libi2pd/util.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd/util.cpp b/libi2pd/util.cpp index 2426f13a..088a7af5 100644 --- a/libi2pd/util.cpp +++ b/libi2pd/util.cpp @@ -201,7 +201,7 @@ namespace net int GetMTUWindowsIpv4 (sockaddr_in inputAddress, int fallback) { typedef const char *(* IPN)(int af, const void *src, char *dst, socklen_t size); - IPN inetntop = (IPN)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetNtop"); + IPN inetntop = (IPN)(void*)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetNtop"); if (!inetntop) inetntop = inet_ntop_xp; // use own implementation if not found ULONG outBufLen = 0; @@ -262,7 +262,7 @@ namespace net int GetMTUWindowsIpv6 (sockaddr_in6 inputAddress, int fallback) { typedef const char *(* IPN)(int af, const void *src, char *dst, socklen_t size); - IPN inetntop = (IPN)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetNtop"); + IPN inetntop = (IPN)(void*)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetNtop"); if (!inetntop) inetntop = inet_ntop_xp; // use own implementation if not found ULONG outBufLen = 0; @@ -341,7 +341,7 @@ namespace net #endif typedef int (* IPN)(int af, const char *src, void *dst); - IPN inetpton = (IPN)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetPton"); + IPN inetpton = (IPN)(void*)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetPton"); if (!inetpton) inetpton = inet_pton_xp; // use own implementation if not found if (localAddress.is_v4()) From 09f233dbfb07fb1c3edd38a47d65e56a99589d50 Mon Sep 17 00:00:00 2001 From: r4sas Date: Tue, 6 Jun 2023 01:00:07 +0300 Subject: [PATCH 0146/1171] NetDB: ignore LeaseSet store request if not floodfill Signed-off-by: r4sas --- libi2pd/NetDb.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 18b6694b..baf96f74 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -267,12 +267,12 @@ namespace data if (wasFloodfill) m_Floodfills.Remove (r->GetIdentHash ()); else if (r->IsEligibleFloodfill ()) - { - if (m_Floodfills.GetSize () < NETDB_NUM_FLOODFILLS_THRESHOLD || r->GetProfile ()->IsReal ()) + { + if (m_Floodfills.GetSize () < NETDB_NUM_FLOODFILLS_THRESHOLD || r->GetProfile ()->IsReal ()) m_Floodfills.Insert (r); else r->ResetFlooldFill (); - } + } } } else @@ -296,10 +296,10 @@ namespace data { LogPrint (eLogInfo, "NetDb: RouterInfo added: ", ident.ToBase64()); if (r->IsFloodfill () && r->IsEligibleFloodfill ()) - { + { if (m_Floodfills.GetSize () < NETDB_NUM_FLOODFILLS_THRESHOLD || - r->GetProfile ()->IsReal ()) // don't insert floodfill until it's known real if we have enough - { + r->GetProfile ()->IsReal ()) // don't insert floodfill until it's known real if we have enough + { std::unique_lock l(m_FloodfillsMutex); m_Floodfills.Insert (r); } @@ -840,7 +840,12 @@ namespace data LogPrint (eLogError, "NetDb: Database store message is too long ", len); return; } - if (!m->from) // unsolicited LS must be received directly + if (!context.IsFloodfill ()) + { + LogPrint (eLogInfo, "NetDb: Not Floodfill, LeaseSet store request ignored for ", ident.ToBase32()); + return; + } + else if (!m->from) // unsolicited LS must be received directly { if (storeType == NETDB_STORE_TYPE_LEASESET) // 1 { From 4e426727e961eb944d2501cee733afe700fbb961 Mon Sep 17 00:00:00 2001 From: r4sas Date: Sat, 10 Jun 2023 04:08:56 +0300 Subject: [PATCH 0147/1171] Webconsole: fix output on i2p tunnels, add b32 on dest page Fixes: * adding of "Client Destinations" section header when there is no such tunnels * Print error when destination is not found instead of empty page Adds: * Print b32 on destination page Signed-off-by: r4sas --- daemon/HTTPServer.cpp | 62 ++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index f9b034ae..50666940 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -422,8 +422,12 @@ namespace http { static void ShowLeaseSetDestination (std::stringstream& s, std::shared_ptr dest, uint32_t token) { + s << "Base32:
\r\n
\r\n
\r\n"; + s << "Base64:
\r\n
\r\n
\r\n"; + if (dest->IsEncryptedLeaseSet ()) { i2p::data::BlindedPublicKey blinded (dest->GetIdentity (), dest->IsPerClientAuth ()); @@ -605,6 +609,8 @@ namespace http { } s << "\r\n"; } + else + ShowError(s, tr("Such destination is not found")); } void ShowI2CPLocalDestination (std::stringstream& s, const std::string& id) @@ -972,34 +978,42 @@ namespace http { void ShowI2PTunnels (std::stringstream& s) { std::string webroot; i2p::config::GetOption("http.webroot", webroot); - s << "" << tr("Client Tunnels") << ":
\r\n

\r\n"; - for (auto& it: i2p::client::context.GetClientTunnels ()) - { - auto& ident = it.second->GetLocalDestination ()->GetIdentHash(); - s << "
"; - s << it.second->GetName () << " ⇐ "; - s << i2p::client::context.GetAddressBook ().ToAddress(ident); - s << "
\r\n"<< std::endl; - } + + auto& clientTunnels = i2p::client::context.GetClientTunnels (); auto httpProxy = i2p::client::context.GetHttpProxy (); - if (httpProxy) - { - auto& ident = httpProxy->GetLocalDestination ()->GetIdentHash(); - s << "
"; - s << "HTTP " << tr("Proxy") << " ⇐ "; - s << i2p::client::context.GetAddressBook ().ToAddress(ident); - s << "
\r\n"<< std::endl; - } auto socksProxy = i2p::client::context.GetSocksProxy (); - if (socksProxy) + if (!clientTunnels.empty () || httpProxy || socksProxy) { - auto& ident = socksProxy->GetLocalDestination ()->GetIdentHash(); - s << "
"; - s << "SOCKS " << tr("Proxy") << " ⇐ "; - s << i2p::client::context.GetAddressBook ().ToAddress(ident); - s << "
\r\n"<< std::endl; + s << "" << tr("Client Tunnels") << ":
\r\n
\r\n"; + if (!clientTunnels.empty ()) + { + for (auto& it: clientTunnels) + { + auto& ident = it.second->GetLocalDestination ()->GetIdentHash(); + s << "
"; + s << it.second->GetName () << " ⇐ "; + s << i2p::client::context.GetAddressBook ().ToAddress(ident); + s << "
\r\n"<< std::endl; + } + } + if (httpProxy) + { + auto& ident = httpProxy->GetLocalDestination ()->GetIdentHash(); + s << "
"; + s << "HTTP " << tr("Proxy") << " ⇐ "; + s << i2p::client::context.GetAddressBook ().ToAddress(ident); + s << "
\r\n"<< std::endl; + } + if (socksProxy) + { + auto& ident = socksProxy->GetLocalDestination ()->GetIdentHash(); + s << "
"; + s << "SOCKS " << tr("Proxy") << " ⇐ "; + s << i2p::client::context.GetAddressBook ().ToAddress(ident); + s << "
\r\n"<< std::endl; + } + s << "
\r\n"; } - s << "
\r\n"; auto& serverTunnels = i2p::client::context.GetServerTunnels (); if (!serverTunnels.empty ()) { From 75aa9f2c0c79c09d9ddc85465edad090dfee884d Mon Sep 17 00:00:00 2001 From: r4sas Date: Sat, 10 Jun 2023 04:30:48 +0300 Subject: [PATCH 0148/1171] i18n: update translation file Signed-off-by: r4sas --- contrib/i18n/English.po | 402 +++++++++++++++++++++------------------- contrib/i18n/README.md | 2 +- 2 files changed, 211 insertions(+), 193 deletions(-) diff --git a/contrib/i18n/English.po b/contrib/i18n/English.po index 22010680..7782187f 100644 --- a/contrib/i18n/English.po +++ b/contrib/i18n/English.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: i2pd\n" "Report-Msgid-Bugs-To: https://github.com/PurpleI2P/i2pd/issues\n" -"POT-Creation-Date: 2023-01-19 04:18\n" +"POT-Creation-Date: 2023-06-10 01:25\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -18,28 +18,28 @@ msgstr "" "X-Poedit-SearchPath-0: daemon/HTTPServer.cpp\n" "X-Poedit-SearchPath-1: libi2pd_client/HTTPProxy.cpp\n" -#: daemon/HTTPServer.cpp:106 +#: daemon/HTTPServer.cpp:107 #, c-format msgid "%d day" msgid_plural "%d days" msgstr[0] "" msgstr[1] "" -#: daemon/HTTPServer.cpp:110 +#: daemon/HTTPServer.cpp:111 #, c-format msgid "%d hour" msgid_plural "%d hours" msgstr[0] "" msgstr[1] "" -#: daemon/HTTPServer.cpp:114 +#: daemon/HTTPServer.cpp:115 #, c-format msgid "%d minute" msgid_plural "%d minutes" msgstr[0] "" msgstr[1] "" -#: daemon/HTTPServer.cpp:117 +#: daemon/HTTPServer.cpp:118 #, c-format msgid "%d second" msgid_plural "%d seconds" @@ -47,560 +47,578 @@ msgstr[0] "" msgstr[1] "" #. tr: Kibibyte -#: daemon/HTTPServer.cpp:125 daemon/HTTPServer.cpp:153 +#: daemon/HTTPServer.cpp:126 #, c-format msgid "%.2f KiB" msgstr "" #. tr: Mebibyte -#: daemon/HTTPServer.cpp:127 +#: daemon/HTTPServer.cpp:128 #, c-format msgid "%.2f MiB" msgstr "" #. tr: Gibibyte -#: daemon/HTTPServer.cpp:129 +#: daemon/HTTPServer.cpp:130 #, c-format msgid "%.2f GiB" msgstr "" -#: daemon/HTTPServer.cpp:146 +#: daemon/HTTPServer.cpp:147 msgid "building" msgstr "" -#: daemon/HTTPServer.cpp:147 +#: daemon/HTTPServer.cpp:148 msgid "failed" msgstr "" -#: daemon/HTTPServer.cpp:148 +#: daemon/HTTPServer.cpp:149 msgid "expiring" msgstr "" -#: daemon/HTTPServer.cpp:149 +#: daemon/HTTPServer.cpp:150 msgid "established" msgstr "" -#: daemon/HTTPServer.cpp:150 +#: daemon/HTTPServer.cpp:151 msgid "unknown" msgstr "" -#: daemon/HTTPServer.cpp:152 +#: daemon/HTTPServer.cpp:153 msgid "exploratory" msgstr "" #. tr: Webconsole page title -#: daemon/HTTPServer.cpp:183 +#: daemon/HTTPServer.cpp:185 msgid "Purple I2P Webconsole" msgstr "" -#: daemon/HTTPServer.cpp:188 +#: daemon/HTTPServer.cpp:190 msgid "i2pd webconsole" msgstr "" -#: daemon/HTTPServer.cpp:191 +#: daemon/HTTPServer.cpp:193 msgid "Main page" msgstr "" -#: daemon/HTTPServer.cpp:192 daemon/HTTPServer.cpp:712 +#: daemon/HTTPServer.cpp:194 daemon/HTTPServer.cpp:742 msgid "Router commands" msgstr "" -#: daemon/HTTPServer.cpp:193 daemon/HTTPServer.cpp:387 -#: daemon/HTTPServer.cpp:399 +#: daemon/HTTPServer.cpp:195 daemon/HTTPServer.cpp:395 +#: daemon/HTTPServer.cpp:407 msgid "Local Destinations" msgstr "" -#: daemon/HTTPServer.cpp:195 daemon/HTTPServer.cpp:357 -#: daemon/HTTPServer.cpp:443 daemon/HTTPServer.cpp:449 -#: daemon/HTTPServer.cpp:609 daemon/HTTPServer.cpp:652 -#: daemon/HTTPServer.cpp:656 +#: daemon/HTTPServer.cpp:197 daemon/HTTPServer.cpp:365 +#: daemon/HTTPServer.cpp:454 daemon/HTTPServer.cpp:474 +#: daemon/HTTPServer.cpp:636 daemon/HTTPServer.cpp:682 +#: daemon/HTTPServer.cpp:686 msgid "LeaseSets" msgstr "" -#: daemon/HTTPServer.cpp:197 daemon/HTTPServer.cpp:662 +#: daemon/HTTPServer.cpp:199 daemon/HTTPServer.cpp:692 msgid "Tunnels" msgstr "" -#: daemon/HTTPServer.cpp:199 daemon/HTTPServer.cpp:364 -#: daemon/HTTPServer.cpp:781 daemon/HTTPServer.cpp:797 +#: daemon/HTTPServer.cpp:201 daemon/HTTPServer.cpp:372 +#: daemon/HTTPServer.cpp:813 daemon/HTTPServer.cpp:830 msgid "Transit Tunnels" msgstr "" -#: daemon/HTTPServer.cpp:201 daemon/HTTPServer.cpp:855 +#: daemon/HTTPServer.cpp:203 daemon/HTTPServer.cpp:898 msgid "Transports" msgstr "" -#: daemon/HTTPServer.cpp:202 +#: daemon/HTTPServer.cpp:204 msgid "I2P tunnels" msgstr "" -#: daemon/HTTPServer.cpp:204 daemon/HTTPServer.cpp:884 -#: daemon/HTTPServer.cpp:894 +#: daemon/HTTPServer.cpp:206 daemon/HTTPServer.cpp:927 +#: daemon/HTTPServer.cpp:937 msgid "SAM sessions" msgstr "" -#: daemon/HTTPServer.cpp:220 daemon/HTTPServer.cpp:1278 -#: daemon/HTTPServer.cpp:1281 daemon/HTTPServer.cpp:1284 -#: daemon/HTTPServer.cpp:1298 daemon/HTTPServer.cpp:1343 -#: daemon/HTTPServer.cpp:1346 daemon/HTTPServer.cpp:1349 +#: daemon/HTTPServer.cpp:222 daemon/HTTPServer.cpp:1329 +#: daemon/HTTPServer.cpp:1332 daemon/HTTPServer.cpp:1335 +#: daemon/HTTPServer.cpp:1362 daemon/HTTPServer.cpp:1365 +#: daemon/HTTPServer.cpp:1379 daemon/HTTPServer.cpp:1424 +#: daemon/HTTPServer.cpp:1427 daemon/HTTPServer.cpp:1430 msgid "ERROR" msgstr "" -#: daemon/HTTPServer.cpp:227 +#: daemon/HTTPServer.cpp:229 msgid "OK" msgstr "" -#: daemon/HTTPServer.cpp:228 +#: daemon/HTTPServer.cpp:230 msgid "Testing" msgstr "" -#: daemon/HTTPServer.cpp:229 +#: daemon/HTTPServer.cpp:231 msgid "Firewalled" msgstr "" -#: daemon/HTTPServer.cpp:230 daemon/HTTPServer.cpp:233 -#: daemon/HTTPServer.cpp:329 +#: daemon/HTTPServer.cpp:232 daemon/HTTPServer.cpp:235 +#: daemon/HTTPServer.cpp:336 msgid "Unknown" msgstr "" -#: daemon/HTTPServer.cpp:231 daemon/HTTPServer.cpp:374 -#: daemon/HTTPServer.cpp:375 daemon/HTTPServer.cpp:952 -#: daemon/HTTPServer.cpp:961 +#: daemon/HTTPServer.cpp:233 daemon/HTTPServer.cpp:382 +#: daemon/HTTPServer.cpp:383 daemon/HTTPServer.cpp:1003 +#: daemon/HTTPServer.cpp:1011 msgid "Proxy" msgstr "" -#: daemon/HTTPServer.cpp:232 +#: daemon/HTTPServer.cpp:234 msgid "Mesh" msgstr "" -#: daemon/HTTPServer.cpp:240 +#: daemon/HTTPServer.cpp:242 msgid "Clock skew" msgstr "" -#: daemon/HTTPServer.cpp:243 +#: daemon/HTTPServer.cpp:245 msgid "Offline" msgstr "" -#: daemon/HTTPServer.cpp:246 +#: daemon/HTTPServer.cpp:248 msgid "Symmetric NAT" msgstr "" -#: daemon/HTTPServer.cpp:249 +#: daemon/HTTPServer.cpp:251 msgid "Full cone NAT" msgstr "" -#: daemon/HTTPServer.cpp:252 +#: daemon/HTTPServer.cpp:254 msgid "No Descriptors" msgstr "" -#: daemon/HTTPServer.cpp:261 +#: daemon/HTTPServer.cpp:263 msgid "Uptime" msgstr "" -#: daemon/HTTPServer.cpp:264 +#: daemon/HTTPServer.cpp:266 msgid "Network status" msgstr "" -#: daemon/HTTPServer.cpp:269 +#: daemon/HTTPServer.cpp:271 msgid "Network status v6" msgstr "" -#: daemon/HTTPServer.cpp:275 daemon/HTTPServer.cpp:282 +#: daemon/HTTPServer.cpp:277 daemon/HTTPServer.cpp:284 msgid "Stopping in" msgstr "" -#: daemon/HTTPServer.cpp:289 +#: daemon/HTTPServer.cpp:291 msgid "Family" msgstr "" -#: daemon/HTTPServer.cpp:290 +#: daemon/HTTPServer.cpp:292 msgid "Tunnel creation success rate" msgstr "" -#: daemon/HTTPServer.cpp:291 +#: daemon/HTTPServer.cpp:296 +msgid "Total tunnel creation success rate" +msgstr "" + +#: daemon/HTTPServer.cpp:298 msgid "Received" msgstr "" #. tr: Kibibyte/s -#: daemon/HTTPServer.cpp:293 daemon/HTTPServer.cpp:296 -#: daemon/HTTPServer.cpp:299 +#: daemon/HTTPServer.cpp:300 daemon/HTTPServer.cpp:303 +#: daemon/HTTPServer.cpp:306 #, c-format msgid "%.2f KiB/s" msgstr "" -#: daemon/HTTPServer.cpp:294 +#: daemon/HTTPServer.cpp:301 msgid "Sent" msgstr "" -#: daemon/HTTPServer.cpp:297 +#: daemon/HTTPServer.cpp:304 msgid "Transit" msgstr "" -#: daemon/HTTPServer.cpp:300 +#: daemon/HTTPServer.cpp:307 msgid "Data path" msgstr "" -#: daemon/HTTPServer.cpp:303 +#: daemon/HTTPServer.cpp:310 msgid "Hidden content. Press on text to see." msgstr "" -#: daemon/HTTPServer.cpp:307 +#: daemon/HTTPServer.cpp:314 msgid "Router Ident" msgstr "" -#: daemon/HTTPServer.cpp:309 +#: daemon/HTTPServer.cpp:316 msgid "Router Family" msgstr "" -#: daemon/HTTPServer.cpp:310 +#: daemon/HTTPServer.cpp:317 msgid "Router Caps" msgstr "" -#: daemon/HTTPServer.cpp:311 +#: daemon/HTTPServer.cpp:318 msgid "Version" msgstr "" -#: daemon/HTTPServer.cpp:312 +#: daemon/HTTPServer.cpp:319 msgid "Our external address" msgstr "" #. tr: Shown when router doesn't publish itself and have "Firewalled" state -#: daemon/HTTPServer.cpp:341 +#: daemon/HTTPServer.cpp:349 msgid "supported" msgstr "" -#: daemon/HTTPServer.cpp:355 +#: daemon/HTTPServer.cpp:363 msgid "Routers" msgstr "" -#: daemon/HTTPServer.cpp:356 +#: daemon/HTTPServer.cpp:364 msgid "Floodfills" msgstr "" -#: daemon/HTTPServer.cpp:363 daemon/HTTPServer.cpp:938 +#: daemon/HTTPServer.cpp:371 daemon/HTTPServer.cpp:987 msgid "Client Tunnels" msgstr "" -#: daemon/HTTPServer.cpp:373 +#: daemon/HTTPServer.cpp:381 msgid "Services" msgstr "" -#: daemon/HTTPServer.cpp:374 daemon/HTTPServer.cpp:375 -#: daemon/HTTPServer.cpp:376 daemon/HTTPServer.cpp:377 -#: daemon/HTTPServer.cpp:378 daemon/HTTPServer.cpp:379 +#: daemon/HTTPServer.cpp:382 daemon/HTTPServer.cpp:383 +#: daemon/HTTPServer.cpp:384 daemon/HTTPServer.cpp:385 +#: daemon/HTTPServer.cpp:386 daemon/HTTPServer.cpp:387 msgid "Enabled" msgstr "" -#: daemon/HTTPServer.cpp:374 daemon/HTTPServer.cpp:375 -#: daemon/HTTPServer.cpp:376 daemon/HTTPServer.cpp:377 -#: daemon/HTTPServer.cpp:378 daemon/HTTPServer.cpp:379 +#: daemon/HTTPServer.cpp:382 daemon/HTTPServer.cpp:383 +#: daemon/HTTPServer.cpp:384 daemon/HTTPServer.cpp:385 +#: daemon/HTTPServer.cpp:386 daemon/HTTPServer.cpp:387 msgid "Disabled" msgstr "" -#: daemon/HTTPServer.cpp:422 +#: daemon/HTTPServer.cpp:434 msgid "Encrypted B33 address" msgstr "" -#: daemon/HTTPServer.cpp:431 +#: daemon/HTTPServer.cpp:442 msgid "Address registration line" msgstr "" -#: daemon/HTTPServer.cpp:436 +#: daemon/HTTPServer.cpp:447 msgid "Domain" msgstr "" -#: daemon/HTTPServer.cpp:437 +#: daemon/HTTPServer.cpp:448 msgid "Generate" msgstr "" -#: daemon/HTTPServer.cpp:438 +#: daemon/HTTPServer.cpp:449 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:444 +#: daemon/HTTPServer.cpp:457 msgid "Address" msgstr "" -#: daemon/HTTPServer.cpp:444 +#: daemon/HTTPServer.cpp:459 msgid "Type" msgstr "" -#: daemon/HTTPServer.cpp:444 +#: daemon/HTTPServer.cpp:460 msgid "EncType" msgstr "" -#: daemon/HTTPServer.cpp:454 daemon/HTTPServer.cpp:667 +#: daemon/HTTPServer.cpp:467 +msgid "Expire LeaseSet" +msgstr "" + +#: daemon/HTTPServer.cpp:479 daemon/HTTPServer.cpp:697 msgid "Inbound tunnels" msgstr "" #. tr: Milliseconds -#: daemon/HTTPServer.cpp:469 daemon/HTTPServer.cpp:489 -#: daemon/HTTPServer.cpp:681 daemon/HTTPServer.cpp:701 +#: daemon/HTTPServer.cpp:494 daemon/HTTPServer.cpp:514 +#: daemon/HTTPServer.cpp:711 daemon/HTTPServer.cpp:731 #, c-format msgid "%dms" msgstr "" -#: daemon/HTTPServer.cpp:474 daemon/HTTPServer.cpp:686 +#: daemon/HTTPServer.cpp:499 daemon/HTTPServer.cpp:716 msgid "Outbound tunnels" msgstr "" -#: daemon/HTTPServer.cpp:496 +#: daemon/HTTPServer.cpp:521 msgid "Tags" msgstr "" -#: daemon/HTTPServer.cpp:497 +#: daemon/HTTPServer.cpp:522 msgid "Incoming" msgstr "" -#: daemon/HTTPServer.cpp:504 daemon/HTTPServer.cpp:510 +#: daemon/HTTPServer.cpp:529 daemon/HTTPServer.cpp:535 msgid "Outgoing" msgstr "" -#: daemon/HTTPServer.cpp:507 daemon/HTTPServer.cpp:526 +#: daemon/HTTPServer.cpp:532 daemon/HTTPServer.cpp:551 msgid "Destination" msgstr "" -#: daemon/HTTPServer.cpp:507 +#: daemon/HTTPServer.cpp:532 daemon/HTTPServer.cpp:814 msgid "Amount" msgstr "" -#: daemon/HTTPServer.cpp:515 +#: daemon/HTTPServer.cpp:540 msgid "Incoming Tags" msgstr "" -#: daemon/HTTPServer.cpp:523 daemon/HTTPServer.cpp:529 +#: daemon/HTTPServer.cpp:548 daemon/HTTPServer.cpp:554 msgid "Tags sessions" msgstr "" -#: daemon/HTTPServer.cpp:526 +#: daemon/HTTPServer.cpp:551 msgid "Status" msgstr "" -#: daemon/HTTPServer.cpp:536 daemon/HTTPServer.cpp:594 +#: daemon/HTTPServer.cpp:561 daemon/HTTPServer.cpp:621 msgid "Local Destination" msgstr "" -#: daemon/HTTPServer.cpp:547 daemon/HTTPServer.cpp:917 +#: daemon/HTTPServer.cpp:572 daemon/HTTPServer.cpp:960 msgid "Streams" msgstr "" -#: daemon/HTTPServer.cpp:570 +#: daemon/HTTPServer.cpp:595 msgid "Close stream" msgstr "" -#: daemon/HTTPServer.cpp:599 +#: daemon/HTTPServer.cpp:613 daemon/HTTPServer.cpp:1430 +msgid "Such destination is not found" +msgstr "" + +#: daemon/HTTPServer.cpp:626 msgid "I2CP session not found" msgstr "" -#: daemon/HTTPServer.cpp:602 +#: daemon/HTTPServer.cpp:629 msgid "I2CP is not enabled" msgstr "" -#: daemon/HTTPServer.cpp:628 +#: daemon/HTTPServer.cpp:658 msgid "Invalid" msgstr "" -#: daemon/HTTPServer.cpp:631 +#: daemon/HTTPServer.cpp:661 msgid "Store type" msgstr "" -#: daemon/HTTPServer.cpp:632 +#: daemon/HTTPServer.cpp:662 msgid "Expires" msgstr "" -#: daemon/HTTPServer.cpp:637 +#: daemon/HTTPServer.cpp:667 msgid "Non Expired Leases" msgstr "" -#: daemon/HTTPServer.cpp:640 +#: daemon/HTTPServer.cpp:670 msgid "Gateway" msgstr "" -#: daemon/HTTPServer.cpp:641 +#: daemon/HTTPServer.cpp:671 msgid "TunnelID" msgstr "" -#: daemon/HTTPServer.cpp:642 +#: daemon/HTTPServer.cpp:672 msgid "EndDate" msgstr "" -#: daemon/HTTPServer.cpp:652 +#: daemon/HTTPServer.cpp:682 msgid "floodfill mode is disabled" msgstr "" -#: daemon/HTTPServer.cpp:663 +#: daemon/HTTPServer.cpp:693 msgid "Queue size" msgstr "" -#: daemon/HTTPServer.cpp:713 +#: daemon/HTTPServer.cpp:743 msgid "Run peer test" msgstr "" -#: daemon/HTTPServer.cpp:714 +#: daemon/HTTPServer.cpp:744 msgid "Reload tunnels configuration" msgstr "" -#: daemon/HTTPServer.cpp:717 +#: daemon/HTTPServer.cpp:747 msgid "Decline transit tunnels" msgstr "" -#: daemon/HTTPServer.cpp:719 +#: daemon/HTTPServer.cpp:749 msgid "Accept transit tunnels" msgstr "" -#: daemon/HTTPServer.cpp:723 daemon/HTTPServer.cpp:728 +#: daemon/HTTPServer.cpp:753 daemon/HTTPServer.cpp:758 msgid "Cancel graceful shutdown" msgstr "" -#: daemon/HTTPServer.cpp:725 daemon/HTTPServer.cpp:730 +#: daemon/HTTPServer.cpp:755 daemon/HTTPServer.cpp:760 msgid "Start graceful shutdown" msgstr "" -#: daemon/HTTPServer.cpp:733 +#: daemon/HTTPServer.cpp:763 msgid "Force shutdown" msgstr "" -#: daemon/HTTPServer.cpp:734 +#: daemon/HTTPServer.cpp:764 msgid "Reload external CSS styles" msgstr "" -#: daemon/HTTPServer.cpp:737 +#: daemon/HTTPServer.cpp:767 msgid "" "Note: any action done here are not persistent and not changes your " "config files." msgstr "" -#: daemon/HTTPServer.cpp:739 +#: daemon/HTTPServer.cpp:770 msgid "Logging level" msgstr "" -#: daemon/HTTPServer.cpp:747 +#: daemon/HTTPServer.cpp:779 msgid "Transit tunnels limit" msgstr "" -#: daemon/HTTPServer.cpp:752 daemon/HTTPServer.cpp:771 +#: daemon/HTTPServer.cpp:784 daemon/HTTPServer.cpp:803 msgid "Change" msgstr "" -#: daemon/HTTPServer.cpp:759 +#: daemon/HTTPServer.cpp:791 msgid "Change language" msgstr "" -#: daemon/HTTPServer.cpp:797 +#: daemon/HTTPServer.cpp:830 msgid "no transit tunnels currently built" msgstr "" -#: daemon/HTTPServer.cpp:878 daemon/HTTPServer.cpp:901 +#: daemon/HTTPServer.cpp:921 daemon/HTTPServer.cpp:944 msgid "SAM disabled" msgstr "" -#: daemon/HTTPServer.cpp:894 +#: daemon/HTTPServer.cpp:937 msgid "no sessions currently running" msgstr "" -#: daemon/HTTPServer.cpp:907 +#: daemon/HTTPServer.cpp:950 msgid "SAM session not found" msgstr "" -#: daemon/HTTPServer.cpp:912 +#: daemon/HTTPServer.cpp:955 msgid "SAM Session" msgstr "" -#: daemon/HTTPServer.cpp:969 +#: daemon/HTTPServer.cpp:1020 msgid "Server Tunnels" msgstr "" -#: daemon/HTTPServer.cpp:985 +#: daemon/HTTPServer.cpp:1036 msgid "Client Forwards" msgstr "" -#: daemon/HTTPServer.cpp:999 +#: daemon/HTTPServer.cpp:1050 msgid "Server Forwards" msgstr "" -#: daemon/HTTPServer.cpp:1199 +#: daemon/HTTPServer.cpp:1250 msgid "Unknown page" msgstr "" -#: daemon/HTTPServer.cpp:1218 +#: daemon/HTTPServer.cpp:1269 msgid "Invalid token" msgstr "" -#: daemon/HTTPServer.cpp:1276 daemon/HTTPServer.cpp:1333 -#: daemon/HTTPServer.cpp:1373 +#: daemon/HTTPServer.cpp:1327 daemon/HTTPServer.cpp:1359 +#: daemon/HTTPServer.cpp:1414 daemon/HTTPServer.cpp:1454 msgid "SUCCESS" msgstr "" -#: daemon/HTTPServer.cpp:1276 +#: daemon/HTTPServer.cpp:1327 msgid "Stream closed" msgstr "" -#: daemon/HTTPServer.cpp:1278 +#: daemon/HTTPServer.cpp:1329 msgid "Stream not found or already was closed" msgstr "" -#: daemon/HTTPServer.cpp:1281 +#: daemon/HTTPServer.cpp:1332 daemon/HTTPServer.cpp:1365 msgid "Destination not found" msgstr "" -#: daemon/HTTPServer.cpp:1284 +#: daemon/HTTPServer.cpp:1335 msgid "StreamID can't be null" msgstr "" -#: daemon/HTTPServer.cpp:1286 daemon/HTTPServer.cpp:1351 +#: daemon/HTTPServer.cpp:1337 daemon/HTTPServer.cpp:1367 +#: daemon/HTTPServer.cpp:1432 msgid "Return to destination page" msgstr "" -#: daemon/HTTPServer.cpp:1287 daemon/HTTPServer.cpp:1300 -#: daemon/HTTPServer.cpp:1375 +#: daemon/HTTPServer.cpp:1338 daemon/HTTPServer.cpp:1368 +#: daemon/HTTPServer.cpp:1381 daemon/HTTPServer.cpp:1456 #, c-format msgid "You will be redirected in %d seconds" msgstr "" -#: daemon/HTTPServer.cpp:1298 +#: daemon/HTTPServer.cpp:1359 +msgid "LeaseSet expiration time updated" +msgstr "" + +#: daemon/HTTPServer.cpp:1362 +msgid "LeaseSet is not found or already expired" +msgstr "" + +#: daemon/HTTPServer.cpp:1379 #, c-format msgid "Transit tunnels count must not exceed %d" msgstr "" -#: daemon/HTTPServer.cpp:1299 daemon/HTTPServer.cpp:1374 +#: daemon/HTTPServer.cpp:1380 daemon/HTTPServer.cpp:1455 msgid "Back to commands list" msgstr "" -#: daemon/HTTPServer.cpp:1335 +#: daemon/HTTPServer.cpp:1416 msgid "Register at reg.i2p" msgstr "" -#: daemon/HTTPServer.cpp:1336 +#: daemon/HTTPServer.cpp:1417 msgid "Description" msgstr "" -#: daemon/HTTPServer.cpp:1336 +#: daemon/HTTPServer.cpp:1417 msgid "A bit information about service on domain" msgstr "" -#: daemon/HTTPServer.cpp:1337 +#: daemon/HTTPServer.cpp:1418 msgid "Submit" msgstr "" -#: daemon/HTTPServer.cpp:1343 +#: daemon/HTTPServer.cpp:1424 msgid "Domain can't end with .b32.i2p" msgstr "" -#: daemon/HTTPServer.cpp:1346 +#: daemon/HTTPServer.cpp:1427 msgid "Domain must end with .i2p" msgstr "" -#: daemon/HTTPServer.cpp:1349 -msgid "Such destination is not found" -msgstr "" - -#: daemon/HTTPServer.cpp:1369 +#: daemon/HTTPServer.cpp:1450 msgid "Unknown command" msgstr "" -#: daemon/HTTPServer.cpp:1373 +#: daemon/HTTPServer.cpp:1454 msgid "Command accepted" msgstr "" @@ -624,20 +642,20 @@ msgstr "" msgid "You may try to find this host on jump services below" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:309 libi2pd_client/HTTPProxy.cpp:324 -#: libi2pd_client/HTTPProxy.cpp:392 libi2pd_client/HTTPProxy.cpp:435 +#: libi2pd_client/HTTPProxy.cpp:333 libi2pd_client/HTTPProxy.cpp:348 +#: libi2pd_client/HTTPProxy.cpp:417 libi2pd_client/HTTPProxy.cpp:460 msgid "Invalid request" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:309 +#: libi2pd_client/HTTPProxy.cpp:333 msgid "Proxy unable to parse your request" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:324 +#: libi2pd_client/HTTPProxy.cpp:348 msgid "Addresshelper is not supported" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:349 +#: libi2pd_client/HTTPProxy.cpp:373 #, c-format msgid "" "Host %s is already in router's addressbook. Be " @@ -645,121 +663,121 @@ msgid "" "Continue." msgstr "" -#: libi2pd_client/HTTPProxy.cpp:351 +#: libi2pd_client/HTTPProxy.cpp:375 msgid "Addresshelper forced update rejected" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:358 +#: libi2pd_client/HTTPProxy.cpp:382 #, c-format msgid "" -"To add host %s in router's addressbook, click here: Continue." +"To add host %s in router's addressbook, click here: Continue." msgstr "" -#: libi2pd_client/HTTPProxy.cpp:360 +#: libi2pd_client/HTTPProxy.cpp:384 msgid "Addresshelper request" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:369 +#: libi2pd_client/HTTPProxy.cpp:393 #, c-format msgid "" "Host %s added to router's addressbook from helper. Click here to proceed: Continue." msgstr "" -#: libi2pd_client/HTTPProxy.cpp:370 +#: libi2pd_client/HTTPProxy.cpp:395 msgid "Addresshelper adding" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:377 +#: libi2pd_client/HTTPProxy.cpp:402 #, c-format msgid "" "Host %s is already in router's addressbook. Click " "here to update record: Continue." msgstr "" -#: libi2pd_client/HTTPProxy.cpp:379 +#: libi2pd_client/HTTPProxy.cpp:404 msgid "Addresshelper update" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:392 +#: libi2pd_client/HTTPProxy.cpp:417 msgid "Invalid request URI" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:435 +#: libi2pd_client/HTTPProxy.cpp:460 msgid "Can't detect destination host from request" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:452 libi2pd_client/HTTPProxy.cpp:456 +#: libi2pd_client/HTTPProxy.cpp:477 libi2pd_client/HTTPProxy.cpp:481 msgid "Outproxy failure" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:452 +#: libi2pd_client/HTTPProxy.cpp:477 msgid "Bad outproxy settings" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:455 +#: libi2pd_client/HTTPProxy.cpp:480 #, c-format msgid "Host %s is not inside I2P network, but outproxy is not enabled" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:544 +#: libi2pd_client/HTTPProxy.cpp:569 msgid "Unknown outproxy URL" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:550 +#: libi2pd_client/HTTPProxy.cpp:575 msgid "Cannot resolve upstream proxy" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:558 +#: libi2pd_client/HTTPProxy.cpp:583 msgid "Hostname is too long" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:585 +#: libi2pd_client/HTTPProxy.cpp:610 msgid "Cannot connect to upstream SOCKS proxy" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:591 +#: libi2pd_client/HTTPProxy.cpp:616 msgid "Cannot negotiate with SOCKS proxy" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:633 +#: libi2pd_client/HTTPProxy.cpp:658 msgid "CONNECT error" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:633 +#: libi2pd_client/HTTPProxy.cpp:658 msgid "Failed to connect" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:644 libi2pd_client/HTTPProxy.cpp:670 +#: libi2pd_client/HTTPProxy.cpp:669 libi2pd_client/HTTPProxy.cpp:695 msgid "SOCKS proxy error" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:652 +#: libi2pd_client/HTTPProxy.cpp:677 msgid "Failed to send request to upstream" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:673 +#: libi2pd_client/HTTPProxy.cpp:698 msgid "No reply from SOCKS proxy" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:680 +#: libi2pd_client/HTTPProxy.cpp:705 msgid "Cannot connect" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:680 +#: libi2pd_client/HTTPProxy.cpp:705 msgid "HTTP out proxy not implemented" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:681 +#: libi2pd_client/HTTPProxy.cpp:706 msgid "Cannot connect to upstream HTTP proxy" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:714 +#: libi2pd_client/HTTPProxy.cpp:739 msgid "Host is down" msgstr "" -#: libi2pd_client/HTTPProxy.cpp:714 +#: libi2pd_client/HTTPProxy.cpp:739 msgid "" "Can't create connection to requested host, it may be down. Please try again " "later." diff --git a/contrib/i18n/README.md b/contrib/i18n/README.md index 56d76c5a..1a9bd289 100644 --- a/contrib/i18n/README.md +++ b/contrib/i18n/README.md @@ -2,7 +2,7 @@ --- ``` -xgettext --omit-header -ctr: -ktr -ktr:1,2 daemon/HTTPServer.cpp libi2pd_client/HTTPProxy.cpp +xgettext --omit-header -ctr: -ktr -kntr:1,2 daemon/HTTPServer.cpp libi2pd_client/HTTPProxy.cpp ``` Regex for transforming gettext translations to our format: From bb52056aec59a296df6bec7ee44184b7a4b75136 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 11 Jun 2023 06:48:47 -0400 Subject: [PATCH 0149/1171] correct index for connected transport --- libi2pd/Transports.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index f66a8f96..8daf56ef 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -710,9 +710,9 @@ namespace transport transports |= it->second.priority[i]; i2p::data::netdb.ExcludeReachableTransports (ident, transports); } - if (it->second.router) + if (it->second.router && it->second.numAttempts) { - auto transport = it->second.priority[it->second.numAttempts]; + auto transport = it->second.priority[it->second.numAttempts-1]; if (transport == i2p::data::RouterInfo::eNTCP2V4 || transport == i2p::data::RouterInfo::eNTCP2V6 || transport == i2p::data::RouterInfo::eNTCP2V6Mesh) it->second.router->GetProfile ()->Connected (); // outgoing NTCP2 connection if always real From 52b2d6c39397f27fbeb9cab52cdf69c3fba5e0cb Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 11 Jun 2023 15:44:16 -0400 Subject: [PATCH 0150/1171] 2.48.0 --- ChangeLog | 27 +++++++++++++++++++++++++++ contrib/rpm/i2pd-git.spec | 5 ++++- contrib/rpm/i2pd.spec | 5 ++++- debian/changelog | 6 ++++++ libi2pd/version.h | 4 ++-- 5 files changed, 43 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index b6005d4f..424aaee5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,33 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog +## [2.48.0] - 2023-06-12 +### Added +- Allow user/password authentication method for SOCK5 proxy +- Publish reject all congestion cap 'G' if transit is not accepted +- 'critical' log level +- Print b32 on webconsole destination page +- Webconsole button to drop a remote LeaseSet +- limits.zombies param - minimum percentage of successfully created tunnels for routers cleanup +- Recognize real routers if successfully connected or responded to tunnel build request +### Changed +- Bypass slow transport sessions for first hop selection +- Limit AESNI inline asm to x86/x64 +- Create smaller I2NP packets if possible +- Make router unreachable if AEAD tag verification fails in SessionCreated +- Don't include a router to floodfills list until it's confirmed as real +- Drop LeaseSet store request if not floodfill +- Bypass medium congestion('D') routers for client tunnels +- Publish encrypted RouterInfo through tunnels +- Check if s is valid x25519 public key +- Check if socket is open before sending data in SSU2 +### Fixed +- Webconsole empty page if destination is not found +- i2p.streaming.answerPings param +- Reload tunnels +- Address caps for unspecified ipv6 address +- Incomplete HTTP headers in I2P tunnels + ## [2.47.0] - 2023-03-11 ### Added - Congestion caps diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index 4ee7a8df..62a28631 100644 --- a/contrib/rpm/i2pd-git.spec +++ b/contrib/rpm/i2pd-git.spec @@ -1,7 +1,7 @@ %define git_hash %(git rev-parse HEAD | cut -c -7) Name: i2pd-git -Version: 2.47.0 +Version: 2.48.0 Release: git%{git_hash}%{?dist} Summary: I2P router written in C++ Conflicts: i2pd @@ -158,6 +158,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Mon Jun 12 2023 orignal - 2.48.0 +- update to 2.48.0 + * Sat Mar 11 2023 orignal - 2.47.0 - update to 2.47.0 diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 407e2d43..19825237 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,5 +1,5 @@ Name: i2pd -Version: 2.47.0 +Version: 2.48.0 Release: 1%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git @@ -155,6 +155,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Mon Jun 12 2023 orignal - 2.48.0 +- update to 2.48.0 + * Sat Mar 11 2023 orignal - 2.47.0 - update to 2.47.0 diff --git a/debian/changelog b/debian/changelog index 44b0b8b5..91b0abdf 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i2pd (2.48.0-1) unstable; urgency=high + + * updated to version 2.48.0/0.9.59 + + -- orignal Mon, 12 Jun 2023 16:00:00 +0000 + i2pd (2.47.0-1) unstable; urgency=high * updated to version 2.47.0/0.9.58 diff --git a/libi2pd/version.h b/libi2pd/version.h index 7d5e79fb..903ceebc 100644 --- a/libi2pd/version.h +++ b/libi2pd/version.h @@ -18,7 +18,7 @@ #define MAKE_VERSION_NUMBER(a,b,c) ((a*100+b)*100+c) #define I2PD_VERSION_MAJOR 2 -#define I2PD_VERSION_MINOR 47 +#define I2PD_VERSION_MINOR 48 #define I2PD_VERSION_MICRO 0 #define I2PD_VERSION_PATCH 0 #ifdef GITVER @@ -33,7 +33,7 @@ #define I2P_VERSION_MAJOR 0 #define I2P_VERSION_MINOR 9 -#define I2P_VERSION_MICRO 58 +#define I2P_VERSION_MICRO 59 #define I2P_VERSION_PATCH 0 #define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO) #define I2P_VERSION_NUMBER MAKE_VERSION_NUMBER(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO) From 3af1f4bc763d6a47d982944b6f8bcbb8eb8541a0 Mon Sep 17 00:00:00 2001 From: r4sas Date: Mon, 12 Jun 2023 00:32:44 +0300 Subject: [PATCH 0151/1171] Use of 'server' type tunnel port as inport (#1936) Signed-off-by: r4sas --- ChangeLog | 8 +++++--- libi2pd_client/I2PTunnel.cpp | 18 +++++++++--------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 424aaee5..881e05d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,9 +5,9 @@ ### Added - Allow user/password authentication method for SOCK5 proxy - Publish reject all congestion cap 'G' if transit is not accepted -- 'critical' log level +- 'critical' log level - Print b32 on webconsole destination page -- Webconsole button to drop a remote LeaseSet +- Webconsole button to drop a remote LeaseSet - limits.zombies param - minimum percentage of successfully created tunnels for routers cleanup - Recognize real routers if successfully connected or responded to tunnel build request ### Changed @@ -26,7 +26,9 @@ - i2p.streaming.answerPings param - Reload tunnels - Address caps for unspecified ipv6 address -- Incomplete HTTP headers in I2P tunnels +- Incomplete HTTP headers in I2P tunnels +- SSU2 socket network exceptions on Windows +- Use of 'server' type tunnel port as inport (#1936) ## [2.47.0] - 2023-03-11 ### Added diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index d1006f26..1118da24 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -351,7 +351,7 @@ namespace client m_InHeader.clear (); m_InHeader << line; break; - } + } } if (endOfHeader) @@ -434,12 +434,12 @@ namespace client } } else - { + { // insert incomplete line back m_InHeader.clear (); m_InHeader << line; break; - } + } } if (endOfHeader) @@ -508,12 +508,12 @@ namespace client } } else - { + { // insert incomplete line back m_InHeader.clear (); m_InHeader << line; break; - } + } } if (endOfHeader) @@ -708,10 +708,10 @@ namespace client int port, std::shared_ptr localDestination, int inport, bool gzip): I2PService (localDestination), m_IsUniqueLocal(true), m_Name (name), m_Address (address), m_Port (port), m_IsAccessList (false) { - if (!inport) inport = port; - m_PortDestination = localDestination->GetStreamingDestination (inport); - if (!m_PortDestination) // default destination - m_PortDestination = localDestination->CreateStreamingDestination (inport, gzip); + int inPort = (inport ? inport : port); + m_PortDestination = localDestination->GetStreamingDestination (inPort); + if (!m_PortDestination) // default destination + m_PortDestination = localDestination->CreateStreamingDestination (inPort, gzip); } void I2PServerTunnel::Start () From 03cc6e05249be47be31ed1ad2c4455c6c537de75 Mon Sep 17 00:00:00 2001 From: r4sas Date: Mon, 12 Jun 2023 05:10:32 +0300 Subject: [PATCH 0152/1171] use uint16_t for ports Signed-off-by: r4sas --- libi2pd/Destination.cpp | 18 +++++++++--------- libi2pd/Destination.h | 18 +++++++++--------- libi2pd_client/BOB.cpp | 26 ++++++++++++++++---------- libi2pd_client/BOB.h | 20 ++++++++++---------- libi2pd_client/ClientContext.cpp | 26 +++++++++++++------------- libi2pd_client/HTTPProxy.cpp | 2 +- libi2pd_client/HTTPProxy.h | 6 +++--- libi2pd_client/I2CP.cpp | 2 +- libi2pd_client/I2CP.h | 4 ++-- libi2pd_client/I2PService.cpp | 6 +++--- libi2pd_client/I2PService.h | 10 +++++----- libi2pd_client/I2PTunnel.cpp | 20 ++++++++++---------- libi2pd_client/I2PTunnel.h | 24 ++++++++++++------------ libi2pd_client/SAM.cpp | 4 ++-- libi2pd_client/SAM.h | 6 +++--- libi2pd_client/SOCKS.cpp | 2 +- libi2pd_client/SOCKS.h | 4 ++-- 17 files changed, 102 insertions(+), 96 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index a755347d..b9555abe 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1111,7 +1111,7 @@ namespace client } } - void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, int port) + void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, uint16_t port) { if (!streamRequestComplete) { @@ -1141,7 +1141,7 @@ namespace client } } - void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, std::shared_ptr dest, int port) + void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, std::shared_ptr dest, uint16_t port) { if (!streamRequestComplete) { @@ -1160,7 +1160,7 @@ namespace client } template - std::shared_ptr ClientDestination::CreateStreamSync (const Dest& dest, int port) + std::shared_ptr ClientDestination::CreateStreamSync (const Dest& dest, uint16_t port) { volatile bool done = false; std::shared_ptr stream; @@ -1184,17 +1184,17 @@ namespace client return stream; } - std::shared_ptr ClientDestination::CreateStream (const i2p::data::IdentHash& dest, int port) + std::shared_ptr ClientDestination::CreateStream (const i2p::data::IdentHash& dest, uint16_t port) { return CreateStreamSync (dest, port); } - std::shared_ptr ClientDestination::CreateStream (std::shared_ptr dest, int port) + std::shared_ptr ClientDestination::CreateStream (std::shared_ptr dest, uint16_t port) { return CreateStreamSync (dest, port); } - std::shared_ptr ClientDestination::CreateStream (std::shared_ptr remote, int port) + std::shared_ptr ClientDestination::CreateStream (std::shared_ptr remote, uint16_t port) { if (m_StreamingDestination) return m_StreamingDestination->CreateNewOutgoingStream (remote, port); @@ -1231,7 +1231,7 @@ namespace client }); } - std::shared_ptr ClientDestination::GetStreamingDestination (int port) const + std::shared_ptr ClientDestination::GetStreamingDestination (uint16_t port) const { if (port) { @@ -1269,7 +1269,7 @@ namespace client m_StreamingDestination->AcceptOnce (acceptor); } - std::shared_ptr ClientDestination::CreateStreamingDestination (int port, bool gzip) + std::shared_ptr ClientDestination::CreateStreamingDestination (uint16_t port, bool gzip) { auto dest = std::make_shared (GetSharedFromThis (), port, gzip); if (port) @@ -1279,7 +1279,7 @@ namespace client return dest; } - std::shared_ptr ClientDestination::RemoveStreamingDestination (int port) + std::shared_ptr ClientDestination::RemoveStreamingDestination (uint16_t port) { if (port) { diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 76508e49..3b395f4d 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -242,15 +242,15 @@ namespace client int GetRefCounter () const { return m_RefCounter; }; // streaming - std::shared_ptr CreateStreamingDestination (int port, bool gzip = true); // additional - std::shared_ptr GetStreamingDestination (int port = 0) const; - std::shared_ptr RemoveStreamingDestination (int port); + std::shared_ptr CreateStreamingDestination (uint16_t port, bool gzip = true); // additional + std::shared_ptr GetStreamingDestination (uint16_t port = 0) const; + std::shared_ptr RemoveStreamingDestination (uint16_t port); // following methods operate with default streaming destination - void CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, int port = 0); - void CreateStream (StreamRequestComplete streamRequestComplete, std::shared_ptr dest, int port = 0); - std::shared_ptr CreateStream (const i2p::data::IdentHash& dest, int port = 0); // sync - std::shared_ptr CreateStream (std::shared_ptr dest, int port = 0); // sync - std::shared_ptr CreateStream (std::shared_ptr remote, int port = 0); + void CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, uint16_t port = 0); + void CreateStream (StreamRequestComplete streamRequestComplete, std::shared_ptr dest, uint16_t port = 0); + std::shared_ptr CreateStream (const i2p::data::IdentHash& dest, uint16_t port = 0); // sync + std::shared_ptr CreateStream (std::shared_ptr dest, uint16_t port = 0); // sync + std::shared_ptr CreateStream (std::shared_ptr remote, uint16_t port = 0); void SendPing (const i2p::data::IdentHash& to); void SendPing (std::shared_ptr to); void AcceptStreams (const i2p::stream::StreamingDestination::Acceptor& acceptor); @@ -286,7 +286,7 @@ namespace client void ReadAuthKey (const std::string& group, const std::map * params); template - std::shared_ptr CreateStreamSync (const Dest& dest, int port); + std::shared_ptr CreateStreamSync (const Dest& dest, uint16_t port); private: diff --git a/libi2pd_client/BOB.cpp b/libi2pd_client/BOB.cpp index 5f738380..3e6590f2 100644 --- a/libi2pd_client/BOB.cpp +++ b/libi2pd_client/BOB.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -127,7 +127,7 @@ namespace client connection->I2PConnect (receiver->data, receiver->dataLen); } - BOBI2POutboundTunnel::BOBI2POutboundTunnel (const std::string& outhost, int port, + BOBI2POutboundTunnel::BOBI2POutboundTunnel (const std::string& outhost, uint16_t port, std::shared_ptr localDestination, bool quiet): BOBI2PTunnel (localDestination), m_Endpoint (boost::asio::ip::address::from_string (outhost), port), m_IsQuiet (quiet) { @@ -164,7 +164,7 @@ namespace client BOBDestination::BOBDestination (std::shared_ptr localDestination, const std::string &nickname, const std::string &inhost, const std::string &outhost, - const int inport, const int outport, const bool quiet): + const uint16_t inport, const uint16_t outport, const bool quiet): m_LocalDestination (localDestination), m_OutboundTunnel (nullptr), m_InboundTunnel (nullptr), m_Nickname(nickname), m_InHost(inhost), m_OutHost(outhost), @@ -209,7 +209,7 @@ namespace client } } - void BOBDestination::CreateInboundTunnel (int port, const std::string& inhost) + void BOBDestination::CreateInboundTunnel (uint16_t port, const std::string& inhost) { if (!m_InboundTunnel) { @@ -230,7 +230,7 @@ namespace client } } - void BOBDestination::CreateOutboundTunnel (const std::string& outhost, int port, bool quiet) + void BOBDestination::CreateOutboundTunnel (const std::string& outhost, uint16_t port, bool quiet) { if (!m_OutboundTunnel) { @@ -595,9 +595,12 @@ namespace client LogPrint (eLogDebug, "BOB: outport ", operand); if (*operand) { - m_OutPort = std::stoi(operand); - if (m_OutPort >= 0) + int port = std::stoi(operand); + if (port >= 0 && port < 65536) + { + m_OutPort = port; SendReplyOK ("outbound port set"); + } else SendReplyError ("port out of range"); } @@ -622,9 +625,12 @@ namespace client LogPrint (eLogDebug, "BOB: inport ", operand); if (*operand) { - m_InPort = std::stoi(operand); - if (m_InPort >= 0) + int port = std::stoi(operand); + if (port >= 0 && port < 65536) + { + m_InPort = port; SendReplyOK ("inbound port set"); + } else SendReplyError ("port out of range"); } @@ -814,7 +820,7 @@ namespace client } } - BOBCommandChannel::BOBCommandChannel (const std::string& address, int port): + BOBCommandChannel::BOBCommandChannel (const std::string& address, uint16_t port): RunnableService ("BOB"), m_Acceptor (GetIOService (), boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(address), port)) { diff --git a/libi2pd_client/BOB.h b/libi2pd_client/BOB.h index 2e6314e2..8b0b31d2 100644 --- a/libi2pd_client/BOB.h +++ b/libi2pd_client/BOB.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -124,7 +124,7 @@ namespace client { public: - BOBI2POutboundTunnel (const std::string& outhost, int port, std::shared_ptr localDestination, bool quiet); + BOBI2POutboundTunnel (const std::string& outhost, uint16_t port, std::shared_ptr localDestination, bool quiet); void Start (); void Stop (); @@ -149,19 +149,19 @@ namespace client BOBDestination (std::shared_ptr localDestination, const std::string &nickname, const std::string &inhost, const std::string &outhost, - const int inport, const int outport, const bool quiet); + const uint16_t inport, const uint16_t outport, const bool quiet); ~BOBDestination (); void Start (); void Stop (); void StopTunnels (); - void CreateInboundTunnel (int port, const std::string& inhost); - void CreateOutboundTunnel (const std::string& outhost, int port, bool quiet); + void CreateInboundTunnel (uint16_t port, const std::string& inhost); + void CreateOutboundTunnel (const std::string& outhost, uint16_t port, bool quiet); const std::string& GetNickname() const { return m_Nickname; } const std::string& GetInHost() const { return m_InHost; } const std::string& GetOutHost() const { return m_OutHost; } - int GetInPort() const { return m_InPort; } - int GetOutPort() const { return m_OutPort; } + uint16_t GetInPort() const { return m_InPort; } + uint16_t GetOutPort() const { return m_OutPort; } bool GetQuiet() const { return m_Quiet; } bool IsRunning() const { return m_IsRunning; } const i2p::data::PrivateKeys& GetKeys () const { return m_LocalDestination->GetPrivateKeys (); }; @@ -175,7 +175,7 @@ namespace client std::string m_Nickname; std::string m_InHost, m_OutHost; - int m_InPort, m_OutPort; + uint16_t m_InPort, m_OutPort; bool m_Quiet; bool m_IsRunning; }; @@ -237,7 +237,7 @@ namespace client boost::asio::streambuf m_ReceiveBuffer, m_SendBuffer; bool m_IsOpen, m_IsQuiet, m_IsActive; std::string m_Nickname, m_InHost, m_OutHost; - int m_InPort, m_OutPort; + uint16_t m_InPort, m_OutPort; i2p::data::PrivateKeys m_Keys; std::map m_Options; BOBDestination * m_CurrentDestination; @@ -248,7 +248,7 @@ namespace client { public: - BOBCommandChannel (const std::string& address, int port); + BOBCommandChannel (const std::string& address, uint16_t port); ~BOBCommandChannel (); void Start (); diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index afb34c2a..829756a1 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -577,12 +577,12 @@ namespace client std::string dest; if (type == I2P_TUNNELS_SECTION_TYPE_CLIENT || type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT) dest = section.second.get (I2P_CLIENT_TUNNEL_DESTINATION); - int port = section.second.get (I2P_CLIENT_TUNNEL_PORT); + uint16_t port = section.second.get (I2P_CLIENT_TUNNEL_PORT); // optional params - bool matchTunnels = section.second.get(I2P_CLIENT_TUNNEL_MATCH_TUNNELS, false); - std::string keys = section.second.get (I2P_CLIENT_TUNNEL_KEYS, "transient"); - std::string address = section.second.get (I2P_CLIENT_TUNNEL_ADDRESS, "127.0.0.1"); - int destinationPort = section.second.get (I2P_CLIENT_TUNNEL_DESTINATION_PORT, 0); + bool matchTunnels = section.second.get (I2P_CLIENT_TUNNEL_MATCH_TUNNELS, false); + std::string keys = section.second.get (I2P_CLIENT_TUNNEL_KEYS, "transient"); + std::string address = section.second.get (I2P_CLIENT_TUNNEL_ADDRESS, "127.0.0.1"); + uint16_t destinationPort = section.second.get (I2P_CLIENT_TUNNEL_DESTINATION_PORT, 0); i2p::data::SigningKeyType sigType = section.second.get (I2P_CLIENT_TUNNEL_SIGNATURE_TYPE, i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519); i2p::data::CryptoKeyType cryptoType = section.second.get (I2P_CLIENT_TUNNEL_CRYPTO_TYPE, i2p::data::CRYPTO_KEY_TYPE_ELGAMAL); // I2CP @@ -720,22 +720,22 @@ namespace client { // mandatory params std::string host = section.second.get (I2P_SERVER_TUNNEL_HOST); - int port = section.second.get (I2P_SERVER_TUNNEL_PORT); + uint16_t port = section.second.get (I2P_SERVER_TUNNEL_PORT); std::string keys = section.second.get (I2P_SERVER_TUNNEL_KEYS); // optional params - int inPort = section.second.get (I2P_SERVER_TUNNEL_INPORT, 0); - std::string accessList = section.second.get (I2P_SERVER_TUNNEL_ACCESS_LIST, ""); + uint16_t inPort = section.second.get (I2P_SERVER_TUNNEL_INPORT, 0); + std::string accessList = section.second.get (I2P_SERVER_TUNNEL_ACCESS_LIST, ""); if(accessList == "") - accessList=section.second.get (I2P_SERVER_TUNNEL_WHITE_LIST, ""); - std::string hostOverride = section.second.get (I2P_SERVER_TUNNEL_HOST_OVERRIDE, ""); + accessList = section.second.get (I2P_SERVER_TUNNEL_WHITE_LIST, ""); + std::string hostOverride = section.second.get (I2P_SERVER_TUNNEL_HOST_OVERRIDE, ""); std::string webircpass = section.second.get (I2P_SERVER_TUNNEL_WEBIRC_PASSWORD, ""); bool gzip = section.second.get (I2P_SERVER_TUNNEL_GZIP, false); i2p::data::SigningKeyType sigType = section.second.get (I2P_SERVER_TUNNEL_SIGNATURE_TYPE, i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519); i2p::data::CryptoKeyType cryptoType = section.second.get (I2P_CLIENT_TUNNEL_CRYPTO_TYPE, i2p::data::CRYPTO_KEY_TYPE_ELGAMAL); std::string address = section.second.get (I2P_SERVER_TUNNEL_ADDRESS, ""); - bool isUniqueLocal = section.second.get(I2P_SERVER_TUNNEL_ENABLE_UNIQUE_LOCAL, true); - bool ssl = section.second.get(I2P_SERVER_TUNNEL_SSL, false); + bool isUniqueLocal = section.second.get (I2P_SERVER_TUNNEL_ENABLE_UNIQUE_LOCAL, true); + bool ssl = section.second.get (I2P_SERVER_TUNNEL_SSL, false); // I2CP std::map options; diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index 61930876..26b47d8b 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -748,7 +748,7 @@ namespace proxy { Done (shared_from_this()); } - HTTPProxy::HTTPProxy(const std::string& name, const std::string& address, int port, const std::string & outproxy, bool addresshelper, std::shared_ptr localDestination): + HTTPProxy::HTTPProxy(const std::string& name, const std::string& address, uint16_t port, const std::string & outproxy, bool addresshelper, std::shared_ptr localDestination): TCPIPAcceptor (address, port, localDestination ? localDestination : i2p::client::context.GetSharedLocalDestination ()), m_Name (name), m_OutproxyUrl (outproxy), m_Addresshelper (addresshelper) { diff --git a/libi2pd_client/HTTPProxy.h b/libi2pd_client/HTTPProxy.h index 69ed4cef..d819a53c 100644 --- a/libi2pd_client/HTTPProxy.h +++ b/libi2pd_client/HTTPProxy.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -15,8 +15,8 @@ namespace proxy { { public: - HTTPProxy(const std::string& name, const std::string& address, int port, const std::string & outproxy, bool addresshelper, std::shared_ptr localDestination); - HTTPProxy(const std::string& name, const std::string& address, int port, std::shared_ptr localDestination = nullptr) : + HTTPProxy(const std::string& name, const std::string& address, uint16_t port, const std::string & outproxy, bool addresshelper, std::shared_ptr localDestination); + HTTPProxy(const std::string& name, const std::string& address, uint16_t port, std::shared_ptr localDestination = nullptr) : HTTPProxy(name, address, port, "", true, localDestination) {} ; ~HTTPProxy() {}; diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index 87f37e5e..2c53e766 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -936,7 +936,7 @@ namespace client } } - I2CPServer::I2CPServer (const std::string& interface, int port, bool isSingleThread): + I2CPServer::I2CPServer (const std::string& interface, uint16_t port, bool isSingleThread): RunnableService ("I2CP"), m_IsSingleThread (isSingleThread), m_Acceptor (GetIOService (), boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(interface), port)) diff --git a/libi2pd_client/I2CP.h b/libi2pd_client/I2CP.h index e38da0ac..f0081ef6 100644 --- a/libi2pd_client/I2CP.h +++ b/libi2pd_client/I2CP.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -210,7 +210,7 @@ namespace client { public: - I2CPServer (const std::string& interface, int port, bool isSingleThread); + I2CPServer (const std::string& interface, uint16_t port, bool isSingleThread); ~I2CPServer (); void Start (); diff --git a/libi2pd_client/I2PService.cpp b/libi2pd_client/I2PService.cpp index 2a6fe44e..c30b7c9f 100644 --- a/libi2pd_client/I2PService.cpp +++ b/libi2pd_client/I2PService.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -107,7 +107,7 @@ namespace client m_ReadyTimerTriggered = false; } - void I2PService::CreateStream (StreamRequestComplete streamRequestComplete, const std::string& dest, int port) { + void I2PService::CreateStream (StreamRequestComplete streamRequestComplete, const std::string& dest, uint16_t port) { assert(streamRequestComplete); auto address = i2p::client::context.GetAddressBook ().GetAddress (dest); if (address) @@ -119,7 +119,7 @@ namespace client } } - void I2PService::CreateStream(StreamRequestComplete streamRequestComplete, std::shared_ptr address, int port) + void I2PService::CreateStream(StreamRequestComplete streamRequestComplete, std::shared_ptr address, uint16_t port) { if(m_ConnectTimeout && !m_LocalDestination->IsReady()) { diff --git a/libi2pd_client/I2PService.h b/libi2pd_client/I2PService.h index e14f85c1..4f67e19c 100644 --- a/libi2pd_client/I2PService.h +++ b/libi2pd_client/I2PService.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -59,8 +59,8 @@ namespace client if (dest) dest->Acquire (); m_LocalDestination = dest; } - void CreateStream (StreamRequestComplete streamRequestComplete, const std::string& dest, int port = 0); - void CreateStream(StreamRequestComplete complete, std::shared_ptr address, int port); + void CreateStream (StreamRequestComplete streamRequestComplete, const std::string& dest, uint16_t port = 0); + void CreateStream(StreamRequestComplete complete, std::shared_ptr address, uint16_t port); inline boost::asio::io_service& GetService () { return m_LocalDestination->GetService (); } virtual void Start () = 0; @@ -155,11 +155,11 @@ namespace client { public: - TCPIPAcceptor (const std::string& address, int port, std::shared_ptr localDestination = nullptr) : + TCPIPAcceptor (const std::string& address, uint16_t port, std::shared_ptr localDestination = nullptr) : I2PService(localDestination), m_LocalEndpoint (boost::asio::ip::address::from_string(address), port), m_Timer (GetService ()) {} - TCPIPAcceptor (const std::string& address, int port, i2p::data::SigningKeyType kt) : + TCPIPAcceptor (const std::string& address, uint16_t port, i2p::data::SigningKeyType kt) : I2PService(kt), m_LocalEndpoint (boost::asio::ip::address::from_string(address), port), m_Timer (GetService ()) {} diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index 1118da24..9a9a4988 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -31,7 +31,7 @@ namespace client } I2PTunnelConnection::I2PTunnelConnection (I2PService * owner, std::shared_ptr socket, - std::shared_ptr leaseSet, int port): + std::shared_ptr leaseSet, uint16_t port): I2PServiceHandler(owner), m_Socket (socket), m_RemoteEndpoint (socket->remote_endpoint ()), m_IsQuiet (true) { @@ -581,7 +581,7 @@ namespace client { public: I2PClientTunnelHandler (I2PClientTunnel * parent, std::shared_ptr address, - int destinationPort, std::shared_ptr socket): + uint16_t destinationPort, std::shared_ptr socket): I2PServiceHandler(parent), m_Address(address), m_DestinationPort (destinationPort), m_Socket(socket) {}; void Handle(); @@ -589,7 +589,7 @@ namespace client private: void HandleStreamRequestComplete (std::shared_ptr stream); std::shared_ptr m_Address; - int m_DestinationPort; + uint16_t m_DestinationPort; std::shared_ptr m_Socket; }; @@ -630,7 +630,7 @@ namespace client } I2PClientTunnel::I2PClientTunnel (const std::string& name, const std::string& destination, - const std::string& address, int port, std::shared_ptr localDestination, int destinationPort): + const std::string& address, uint16_t port, std::shared_ptr localDestination, uint16_t destinationPort): TCPIPAcceptor (address, port, localDestination), m_Name (name), m_Destination (destination), m_DestinationPort (destinationPort), m_KeepAliveInterval (0) { @@ -705,10 +705,10 @@ namespace client } I2PServerTunnel::I2PServerTunnel (const std::string& name, const std::string& address, - int port, std::shared_ptr localDestination, int inport, bool gzip): + uint16_t port, std::shared_ptr localDestination, uint16_t inport, bool gzip): I2PService (localDestination), m_IsUniqueLocal(true), m_Name (name), m_Address (address), m_Port (port), m_IsAccessList (false) { - int inPort = (inport ? inport : port); + uint16_t inPort = (inport ? inport : port); m_PortDestination = localDestination->GetStreamingDestination (inPort); if (!m_PortDestination) // default destination m_PortDestination = localDestination->CreateStreamingDestination (inPort, gzip); @@ -870,8 +870,8 @@ namespace client } I2PServerTunnelHTTP::I2PServerTunnelHTTP (const std::string& name, const std::string& address, - int port, std::shared_ptr localDestination, - const std::string& host, int inport, bool gzip): + uint16_t port, std::shared_ptr localDestination, + const std::string& host, uint16_t inport, bool gzip): I2PServerTunnel (name, address, port, localDestination, inport, gzip), m_Host (host) { @@ -883,8 +883,8 @@ namespace client } I2PServerTunnelIRC::I2PServerTunnelIRC (const std::string& name, const std::string& address, - int port, std::shared_ptr localDestination, - const std::string& webircpass, int inport, bool gzip): + uint16_t port, std::shared_ptr localDestination, + const std::string& webircpass, uint16_t inport, bool gzip): I2PServerTunnel (name, address, port, localDestination, inport, gzip), m_WebircPass (webircpass) { diff --git a/libi2pd_client/I2PTunnel.h b/libi2pd_client/I2PTunnel.h index 4c7b2002..b94eb9e4 100644 --- a/libi2pd_client/I2PTunnel.h +++ b/libi2pd_client/I2PTunnel.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -41,7 +41,7 @@ namespace client public: I2PTunnelConnection (I2PService * owner, std::shared_ptr socket, - std::shared_ptr leaseSet, int port = 0); // to I2P + std::shared_ptr leaseSet, uint16_t port = 0); // to I2P I2PTunnelConnection (I2PService * owner, std::shared_ptr socket, std::shared_ptr stream); // to I2P using simplified API I2PTunnelConnection (I2PService * owner, std::shared_ptr stream, @@ -154,7 +154,7 @@ namespace client public: I2PClientTunnel (const std::string& name, const std::string& destination, - const std::string& address, int port, std::shared_ptr localDestination, int destinationPort = 0); + const std::string& address, uint16_t port, std::shared_ptr localDestination, uint16_t destinationPort = 0); ~I2PClientTunnel () {} void Start (); @@ -174,7 +174,7 @@ namespace client std::string m_Name, m_Destination; std::shared_ptr m_Address; - int m_DestinationPort; + uint16_t m_DestinationPort; uint32_t m_KeepAliveInterval; std::unique_ptr m_KeepAliveTimer; }; @@ -183,8 +183,8 @@ namespace client { public: - I2PServerTunnel (const std::string& name, const std::string& address, int port, - std::shared_ptr localDestination, int inport = 0, bool gzip = true); + I2PServerTunnel (const std::string& name, const std::string& address, uint16_t port, + std::shared_ptr localDestination, uint16_t inport = 0, bool gzip = true); void Start (); void Stop (); @@ -200,7 +200,7 @@ namespace client void SetLocalAddress (const std::string& localAddress); const std::string& GetAddress() const { return m_Address; } - int GetPort () const { return m_Port; }; + uint16_t GetPort () const { return m_Port; }; uint16_t GetLocalPort () const { return m_PortDestination->GetLocalPort (); }; const boost::asio::ip::tcp::endpoint& GetEndpoint () const { return m_Endpoint; } @@ -219,7 +219,7 @@ namespace client bool m_IsUniqueLocal; std::string m_Name, m_Address; - int m_Port; + uint16_t m_Port; boost::asio::ip::tcp::endpoint m_Endpoint; std::shared_ptr m_PortDestination; std::set m_AccessList; @@ -232,9 +232,9 @@ namespace client { public: - I2PServerTunnelHTTP (const std::string& name, const std::string& address, int port, + I2PServerTunnelHTTP (const std::string& name, const std::string& address, uint16_t port, std::shared_ptr localDestination, const std::string& host, - int inport = 0, bool gzip = true); + uint16_t inport = 0, bool gzip = true); private: @@ -249,9 +249,9 @@ namespace client { public: - I2PServerTunnelIRC (const std::string& name, const std::string& address, int port, + I2PServerTunnelIRC (const std::string& name, const std::string& address, uint16_t port, std::shared_ptr localDestination, const std::string& webircpass, - int inport = 0, bool gzip = true); + uint16_t inport = 0, bool gzip = true); private: diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 4e19990a..bb9d6a6b 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -1217,7 +1217,7 @@ namespace client subsessions.clear (); } - SAMSubSession::SAMSubSession (std::shared_ptr master, const std::string& name, SAMSessionType type, int port): + SAMSubSession::SAMSubSession (std::shared_ptr master, const std::string& name, SAMSessionType type, uint16_t port): SAMSession (master->m_Bridge, name, type), masterSession (master), inPort (port) { if (Type == eSAMSessionTypeStream) @@ -1244,7 +1244,7 @@ namespace client // TODO: implement datagrams } - SAMBridge::SAMBridge (const std::string& address, int portTCP, int portUDP, bool singleThread): + SAMBridge::SAMBridge (const std::string& address, uint16_t portTCP, uint16_t portUDP, bool singleThread): RunnableService ("SAM"), m_IsSingleThread (singleThread), m_Acceptor (GetIOService (), boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(address), portTCP)), m_DatagramEndpoint (boost::asio::ip::address::from_string(address), (!portUDP) ? portTCP-1 : portUDP), m_DatagramSocket (GetIOService (), m_DatagramEndpoint), diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index 97ac0b8e..b4c72754 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -221,9 +221,9 @@ namespace client struct SAMSubSession: public SAMSession { std::shared_ptr masterSession; - int inPort; + uint16_t inPort; - SAMSubSession (std::shared_ptr master, const std::string& name, SAMSessionType type, int port); + SAMSubSession (std::shared_ptr master, const std::string& name, SAMSessionType type, uint16_t port); // implements SAMSession std::shared_ptr GetLocalDestination (); void StopLocalDestination (); @@ -233,7 +233,7 @@ namespace client { public: - SAMBridge (const std::string& address, int portTCP, int portUDP, bool singleThread); + SAMBridge (const std::string& address, uint16_t portTCP, uint16_t portUDP, bool singleThread); ~SAMBridge (); void Start (); diff --git a/libi2pd_client/SOCKS.cpp b/libi2pd_client/SOCKS.cpp index c40cb479..693c5185 100644 --- a/libi2pd_client/SOCKS.cpp +++ b/libi2pd_client/SOCKS.cpp @@ -837,7 +837,7 @@ namespace proxy shared_from_this(), std::placeholders::_1, std::placeholders::_2)); } - SOCKSServer::SOCKSServer(const std::string& name, const std::string& address, int port, + SOCKSServer::SOCKSServer(const std::string& name, const std::string& address, uint16_t port, bool outEnable, const std::string& outAddress, uint16_t outPort, std::shared_ptr localDestination) : TCPIPAcceptor (address, port, localDestination ? localDestination : i2p::client::context.GetSharedLocalDestination ()), m_Name (name) diff --git a/libi2pd_client/SOCKS.h b/libi2pd_client/SOCKS.h index f41cfd72..bd88d6e6 100644 --- a/libi2pd_client/SOCKS.h +++ b/libi2pd_client/SOCKS.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -23,7 +23,7 @@ namespace proxy { public: - SOCKSServer(const std::string& name, const std::string& address, int port, bool outEnable, const std::string& outAddress, uint16_t outPort, + SOCKSServer(const std::string& name, const std::string& address, uint16_t port, bool outEnable, const std::string& outAddress, uint16_t outPort, std::shared_ptr localDestination = nullptr); ~SOCKSServer() {}; From a0795d85341b86f56893bb5e49cf1938467cd280 Mon Sep 17 00:00:00 2001 From: r4sas Date: Mon, 12 Jun 2023 05:12:07 +0300 Subject: [PATCH 0153/1171] set server tunnel inport in ClientContext from port (#1936) Signed-off-by: r4sas --- libi2pd_client/ClientContext.cpp | 2 +- libi2pd_client/I2PTunnel.cpp | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index 829756a1..d8c0bd2d 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -723,7 +723,7 @@ namespace client uint16_t port = section.second.get (I2P_SERVER_TUNNEL_PORT); std::string keys = section.second.get (I2P_SERVER_TUNNEL_KEYS); // optional params - uint16_t inPort = section.second.get (I2P_SERVER_TUNNEL_INPORT, 0); + uint16_t inPort = section.second.get (I2P_SERVER_TUNNEL_INPORT, port); std::string accessList = section.second.get (I2P_SERVER_TUNNEL_ACCESS_LIST, ""); if(accessList == "") accessList = section.second.get (I2P_SERVER_TUNNEL_WHITE_LIST, ""); diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index 9a9a4988..ad4e14b8 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -708,10 +708,9 @@ namespace client uint16_t port, std::shared_ptr localDestination, uint16_t inport, bool gzip): I2PService (localDestination), m_IsUniqueLocal(true), m_Name (name), m_Address (address), m_Port (port), m_IsAccessList (false) { - uint16_t inPort = (inport ? inport : port); - m_PortDestination = localDestination->GetStreamingDestination (inPort); + m_PortDestination = localDestination->GetStreamingDestination (inport); if (!m_PortDestination) // default destination - m_PortDestination = localDestination->CreateStreamingDestination (inPort, gzip); + m_PortDestination = localDestination->CreateStreamingDestination (inport, gzip); } void I2PServerTunnel::Start () From fba23a45286f844710fa5c561ba60430ebc70d5e Mon Sep 17 00:00:00 2001 From: r4sas Date: Mon, 12 Jun 2023 16:33:21 +0300 Subject: [PATCH 0154/1171] i18n: update translations Signed-off-by: r4sas --- contrib/i18n/README.md | 9 +++++---- i18n/Chinese.cpp | 2 +- i18n/French.cpp | 18 +++++++++++------- i18n/Russian.cpp | 6 +++++- i18n/Swedish.cpp | 14 +++++++++++++- 5 files changed, 35 insertions(+), 14 deletions(-) diff --git a/contrib/i18n/README.md b/contrib/i18n/README.md index 1a9bd289..ce775ecb 100644 --- a/contrib/i18n/README.md +++ b/contrib/i18n/README.md @@ -8,6 +8,11 @@ xgettext --omit-header -ctr: -ktr -kntr:1,2 daemon/HTTPServer.cpp libi2pd_client Regex for transforming gettext translations to our format: --- +``` +in: ^(\"|#[:.,]|msgctxt)(.*)$\n +out: +``` + ``` in: msgid\ \"(.*)\"\nmsgid_plural\ \"(.*)\"\nmsgstr\[0\]\ \"(.*)\"\n(msgstr\[1\]\ \"(.*)\"\n)?(msgstr\[2\]\ \"(.*)\"\n)?(msgstr\[3\]\ \"(.*)\"\n)?(msgstr\[4\]\ \"(.*)\"\n)?(msgstr\[5\]\ \"(.*)\"\n)? out: #{"$2", {"$3", "$5", "$7", "$9", "$11"}},\n @@ -18,10 +23,6 @@ in: msgid\ \"(.*)\"\nmsgstr\ \"(.*)\"\n out: {"$1", "$2"},\n ``` -``` -in: ^#[:.,](.*)$\n -out: -``` ``` in: \n\n diff --git a/i18n/Chinese.cpp b/i18n/Chinese.cpp index cd38fa0f..5ecfe067 100644 --- a/i18n/Chinese.cpp +++ b/i18n/Chinese.cpp @@ -109,6 +109,7 @@ namespace chinese // language namespace {"Local Destination", "本地目标"}, {"Streams", "流"}, {"Close stream", "断开流"}, + {"Such destination is not found", "找不到此目标"}, {"I2CP session not found", "未找到 I2CP 会话"}, {"I2CP is not enabled", "I2CP 未启用"}, {"Invalid", "无效"}, @@ -158,7 +159,6 @@ namespace chinese // language namespace {"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", "已接受指令"}, {"Proxy error", "代理错误"}, diff --git a/i18n/French.cpp b/i18n/French.cpp index 0ce044e1..8bec887c 100644 --- a/i18n/French.cpp +++ b/i18n/French.cpp @@ -69,6 +69,7 @@ namespace french // language namespace {"Stopping in", "Arrêt dans"}, {"Family", "Famille"}, {"Tunnel creation success rate", "Taux de succès de création de tunnels"}, + {"Total tunnel creation success rate", "Taux de réussite de création de tunnel"}, {"Received", "Reçu"}, {"%.2f KiB/s", "%.2f Kio/s"}, {"Sent", "Envoyé"}, @@ -91,10 +92,11 @@ namespace french // language namespace {"Address registration line", "Ligne d'inscription de l'adresse"}, {"Domain", "Domaine"}, {"Generate", "Générer"}, - {"Note: result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "Note: La chaîne résultante peut seulement être utilisée pour enregistrer les domaines 2LD (exemple.i2p). Pour enregistrer des sous-domaines, veuillez utiliser i2pd-tools."}, + {"Note: result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "Note : La chaîne résultante peut seulement être utilisée pour enregistrer les domaines 2LD (exemple.i2p). Pour enregistrer des sous-domaines, veuillez utiliser i2pd-tools."}, {"Address", "Adresse"}, {"Type", "Type"}, {"EncType", "EncType"}, + {"Expire LeaseSet", "Expiration du LeaseSet"}, {"Inbound tunnels", "Tunnels entrants"}, {"%dms", "%dms"}, {"Outbound tunnels", "Tunnels sortants"}, @@ -109,6 +111,7 @@ namespace french // language namespace {"Local Destination", "Destination locale"}, {"Streams", "Flux"}, {"Close stream", "Fermer le flux"}, + {"Such destination is not found", "Cette destination est introuvable"}, {"I2CP session not found", "Session I2CP introuvable"}, {"I2CP is not enabled", "I2CP est désactivé"}, {"Invalid", "Invalide"}, @@ -128,7 +131,7 @@ namespace french // language namespace {"Start graceful shutdown", "Démarrer l'arrêt gracieux"}, {"Force shutdown", "Forcer l'arrêt"}, {"Reload external CSS styles", "Rafraîchir les styles CSS externes"}, - {"Note: any action done here are not persistent and not changes your config files.", "Note: Toute action effectuée ici n'est pas permanente et ne modifie pas vos fichiers de configuration."}, + {"Note: any action done here are not persistent and not changes your config files.", "Note : Toute action effectuée ici n'est pas permanente et ne modifie pas vos fichiers de configuration."}, {"Logging level", "Niveau de journalisation"}, {"Transit tunnels limit", "Limite sur les tunnels transitoires"}, {"Change", "Changer"}, @@ -150,6 +153,8 @@ namespace french // language namespace {"StreamID can't be null", "StreamID ne peut pas être vide"}, {"Return to destination page", "Retourner à la page de destination"}, {"You will be redirected in %d seconds", "Vous serez redirigé dans %d secondes"}, + {"LeaseSet expiration time updated", "Temps d'expiration du LeaseSet mis à jour"}, + {"LeaseSet is not found or already expired", "Le LeaseSet est introuvable ou a déjà expirée"}, {"Transit tunnels count must not exceed %d", "Le nombre de tunnels de transit ne doit pas excéder %d"}, {"Back to commands list", "Retour à la liste des commandes"}, {"Register at reg.i2p", "Inscription à reg.i2p"}, @@ -158,24 +163,23 @@ namespace french // language namespace {"Submit", "Soumettre"}, {"Domain can't end with .b32.i2p", "Le domaine ne peut pas terminer par .b32.i2p"}, {"Domain must end with .i2p", "Le domaine doit terminer par .i2p"}, - {"Such destination is not found", "Cette destination est introuvable"}, {"Unknown command", "Commande inconnue"}, {"Command accepted", "Commande acceptée"}, {"Proxy error", "Erreur de proxy"}, {"Proxy info", "Information sur le proxy"}, - {"Proxy error: Host not found", "Erreur de proxy: Hôte introuvable"}, + {"Proxy error: Host not found", "Erreur de proxy : Hôte introuvable"}, {"Remote host not found in router's addressbook", "Hôte distant introuvable dans le carnet d'adresse du routeur"}, {"You may try to find this host on jump services below", "Vous pouvez essayer de trouver cet hôte sur des services de redirection ci-dessous"}, {"Invalid request", "Requête invalide"}, {"Proxy unable to parse your request", "Proxy incapable de comprendre votre requête"}, {"Addresshelper is not supported", "Assistant d'adresse non supporté"}, - {"Host %s is already in router's addressbook. Be careful: source of this URL may be harmful! Click here to update record: Continue.", "L'hôte %s est déjà dans le carnet d'adresses du routeur. Attention : la source de cette URL peut être nuisible ! Cliquez ici pour mettre à jour l'enregistrement : Continuer."}, + {"Host %s is already in router's addressbook. Be careful: source of this URL may be harmful! Click here to update record: Continue.", "L'hôte %s est déjà dans le carnet d'adresses du routeur. Attention : la source de cette URL peut être nuisible ! Cliquez ici pour mettre à jour l'enregistrement : Continuer."}, {"Addresshelper forced update rejected", "Mise à jour forcée des assistants d'adresses rejetée"}, - {"To add host %s in router's addressbook, click here: Continue.", "Pour ajouter l'hôte %s au carnet d'adresses du routeur, cliquez ici : Continuer."}, + {"To add host %s in router's addressbook, click here: Continue.", "Pour ajouter l'hôte %s au carnet d'adresses du routeur, cliquez ici : Continuer."}, {"Addresshelper request", "Demande à l'assistant d'adresse"}, {"Host %s added to router's addressbook from helper. Click here to proceed: Continue.", "L'hôte %s a été ajouté au carnet d'adresses du routeur depuis l'assistant. Cliquez ici pour continuer : Continuer."}, {"Addresshelper adding", "Ajout de l'assistant d'adresse"}, - {"Host %s is already in router's addressbook. Click here to update record: Continue.", "L'hôte %s est déjà dans le carnet d'adresses du routeur. Cliquez ici pour mettre à jour le dossier : Continuer."}, + {"Host %s is already in router's addressbook. Click here to update record: Continue.", "L'hôte %s est déjà dans le carnet d'adresses du routeur. Cliquez ici pour mettre à jour le dossier : Continuer."}, {"Addresshelper update", "Mise à jour de l'assistant d'adresse"}, {"Invalid request URI", "URI de la requête invalide"}, {"Can't detect destination host from request", "Impossible de détecter l'hôte de destination à partir de la requête"}, diff --git a/i18n/Russian.cpp b/i18n/Russian.cpp index dbfb13f2..15952710 100644 --- a/i18n/Russian.cpp +++ b/i18n/Russian.cpp @@ -69,6 +69,7 @@ namespace russian // language namespace {"Stopping in", "Остановка через"}, {"Family", "Семейство"}, {"Tunnel creation success rate", "Успешно построенных туннелей"}, + {"Total tunnel creation success rate", "Общий процент успешно построенных туннелей"}, {"Received", "Получено"}, {"%.2f KiB/s", "%.2f КиБ/с"}, {"Sent", "Отправлено"}, @@ -95,6 +96,7 @@ namespace russian // language namespace {"Address", "Адрес"}, {"Type", "Тип"}, {"EncType", "ТипШифр"}, + {"Expire LeaseSet", "Просрочить Лизсет"}, {"Inbound tunnels", "Входящие туннели"}, {"%dms", "%dмс"}, {"Outbound tunnels", "Исходящие туннели"}, @@ -109,6 +111,7 @@ namespace russian // language namespace {"Local Destination", "Локальное назначение"}, {"Streams", "Стримы"}, {"Close stream", "Закрыть стрим"}, + {"Such destination is not found", "Такая точка назначения не найдена"}, {"I2CP session not found", "I2CP сессия не найдена"}, {"I2CP is not enabled", "I2CP не включен"}, {"Invalid", "Некорректный"}, @@ -150,6 +153,8 @@ namespace russian // language namespace {"StreamID can't be null", "StreamID не может быть пустым"}, {"Return to destination page", "Вернуться на страницу точки назначения"}, {"You will be redirected in %d seconds", "Вы будете переадресованы через %d секунд"}, + {"LeaseSet expiration time updated", "Время действия LeaseSet обновлено"}, + {"LeaseSet is not found or already expired", "Лизсет не найден или время действия уже истекло"}, {"Transit tunnels count must not exceed %d", "Число транзитных туннелей не должно превышать %d"}, {"Back to commands list", "Вернуться к списку команд"}, {"Register at reg.i2p", "Зарегистрировать на reg.i2p"}, @@ -158,7 +163,6 @@ namespace russian // language namespace {"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", "Команда принята"}, {"Proxy error", "Ошибка прокси"}, diff --git a/i18n/Swedish.cpp b/i18n/Swedish.cpp index e7f84e69..05ed1e18 100644 --- a/i18n/Swedish.cpp +++ b/i18n/Swedish.cpp @@ -61,6 +61,8 @@ namespace swedish // language namespace {"Clock skew", "Tidsförskjutning"}, {"Offline", "Nedkopplad"}, {"Symmetric NAT", "Symmetrisk NAT"}, + {"Full cone NAT", "Full kon NAT"}, + {"No Descriptors", "Inga Beskrivningar"}, {"Uptime", "Upptid"}, {"Network status", "Nätverkstillstånd"}, {"Network status v6", "Nätverkstillstånd v6"}, @@ -107,6 +109,7 @@ namespace swedish // language namespace {"Local Destination", "Lokal Plats"}, {"Streams", "Strömmar"}, {"Close stream", "Stäng strömmen"}, + {"Such destination is not found", "En sådan plats hittas ej"}, {"I2CP session not found", "I2CP-period hittades inte"}, {"I2CP is not enabled", "I2CP är inte påslaget"}, {"Invalid", "Ogiltig"}, @@ -116,8 +119,10 @@ namespace swedish // language namespace {"Gateway", "Gateway"}, {"TunnelID", "TunnelID"}, {"EndDate", "EndDate"}, + {"floodfill mode is disabled", "Floodfill läget är inaktiverat"}, {"Queue size", "Köstorlek"}, {"Run peer test", "Utför utsiktstest"}, + {"Reload tunnels configuration", "Ladda om tunnelkonfiguration"}, {"Decline transit tunnels", "Avvisa förmedlande tunnlar"}, {"Accept transit tunnels", "Tillåt förmedlande tunnlar"}, {"Cancel graceful shutdown", "Avbryt välvillig avstängning"}, @@ -154,7 +159,6 @@ namespace swedish // language namespace {"Submit", "Skicka"}, {"Domain can't end with .b32.i2p", "Domänen får inte sluta med .b32.i2p"}, {"Domain must end with .i2p", "Domänen måste sluta med .i2p"}, - {"Such destination is not found", "En sådan plats hittas ej"}, {"Unknown command", "Okänt kommando"}, {"Command accepted", "Kommando accepterades"}, {"Proxy error", "Proxyfel"}, @@ -165,6 +169,14 @@ namespace swedish // language namespace {"Invalid request", "Ogiltig förfrågan"}, {"Proxy unable to parse your request", "Proxyt kan inte behandla din förfrågan"}, {"Addresshelper is not supported", "Adresshjälparen stöds ej"}, + {"Host %s is already in router's addressbook. Be careful: source of this URL may be harmful! Click here to update record: Continue.", "Värd %s är redan i routerns adressbok. Var försiktig: källan till denna URL kan vara skadlig! Klicka här för att uppdatera registreringen: Fortsätt."}, + {"Addresshelper forced update rejected", "Tvingad uppdatering av adresshjälparen nekad"}, + {"To add host %s in router's addressbook, click here: Continue.", "För att lägga till värd %s i routerns adressbok, klicka här: Fortsätt."}, + {"Addresshelper request", "Adresshjälpare förfrågan"}, + {"Host %s added to router's addressbook from helper. Click here to proceed: Continue.", "Värd %s tillagd i routerns adressbok från hjälparen. Klicka här för att fortsätta: Fortsätt."}, + {"Addresshelper adding", "Adresshjälpare tilläggning"}, + {"Host %s is already in router's addressbook. Click here to update record: Continue.", "Värd %s är redan i routerns adressbok. Klicka här för att uppdatera registreringen: Fortsätt."}, + {"Addresshelper update", "Adresshjälpare uppdatering"}, {"Invalid request URI", "Ogiltig förfrågnings-URI"}, {"Can't detect destination host from request", "Kan inte upptäcka platsvärden från förfrågan"}, {"Outproxy failure", "Utproxyfel"}, From ca02b5d860d7989c44355f9cbc35bc0e2449638d Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 12 Jun 2023 14:45:34 +0000 Subject: [PATCH 0155/1171] debian: add compat patches for previous releases Signed-off-by: R4SAS --- contrib/debian/README | 7 +++++-- contrib/debian/bionic/compat | 1 + contrib/debian/bionic/control | 18 ++++++++++++++++++ contrib/debian/trusty/compat | 1 + contrib/debian/trusty/control | 18 ++++++++++++++++++ contrib/debian/trusty/patches/01-upnp.patch | 17 +++++++++++++++++ .../debian/trusty/patches/02-service.patch | 19 +++++++++++++++++++ contrib/debian/trusty/patches/series | 2 ++ contrib/debian/trusty/rules | 18 ++++++++++++++++++ contrib/debian/xenial/compat | 1 + contrib/debian/xenial/control | 18 ++++++++++++++++++ contrib/debian/xenial/patches/01-upnp.patch | 17 +++++++++++++++++ .../debian/xenial/patches/02-service.patch | 19 +++++++++++++++++++ contrib/debian/xenial/patches/series | 2 ++ contrib/debian/xenial/rules | 13 +++++++++++++ 15 files changed, 169 insertions(+), 2 deletions(-) create mode 100644 contrib/debian/bionic/compat create mode 100644 contrib/debian/bionic/control create mode 100644 contrib/debian/trusty/compat create mode 100644 contrib/debian/trusty/control create mode 100644 contrib/debian/trusty/patches/01-upnp.patch create mode 100644 contrib/debian/trusty/patches/02-service.patch create mode 100644 contrib/debian/trusty/patches/series create mode 100755 contrib/debian/trusty/rules create mode 100644 contrib/debian/xenial/compat create mode 100644 contrib/debian/xenial/control create mode 100644 contrib/debian/xenial/patches/01-upnp.patch create mode 100644 contrib/debian/xenial/patches/02-service.patch create mode 100644 contrib/debian/xenial/patches/series create mode 100755 contrib/debian/xenial/rules diff --git a/contrib/debian/README b/contrib/debian/README index cccbc4de..7dc3a61f 100644 --- a/contrib/debian/README +++ b/contrib/debian/README @@ -1,2 +1,5 @@ -This forder contain systemd unit files. -To use systemd daemon control, place files from this directory to debian folder before building package. +This forder contain files required for building debian packages. + +The trunk repository is contains the packaging files for the latest stable version of Debian (if we not forgot to update them). + +Files in subdirectories contains fixes to make possible to build package on specific versions of Debian/Ubuntu. They are used when building the release package. diff --git a/contrib/debian/bionic/compat b/contrib/debian/bionic/compat new file mode 100644 index 00000000..b4de3947 --- /dev/null +++ b/contrib/debian/bionic/compat @@ -0,0 +1 @@ +11 diff --git a/contrib/debian/bionic/control b/contrib/debian/bionic/control new file mode 100644 index 00000000..d872881c --- /dev/null +++ b/contrib/debian/bionic/control @@ -0,0 +1,18 @@ +Source: i2pd +Section: net +Priority: optional +Maintainer: r4sas +Build-Depends: debhelper (>= 11~), libboost-system-dev (>= 1.46), libboost-date-time-dev (>= 1.46), libboost-filesystem-dev (>= 1.46), libboost-program-options-dev (>= 1.46), libminiupnpc-dev, libssl-dev, zlib1g-dev +Standards-Version: 4.2.0 +Homepage: http://i2pd.website/ +Vcs-Git: git://github.com/PurpleI2P/i2pd.git +Vcs-Browser: https://github.com/PurpleI2P/i2pd + +Package: i2pd +Architecture: any +Pre-Depends: ${misc:Pre-Depends}, adduser +Depends: ${shlibs:Depends}, ${misc:Depends}, lsb-base, +Description: Full-featured C++ implementation of I2P client. + I2P (Invisible Internet Protocol) is a universal anonymous network layer. All + communications over I2P are anonymous and end-to-end encrypted, participants + don't reveal their real IP addresses. diff --git a/contrib/debian/trusty/compat b/contrib/debian/trusty/compat new file mode 100644 index 00000000..ec635144 --- /dev/null +++ b/contrib/debian/trusty/compat @@ -0,0 +1 @@ +9 diff --git a/contrib/debian/trusty/control b/contrib/debian/trusty/control new file mode 100644 index 00000000..fc618ddc --- /dev/null +++ b/contrib/debian/trusty/control @@ -0,0 +1,18 @@ +Source: i2pd +Section: net +Priority: optional +Maintainer: r4sas +Build-Depends: debhelper (>= 9), libboost-system-dev (>= 1.46), libboost-date-time-dev (>= 1.46), libboost-filesystem-dev (>= 1.46), libboost-program-options-dev (>= 1.46), libminiupnpc-dev, libssl-dev, zlib1g-dev +Standards-Version: 3.9.8 +Homepage: http://i2pd.website/ +Vcs-Git: git://github.com/PurpleI2P/i2pd.git +Vcs-Browser: https://github.com/PurpleI2P/i2pd + +Package: i2pd +Architecture: any +Pre-Depends: ${misc:Pre-Depends}, adduser +Depends: ${shlibs:Depends}, ${misc:Depends}, lsb-base, +Description: Full-featured C++ implementation of I2P client. + I2P (Invisible Internet Protocol) is a universal anonymous network layer. All + communications over I2P are anonymous and end-to-end encrypted, participants + don't reveal their real IP addresses. diff --git a/contrib/debian/trusty/patches/01-upnp.patch b/contrib/debian/trusty/patches/01-upnp.patch new file mode 100644 index 00000000..bec8f2b0 --- /dev/null +++ b/contrib/debian/trusty/patches/01-upnp.patch @@ -0,0 +1,17 @@ +Description: Enable UPnP usage in package +Author: r4sas + +Reviewed-By: r4sas +Last-Update: 2022-03-23 + +--- i2pd.orig/Makefile ++++ i2pd/Makefile +@@ -31,7 +31,7 @@ include filelist.mk + + USE_AESNI := $(or $(USE_AESNI),yes) + USE_STATIC := $(or $(USE_STATIC),no) +-USE_UPNP := $(or $(USE_UPNP),no) ++USE_UPNP := $(or $(USE_UPNP),yes) + DEBUG := $(or $(DEBUG),yes) + + # for debugging purposes only, when commit hash needed in trunk builds in i2pd version string diff --git a/contrib/debian/trusty/patches/02-service.patch b/contrib/debian/trusty/patches/02-service.patch new file mode 100644 index 00000000..12b35525 --- /dev/null +++ b/contrib/debian/trusty/patches/02-service.patch @@ -0,0 +1,19 @@ +Description: Disable LogsDirectory and LogsDirectoryMode options in service +Author: r4sas + +Reviewed-By: r4sas +Last-Update: 2023-05-17 + +--- a/contrib/i2pd.service ++++ b/contrib/i2pd.service +@@ -8,8 +8,8 @@ User=i2pd + Group=i2pd + RuntimeDirectory=i2pd + RuntimeDirectoryMode=0700 +-LogsDirectory=i2pd +-LogsDirectoryMode=0700 ++#LogsDirectory=i2pd ++#LogsDirectoryMode=0700 + Type=forking + ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --tunnelsdir=/etc/i2pd/tunnels.conf.d --pidfile=/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service + ExecReload=/bin/sh -c "kill -HUP $MAINPID" diff --git a/contrib/debian/trusty/patches/series b/contrib/debian/trusty/patches/series new file mode 100644 index 00000000..d8caec41 --- /dev/null +++ b/contrib/debian/trusty/patches/series @@ -0,0 +1,2 @@ +01-upnp.patch +02-service.patch diff --git a/contrib/debian/trusty/rules b/contrib/debian/trusty/rules new file mode 100755 index 00000000..97a4e008 --- /dev/null +++ b/contrib/debian/trusty/rules @@ -0,0 +1,18 @@ +#!/usr/bin/make -f +#export DH_VERBOSE=1 + +export DEB_BUILD_MAINT_OPTIONS=hardening=+all + +include /usr/share/dpkg/architecture.mk + +ifeq ($(DEB_HOST_ARCH),i386) + export DEB_BUILD_OPTIONS=parallel=1 +endif + +export DEB_CXXFLAGS_MAINT_APPEND=-Wall -pedantic +export DEB_LDFLAGS_MAINT_APPEND= + +%: + dh $@ --parallel + +override_dh_auto_install: diff --git a/contrib/debian/xenial/compat b/contrib/debian/xenial/compat new file mode 100644 index 00000000..ec635144 --- /dev/null +++ b/contrib/debian/xenial/compat @@ -0,0 +1 @@ +9 diff --git a/contrib/debian/xenial/control b/contrib/debian/xenial/control new file mode 100644 index 00000000..fc618ddc --- /dev/null +++ b/contrib/debian/xenial/control @@ -0,0 +1,18 @@ +Source: i2pd +Section: net +Priority: optional +Maintainer: r4sas +Build-Depends: debhelper (>= 9), libboost-system-dev (>= 1.46), libboost-date-time-dev (>= 1.46), libboost-filesystem-dev (>= 1.46), libboost-program-options-dev (>= 1.46), libminiupnpc-dev, libssl-dev, zlib1g-dev +Standards-Version: 3.9.8 +Homepage: http://i2pd.website/ +Vcs-Git: git://github.com/PurpleI2P/i2pd.git +Vcs-Browser: https://github.com/PurpleI2P/i2pd + +Package: i2pd +Architecture: any +Pre-Depends: ${misc:Pre-Depends}, adduser +Depends: ${shlibs:Depends}, ${misc:Depends}, lsb-base, +Description: Full-featured C++ implementation of I2P client. + I2P (Invisible Internet Protocol) is a universal anonymous network layer. All + communications over I2P are anonymous and end-to-end encrypted, participants + don't reveal their real IP addresses. diff --git a/contrib/debian/xenial/patches/01-upnp.patch b/contrib/debian/xenial/patches/01-upnp.patch new file mode 100644 index 00000000..bec8f2b0 --- /dev/null +++ b/contrib/debian/xenial/patches/01-upnp.patch @@ -0,0 +1,17 @@ +Description: Enable UPnP usage in package +Author: r4sas + +Reviewed-By: r4sas +Last-Update: 2022-03-23 + +--- i2pd.orig/Makefile ++++ i2pd/Makefile +@@ -31,7 +31,7 @@ include filelist.mk + + USE_AESNI := $(or $(USE_AESNI),yes) + USE_STATIC := $(or $(USE_STATIC),no) +-USE_UPNP := $(or $(USE_UPNP),no) ++USE_UPNP := $(or $(USE_UPNP),yes) + DEBUG := $(or $(DEBUG),yes) + + # for debugging purposes only, when commit hash needed in trunk builds in i2pd version string diff --git a/contrib/debian/xenial/patches/02-service.patch b/contrib/debian/xenial/patches/02-service.patch new file mode 100644 index 00000000..12b35525 --- /dev/null +++ b/contrib/debian/xenial/patches/02-service.patch @@ -0,0 +1,19 @@ +Description: Disable LogsDirectory and LogsDirectoryMode options in service +Author: r4sas + +Reviewed-By: r4sas +Last-Update: 2023-05-17 + +--- a/contrib/i2pd.service ++++ b/contrib/i2pd.service +@@ -8,8 +8,8 @@ User=i2pd + Group=i2pd + RuntimeDirectory=i2pd + RuntimeDirectoryMode=0700 +-LogsDirectory=i2pd +-LogsDirectoryMode=0700 ++#LogsDirectory=i2pd ++#LogsDirectoryMode=0700 + Type=forking + ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --tunnelsdir=/etc/i2pd/tunnels.conf.d --pidfile=/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service + ExecReload=/bin/sh -c "kill -HUP $MAINPID" diff --git a/contrib/debian/xenial/patches/series b/contrib/debian/xenial/patches/series new file mode 100644 index 00000000..d8caec41 --- /dev/null +++ b/contrib/debian/xenial/patches/series @@ -0,0 +1,2 @@ +01-upnp.patch +02-service.patch diff --git a/contrib/debian/xenial/rules b/contrib/debian/xenial/rules new file mode 100755 index 00000000..11791d9b --- /dev/null +++ b/contrib/debian/xenial/rules @@ -0,0 +1,13 @@ +#!/usr/bin/make -f +#export DH_VERBOSE=1 +export DEB_BUILD_MAINT_OPTIONS = hardening=+all + +include /usr/share/dpkg/architecture.mk + +export DEB_CXXFLAGS_MAINT_APPEND = -Wall -pedantic +export DEB_LDFLAGS_MAINT_APPEND = + +%: + dh $@ --parallel + +override_dh_auto_install: From fee940238a4b8cba86eecb2204aadc445f824c24 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 17 Jun 2023 07:52:06 -0400 Subject: [PATCH 0156/1171] handle SOCK5 authrosation with empty user/password --- libi2pd_client/SOCKS.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/libi2pd_client/SOCKS.cpp b/libi2pd_client/SOCKS.cpp index 693c5185..649ad814 100644 --- a/libi2pd_client/SOCKS.cpp +++ b/libi2pd_client/SOCKS.cpp @@ -587,7 +587,10 @@ namespace proxy EnterState(GET5_USER_SIZE); break; case GET5_USER_SIZE: - EnterState(GET5_USER, *sock_buff); + if (*sock_buff) + EnterState(GET5_USER, *sock_buff); + else // empty user + EnterState(GET5_PASSWD_SIZE); break; case GET5_USER: // skip user for now @@ -595,7 +598,13 @@ namespace proxy if (m_parseleft == 0) EnterState(GET5_PASSWD_SIZE); break; case GET5_PASSWD_SIZE: - EnterState(GET5_PASSWD, *sock_buff); + if (*sock_buff) + EnterState(GET5_PASSWD, *sock_buff); + else // empty password + { + Socks5UserPasswdResponse (); + EnterState(GET5_REQUESTV); + } break; case GET5_PASSWD: // skip passwd for now From 07c529173e9833220eb89353c758cae03faf73f4 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 17 Jun 2023 10:08:04 -0400 Subject: [PATCH 0157/1171] send current version of the subnegotiation in user/password response --- libi2pd_client/SOCKS.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd_client/SOCKS.cpp b/libi2pd_client/SOCKS.cpp index 649ad814..547a2da2 100644 --- a/libi2pd_client/SOCKS.cpp +++ b/libi2pd_client/SOCKS.cpp @@ -332,7 +332,7 @@ namespace proxy void SOCKSHandler::Socks5UserPasswdResponse () { - m_response[0] = 5; // Version + m_response[0] = 1; // Version of the subnegotiation m_response[1] = 0; // Response code LogPrint(eLogDebug, "SOCKS: v5 user/password response"); boost::asio::async_write(*m_sock, boost::asio::const_buffers_1(m_response, 2), From 13f263b7910a30d59c4090a07d8773d0a1c99260 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 30 Jun 2023 11:54:55 -0400 Subject: [PATCH 0158/1171] correct transport comptibility for OBEP in second attempt --- libi2pd/TunnelPool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index 3dc0256e..a2168f64 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -522,7 +522,7 @@ namespace tunnel } if ((i == numHops - 1) && (!hop->IsV4 () || (inbound && !hop->IsPublished (true)))) // IBGW is not published ipv4 { - auto hop1 = nextHop (prevHop, true); + auto hop1 = nextHop (prevHop, inbound); if (hop1) hop = hop1; } prevHop = hop; From 5f430269862c710ddaa7d97b8823b68a7fe5f24a Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 6 Jul 2023 12:30:33 -0400 Subject: [PATCH 0159/1171] check if local destination is not null --- libi2pd_client/BOB.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libi2pd_client/BOB.cpp b/libi2pd_client/BOB.cpp index 3e6590f2..498a5460 100644 --- a/libi2pd_client/BOB.cpp +++ b/libi2pd_client/BOB.cpp @@ -667,6 +667,11 @@ namespace client return; } auto localDestination = m_CurrentDestination ? m_CurrentDestination->GetLocalDestination () : i2p::client::context.GetSharedLocalDestination (); + if (!localDestination) + { + SendReplyError ("No local destination"); + return; + } if (addr->IsIdentHash ()) { // we might have leaseset already From b8f998f76a4acb0f0764e151308f6150a19f076c Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 6 Jul 2023 13:08:39 -0400 Subject: [PATCH 0160/1171] don't delete BOBDestination if used by another BOBSession --- libi2pd_client/BOB.cpp | 24 +++++++++++------------- libi2pd_client/BOB.h | 10 +++++----- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/libi2pd_client/BOB.cpp b/libi2pd_client/BOB.cpp index 498a5460..23c3b72f 100644 --- a/libi2pd_client/BOB.cpp +++ b/libi2pd_client/BOB.cpp @@ -357,13 +357,13 @@ namespace client os << data << std::endl; } - void BOBCommandSession::BuildStatusLine(bool currentTunnel, BOBDestination *dest, std::string &out) + void BOBCommandSession::BuildStatusLine(bool currentTunnel, std::shared_ptr dest, std::string &out) { // helper lambdas const auto issetStr = [](const std::string &str) { return str.empty() ? "not_set" : str; }; // for inhost, outhost const auto issetNum = [&issetStr](const int p) { return issetStr(p == 0 ? "" : std::to_string(p)); }; // for inport, outport const auto destExists = [](const BOBDestination * const dest) { return dest != nullptr; }; - const auto destReady = [](const BOBDestination * const dest) { return dest->IsRunning(); }; + const auto destReady = [](const BOBDestination * const dest) { return dest && dest->IsRunning(); }; const auto bool_str = [](const bool v) { return v ? "true" : "false"; }; // bool -> str // tunnel info @@ -373,9 +373,9 @@ namespace client const std::string outhost = issetStr(currentTunnel ? m_OutHost : dest->GetOutHost()); const std::string inport = issetNum(currentTunnel ? m_InPort : dest->GetInPort()); const std::string outport = issetNum(currentTunnel ? m_OutPort : dest->GetOutPort()); - const bool keys = destExists(dest); // key must exist when destination is created - const bool starting = destExists(dest) && !destReady(dest); - const bool running = destExists(dest) && destReady(dest); + const bool keys = destExists(dest.get ()); // key must exist when destination is created + const bool starting = destExists(dest.get ()) && !destReady(dest.get ()); + const bool running = destExists(dest.get ()) && destReady(dest.get ()); const bool stopping = false; // build line @@ -446,7 +446,7 @@ namespace client if (!m_CurrentDestination) { - m_CurrentDestination = new BOBDestination (i2p::client::context.CreateNewLocalDestination (m_Keys, true, &m_Options), // deleted in clear command + m_CurrentDestination = std::make_shared (i2p::client::context.CreateNewLocalDestination (m_Keys, true, &m_Options), // deleted in clear command m_Nickname, m_InHost, m_OutHost, m_InPort, m_OutPort, m_IsQuiet); m_Owner.AddDestination (m_Nickname, m_CurrentDestination); } @@ -666,7 +666,8 @@ namespace client SendReplyError ("Address Not found"); return; } - auto localDestination = m_CurrentDestination ? m_CurrentDestination->GetLocalDestination () : i2p::client::context.GetSharedLocalDestination (); + auto localDestination = (m_CurrentDestination && m_CurrentDestination->IsRunning ()) ? + m_CurrentDestination->GetLocalDestination () : i2p::client::context.GetSharedLocalDestination (); if (!localDestination) { SendReplyError ("No local destination"); @@ -880,8 +881,6 @@ namespace client { if (IsRunning ()) Stop (); - for (const auto& it: m_Destinations) - delete it.second; } void BOBCommandChannel::Start () @@ -898,9 +897,9 @@ namespace client StopIOService (); } - void BOBCommandChannel::AddDestination (const std::string& name, BOBDestination * dest) + void BOBCommandChannel::AddDestination (const std::string& name, std::shared_ptr dest) { - m_Destinations[name] = dest; + m_Destinations.emplace (name, dest); } void BOBCommandChannel::DeleteDestination (const std::string& name) @@ -909,12 +908,11 @@ namespace client if (it != m_Destinations.end ()) { it->second->Stop (); - delete it->second; m_Destinations.erase (it); } } - BOBDestination * BOBCommandChannel::FindDestination (const std::string& name) + std::shared_ptr BOBCommandChannel::FindDestination (const std::string& name) { auto it = m_Destinations.find (name); if (it != m_Destinations.end ()) diff --git a/libi2pd_client/BOB.h b/libi2pd_client/BOB.h index 8b0b31d2..1f5fda5f 100644 --- a/libi2pd_client/BOB.h +++ b/libi2pd_client/BOB.h @@ -228,7 +228,7 @@ namespace client void SendReplyError (const char * msg); void SendRaw (const char * data); - void BuildStatusLine(bool currentTunnel, BOBDestination *destination, std::string &out); + void BuildStatusLine(bool currentTunnel, std::shared_ptr destination, std::string &out); private: @@ -240,7 +240,7 @@ namespace client uint16_t m_InPort, m_OutPort; i2p::data::PrivateKeys m_Keys; std::map m_Options; - BOBDestination * m_CurrentDestination; + std::shared_ptr m_CurrentDestination; }; typedef void (BOBCommandSession::*BOBCommandHandler)(const char * operand, size_t len); @@ -255,9 +255,9 @@ namespace client void Stop (); boost::asio::io_service& GetService () { return GetIOService (); }; - void AddDestination (const std::string& name, BOBDestination * dest); + void AddDestination (const std::string& name, std::shared_ptr dest); void DeleteDestination (const std::string& name); - BOBDestination * FindDestination (const std::string& name); + std::shared_ptr FindDestination (const std::string& name); private: @@ -267,7 +267,7 @@ namespace client private: boost::asio::ip::tcp::acceptor m_Acceptor; - std::map m_Destinations; + std::map > m_Destinations; std::map m_CommandHandlers; std::map m_HelpStrings; From 638e9b4d7ff7366c8e902d45ae1a0d3ae13189d8 Mon Sep 17 00:00:00 2001 From: Chad Fraleigh Date: Sat, 8 Jul 2023 17:07:04 -0700 Subject: [PATCH 0161/1171] Fixed division by zero due to thread race condition. --- libi2pd/NetDb.cpp | 4 +++- libi2pd/Transports.cpp | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index baf96f74..5134dbe0 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -1253,7 +1253,9 @@ namespace data uint16_t inds[3]; RAND_bytes ((uint8_t *)inds, sizeof (inds)); std::unique_lock l(m_RouterInfosMutex); - inds[0] %= m_RouterInfos.size (); + auto count = m_RouterInfos.size (); + if(count == 0) return nullptr; + inds[0] %= count; auto it = m_RouterInfos.begin (); std::advance (it, inds[0]); // try random router diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 8daf56ef..38d6e270 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -861,7 +861,9 @@ namespace transport uint16_t inds[3]; RAND_bytes ((uint8_t *)inds, sizeof (inds)); std::unique_lock l(m_PeersMutex); - inds[0] %= m_Peers.size (); + auto count = m_Peers.size (); + if(count == 0) return nullptr; + inds[0] %= count; auto it = m_Peers.begin (); std::advance (it, inds[0]); // try random peer From 2bb48b4546a0d174af55b32afac293cbeb8e4302 Mon Sep 17 00:00:00 2001 From: Chad Fraleigh Date: Sun, 9 Jul 2023 13:12:22 -0700 Subject: [PATCH 0162/1171] Fixed crash when Base64ToByteStream() is only given '=' characters. --- libi2pd/Base.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libi2pd/Base.cpp b/libi2pd/Base.cpp index 94446e86..8f84728c 100644 --- a/libi2pd/Base.cpp +++ b/libi2pd/Base.cpp @@ -187,6 +187,9 @@ namespace data else return 0; + if(*InBuffer == P64) + return 0; + ps = (unsigned char *)(InBuffer + InCount - 1); while ( *ps-- == P64 ) outCount--; From 47dc5591b92b5fbf2385f5e25b0726dd5768ec12 Mon Sep 17 00:00:00 2001 From: Chad Fraleigh Date: Sun, 9 Jul 2023 15:09:17 -0700 Subject: [PATCH 0163/1171] Eliminate undefined behavior of bit shifting signed int. --- libi2pd/Base.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Base.cpp b/libi2pd/Base.cpp index 94446e86..5f8b7e58 100644 --- a/libi2pd/Base.cpp +++ b/libi2pd/Base.cpp @@ -298,7 +298,7 @@ namespace data size_t ByteStreamToBase32 (const uint8_t * inBuf, size_t len, char * outBuf, size_t outLen) { size_t ret = 0, pos = 1; - int bits = 8, tmp = inBuf[0]; + unsigned int bits = 8, tmp = inBuf[0]; while (ret < outLen && (bits > 0 || pos < len)) { if (bits < 5) From c4be5f7fdb4ff4113b62f5b8f049887a9fcacdf4 Mon Sep 17 00:00:00 2001 From: Chad Fraleigh Date: Sun, 9 Jul 2023 18:45:30 -0700 Subject: [PATCH 0164/1171] Use offset from Identity::signingKey instead of Identity::certificate for key. --- libi2pd/Identity.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Identity.cpp b/libi2pd/Identity.cpp index ca47e797..a4a9f716 100644 --- a/libi2pd/Identity.cpp +++ b/libi2pd/Identity.cpp @@ -581,7 +581,7 @@ namespace data if (keyType == SIGNING_KEY_TYPE_DSA_SHA1) m_Signer.reset (new i2p::crypto::DSASigner (m_SigningPrivateKey, m_Public->GetStandardIdentity ().signingKey)); else if (keyType == SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519 && !IsOfflineSignature ()) - m_Signer.reset (new i2p::crypto::EDDSA25519Signer (m_SigningPrivateKey, m_Public->GetStandardIdentity ().certificate - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH)); // TODO: remove public key check + m_Signer.reset (new i2p::crypto::EDDSA25519Signer (m_SigningPrivateKey, m_Public->GetStandardIdentity ().signingKey + (sizeof(Identity::signingKey) - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH))); // TODO: remove public key check else { // public key is not required From 17c4038c6048a1567eba76b89a8a9e19d7e81d38 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 11 Jul 2023 13:16:35 -0400 Subject: [PATCH 0165/1171] select router with ipv4 for endpoint --- libi2pd/NetDb.cpp | 19 ++++++++++++------- libi2pd/NetDb.hpp | 4 ++-- libi2pd/Tunnel.cpp | 4 ++-- libi2pd/TunnelPool.cpp | 19 ++++++++----------- libi2pd/TunnelPool.h | 4 ++-- libi2pd_client/MatchedDestination.cpp | 3 ++- 6 files changed, 28 insertions(+), 25 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 5134dbe0..7bccb2a0 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -59,7 +59,7 @@ namespace data { Reseed (); } - else if (!GetRandomRouter (i2p::context.GetSharedRouterInfo (), false)) + else if (!GetRandomRouter (i2p::context.GetSharedRouterInfo (), false, false)) Reseed (); // we don't have a router we can connect to. Trying to reseed auto it = m_RouterInfos.find (i2p::context.GetIdentHash ()); @@ -1199,15 +1199,17 @@ namespace data }); } - std::shared_ptr NetDb::GetRandomRouter (std::shared_ptr compatibleWith, bool reverse) const + std::shared_ptr NetDb::GetRandomRouter (std::shared_ptr compatibleWith, + bool reverse, bool endpoint) const { return GetRandomRouter ( - [compatibleWith, reverse](std::shared_ptr router)->bool + [compatibleWith, reverse, endpoint](std::shared_ptr router)->bool { return !router->IsHidden () && router != compatibleWith && (reverse ? compatibleWith->IsReachableFrom (*router) : router->IsReachableFrom (*compatibleWith)) && - router->IsECIES () && !router->IsHighCongestion (false); + router->IsECIES () && !router->IsHighCongestion (false) && + (!endpoint || (router->IsV4 () && (!reverse || router->IsPublished (true)))); // endpoint must be ipv4 and published if inbound(reverse) }); } @@ -1231,17 +1233,20 @@ namespace data }); } - std::shared_ptr NetDb::GetHighBandwidthRandomRouter (std::shared_ptr compatibleWith, bool reverse) const + std::shared_ptr NetDb::GetHighBandwidthRandomRouter (std::shared_ptr compatibleWith, + bool reverse, bool endpoint) const { return GetRandomRouter ( - [compatibleWith, reverse](std::shared_ptr router)->bool + [compatibleWith, reverse, endpoint](std::shared_ptr router)->bool { return !router->IsHidden () && router != compatibleWith && (reverse ? compatibleWith->IsReachableFrom (*router) : router->IsReachableFrom (*compatibleWith)) && (router->GetCaps () & RouterInfo::eHighBandwidth) && router->GetVersion () >= NETDB_MIN_HIGHBANDWIDTH_VERSION && - router->IsECIES () && !router->IsHighCongestion (true); + router->IsECIES () && !router->IsHighCongestion (true) && + (!endpoint || (router->IsV4 () && (!reverse || router->IsPublished (true)))); // endpoint must be ipv4 and published if inbound(reverse) + }); } diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index adfdcde7..b7d9a5b3 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -84,8 +84,8 @@ namespace data void HandleNTCP2RouterInfoMsg (std::shared_ptr m); std::shared_ptr GetRandomRouter () const; - std::shared_ptr GetRandomRouter (std::shared_ptr compatibleWith, bool reverse) const; - std::shared_ptr GetHighBandwidthRandomRouter (std::shared_ptr compatibleWith, bool reverse) const; + std::shared_ptr GetRandomRouter (std::shared_ptr compatibleWith, bool reverse, bool endpoint) const; + std::shared_ptr GetHighBandwidthRandomRouter (std::shared_ptr compatibleWith, bool reverse, bool endpoint) const; std::shared_ptr GetRandomSSU2PeerTestRouter (bool v4, const std::set& excluded) const; std::shared_ptr GetRandomSSU2Introducer (bool v4, const std::set& excluded) const; std::shared_ptr GetClosestFloodfill (const IdentHash& destination, const std::set& excluded) const; diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index db6f74f9..6234ceb4 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -709,7 +709,7 @@ namespace tunnel auto inboundTunnel = GetNextInboundTunnel (); auto router = i2p::transport::transports.RoutesRestricted() ? i2p::transport::transports.GetRestrictedPeer() : - i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false); // reachable by us + i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false, true); // reachable by us if (!inboundTunnel || !router) return; LogPrint (eLogDebug, "Tunnel: Creating one hop outbound tunnel"); CreateTunnel ( @@ -781,7 +781,7 @@ namespace tunnel auto router = i2p::transport::transports.RoutesRestricted() ? i2p::transport::transports.GetRestrictedPeer() : // should be reachable by us because we send build request directly - i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false); + i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false, true); if (!router) { LogPrint (eLogWarning, "Tunnel: Can't find any router, skip creating tunnel"); return; diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index a2168f64..5b305de1 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -470,13 +470,14 @@ namespace tunnel return i2p::tunnel::tunnels.GetExploratoryPool () == shared_from_this (); } - std::shared_ptr TunnelPool::SelectNextHop (std::shared_ptr prevHop, bool reverse) const + std::shared_ptr TunnelPool::SelectNextHop (std::shared_ptr prevHop, + bool reverse, bool endpoint) const { - auto hop = IsExploratory () ? i2p::data::netdb.GetRandomRouter (prevHop, reverse): - i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop, reverse); + auto hop = IsExploratory () ? i2p::data::netdb.GetRandomRouter (prevHop, reverse, endpoint): + i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop, reverse, endpoint); if (!hop || hop->GetProfile ()->IsBad ()) - hop = i2p::data::netdb.GetRandomRouter (prevHop, reverse); + hop = i2p::data::netdb.GetRandomRouter (prevHop, reverse, endpoint); return hop; } @@ -508,7 +509,7 @@ namespace tunnel for(int i = start; i < numHops; i++ ) { - auto hop = nextHop (prevHop, inbound); + auto hop = nextHop (prevHop, inbound, i == numHops - 1); if (!hop && !i) // if no suitable peer found for first hop, try already connected { LogPrint (eLogInfo, "Tunnels: Can't select first hop for a tunnel. Trying already connected"); @@ -520,11 +521,6 @@ namespace tunnel LogPrint (eLogError, "Tunnels: Can't select next hop for ", prevHop->GetIdentHashBase64 ()); return false; } - if ((i == numHops - 1) && (!hop->IsV4 () || (inbound && !hop->IsPublished (true)))) // IBGW is not published ipv4 - { - auto hop1 = nextHop (prevHop, inbound); - if (hop1) hop = hop1; - } prevHop = hop; path.Add (hop); } @@ -566,7 +562,8 @@ namespace tunnel if (m_CustomPeerSelector) return m_CustomPeerSelector->SelectPeers(path, numHops, isInbound); } - return StandardSelectPeers(path, numHops, isInbound, std::bind(&TunnelPool::SelectNextHop, this, std::placeholders::_1, std::placeholders::_2)); + return StandardSelectPeers(path, numHops, isInbound, std::bind(&TunnelPool::SelectNextHop, this, + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); } bool TunnelPool::SelectExplicitPeers (Path& path, bool isInbound) diff --git a/libi2pd/TunnelPool.h b/libi2pd/TunnelPool.h index e9dd142e..c1fd19cd 100644 --- a/libi2pd/TunnelPool.h +++ b/libi2pd/TunnelPool.h @@ -56,7 +56,7 @@ namespace tunnel class TunnelPool: public std::enable_shared_from_this // per local destination { - typedef std::function(std::shared_ptr, bool)> SelectHopFunc; + typedef std::function(std::shared_ptr, bool, bool)> SelectHopFunc; public: TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, @@ -112,7 +112,7 @@ namespace tunnel std::shared_ptr GetLowestLatencyOutboundTunnel(std::shared_ptr exclude = nullptr) const; // for overriding tunnel peer selection - std::shared_ptr SelectNextHop (std::shared_ptr prevHop, bool reverse) const; + std::shared_ptr SelectNextHop (std::shared_ptr prevHop, bool reverse, bool endpoint) const; bool StandardSelectPeers(Path & path, int numHops, bool inbound, SelectHopFunc nextHop); private: diff --git a/libi2pd_client/MatchedDestination.cpp b/libi2pd_client/MatchedDestination.cpp index 1e2e8275..40752f5b 100644 --- a/libi2pd_client/MatchedDestination.cpp +++ b/libi2pd_client/MatchedDestination.cpp @@ -73,7 +73,8 @@ namespace client { auto pool = GetTunnelPool(); if(!pool || !pool->StandardSelectPeers(path, hops, inbound, - std::bind(&i2p::tunnel::TunnelPool::SelectNextHop, pool, std::placeholders::_1, std::placeholders::_2))) + std::bind(&i2p::tunnel::TunnelPool::SelectNextHop, pool, std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3))) return false; // more here for outbound tunnels if(!inbound && m_RemoteLeaseSet) From ea7cf1cf6905257cd668848283ad86dfb5c6eb00 Mon Sep 17 00:00:00 2001 From: Vort Date: Sat, 15 Jul 2023 18:44:37 +0300 Subject: [PATCH 0166/1171] fix termination block processing and size check --- libi2pd/NTCP2.cpp | 2 +- libi2pd/SSU2Session.cpp | 23 ++++++++++++++--------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 5e1cbaf6..364ebe8e 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -884,7 +884,7 @@ namespace transport auto size = bufbe16toh (frame + offset); offset += 2; LogPrint (eLogDebug, "NTCP2: Block type ", (int)blk, " of size ", size); - if (size > len) + if (offset + size > len) { LogPrint (eLogError, "NTCP2: Unexpected block length ", size); break; diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 49004437..23afd4c3 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1486,7 +1486,7 @@ namespace transport auto size = bufbe16toh (buf + offset); offset += 2; LogPrint (eLogDebug, "SSU2: Block type ", (int)blk, " of size ", size); - if (size > len) + if (offset + size > len) { LogPrint (eLogError, "SSU2: Unexpected block length ", size); break; @@ -1532,16 +1532,21 @@ namespace transport break; case eSSU2BlkTermination: { - uint8_t rsn = buf[11]; // reason - LogPrint (eLogDebug, "SSU2: Termination reason=", (int)rsn); - if (IsEstablished () && rsn != eSSU2TerminationReasonTerminationReceived) - RequestTermination (eSSU2TerminationReasonTerminationReceived); - else if (m_State != eSSU2SessionStateTerminated) + if (size >= 9) { - if (m_State == eSSU2SessionStateClosing && rsn == eSSU2TerminationReasonTerminationReceived) - m_State = eSSU2SessionStateClosingConfirmed; - Done (); + uint8_t rsn = buf[offset + 8]; // reason + LogPrint (eLogDebug, "SSU2: Termination reason=", (int)rsn); + if (IsEstablished () && rsn != eSSU2TerminationReasonTerminationReceived) + RequestTermination (eSSU2TerminationReasonTerminationReceived); + else if (m_State != eSSU2SessionStateTerminated) + { + if (m_State == eSSU2SessionStateClosing && rsn == eSSU2TerminationReasonTerminationReceived) + m_State = eSSU2SessionStateClosingConfirmed; + Done (); + } } + else + LogPrint(eLogWarning, "SSU2: Unexpected termination block size ", size); break; } case eSSU2BlkRelayRequest: From 8e63f8f333d21724bb5143f99f8ee0c471ddd473 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 15 Jul 2023 17:11:56 -0400 Subject: [PATCH 0167/1171] consider all addresses non published for U and H routers --- libi2pd/RouterInfo.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 5ba8a5b1..646711c1 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -995,6 +995,7 @@ namespace data bool RouterInfo::IsPublished (bool v4) const { + if (m_Caps & (eUnreachable | eHidden)) return false; // if router sets U or H we assume that all addreses are not published auto addr = GetAddresses (); if (v4) return ((*addr)[eNTCP2V4Idx] && ((*addr)[eNTCP2V4Idx])->published) || From 940a97db11d2e092273090319b4cf2f148bb0971 Mon Sep 17 00:00:00 2001 From: r4sas Date: Sun, 16 Jul 2023 14:02:30 +0300 Subject: [PATCH 0168/1171] [gha] fix msvc build Signed-off-by: r4sas --- .github/workflows/build-windows-msvc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-windows-msvc.yml b/.github/workflows/build-windows-msvc.yml index 356bb466..172e0596 100644 --- a/.github/workflows/build-windows-msvc.yml +++ b/.github/workflows/build-windows-msvc.yml @@ -29,7 +29,7 @@ jobs: - name: Install Boost uses: crazy-max/ghaction-chocolatey@v2 with: - args: install boost-msvc-14.3 + args: install boost-msvc-14.3 --version=1.81.0 - name: Install OpenSSL uses: crazy-max/ghaction-chocolatey@v2 From e7157cf15efddbe50a057c72afee5eb0a3276199 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 17 Jul 2023 17:57:30 -0400 Subject: [PATCH 0169/1171] don't create paired inbound tunnel if length is different --- libi2pd/TunnelPool.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index 5b305de1..fd31cb09 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -296,10 +296,12 @@ namespace tunnel for (const auto& it : m_InboundTunnels) if (it->IsEstablished ()) num++; } - if (!num && !m_OutboundTunnels.empty () && m_NumOutboundHops > 0) + if (!num && !m_OutboundTunnels.empty () && m_NumOutboundHops > 0 && + m_NumInboundHops == m_NumOutboundHops) { for (auto it: m_OutboundTunnels) { + // try to create inbound tunnel through the same path as succesive outbound CreatePairedInboundTunnel (it); num++; if (num >= m_NumInboundTunnels) break; From c620fc1232e4a7823b2ac1558ffeb454c3a9f8b4 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 17 Jul 2023 18:44:51 -0400 Subject: [PATCH 0170/1171] clear unreachable flag upon succesive connect --- libi2pd/NetDb.cpp | 9 +++------ libi2pd/Profiling.cpp | 6 +++--- libi2pd/Profiling.h | 2 +- libi2pd/Transports.cpp | 1 + 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 7bccb2a0..112d3cb3 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -424,12 +424,9 @@ namespace data if (r) { r->SetUnreachable (unreachable); - if (unreachable) - { - auto profile = r->GetProfile (); - if (profile) - profile->Unreachable (); - } + auto profile = r->GetProfile (); + if (profile) + profile->Unreachable (unreachable); } } diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index 47fc15e7..879aea29 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -165,12 +165,12 @@ namespace data } } - void RouterProfile::Unreachable () + void RouterProfile::Unreachable (bool unreachable) { - m_LastUnreachableTime = i2p::util::GetSecondsSinceEpoch (); + m_LastUnreachableTime = unreachable ? i2p::util::GetSecondsSinceEpoch () : 0; UpdateTime (); } - + void RouterProfile::Connected () { m_HasConnected = true; diff --git a/libi2pd/Profiling.h b/libi2pd/Profiling.h index 6b814893..c351b41d 100644 --- a/libi2pd/Profiling.h +++ b/libi2pd/Profiling.h @@ -55,7 +55,7 @@ namespace data void TunnelBuildResponse (uint8_t ret); void TunnelNonReplied (); - void Unreachable (); + void Unreachable (bool unreachable); void Connected (); boost::posix_time::ptime GetLastUpdateTime () const { return m_LastUpdateTime; }; diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 38d6e270..01e484f4 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -716,6 +716,7 @@ namespace transport if (transport == i2p::data::RouterInfo::eNTCP2V4 || transport == i2p::data::RouterInfo::eNTCP2V6 || transport == i2p::data::RouterInfo::eNTCP2V6Mesh) it->second.router->GetProfile ()->Connected (); // outgoing NTCP2 connection if always real + i2p::data::netdb.SetUnreachable (ident, false); // clear unreachable } it->second.numAttempts = 0; it->second.router = nullptr; // we don't need RouterInfo after successive connect From 902899ae2422d82147a5e73dac13d7a7f2297a30 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 17 Jul 2023 19:49:42 -0400 Subject: [PATCH 0171/1171] don't pick completely unreachable peers --- libi2pd/NetDb.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 112d3cb3..061ccc23 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -1203,7 +1203,7 @@ namespace data [compatibleWith, reverse, endpoint](std::shared_ptr router)->bool { return !router->IsHidden () && router != compatibleWith && - (reverse ? compatibleWith->IsReachableFrom (*router) : + (reverse ? (compatibleWith->IsReachableFrom (*router) && router->GetCompatibleTransports (true)): router->IsReachableFrom (*compatibleWith)) && router->IsECIES () && !router->IsHighCongestion (false) && (!endpoint || (router->IsV4 () && (!reverse || router->IsPublished (true)))); // endpoint must be ipv4 and published if inbound(reverse) @@ -1237,7 +1237,7 @@ namespace data [compatibleWith, reverse, endpoint](std::shared_ptr router)->bool { return !router->IsHidden () && router != compatibleWith && - (reverse ? compatibleWith->IsReachableFrom (*router) : + (reverse ? (compatibleWith->IsReachableFrom (*router) && router->GetCompatibleTransports (true)) : router->IsReachableFrom (*compatibleWith)) && (router->GetCaps () & RouterInfo::eHighBandwidth) && router->GetVersion () >= NETDB_MIN_HIGHBANDWIDTH_VERSION && From 0754255c1f597beba3f9dae5c21f7c99e927918b Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 17 Jul 2023 21:08:26 -0400 Subject: [PATCH 0172/1171] drop incoming session from too old or from future routers --- libi2pd/NTCP2.cpp | 11 +++++++++-- libi2pd/SSU2Session.cpp | 11 +++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 364ebe8e..fa852f92 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -695,12 +695,19 @@ namespace transport SendTerminationAndTerminate (eNTCP2RouterInfoSignatureVerificationFail); return; } - if (i2p::util::GetMillisecondsSinceEpoch () > ri.GetTimestamp () + i2p::data::NETDB_MIN_EXPIRATION_TIMEOUT*1000LL) // 90 minutes + auto ts = i2p::util::GetMillisecondsSinceEpoch (); + if (ts > ri.GetTimestamp () + i2p::data::NETDB_MIN_EXPIRATION_TIMEOUT*1000LL) // 90 minutes { - LogPrint (eLogError, "NTCP2: RouterInfo is too old in SessionConfirmed"); + LogPrint (eLogError, "NTCP2: RouterInfo is too old in SessionConfirmed for ", (ts - ri.GetTimestamp ())/1000LL, " seconds"); SendTerminationAndTerminate (eNTCP2Message3Error); return; } + if (ts + i2p::data::NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < ri.GetTimestamp ()) // 2 minutes + { + LogPrint (eLogError, "NTCP2: RouterInfo is from future for ", (ri.GetTimestamp () - ts)/1000LL, " seconds"); + SendTerminationAndTerminate (eNTCP2Message3Error); + return; + } auto addr = m_RemoteEndpoint.address ().is_v4 () ? ri.GetNTCP2V4Address () : (i2p::util::net::IsYggdrasilAddress (m_RemoteEndpoint.address ()) ? ri.GetYggdrasilAddress () : ri.GetNTCP2V6Address ()); if (!addr || memcmp (m_Establisher->m_RemoteStaticKey, addr->s, 32)) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 23afd4c3..51c167ea 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1053,6 +1053,17 @@ namespace transport LogPrint (eLogError, "SSU2: SessionConfirmed malformed RouterInfo block"); return false; } + auto ts = i2p::util::GetMillisecondsSinceEpoch(); + if (ts > ri->GetTimestamp () + i2p::data::NETDB_MIN_EXPIRATION_TIMEOUT*1000LL) // 90 minutes + { + LogPrint (eLogError, "SSU2: RouterInfo in SessionConfirmed is too old for ", (ts - ri->GetTimestamp ())/1000LL, " seconds"); + return false; + } + if (ts + i2p::data::NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < ri->GetTimestamp ()) // 2 minutes + { + LogPrint (eLogError, "SSU2: RouterInfo in SessionConfirmed is from future for ", (ri->GetTimestamp () - ts)/1000LL, " seconds"); + return false; + } m_Address = m_RemoteEndpoint.address ().is_v6 () ? ri->GetSSU2V6Address () : ri->GetSSU2V4Address (); if (!m_Address || memcmp (S, m_Address->s, 32)) { From f13cc0b862646c0d13514d429d1472df1b948883 Mon Sep 17 00:00:00 2001 From: Vort Date: Wed, 19 Jul 2023 16:38:04 +0300 Subject: [PATCH 0173/1171] allow 0 hops with explicitPeers --- libi2pd/TunnelPool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index fd31cb09..23cc53e3 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -570,9 +570,9 @@ namespace tunnel bool TunnelPool::SelectExplicitPeers (Path& path, bool isInbound) { + if (!m_ExplicitPeers->size ()) return false; int numHops = isInbound ? m_NumInboundHops : m_NumOutboundHops; if (numHops > (int)m_ExplicitPeers->size ()) numHops = m_ExplicitPeers->size (); - if (!numHops) return false; for (int i = 0; i < numHops; i++) { auto& ident = (*m_ExplicitPeers)[i]; From 6e9a3422e9e723197c3ad56fbc9357f2656fe1f3 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 21 Jul 2023 07:59:09 -0400 Subject: [PATCH 0174/1171] correct min size for keepalive --- libi2pd/SSU2Session.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 51c167ea..dcc5ad52 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -243,7 +243,7 @@ namespace transport if (IsEstablished ()) { uint8_t payload[20]; - size_t payloadSize = CreatePaddingBlock (payload, 20, 5); + size_t payloadSize = CreatePaddingBlock (payload, 20, 8); SendData (payload, payloadSize); } } From c7efd465fa5bd06d4fccfde0e771a1920c624049 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 21 Jul 2023 18:25:28 -0400 Subject: [PATCH 0175/1171] padding for path response --- libi2pd/SSU2Session.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index dcc5ad52..4a1395b3 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -2857,7 +2857,7 @@ namespace transport void SSU2Session::SendPathResponse (const uint8_t * data, size_t len) { - if (len < 8 || len > m_MaxPayloadSize - 3) + if (len > m_MaxPayloadSize - 3) { LogPrint (eLogWarning, "SSU2: Incorrect data size for path response ", len); return; @@ -2866,7 +2866,10 @@ namespace transport payload[0] = eSSU2BlkPathResponse; htobe16buf (payload + 1, len); memcpy (payload + 3, data, len); - SendData (payload, len + 3); + size_t payloadSize = len + 3; + if (payloadSize < m_MaxPayloadSize) + payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, payloadSize < 8 ? 8 : 0); + SendData (payload, payloadSize); } void SSU2Session::SendPathChallenge () @@ -2884,7 +2887,7 @@ namespace transport } len += 3; if (len < m_MaxPayloadSize) - len += CreatePaddingBlock (payload + len, m_MaxPayloadSize - len); + len += CreatePaddingBlock (payload + len, m_MaxPayloadSize - len, len < 8 ? 8 : 0); SendData (payload, len); } From b8e19bf5f1e3fbcf0f45ccfb85b1923142d96e46 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 22 Jul 2023 08:50:49 -0400 Subject: [PATCH 0176/1171] reduced peer test interval and added peer test interval variance --- libi2pd/SSU2.cpp | 12 ++++++++---- libi2pd/SSU2.h | 3 ++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index a9e04790..6594f6d9 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -1078,7 +1078,8 @@ namespace transport { if (m_IsPublished) { - m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL)); + m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds( + SSU2_KEEP_ALIVE_INTERVAL + rand () % SSU2_KEEP_ALIVE_INTERVAL_VARIANCE)); m_IntroducersUpdateTimer.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer, this, std::placeholders::_1, true)); } @@ -1091,7 +1092,8 @@ namespace transport m_IntroducersUpdateTimer.cancel (); i2p::context.ClearSSU2Introducers (true); m_Introducers.clear (); - m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL/2)); + m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds( + (SSU2_KEEP_ALIVE_INTERVAL + rand () % SSU2_KEEP_ALIVE_INTERVAL_VARIANCE)/2)); m_IntroducersUpdateTimer.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer, this, std::placeholders::_1, true)); } @@ -1101,7 +1103,8 @@ namespace transport { if (m_IsPublished) { - m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL)); + m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds( + SSU2_KEEP_ALIVE_INTERVAL + rand () % SSU2_KEEP_ALIVE_INTERVAL_VARIANCE)); m_IntroducersUpdateTimerV6.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer, this, std::placeholders::_1, false)); } @@ -1114,7 +1117,8 @@ namespace transport m_IntroducersUpdateTimerV6.cancel (); i2p::context.ClearSSU2Introducers (false); m_IntroducersV6.clear (); - m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL/2)); + m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds( + (SSU2_KEEP_ALIVE_INTERVAL + rand () % SSU2_KEEP_ALIVE_INTERVAL_VARIANCE)/2)); m_IntroducersUpdateTimerV6.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer, this, std::placeholders::_1, false)); } diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index 2e652786..a1fafc63 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -29,7 +29,8 @@ namespace transport const size_t SSU2_MAX_NUM_INTRODUCERS = 3; const int SSU2_TO_INTRODUCER_SESSION_DURATION = 3600; // 1 hour const int SSU2_TO_INTRODUCER_SESSION_EXPIRATION = 4800; // 80 minutes - const int SSU2_KEEP_ALIVE_INTERVAL = 30; // in seconds + const int SSU2_KEEP_ALIVE_INTERVAL = 15; // in seconds + const int SSU2_KEEP_ALIVE_INTERVAL_VARIANCE = 4; // in seconds const int SSU2_PROXY_CONNECT_RETRY_TIMEOUT = 30; // in seconds class SSU2Server: private i2p::util::RunnableServiceWithWork From 413e25f20e16a0a0e1b01ed9cdf1d76e20ba3a5b Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 22 Jul 2023 10:13:05 -0400 Subject: [PATCH 0177/1171] don't pick too old session for introducer --- libi2pd/SSU2.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 6594f6d9..f3f0542d 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -1035,10 +1035,13 @@ namespace transport for (const auto& it : sessions) { + uint32_t exp = it->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION; + if (ts + SSU2_TO_INTRODUCER_SESSION_DURATION/2 > exp) + continue; // don't pick too old session for introducer i2p::data::RouterInfo::Introducer introducer; introducer.iTag = it->GetRelayTag (); introducer.iH = it->GetRemoteIdentity ()->GetIdentHash (); - introducer.iExp = it->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION; + introducer.iExp = exp; excluded.insert (it->GetRemoteIdentity ()->GetIdentHash ()); if (i2p::context.AddSSU2Introducer (introducer, v4)) { From d6834d6a9a205756f77a1ec02488db947a1c4d4d Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 22 Jul 2023 15:03:03 -0400 Subject: [PATCH 0178/1171] keep non-published, but not-expired introducers in the introducers list --- libi2pd/SSU2.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index f3f0542d..959bef54 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -983,7 +983,7 @@ namespace transport void SSU2Server::UpdateIntroducers (bool v4) { uint32_t ts = i2p::util::GetSecondsSinceEpoch (); - std::list newList; + std::list newList, impliedList; auto& introducers = v4 ? m_Introducers : m_IntroducersV6; std::set excluded; for (const auto& it : introducers) @@ -997,12 +997,17 @@ namespace transport } if (session && session->IsEstablished ()) { - if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION) - session->SendKeepAlive (); if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION) newList.push_back (it); else + { + if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION) + { + impliedList.push_back (it); // keep in introducers list, but not publish + session->SendKeepAlive (); + } session = nullptr; + } } if (!session) i2p::context.RemoveSSU2Introducer (it, v4); @@ -1024,10 +1029,7 @@ namespace transport { session->SetCreationTime (session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION); if (std::find (newList.begin (), newList.end (), it) == newList.end ()) - { - newList.push_back (it); sessions.push_back (session); - } } } } @@ -1075,6 +1077,7 @@ namespace transport } } } + introducers.splice (introducers.end (), impliedList); // insert non-published, but non-expired introducers back } void SSU2Server::ScheduleIntroducersUpdateTimer () From 4aa631c33f7db3e75979a3e21da3597ebd83bc6b Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 22 Jul 2023 16:51:19 -0400 Subject: [PATCH 0179/1171] clear implied list if no more introducers found --- libi2pd/SSU2.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 959bef54..c371928c 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -1019,6 +1019,7 @@ namespace transport { // bump creation time for previous introducers if no new sessions found LogPrint (eLogDebug, "SSU2: No new introducers found. Trying to reuse existing"); + impliedList.clear (); for (auto& it : introducers) { auto it1 = m_SessionsByRouterHash.find (it); From 2064504ccedc84d16007db4b22f8385c949dec28 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 23 Jul 2023 07:17:10 -0400 Subject: [PATCH 0180/1171] fixed send keepalive for existing session --- libi2pd/SSU2.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index c371928c..0832b78c 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -997,17 +997,16 @@ namespace transport } if (session && session->IsEstablished ()) { - if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION) + if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION) newList.push_back (it); else { if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION) - { impliedList.push_back (it); // keep in introducers list, but not publish - session->SendKeepAlive (); - } - session = nullptr; - } + else + session = nullptr; + } + if (session) session->SendKeepAlive (); } if (!session) i2p::context.RemoveSSU2Introducer (it, v4); From ae5239de435e1dcdff342961af9b506f60a494d4 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 23 Jul 2023 07:42:36 -0400 Subject: [PATCH 0181/1171] remove introducer from RouterInfo after 60 minutes --- libi2pd/SSU2.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 0832b78c..ac42ca7a 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -997,16 +997,19 @@ namespace transport } if (session && session->IsEstablished ()) { - if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION) - newList.push_back (it); - else + if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION) { - if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION) + session->SendKeepAlive (); + if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION) + newList.push_back (it); + else + { impliedList.push_back (it); // keep in introducers list, but not publish - else - session = nullptr; + session = nullptr; + } } - if (session) session->SendKeepAlive (); + else + session = nullptr; } if (!session) i2p::context.RemoveSSU2Introducer (it, v4); From 68f4961f1aff340f5e0269af7653cf029918d97a Mon Sep 17 00:00:00 2001 From: Vort Date: Sun, 30 Jul 2023 15:29:10 +0300 Subject: [PATCH 0182/1171] separate test status from network status --- Win32/Win32App.cpp | 9 ++++--- daemon/HTTPServer.cpp | 9 ++++--- libi2pd/RouterContext.cpp | 31 ++++++++++++++++++------ libi2pd/RouterContext.h | 14 +++++++---- libi2pd/SSU2.cpp | 4 +-- libi2pd/SSU2Session.cpp | 51 ++++++++++++++++++++++++++++++--------- libi2pd/SSU2Session.h | 2 ++ libi2pd/Transports.cpp | 12 ++++----- 8 files changed, 92 insertions(+), 40 deletions(-) diff --git a/Win32/Win32App.cpp b/Win32/Win32App.cpp index fc61a8ac..9f750c4c 100644 --- a/Win32/Win32App.cpp +++ b/Win32/Win32App.cpp @@ -145,18 +145,19 @@ namespace win32 s << bytes << " Bytes\n"; } - static void ShowNetworkStatus (std::stringstream& s, RouterStatus status) + static void ShowNetworkStatus (std::stringstream& s, RouterStatus status, bool testing) { switch (status) { case eRouterStatusOK: s << "OK"; break; - case eRouterStatusTesting: s << "Test"; break; case eRouterStatusFirewalled: s << "FW"; break; case eRouterStatusUnknown: s << "Unk"; break; case eRouterStatusProxy: s << "Proxy"; break; case eRouterStatusMesh: s << "Mesh"; break; default: s << "Unk"; }; + if (testing) + s << " (Test)"; if (i2p::context.GetError () != eRouterErrorNone) { switch (i2p::context.GetError ()) @@ -179,11 +180,11 @@ namespace win32 { s << "\n"; s << "Status: "; - ShowNetworkStatus (s, i2p::context.GetStatus ()); + ShowNetworkStatus (s, i2p::context.GetStatus (), i2p::context.GetTesting ()); if (i2p::context.SupportsV6 ()) { s << " / "; - ShowNetworkStatus (s, i2p::context.GetStatusV6 ()); + ShowNetworkStatus (s, i2p::context.GetStatusV6 (), i2p::context.GetTestingV6 ()); } s << "; "; s << "Success Rate: " << i2p::tunnel::tunnels.GetTunnelCreationSuccessRate() << "%\n"; diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 50666940..2d6800b4 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -222,18 +222,19 @@ namespace http { s << "" << tr("ERROR") << ": " << string << "
\r\n"; } - static void ShowNetworkStatus (std::stringstream& s, RouterStatus status, RouterError error) + static void ShowNetworkStatus (std::stringstream& s, RouterStatus status, bool testing, RouterError error) { switch (status) { case eRouterStatusOK: s << tr("OK"); break; - case eRouterStatusTesting: s << tr("Testing"); break; case eRouterStatusFirewalled: s << tr("Firewalled"); break; case eRouterStatusUnknown: s << tr("Unknown"); break; case eRouterStatusProxy: s << tr("Proxy"); break; case eRouterStatusMesh: s << tr("Mesh"); break; default: s << tr("Unknown"); } + if (testing) + s << " (" << tr("Testing") << ")"; if (error != eRouterErrorNone) { switch (error) @@ -264,12 +265,12 @@ namespace http { ShowUptime(s, i2p::context.GetUptime ()); s << "
\r\n"; s << "" << tr("Network status") << ": "; - ShowNetworkStatus (s, i2p::context.GetStatus (), i2p::context.GetError ()); + ShowNetworkStatus (s, i2p::context.GetStatus (), i2p::context.GetTesting(), i2p::context.GetError ()); s << "
\r\n"; if (i2p::context.SupportsV6 ()) { s << "" << tr("Network status v6") << ": "; - ShowNetworkStatus (s, i2p::context.GetStatusV6 (), i2p::context.GetErrorV6 ()); + ShowNetworkStatus (s, i2p::context.GetStatusV6 (), i2p::context.GetTestingV6(), i2p::context.GetErrorV6 ()); s << "
\r\n"; } #if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY)) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 3e7d7a2c..fa3ba7bd 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -31,7 +31,8 @@ namespace i2p RouterContext::RouterContext (): m_LastUpdateTime (0), m_AcceptsTunnels (true), m_IsFloodfill (false), m_ShareRatio (100), m_Status (eRouterStatusUnknown), m_StatusV6 (eRouterStatusUnknown), - m_Error (eRouterErrorNone), m_ErrorV6 (eRouterErrorNone), m_NetID (I2PD_NET_ID), + m_Error (eRouterErrorNone), m_ErrorV6 (eRouterErrorNone), + m_Testing (false), m_TestingV6 (false), m_NetID (I2PD_NET_ID), m_PublishReplyToken (0), m_IsHiddenMode (false) { } @@ -277,8 +278,29 @@ namespace i2p fk.write ((char *)m_SSU2Keys.get (), sizeof (SSU2PrivateKeys)); } + void RouterContext::SetTesting (bool testing) + { + if (testing != m_Testing) + { + m_Testing = testing; + if (m_Testing) + m_Error = eRouterErrorNone; + } + } + + void RouterContext::SetTestingV6 (bool testing) + { + if (testing != m_TestingV6) + { + m_TestingV6 = testing; + if (m_TestingV6) + m_ErrorV6 = eRouterErrorNone; + } + } + void RouterContext::SetStatus (RouterStatus status) { + SetTesting (false); if (status != m_Status) { m_Status = status; @@ -290,9 +312,6 @@ namespace i2p case eRouterStatusFirewalled: SetUnreachable (true, false); // ipv4 break; - case eRouterStatusTesting: - m_Error = eRouterErrorNone; - break; default: ; } @@ -301,6 +320,7 @@ namespace i2p void RouterContext::SetStatusV6 (RouterStatus status) { + SetTestingV6 (false); if (status != m_StatusV6) { m_StatusV6 = status; @@ -312,9 +332,6 @@ namespace i2p case eRouterStatusFirewalled: SetUnreachable (false, true); // ipv6 break; - case eRouterStatusTesting: - m_ErrorV6 = eRouterErrorNone; - break; default: ; } diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index b8183339..d49b5523 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -42,11 +42,10 @@ namespace garlic enum RouterStatus { eRouterStatusOK = 0, - eRouterStatusTesting = 1, - eRouterStatusFirewalled = 2, - eRouterStatusUnknown = 3, - eRouterStatusProxy = 4, - eRouterStatusMesh = 5 + eRouterStatusFirewalled = 1, + eRouterStatusUnknown = 2, + eRouterStatusProxy = 3, + eRouterStatusMesh = 4 }; enum RouterError @@ -121,10 +120,14 @@ namespace garlic uint64_t GetLastUpdateTime () const { return m_LastUpdateTime; }; uint64_t GetBandwidthLimit () const { return m_BandwidthLimit; }; uint64_t GetTransitBandwidthLimit () const { return (m_BandwidthLimit*m_ShareRatio)/100LL; }; + bool GetTesting () const { return m_Testing; }; + void SetTesting (bool testing); RouterStatus GetStatus () const { return m_Status; }; void SetStatus (RouterStatus status); RouterError GetError () const { return m_Error; }; void SetError (RouterError error) { m_Error = error; }; + bool GetTestingV6 () const { return m_TestingV6; }; + void SetTestingV6 (bool testing); RouterStatus GetStatusV6 () const { return m_StatusV6; }; void SetStatusV6 (RouterStatus status); RouterError GetErrorV6 () const { return m_ErrorV6; }; @@ -231,6 +234,7 @@ namespace garlic int m_ShareRatio; RouterStatus m_Status, m_StatusV6; RouterError m_Error, m_ErrorV6; + bool m_Testing, m_TestingV6; int m_NetID; std::unique_ptr m_NTCP2Keys; std::unique_ptr m_SSU2Keys; diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index ac42ca7a..53ef8db7 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -1140,7 +1140,7 @@ namespace transport // timeout expired if (v4) { - if (i2p::context.GetStatus () == eRouterStatusTesting) + if (i2p::context.GetTesting ()) { // we still don't know if we need introducers ScheduleIntroducersUpdateTimer (); @@ -1163,7 +1163,7 @@ namespace transport } else { - if (i2p::context.GetStatusV6 () == eRouterStatusTesting) + if (i2p::context.GetTestingV6 ()) { // we still don't know if we need introducers ScheduleIntroducersUpdateTimerV6 (); diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 4a1395b3..54add930 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1651,8 +1651,8 @@ namespace transport break; case eSSU2SessionStateSessionCreatedReceived: case eSSU2SessionStateTokenReceived: - if ((m_RemoteEndpoint.address ().is_v4 () && i2p::context.GetStatus () == eRouterStatusTesting) || - (m_RemoteEndpoint.address ().is_v6 () && i2p::context.GetStatusV6 () == eRouterStatusTesting)) + if ((m_RemoteEndpoint.address ().is_v4 () && i2p::context.GetTesting ()) || + (m_RemoteEndpoint.address ().is_v6 () && i2p::context.GetTestingV6 ())) { if (m_Server.IsSyncClockFromPeers ()) { @@ -1750,14 +1750,14 @@ namespace transport LogPrint (eLogInfo, "SSU2: Our port ", ep.port (), " received from ", m_RemoteEndpoint, " is different from ", m_Server.GetPort (isV4)); if (isV4) { - if (i2p::context.GetStatus () == eRouterStatusTesting) + if (i2p::context.GetTesting ()) i2p::context.SetError (eRouterErrorSymmetricNAT); else if (m_State == eSSU2SessionStatePeerTest) i2p::context.SetError (eRouterErrorFullConeNAT); } else { - if (i2p::context.GetStatusV6 () == eRouterStatusTesting) + if (i2p::context.GetTestingV6 ()) i2p::context.SetErrorV6 (eRouterErrorSymmetricNAT); else if (m_State == eSSU2SessionStatePeerTest) i2p::context.SetErrorV6 (eRouterErrorFullConeNAT); @@ -2230,7 +2230,7 @@ namespace transport if (buf[1] == eSSU2PeerTestCodeAccept) { if (GetRouterStatus () == eRouterStatusUnknown) - SetRouterStatus (eRouterStatusTesting); + SetTestingState (true); auto r = i2p::data::netdb.FindRouter (buf + 3); // find Charlie if (r && it->second.first) { @@ -2256,13 +2256,17 @@ namespace transport } else { - if (GetRouterStatus () == eRouterStatusTesting) + if (GetTestingState ()) { - SetRouterStatus (eRouterStatusFirewalled); - if (m_Address->IsV4 ()) - m_Server.RescheduleIntroducersUpdateTimer (); - else - m_Server.RescheduleIntroducersUpdateTimerV6 (); + SetTestingState (false); + if (GetRouterStatus () != eRouterStatusFirewalled) + { + SetRouterStatus (eRouterStatusFirewalled); + if (m_Address->IsV4 ()) + m_Server.RescheduleIntroducersUpdateTimer (); + else + m_Server.RescheduleIntroducersUpdateTimerV6 (); + } } } LogPrint (eLogDebug, "SSU2: Peer test 4 received from ", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()), @@ -2291,7 +2295,7 @@ namespace transport { LogPrint (eLogInfo, "SSU2: Peer test 4 error code ", (int)buf[1], " from ", i2p::data::GetIdentHashAbbreviation (buf[1] < 64 ? GetRemoteIdentity ()->GetIdentHash () : i2p::data::IdentHash (buf + 3))); - if (GetRouterStatus () == eRouterStatusTesting) + if (GetTestingState ()) SetRouterStatus (eRouterStatusUnknown); it->second.first->Done (); } @@ -2445,6 +2449,29 @@ namespace transport } } + bool SSU2Session::GetTestingState () const + { + if (m_Address) + { + if (m_Address->IsV4 ()) + return i2p::context.GetTesting (); + if (m_Address->IsV6 ()) + return i2p::context.GetTestingV6 (); + } + return false; + } + + void SSU2Session::SetTestingState (bool testing) const + { + if (m_Address) + { + if (m_Address->IsV4 ()) + i2p::context.SetTesting (testing); + else if (m_Address->IsV6 ()) + i2p::context.SetTestingV6 (testing); + } + } + size_t SSU2Session::CreateAddressBlock (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& ep) { if (len < 9) return 0; diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index 304efdab..14d76971 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -308,6 +308,8 @@ namespace transport void AdjustMaxPayloadSize (); RouterStatus GetRouterStatus () const; void SetRouterStatus (RouterStatus status) const; + bool GetTestingState () const; + void SetTestingState(bool testing) const; std::shared_ptr ExtractRouterInfo (const uint8_t * buf, size_t size); void CreateNonce (uint64_t seqn, uint8_t * nonce); bool UpdateReceivePacketNum (uint32_t packetNum); // for Ack, returns false if duplicate diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 01e484f4..b452c05e 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -650,8 +650,8 @@ namespace transport auto router = i2p::data::netdb.GetRandomSSU2PeerTestRouter (true, excluded); // v4 if (router) { - if (i2p::context.GetStatus () != eRouterStatusTesting) - i2p::context.SetStatus (eRouterStatusTesting); + if (!i2p::context.GetTesting ()) + i2p::context.SetTesting (true); m_SSU2Server->StartPeerTest (router, true); excluded.insert (router->GetIdentHash ()); } @@ -669,8 +669,8 @@ namespace transport auto router = i2p::data::netdb.GetRandomSSU2PeerTestRouter (false, excluded); // v6 if (router) { - if (i2p::context.GetStatusV6 () != eRouterStatusTesting) - i2p::context.SetStatusV6 (eRouterStatusTesting); + if (!i2p::context.GetTestingV6 ()) + i2p::context.SetTestingV6 (true); m_SSU2Server->StartPeerTest (router, false); excluded.insert (router->GetIdentHash ()); } @@ -832,8 +832,8 @@ namespace transport ++it; } } - bool ipv4Testing = i2p::context.GetStatus () == eRouterStatusTesting; - bool ipv6Testing = i2p::context.GetStatusV6 () == eRouterStatusTesting; + bool ipv4Testing = i2p::context.GetTesting (); + bool ipv6Testing = i2p::context.GetTestingV6 (); // if still testing, repeat peer test if (ipv4Testing || ipv6Testing) PeerTest (ipv4Testing, ipv6Testing); From 38795a41cbbb21a756ecb4fd13f045e6f5f5811f Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 5 Aug 2023 08:55:06 -0400 Subject: [PATCH 0183/1171] don't publish introducers with zero iTag --- libi2pd/SSU2.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 53ef8db7..5d0e7d22 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -1028,7 +1028,7 @@ namespace transport if (it1 != m_SessionsByRouterHash.end ()) { auto session = it1->second; - if (session->IsEstablished ()) + if (session->IsEstablished () && session->GetRelayTag () && session->IsOutgoing ()) { session->SetCreationTime (session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION); if (std::find (newList.begin (), newList.end (), it) == newList.end ()) @@ -1040,11 +1040,12 @@ namespace transport for (const auto& it : sessions) { + uint32_t tag = it->GetRelayTag (); uint32_t exp = it->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION; - if (ts + SSU2_TO_INTRODUCER_SESSION_DURATION/2 > exp) + if (!tag || ts + SSU2_TO_INTRODUCER_SESSION_DURATION/2 > exp) continue; // don't pick too old session for introducer i2p::data::RouterInfo::Introducer introducer; - introducer.iTag = it->GetRelayTag (); + introducer.iTag = tag; introducer.iH = it->GetRemoteIdentity ()->GetIdentHash (); introducer.iExp = exp; excluded.insert (it->GetRemoteIdentity ()->GetIdentHash ()); From 9bac680f2a3181bb861beb2dbf739d92a5ab6597 Mon Sep 17 00:00:00 2001 From: Vort Date: Sat, 5 Aug 2023 17:49:22 +0300 Subject: [PATCH 0184/1171] improve transport session logging --- libi2pd/NTCP2.cpp | 23 ++++++++++++++++++----- libi2pd/SSU2Session.cpp | 15 ++++++++++++++- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index fa852f92..bbd93435 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -375,7 +375,16 @@ namespace transport m_Server.RemoveNTCP2Session (shared_from_this ()); m_SendQueue.clear (); m_SendQueueSize = 0; - LogPrint (eLogDebug, "NTCP2: Session terminated"); + auto remoteIdentity = GetRemoteIdentity (); + if (remoteIdentity) + { + LogPrint (eLogDebug, "NTCP2: Session with ", GetRemoteEndpoint (), + " (", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()), ") terminated"); + } + else + { + LogPrint (eLogDebug, "NTCP2: Session with ", GetRemoteEndpoint (), " terminated"); + } } } @@ -691,11 +700,13 @@ namespace transport i2p::data::RouterInfo ri (buf.data () + 4, size - 1); // 1 byte block type + 2 bytes size + 1 byte flag if (ri.IsUnreachable ()) { - LogPrint (eLogError, "NTCP2: Signature verification failed in SessionConfirmed"); + LogPrint (eLogError, "NTCP2: RouterInfo verification failed in SessionConfirmed from ", GetRemoteEndpoint ()); SendTerminationAndTerminate (eNTCP2RouterInfoSignatureVerificationFail); return; } - auto ts = i2p::util::GetMillisecondsSinceEpoch (); + LogPrint(eLogDebug, "NTCP2: SessionConfirmed from ", GetRemoteEndpoint (), + " (", i2p::data::GetIdentHashAbbreviation (ri.GetIdentHash ()), ")"); + auto ts = i2p::util::GetMillisecondsSinceEpoch (); if (ts > ri.GetTimestamp () + i2p::data::NETDB_MIN_EXPIRATION_TIMEOUT*1000LL) // 90 minutes { LogPrint (eLogError, "NTCP2: RouterInfo is too old in SessionConfirmed for ", (ts - ri.GetTimestamp ())/1000LL, " seconds"); @@ -1409,7 +1420,8 @@ namespace transport LogPrint (eLogError, "NTCP2: Can't connect to unspecified address"); return; } - LogPrint (eLogDebug, "NTCP2: Connecting to ", conn->GetRemoteEndpoint ()); + LogPrint (eLogDebug, "NTCP2: Connecting to ", conn->GetRemoteEndpoint (), + " (", i2p::data::GetIdentHashAbbreviation (conn->GetRemoteIdentity ()->GetIdentHash ()), ")"); GetService ().post([this, conn]() { if (this->AddNTCP2Session (conn)) @@ -1465,7 +1477,8 @@ namespace transport } else { - LogPrint (eLogDebug, "NTCP2: Connected to ", conn->GetRemoteEndpoint ()); + LogPrint (eLogDebug, "NTCP2: Connected to ", conn->GetRemoteEndpoint (), + " (", i2p::data::GetIdentHashAbbreviation (conn->GetRemoteIdentity ()->GetIdentHash ()), ")"); conn->ClientLogin (); } } diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 54add930..f0e539c7 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -114,6 +114,8 @@ namespace transport { if (m_State == eSSU2SessionStateUnknown || m_State == eSSU2SessionStateTokenReceived) { + LogPrint(eLogDebug, "SSU2: Connecting to ", GetRemoteEndpoint (), + " (", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()), ")"); ScheduleConnectTimer (); auto token = m_Server.FindOutgoingToken (m_RemoteEndpoint); if (token) @@ -269,7 +271,16 @@ namespace transport m_ReceivedI2NPMsgIDs.clear (); m_Server.RemoveSession (m_SourceConnID); transports.PeerDisconnected (shared_from_this ()); - LogPrint (eLogDebug, "SSU2: Session terminated"); + auto remoteIdentity = GetRemoteIdentity (); + if (remoteIdentity) + { + LogPrint (eLogDebug, "SSU2: Session with ", GetRemoteEndpoint (), + " (", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()), ") terminated"); + } + else + { + LogPrint (eLogDebug, "SSU2: Session with ", GetRemoteEndpoint (), " terminated"); + } } } @@ -298,6 +309,8 @@ namespace transport m_OnEstablished (); m_OnEstablished = nullptr; } + LogPrint(eLogDebug, "SSU2: Session with ", GetRemoteEndpoint (), + " (", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()), ") established"); } void SSU2Session::Done () From 8447822c3596cadadfa6c7bd7ab0643ddd814b34 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 5 Aug 2023 15:25:16 -0400 Subject: [PATCH 0185/1171] don't publish intrducers with zero tag --- libi2pd/RouterInfo.cpp | 3 +++ libi2pd/SSU2.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 646711c1..399e26a1 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -1321,6 +1321,7 @@ namespace data int i = 0; for (const auto& introducer: address.ssu->introducers) { + if (!introducer.iTag) continue; if (introducer.iExp) // expiration is specified { WriteString ("iexp" + boost::lexical_cast(i), properties); @@ -1333,6 +1334,7 @@ namespace data i = 0; for (const auto& introducer: address.ssu->introducers) { + if (!introducer.iTag) continue; WriteString ("ih" + boost::lexical_cast(i), properties); properties << '='; char value[64]; @@ -1345,6 +1347,7 @@ namespace data i = 0; for (const auto& introducer: address.ssu->introducers) { + if (!introducer.iTag) continue; WriteString ("itag" + boost::lexical_cast(i), properties); properties << '='; WriteString (boost::lexical_cast(introducer.iTag), properties); diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 5d0e7d22..7099ba0c 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -995,7 +995,7 @@ namespace transport session = it1->second; excluded.insert (it); } - if (session && session->IsEstablished ()) + if (session && session->IsEstablished () && session->GetRelayTag () && session->IsOutgoing ()) // still session with introducer? { if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION) { From 7bcc905f05b1356bb2f02cdc2abfe5a6a516207c Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 7 Aug 2023 21:28:13 -0400 Subject: [PATCH 0186/1171] exclude SSU1 introducers --- libi2pd/RouterInfo.cpp | 2 +- libi2pd/RouterInfo.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 399e26a1..63cb79ef 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -579,7 +579,7 @@ namespace data int numValid = 0; for (auto& it: address->ssu->introducers) { - if (it.iTag && ts < it.iExp) + if (it.iTag && ts < it.iExp && !it.iH.IsZero ()) numValid++; else it.iTag = 0; diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 47ee1dae..9aff2240 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -125,7 +125,7 @@ namespace data struct Introducer { - Introducer (): iTag (0), iExp (0) {}; + Introducer (): iTag (0), iExp (0) { iH.Fill(0); }; IdentHash iH; uint32_t iTag; uint32_t iExp; From 627b8dca8334ad036f948013bc564abcee8c291b Mon Sep 17 00:00:00 2001 From: Chad Fraleigh Date: Sun, 13 Aug 2023 17:08:14 -0700 Subject: [PATCH 0187/1171] Fixed buf offset EVP_EncryptFinal_ex() to include outlen. --- libi2pd/Crypto.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index 4a78f2b1..12087443 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -991,7 +991,7 @@ namespace crypto EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce); EVP_EncryptUpdate(ctx, NULL, &outlen, ad, adLen); EVP_EncryptUpdate(ctx, buf, &outlen, msg, msgLen); - EVP_EncryptFinal_ex(ctx, buf, &outlen); + EVP_EncryptFinal_ex(ctx, buf + outlen, &outlen); EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, buf + msgLen); } else From 662a59d0fda3f763a2f67654dd50cc2cf38a8178 Mon Sep 17 00:00:00 2001 From: Chad Fraleigh Date: Mon, 14 Aug 2023 19:21:30 -0700 Subject: [PATCH 0188/1171] Eliminate additional undefined behavior of bit shifting signed int. --- libi2pd/Base.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Base.cpp b/libi2pd/Base.cpp index 0e69b663..e979c5b4 100644 --- a/libi2pd/Base.cpp +++ b/libi2pd/Base.cpp @@ -272,7 +272,7 @@ namespace data size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen) { - int tmp = 0, bits = 0; + unsigned int tmp = 0, bits = 0; size_t ret = 0; for (size_t i = 0; i < len; i++) { From c112276eea649c3b406953e3400573d78a049f20 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 26 Aug 2023 10:57:05 -0400 Subject: [PATCH 0189/1171] memory poll for RouterProfile --- libi2pd/NetDb.cpp | 1 + libi2pd/NetDb.hpp | 2 ++ libi2pd/Profiling.cpp | 3 ++- libi2pd/Profiling.h | 3 +-- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 061ccc23..02d4dfd8 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -175,6 +175,7 @@ namespace data if (ts - lastProfilesCleanup >= (uint64_t)(i2p::data::PEER_PROFILE_AUTOCLEAN_TIMEOUT + profilesCleanupVariance) || ts + i2p::data::PEER_PROFILE_AUTOCLEAN_TIMEOUT < lastProfilesCleanup) { + m_RouterProfilesPool.CleanUpMt (); if (m_PersistProfiles) PersistProfiles (); DeleteObsoleteProfiles (); lastProfilesCleanup = ts; diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index b7d9a5b3..44dff3b8 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -128,6 +128,7 @@ namespace data }; std::shared_ptr NewLease (const Lease& lease) { return m_LeasesPool.AcquireSharedMt (lease); }; std::shared_ptr NewIdentity (const uint8_t * buf, size_t len) { return m_IdentitiesPool.AcquireSharedMt (buf, len); }; + std::shared_ptr NewRouterProfile () { return m_RouterProfilesPool.AcquireSharedMt (); }; uint32_t GetPublishReplyToken () const { return m_PublishReplyToken; }; @@ -185,6 +186,7 @@ namespace data i2p::util::MemoryPoolMt m_RouterInfoAddressVectorsPool; i2p::util::MemoryPoolMt m_LeasesPool; i2p::util::MemoryPoolMt m_IdentitiesPool; + i2p::util::MemoryPoolMt m_RouterProfilesPool; }; extern NetDb netdb; diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index 879aea29..2031fa39 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -16,6 +16,7 @@ #include "FS.h" #include "Log.h" #include "Timestamp.h" +#include "NetDb.hpp" #include "Profiling.h" namespace i2p @@ -237,7 +238,7 @@ namespace data if (it != g_Profiles.end ()) return it->second; } - auto profile = std::make_shared (); + auto profile = netdb.NewRouterProfile (); profile->Load (identHash); // if possible std::unique_lock l(g_ProfilesMutex); g_Profiles.emplace (identHash, profile); diff --git a/libi2pd/Profiling.h b/libi2pd/Profiling.h index c351b41d..6531e060 100644 --- a/libi2pd/Profiling.h +++ b/libi2pd/Profiling.h @@ -31,7 +31,7 @@ namespace data const char PEER_PROFILE_USAGE_CONNECTED[] = "connected"; const int PEER_PROFILE_EXPIRATION_TIMEOUT = 36; // in hours (1.5 days) - const int PEER_PROFILE_AUTOCLEAN_TIMEOUT = 6 * 3600; // in seconds (6 hours) + const int PEER_PROFILE_AUTOCLEAN_TIMEOUT = 3 * 3600; // in seconds (3 hours) const int PEER_PROFILE_AUTOCLEAN_VARIANCE = 3600; // in seconds (1 hour) const int PEER_PROFILE_DECLINED_RECENTLY_INTERVAL = 150; // in seconds (2.5 minutes) const int PEER_PROFILE_PERSIST_INTERVAL = 3300; // in seconds (55 minutes) @@ -43,7 +43,6 @@ namespace data public: RouterProfile (); - RouterProfile& operator= (const RouterProfile& ) = default; void Save (const IdentHash& identHash); void Load (const IdentHash& identHash); From 32c5ff23a62b8b8f200b4717244524bb3ab68638 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=B0=9C=E0=B0=BF=E0=B0=82=E0=B0=A6=E0=B0=82=20=E0=B0=B5?= =?UTF-8?q?=E0=B0=BE=E0=B0=90=E0=B0=BF?= <109575325+jindam-vani@users.noreply.github.com> Date: Thu, 31 Aug 2023 16:51:21 +0000 Subject: [PATCH 0190/1171] Differentiate cryptocurrency & its associated address (#1951) --- README.md | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index d0481ed9..e7fb7318 100644 --- a/README.md +++ b/README.md @@ -99,13 +99,23 @@ Current status: [![Crowdin](https://badges.crowdin.net/i2pd/localized.svg)](http Donations --------- -BTC: 3MDoGJW9TLMTCDGrR9bLgWXfm6sjmgy86f -LTC: LKQirrYrDeTuAPnpYq5y7LVKtywfkkHi59 -ETH: 0x9e5bac70d20d1079ceaa111127f4fb3bccce379d -DASH: Xw8YUrQpYzP9tZBmbjqxS3M97Q7v3vJKUF -ZEC: t1cTckLuXsr1dwVrK4NDzfhehss4NvMadAJ -GST: GbD2JSQHBHCKLa9WTHmigJRpyFgmBj4woG -XMR: 497pJc7X4xqKvcLBLpSUtRgWqMMyo24u4btCos3cak6gbMkpobgSU6492ztUcUBghyeHpYeczB55s38NpuHoH5WGNSPDRMH +**E-Mail**: ```i2porignal at yandex.ru``` + +**BTC**: ```3MDoGJW9TLMTCDGrR9bLgWXfm6sjmgy86f``` + +**LTC**: ```LKQirrYrDeTuAPnpYq5y7LVKtywfkkHi59``` + +**ETH**: ```0x9e5bac70d20d1079ceaa111127f4fb3bccce379d``` + +**GST**: ```GbD2JSQHBHCKLa9WTHmigJRpyFgmBj4woG``` + +**DASH**: ```Xw8YUrQpYzP9tZBmbjqxS3M97Q7v3vJKUF``` + +**ZEC**: ```t1cTckLuXsr1dwVrK4NDzfhehss4NvMadAJ``` + +**ANC**: ```AQJYweYYUqM1nVfLqfoSMpUMfzxvS4Xd7z``` + +**XMR**: ```497pJc7X4xqKvcLBLpSUtRgWqMMyo24u4btCos3cak6gbMkpobgSU6492ztUcUBghyeHpYeczB55s38NpuHoH5WGNSPDRMH``` License ------- From 7b6aa41ca8dc3ca2a0c9d01ff9870794ad98e403 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Thu, 31 Aug 2023 16:52:51 +0000 Subject: [PATCH 0191/1171] CPU: remove AVX code, switch to __builtin for AES detection (#1959) * [cpu] remove avx detect and code blocks, try to switch to __builtin * [cpu] use __builtin_* only on x86 systems * [cpu] perform check in separate function * [cpu] set AES definition on MSVC * update x86 and aes support checks at compile time * [cmake] update comment about AES on MSVC --- .editorconfig | 3 + build/CMakeLists.txt | 11 +- contrib/i2pd.conf | 2 - daemon/Daemon.cpp | 3 +- libi2pd/CPU.cpp | 60 ++++---- libi2pd/CPU.h | 5 +- libi2pd/Config.cpp | 4 +- libi2pd/Crypto.cpp | 332 ++++++++++++++++++++++--------------------- libi2pd/Crypto.h | 2 +- libi2pd/Identity.cpp | 29 +--- libi2pd/api.cpp | 3 +- 11 files changed, 222 insertions(+), 232 deletions(-) diff --git a/.editorconfig b/.editorconfig index e1f1243a..0f57a84a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -34,3 +34,6 @@ trim_trailing_whitespace = false [*.yml] indent_style = space indent_size = 2 + +[*.patch] +trim_trailing_whitespace = false diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index f5d01a0b..3185ffab 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -197,14 +197,11 @@ endif() # Note: AES-NI and AVX is available on x86-based CPU's. # Here also ARM64 implementation, but currently we don't support it. -# MSVC is not supported. -if(MSVC) - message(STATUS "AES-NI is not supported on MSVC, option was disabled") - set(WITH_AESNI OFF) -endif() - +# MSVC is not supported due to different ASM processing, so we hope OpenSSL has its own checks to run optimized code. if(WITH_AESNI AND (ARCHITECTURE MATCHES "x86_64" OR ARCHITECTURE MATCHES "i386")) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes") + if(NOT MSVC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes") + endif() add_definitions(-D__AES__) endif() diff --git a/contrib/i2pd.conf b/contrib/i2pd.conf index 5facbbd5..545973a3 100644 --- a/contrib/i2pd.conf +++ b/contrib/i2pd.conf @@ -280,8 +280,6 @@ verify = true [cpuext] ## Use CPU AES-NI instructions set when work with cryptography when available (default: true) # aesni = true -## Use CPU AVX instructions set when work with cryptography when available (default: true) -# avx = true ## Force usage of CPU instructions set, even if they not found (default: false) ## DO NOT TOUCH that option if you really don't know what are you doing! # force = false diff --git a/daemon/Daemon.cpp b/daemon/Daemon.cpp index 8e9721db..f04236fe 100644 --- a/daemon/Daemon.cpp +++ b/daemon/Daemon.cpp @@ -150,12 +150,11 @@ namespace util bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation); bool aesni; i2p::config::GetOption("cpuext.aesni", aesni); - bool avx; i2p::config::GetOption("cpuext.avx", avx); bool forceCpuExt; i2p::config::GetOption("cpuext.force", forceCpuExt); bool ssu; i2p::config::GetOption("ssu", ssu); if (!ssu && i2p::config::IsDefault ("precomputation.elgamal")) precomputation = false; // we don't elgamal table if no ssu, unless it's specified explicitly - i2p::crypto::InitCrypto (precomputation, aesni, avx, forceCpuExt); + i2p::crypto::InitCrypto (precomputation, aesni, forceCpuExt); i2p::transport::InitAddressFromIface (); // get address4/6 from interfaces diff --git a/libi2pd/CPU.cpp b/libi2pd/CPU.cpp index 0804e2ac..d42f1ddd 100644 --- a/libi2pd/CPU.cpp +++ b/libi2pd/CPU.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -7,52 +7,52 @@ */ #include "CPU.h" -#if defined(__x86_64__) || defined(__i386__) -#include -#endif #include "Log.h" -#ifndef bit_AES -#define bit_AES (1 << 25) -#endif -#ifndef bit_AVX -#define bit_AVX (1 << 28) -#endif +#if defined(_MSC_VER) +#include +#ifndef bit_AES + #define bit_AES (1 << 25) +#endif +#endif namespace i2p { namespace cpu { bool aesni = false; - bool avx = false; - void Detect(bool AesSwitch, bool AvxSwitch, bool force) + inline bool cpu_support_aes() { -#if defined(__x86_64__) || defined(__i386__) - int info[4]; - __cpuid(0, info[0], info[1], info[2], info[3]); - if (info[0] >= 0x00000001) { - __cpuid(0x00000001, info[0], info[1], info[2], info[3]); -#if defined (_WIN32) && (WINVER == 0x0501) // WinXP - if (AesSwitch && force) { // only if forced -#else - if ((info[2] & bit_AES && AesSwitch) || (AesSwitch && force)) { +#if (defined(_M_AMD64) || defined(__x86_64__)) || (defined(_M_IX86) || defined(__i386__)) +#if defined(_MSC_VER) + int cpu_info[4]; + __cpuid(cpu_info, 1); + return ((cpu_info[2] & bit_AES) != 0); +#elif defined(__clang__) +#if __clang_major__ >= 6 + __builtin_cpu_init(); #endif - aesni = true; - } -#if defined (_WIN32) && (WINVER == 0x0501) // WinXP - if (AvxSwitch && force) { // only if forced + return __builtin_cpu_supports("aes"); +#elif defined(__GNUC__) + __builtin_cpu_init(); + return __builtin_cpu_supports("aes"); #else - if ((info[2] & bit_AVX && AvxSwitch) || (AvxSwitch && force)) { + return false; #endif - avx = true; - } +#else + return false; +#endif + } + + void Detect(bool AesSwitch, bool force) + { + if ((cpu_support_aes() && AesSwitch) || (AesSwitch && force)) { + aesni = true; } -#endif // defined(__x86_64__) || defined(__i386__) LogPrint(eLogInfo, "AESNI ", (aesni ? "enabled" : "disabled")); - LogPrint(eLogInfo, "AVX ", (avx ? "enabled" : "disabled")); } } } diff --git a/libi2pd/CPU.h b/libi2pd/CPU.h index f021bccb..a0695884 100644 --- a/libi2pd/CPU.h +++ b/libi2pd/CPU.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -14,9 +14,8 @@ namespace i2p namespace cpu { extern bool aesni; - extern bool avx; - void Detect(bool AesSwitch, bool AvxSwitch, bool force); + void Detect(bool AesSwitch, bool force); } } diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 6b515ef9..5551b010 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -193,7 +193,7 @@ namespace config { options_description precomputation("Precomputation options"); precomputation.add_options() ("precomputation.elgamal", -#if defined(__x86_64__) +#if (defined(_M_AMD64) || defined(__x86_64__)) value()->default_value(false), #else value()->default_value(true), @@ -308,7 +308,7 @@ namespace config { options_description cpuext("CPU encryption extensions options"); cpuext.add_options() ("cpuext.aesni", bool_switch()->default_value(true), "Use auto detection for AESNI CPU extensions. If false, AESNI will be not used") - ("cpuext.avx", bool_switch()->default_value(true), "Use auto detection for AVX CPU extensions. If false, AVX will be not used") + ("cpuext.avx", bool_switch()->default_value(false), "Deprecated option") ("cpuext.force", bool_switch()->default_value(false), "Force usage of CPU extensions. Useful when cpuinfo is not available on virtual machines") ; diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index 12087443..b5bc33d1 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -28,6 +28,12 @@ #include "I2PEndian.h" #include "Log.h" +#if defined(__AES__) && !defined(_MSC_VER) && ((defined(_M_AMD64) || defined(__x86_64__)) || (defined(_M_IX86) || defined(__i386__))) + #define SUPPORTS_AES 1 +#else + #define SUPPORTS_AES 0 +#endif + namespace i2p { namespace crypto @@ -361,7 +367,7 @@ namespace crypto BIGNUM * b1 = BN_CTX_get (ctx); BIGNUM * b = BN_CTX_get (ctx); // select random k -#if defined(__x86_64__) +#if (defined(_M_AMD64) || defined(__x86_64__)) BN_rand (k, ELGAMAL_FULL_EXPONENT_NUM_BITS, -1, 1); // full exponent for x64 #else BN_rand (k, ELGAMAL_SHORT_EXPONENT_NUM_BITS, -1, 1); // short exponent of 226 bits @@ -428,7 +434,7 @@ namespace crypto void GenerateElGamalKeyPair (uint8_t * priv, uint8_t * pub) { -#if defined(__x86_64__) || defined(__i386__) || defined(_MSC_VER) +#if (defined(_M_AMD64) || defined(__x86_64__)) || (defined(_M_IX86) || defined(__i386__)) || defined(_MSC_VER) RAND_bytes (priv, 256); #else // lower 226 bits (28 bytes and 2 bits) only. short exponent @@ -555,7 +561,7 @@ namespace crypto } // AES -#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) +#if SUPPORTS_AES #define KeyExpansion256(round0,round1) \ "pshufd $0xff, %%xmm2, %%xmm2 \n" \ "movaps %%xmm1, %%xmm4 \n" \ @@ -580,7 +586,7 @@ namespace crypto "movaps %%xmm3, "#round1"(%[sched]) \n" #endif -#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) +#if SUPPORTS_AES void ECBCryptoAESNI::ExpandKey (const AESKey& key) { __asm__ @@ -621,7 +627,7 @@ namespace crypto #endif -#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) +#if SUPPORTS_AES #define EncryptAES256(sched) \ "pxor (%["#sched"]), %%xmm0 \n" \ "aesenc 16(%["#sched"]), %%xmm0 \n" \ @@ -642,16 +648,18 @@ namespace crypto void ECBEncryption::Encrypt (const ChipherBlock * in, ChipherBlock * out) { -#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) +#if SUPPORTS_AES if(i2p::cpu::aesni) { __asm__ - ( - "movups (%[in]), %%xmm0 \n" - EncryptAES256(sched) - "movups %%xmm0, (%[out]) \n" - : : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out) : "%xmm0", "memory" - ); + ( + "movups (%[in]), %%xmm0 \n" + EncryptAES256(sched) + "movups %%xmm0, (%[out]) \n" + : + : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out) + : "%xmm0", "memory" + ); } else #endif @@ -660,7 +668,7 @@ namespace crypto } } -#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) +#if SUPPORTS_AES #define DecryptAES256(sched) \ "pxor 224(%["#sched"]), %%xmm0 \n" \ "aesdec 208(%["#sched"]), %%xmm0 \n" \ @@ -681,16 +689,18 @@ namespace crypto void ECBDecryption::Decrypt (const ChipherBlock * in, ChipherBlock * out) { -#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) +#if SUPPORTS_AES if(i2p::cpu::aesni) { __asm__ - ( - "movups (%[in]), %%xmm0 \n" - DecryptAES256(sched) - "movups %%xmm0, (%[out]) \n" - : : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out) : "%xmm0", "memory" - ); + ( + "movups (%[in]), %%xmm0 \n" + DecryptAES256(sched) + "movups %%xmm0, (%[out]) \n" + : + : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out) + : "%xmm0", "memory" + ); } else #endif @@ -699,7 +709,7 @@ namespace crypto } } -#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) +#if SUPPORTS_AES #define CallAESIMC(offset) \ "movaps "#offset"(%[shed]), %%xmm0 \n" \ "aesimc %%xmm0, %%xmm0 \n" \ @@ -708,7 +718,7 @@ namespace crypto void ECBEncryption::SetKey (const AESKey& key) { -#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) +#if SUPPORTS_AES if(i2p::cpu::aesni) { ExpandKey (key); @@ -722,28 +732,30 @@ namespace crypto void ECBDecryption::SetKey (const AESKey& key) { -#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) +#if SUPPORTS_AES if(i2p::cpu::aesni) { ExpandKey (key); // expand encryption key first // then invert it using aesimc __asm__ - ( - CallAESIMC(16) - CallAESIMC(32) - CallAESIMC(48) - CallAESIMC(64) - CallAESIMC(80) - CallAESIMC(96) - CallAESIMC(112) - CallAESIMC(128) - CallAESIMC(144) - CallAESIMC(160) - CallAESIMC(176) - CallAESIMC(192) - CallAESIMC(208) - : : [shed]"r"(GetKeySchedule ()) : "%xmm0", "memory" - ); + ( + CallAESIMC(16) + CallAESIMC(32) + CallAESIMC(48) + CallAESIMC(64) + CallAESIMC(80) + CallAESIMC(96) + CallAESIMC(112) + CallAESIMC(128) + CallAESIMC(144) + CallAESIMC(160) + CallAESIMC(176) + CallAESIMC(192) + CallAESIMC(208) + : + : [shed]"r"(GetKeySchedule ()) + : "%xmm0", "memory" + ); } else #endif @@ -754,28 +766,28 @@ namespace crypto void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out) { -#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) +#if SUPPORTS_AES if(i2p::cpu::aesni) { __asm__ - ( - "movups (%[iv]), %%xmm1 \n" - "1: \n" - "movups (%[in]), %%xmm0 \n" - "pxor %%xmm1, %%xmm0 \n" - EncryptAES256(sched) - "movaps %%xmm0, %%xmm1 \n" - "movups %%xmm0, (%[out]) \n" - "add $16, %[in] \n" - "add $16, %[out] \n" - "dec %[num] \n" - "jnz 1b \n" - "movups %%xmm1, (%[iv]) \n" - : - : [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()), - [in]"r"(in), [out]"r"(out), [num]"r"(numBlocks) - : "%xmm0", "%xmm1", "cc", "memory" - ); + ( + "movups (%[iv]), %%xmm1 \n" + "1: \n" + "movups (%[in]), %%xmm0 \n" + "pxor %%xmm1, %%xmm0 \n" + EncryptAES256(sched) + "movaps %%xmm0, %%xmm1 \n" + "movups %%xmm0, (%[out]) \n" + "add $16, %[in] \n" + "add $16, %[out] \n" + "dec %[num] \n" + "jnz 1b \n" + "movups %%xmm1, (%[iv]) \n" + : + : [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()), + [in]"r"(in), [out]"r"(out), [num]"r"(numBlocks) + : "%xmm0", "%xmm1", "cc", "memory" + ); } else #endif @@ -799,22 +811,22 @@ namespace crypto void CBCEncryption::Encrypt (const uint8_t * in, uint8_t * out) { -#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) +#if SUPPORTS_AES if(i2p::cpu::aesni) { __asm__ - ( - "movups (%[iv]), %%xmm1 \n" - "movups (%[in]), %%xmm0 \n" - "pxor %%xmm1, %%xmm0 \n" - EncryptAES256(sched) - "movups %%xmm0, (%[out]) \n" - "movups %%xmm0, (%[iv]) \n" - : - : [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()), - [in]"r"(in), [out]"r"(out) - : "%xmm0", "%xmm1", "memory" - ); + ( + "movups (%[iv]), %%xmm1 \n" + "movups (%[in]), %%xmm0 \n" + "pxor %%xmm1, %%xmm0 \n" + EncryptAES256(sched) + "movups %%xmm0, (%[out]) \n" + "movups %%xmm0, (%[iv]) \n" + : + : [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()), + [in]"r"(in), [out]"r"(out) + : "%xmm0", "%xmm1", "memory" + ); } else #endif @@ -823,29 +835,29 @@ namespace crypto void CBCDecryption::Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out) { -#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) +#if SUPPORTS_AES if(i2p::cpu::aesni) { __asm__ - ( - "movups (%[iv]), %%xmm1 \n" - "1: \n" - "movups (%[in]), %%xmm0 \n" - "movaps %%xmm0, %%xmm2 \n" - DecryptAES256(sched) - "pxor %%xmm1, %%xmm0 \n" - "movups %%xmm0, (%[out]) \n" - "movaps %%xmm2, %%xmm1 \n" - "add $16, %[in] \n" - "add $16, %[out] \n" - "dec %[num] \n" - "jnz 1b \n" - "movups %%xmm1, (%[iv]) \n" - : - : [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()), - [in]"r"(in), [out]"r"(out), [num]"r"(numBlocks) - : "%xmm0", "%xmm1", "%xmm2", "cc", "memory" - ); + ( + "movups (%[iv]), %%xmm1 \n" + "1: \n" + "movups (%[in]), %%xmm0 \n" + "movaps %%xmm0, %%xmm2 \n" + DecryptAES256(sched) + "pxor %%xmm1, %%xmm0 \n" + "movups %%xmm0, (%[out]) \n" + "movaps %%xmm2, %%xmm1 \n" + "add $16, %[in] \n" + "add $16, %[out] \n" + "dec %[num] \n" + "jnz 1b \n" + "movups %%xmm1, (%[iv]) \n" + : + : [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()), + [in]"r"(in), [out]"r"(out), [num]"r"(numBlocks) + : "%xmm0", "%xmm1", "%xmm2", "cc", "memory" + ); } else #endif @@ -869,22 +881,22 @@ namespace crypto void CBCDecryption::Decrypt (const uint8_t * in, uint8_t * out) { -#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) +#if SUPPORTS_AES if(i2p::cpu::aesni) { __asm__ - ( - "movups (%[iv]), %%xmm1 \n" - "movups (%[in]), %%xmm0 \n" - "movups %%xmm0, (%[iv]) \n" - DecryptAES256(sched) - "pxor %%xmm1, %%xmm0 \n" - "movups %%xmm0, (%[out]) \n" - : - : [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()), - [in]"r"(in), [out]"r"(out) - : "%xmm0", "%xmm1", "memory" - ); + ( + "movups (%[iv]), %%xmm1 \n" + "movups (%[in]), %%xmm0 \n" + "movups %%xmm0, (%[iv]) \n" + DecryptAES256(sched) + "pxor %%xmm1, %%xmm0 \n" + "movups %%xmm0, (%[out]) \n" + : + : [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()), + [in]"r"(in), [out]"r"(out) + : "%xmm0", "%xmm1", "memory" + ); } else #endif @@ -893,34 +905,34 @@ namespace crypto void TunnelEncryption::Encrypt (const uint8_t * in, uint8_t * out) { -#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) +#if SUPPORTS_AES if(i2p::cpu::aesni) { __asm__ - ( - // encrypt IV - "movups (%[in]), %%xmm0 \n" - EncryptAES256(sched_iv) - "movaps %%xmm0, %%xmm1 \n" - // double IV encryption - EncryptAES256(sched_iv) - "movups %%xmm0, (%[out]) \n" - // encrypt data, IV is xmm1 - "1: \n" - "add $16, %[in] \n" - "add $16, %[out] \n" - "movups (%[in]), %%xmm0 \n" - "pxor %%xmm1, %%xmm0 \n" - EncryptAES256(sched_l) - "movaps %%xmm0, %%xmm1 \n" - "movups %%xmm0, (%[out]) \n" - "dec %[num] \n" - "jnz 1b \n" - : - : [sched_iv]"r"(m_IVEncryption.GetKeySchedule ()), [sched_l]"r"(m_LayerEncryption.ECB().GetKeySchedule ()), - [in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes - : "%xmm0", "%xmm1", "cc", "memory" - ); + ( + // encrypt IV + "movups (%[in]), %%xmm0 \n" + EncryptAES256(sched_iv) + "movaps %%xmm0, %%xmm1 \n" + // double IV encryption + EncryptAES256(sched_iv) + "movups %%xmm0, (%[out]) \n" + // encrypt data, IV is xmm1 + "1: \n" + "add $16, %[in] \n" + "add $16, %[out] \n" + "movups (%[in]), %%xmm0 \n" + "pxor %%xmm1, %%xmm0 \n" + EncryptAES256(sched_l) + "movaps %%xmm0, %%xmm1 \n" + "movups %%xmm0, (%[out]) \n" + "dec %[num] \n" + "jnz 1b \n" + : + : [sched_iv]"r"(m_IVEncryption.GetKeySchedule ()), [sched_l]"r"(m_LayerEncryption.ECB().GetKeySchedule ()), + [in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes + : "%xmm0", "%xmm1", "cc", "memory" + ); } else #endif @@ -934,35 +946,35 @@ namespace crypto void TunnelDecryption::Decrypt (const uint8_t * in, uint8_t * out) { -#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) +#if SUPPORTS_AES if(i2p::cpu::aesni) { __asm__ - ( - // decrypt IV - "movups (%[in]), %%xmm0 \n" - DecryptAES256(sched_iv) - "movaps %%xmm0, %%xmm1 \n" - // double IV encryption - DecryptAES256(sched_iv) - "movups %%xmm0, (%[out]) \n" - // decrypt data, IV is xmm1 - "1: \n" - "add $16, %[in] \n" - "add $16, %[out] \n" - "movups (%[in]), %%xmm0 \n" - "movaps %%xmm0, %%xmm2 \n" - DecryptAES256(sched_l) - "pxor %%xmm1, %%xmm0 \n" - "movups %%xmm0, (%[out]) \n" - "movaps %%xmm2, %%xmm1 \n" - "dec %[num] \n" - "jnz 1b \n" - : - : [sched_iv]"r"(m_IVDecryption.GetKeySchedule ()), [sched_l]"r"(m_LayerDecryption.ECB().GetKeySchedule ()), - [in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes - : "%xmm0", "%xmm1", "%xmm2", "cc", "memory" - ); + ( + // decrypt IV + "movups (%[in]), %%xmm0 \n" + DecryptAES256(sched_iv) + "movaps %%xmm0, %%xmm1 \n" + // double IV encryption + DecryptAES256(sched_iv) + "movups %%xmm0, (%[out]) \n" + // decrypt data, IV is xmm1 + "1: \n" + "add $16, %[in] \n" + "add $16, %[out] \n" + "movups (%[in]), %%xmm0 \n" + "movaps %%xmm0, %%xmm2 \n" + DecryptAES256(sched_l) + "pxor %%xmm1, %%xmm0 \n" + "movups %%xmm0, (%[out]) \n" + "movaps %%xmm2, %%xmm1 \n" + "dec %[num] \n" + "jnz 1b \n" + : + : [sched_iv]"r"(m_IVDecryption.GetKeySchedule ()), [sched_l]"r"(m_LayerDecryption.ECB().GetKeySchedule ()), + [in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes + : "%xmm0", "%xmm1", "%xmm2", "cc", "memory" + ); } else #endif @@ -1285,9 +1297,9 @@ namespace crypto } }*/ - void InitCrypto (bool precomputation, bool aesni, bool avx, bool force) + void InitCrypto (bool precomputation, bool aesni, bool force) { - i2p::cpu::Detect (aesni, avx, force); + i2p::cpu::Detect (aesni, force); #if LEGACY_OPENSSL SSL_library_init (); #endif @@ -1297,7 +1309,7 @@ namespace crypto CRYPTO_set_locking_callback (OpensslLockingCallback);*/ if (precomputation) { -#if defined(__x86_64__) +#if (defined(_M_AMD64) || defined(__x86_64__)) g_ElggTable = new BIGNUM * [ELGAMAL_FULL_EXPONENT_NUM_BYTES][255]; PrecalculateElggTable (g_ElggTable, ELGAMAL_FULL_EXPONENT_NUM_BYTES); #else @@ -1312,7 +1324,7 @@ namespace crypto if (g_ElggTable) { DestroyElggTable (g_ElggTable, -#if defined(__x86_64__) +#if (defined(_M_AMD64) || defined(__x86_64__)) ELGAMAL_FULL_EXPONENT_NUM_BYTES #else ELGAMAL_SHORT_EXPONENT_NUM_BYTES diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index d4cbda97..1419293b 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -307,7 +307,7 @@ namespace crypto void InitNoiseIKState (NoiseSymmetricState& state, const uint8_t * pub); // Noise_IK (ratchets) // init and terminate - void InitCrypto (bool precomputation, bool aesni, bool avx, bool force); + void InitCrypto (bool precomputation, bool aesni, bool force); void TerminateCrypto (); } } diff --git a/libi2pd/Identity.cpp b/libi2pd/Identity.cpp index a4a9f716..3a659c11 100644 --- a/libi2pd/Identity.cpp +++ b/libi2pd/Identity.cpp @@ -803,29 +803,12 @@ namespace data XORMetric operator^(const IdentHash& key1, const IdentHash& key2) { XORMetric m; -#if (defined(__x86_64__) || defined(__i386__)) && defined(__AVX__) // not all X86 targets supports AVX (like old Pentium, see #1600) - if(i2p::cpu::avx) - { - __asm__ - ( - "vmovups %1, %%ymm0 \n" - "vmovups %2, %%ymm1 \n" - "vxorps %%ymm0, %%ymm1, %%ymm1 \n" - "vmovups %%ymm1, %0 \n" - : "=m"(*m.metric) - : "m"(*key1), "m"(*key2) - : "memory", "%xmm0", "%xmm1" // should be replaced by %ymm0/1 once supported by compiler - ); - } - else -#endif - { - const uint64_t * hash1 = key1.GetLL (), * hash2 = key2.GetLL (); - m.metric_ll[0] = hash1[0] ^ hash2[0]; - m.metric_ll[1] = hash1[1] ^ hash2[1]; - m.metric_ll[2] = hash1[2] ^ hash2[2]; - m.metric_ll[3] = hash1[3] ^ hash2[3]; - } + + const uint64_t * hash1 = key1.GetLL (), * hash2 = key2.GetLL (); + m.metric_ll[0] = hash1[0] ^ hash2[0]; + m.metric_ll[1] = hash1[1] ^ hash2[1]; + m.metric_ll[2] = hash1[2] ^ hash2[2]; + m.metric_ll[3] = hash1[3] ^ hash2[3]; return m; } diff --git a/libi2pd/api.cpp b/libi2pd/api.cpp index 3bfb801c..ad24519f 100644 --- a/libi2pd/api.cpp +++ b/libi2pd/api.cpp @@ -38,9 +38,8 @@ namespace api bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation); bool aesni; i2p::config::GetOption("cpuext.aesni", aesni); - bool avx; i2p::config::GetOption("cpuext.avx", avx); bool forceCpuExt; i2p::config::GetOption("cpuext.force", forceCpuExt); - i2p::crypto::InitCrypto (precomputation, aesni, avx, forceCpuExt); + i2p::crypto::InitCrypto (precomputation, aesni, forceCpuExt); int netID; i2p::config::GetOption("netid", netID); i2p::context.SetNetID (netID); From c53ad2012ceb9c7489c97378e86500332d8edbac Mon Sep 17 00:00:00 2001 From: r4sas Date: Wed, 6 Sep 2023 20:26:46 +0000 Subject: [PATCH 0192/1171] [cpu] use cpuid on gcc < 5 Signed-off-by: r4sas --- libi2pd/CPU.cpp | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/libi2pd/CPU.cpp b/libi2pd/CPU.cpp index d42f1ddd..14ce3788 100644 --- a/libi2pd/CPU.cpp +++ b/libi2pd/CPU.cpp @@ -9,12 +9,16 @@ #include "CPU.h" #include "Log.h" -#if defined(_MSC_VER) -#include - #ifndef bit_AES #define bit_AES (1 << 25) #endif + +#if (defined(__GNUC__) && __GNUC__ < 5) + #include +#endif + +#ifdef _MSC_VER + #include #endif namespace i2p @@ -26,18 +30,18 @@ namespace cpu inline bool cpu_support_aes() { #if (defined(_M_AMD64) || defined(__x86_64__)) || (defined(_M_IX86) || defined(__i386__)) -#if defined(_MSC_VER) - int cpu_info[4]; - __cpuid(cpu_info, 1); - return ((cpu_info[2] & bit_AES) != 0); +#if (defined(__GNUC__) && __GNUC__ > 4) + __builtin_cpu_init(); + return __builtin_cpu_supports("aes"); #elif defined(__clang__) #if __clang_major__ >= 6 __builtin_cpu_init(); #endif return __builtin_cpu_supports("aes"); -#elif defined(__GNUC__) - __builtin_cpu_init(); - return __builtin_cpu_supports("aes"); +#elif (defined(_MSC_VER) || (defined(__GNUC__) && __GNUC__ < 5)) + int cpu_info[4]; + __cpuid(cpu_info, 1); + return ((cpu_info[2] & bit_AES) != 0); #else return false; #endif From 4a5e16b99405182c6daa5862088a9b9247e1c6b4 Mon Sep 17 00:00:00 2001 From: r4sas Date: Thu, 7 Sep 2023 16:56:53 +0000 Subject: [PATCH 0193/1171] [cpu] tests with preprocessor Signed-off-by: r4sas --- libi2pd/CPU.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/libi2pd/CPU.cpp b/libi2pd/CPU.cpp index 14ce3788..53771ff0 100644 --- a/libi2pd/CPU.cpp +++ b/libi2pd/CPU.cpp @@ -30,21 +30,26 @@ namespace cpu inline bool cpu_support_aes() { #if (defined(_M_AMD64) || defined(__x86_64__)) || (defined(_M_IX86) || defined(__i386__)) -#if (defined(__GNUC__) && __GNUC__ > 4) +# if (defined(__GNUC__) && __GNUC__ > 4) +# warning("CPU: IN GCC!!!") __builtin_cpu_init(); return __builtin_cpu_supports("aes"); -#elif defined(__clang__) -#if __clang_major__ >= 6 +# elif (defined(__clang__) && !defined(__GNUC__)) +# warning("CPU: IN CLANG!!!") +# warning(__clang__) +# if (__clang_major__ >= 6) __builtin_cpu_init(); -#endif +# endif return __builtin_cpu_supports("aes"); -#elif (defined(_MSC_VER) || (defined(__GNUC__) && __GNUC__ < 5)) +# elif (defined(_MSC_VER) || (defined(__GNUC__) && __GNUC__ < 5)) +# warning("CPU: IN MSVC!!!") int cpu_info[4]; __cpuid(cpu_info, 1); return ((cpu_info[2] & bit_AES) != 0); -#else +# else +# warning("CPU: FALSE") return false; -#endif +# endif #else return false; #endif From 4ed19c05f68e58a15c57f2791b1b0e1d863dda55 Mon Sep 17 00:00:00 2001 From: r4sas Date: Thu, 7 Sep 2023 21:20:52 +0000 Subject: [PATCH 0194/1171] [cpu] split AES detect for GNU C < 5 Signed-off-by: r4sas --- libi2pd/CPU.cpp | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/libi2pd/CPU.cpp b/libi2pd/CPU.cpp index 53771ff0..106882eb 100644 --- a/libi2pd/CPU.cpp +++ b/libi2pd/CPU.cpp @@ -30,29 +30,30 @@ namespace cpu inline bool cpu_support_aes() { #if (defined(_M_AMD64) || defined(__x86_64__)) || (defined(_M_IX86) || defined(__i386__)) -# if (defined(__GNUC__) && __GNUC__ > 4) -# warning("CPU: IN GCC!!!") +#if defined(__clang__) +# if (__clang_major__ >= 6) + __builtin_cpu_init(); +# endif + return __builtin_cpu_supports("aes"); +#elif (defined(__GNUC__) && __GNUC__ >= 5) __builtin_cpu_init(); return __builtin_cpu_supports("aes"); -# elif (defined(__clang__) && !defined(__GNUC__)) -# warning("CPU: IN CLANG!!!") -# warning(__clang__) -# if (__clang_major__ >= 6) - __builtin_cpu_init(); -# endif - return __builtin_cpu_supports("aes"); -# elif (defined(_MSC_VER) || (defined(__GNUC__) && __GNUC__ < 5)) -# warning("CPU: IN MSVC!!!") +#elif (defined(__GNUC__) && __GNUC__ < 5) + int cpu_info[4]; + bool flag = false; + __cpuid(0, cpu_info[0], cpu_info[1], cpu_info[2], cpu_info[3]); + if (cpu_info[0] >= 0x00000001) { + __cpuid(0x00000001, cpu_info[0], cpu_info[1], cpu_info[2], cpu_info[3]); + flag = ((cpu_info[2] & bit_AES) != 0); + } + return flag; +#elif defined(_MSC_VER) int cpu_info[4]; __cpuid(cpu_info, 1); return ((cpu_info[2] & bit_AES) != 0); -# else -# warning("CPU: FALSE") - return false; -# endif -#else - return false; #endif +#endif + return false; } void Detect(bool AesSwitch, bool force) From 70829ee79e971f325ea4f3b753d0f8b02bce9fce Mon Sep 17 00:00:00 2001 From: r4sas Date: Sun, 10 Sep 2023 13:02:52 +0300 Subject: [PATCH 0195/1171] [rpm] add Fedora ELN support Signed-off-by: r4sas --- contrib/rpm/i2pd-git.spec | 68 +++++++++++++++----------------------- contrib/rpm/i2pd.spec | 69 ++++++++++++++++----------------------- 2 files changed, 55 insertions(+), 82 deletions(-) diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index 62a28631..ff46bc0f 100644 --- a/contrib/rpm/i2pd-git.spec +++ b/contrib/rpm/i2pd-git.spec @@ -11,9 +11,9 @@ URL: https://github.com/PurpleI2P/i2pd Source0: https://github.com/PurpleI2P/i2pd/archive/openssl/i2pd-openssl.tar.gz %if 0%{?rhel} == 7 -BuildRequires: cmake3 + BuildRequires: cmake3 %else -BuildRequires: cmake + BuildRequires: cmake %endif BuildRequires: chrpath @@ -28,9 +28,11 @@ Requires: logrotate Requires: systemd Requires(pre): %{_sbindir}/useradd %{_sbindir}/groupadd + %description C++ implementation of I2P. + %prep %setup -q -n i2pd-openssl @@ -38,72 +40,56 @@ C++ implementation of I2P. %build cd build %if 0%{?rhel} == 7 -%cmake3 \ + %cmake3 \ -DWITH_LIBRARY=OFF \ -DWITH_UPNP=ON \ -DWITH_HARDENING=ON \ -DBUILD_SHARED_LIBS:BOOL=OFF %else -%cmake \ + %cmake \ -DWITH_LIBRARY=OFF \ -DWITH_UPNP=ON \ -DWITH_HARDENING=ON \ -%if 0%{?fedora} > 29 + %if 0%{?fedora} > 29 -DBUILD_SHARED_LIBS:BOOL=OFF \ . -%else + %else -DBUILD_SHARED_LIBS:BOOL=OFF -%endif + %endif %endif - -%if 0%{?rhel} == 9 -pushd redhat-linux-build -%endif - -%if 0%{?fedora} >= 35 -pushd redhat-linux-build +%if 0%{?rhel} == 9 || 0%{?fedora} >= 35 || 0%{?eln} + pushd redhat-linux-build %else -%if 0%{?fedora} >= 33 -pushd %{_target_platform} -%endif -%endif + %if 0%{?fedora} >= 33 + pushd %{_target_platform} + %endif -%if 0%{?mageia} > 7 -pushd build + %if 0%{?mageia} > 7 + pushd build + %endif %endif make %{?_smp_mflags} -%if 0%{?rhel} == 9 -popd +%if 0%{?rhel} == 9 || 0%{?fedora} >= 33 || 0%{?mageia} > 7 + popd %endif -%if 0%{?fedora} >= 33 -popd -%endif - -%if 0%{?mageia} > 7 -popd -%endif %install pushd build -%if 0%{?rhel} == 9 -pushd redhat-linux-build -%endif - -%if 0%{?fedora} >= 35 -pushd redhat-linux-build +%if 0%{?rhel} == 9 || 0%{?fedora} >= 35 || 0%{?eln} + pushd redhat-linux-build %else -%if 0%{?fedora} >= 33 -pushd %{_target_platform} -%endif -%endif + %if 0%{?fedora} >= 33 + pushd %{_target_platform} + %endif -%if 0%{?mageia} -pushd build + %if 0%{?mageia} + pushd build + %endif %endif chrpath -d i2pd diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 19825237..5d1adfb7 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,6 +1,6 @@ Name: i2pd Version: 2.48.0 -Release: 1%{?dist} +Release: 2%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git @@ -9,9 +9,9 @@ URL: https://github.com/PurpleI2P/i2pd Source0: https://github.com/PurpleI2P/i2pd/archive/%{version}/%name-%version.tar.gz %if 0%{?rhel} == 7 -BuildRequires: cmake3 + BuildRequires: cmake3 %else -BuildRequires: cmake + BuildRequires: cmake %endif BuildRequires: chrpath @@ -26,9 +26,11 @@ Requires: logrotate Requires: systemd Requires(pre): %{_sbindir}/useradd %{_sbindir}/groupadd + %description C++ implementation of I2P. + %prep %setup -q @@ -36,71 +38,56 @@ C++ implementation of I2P. %build cd build %if 0%{?rhel} == 7 -%cmake3 \ + %cmake3 \ -DWITH_LIBRARY=OFF \ -DWITH_UPNP=ON \ -DWITH_HARDENING=ON \ -DBUILD_SHARED_LIBS:BOOL=OFF %else -%cmake \ + %cmake \ -DWITH_LIBRARY=OFF \ -DWITH_UPNP=ON \ -DWITH_HARDENING=ON \ -%if 0%{?fedora} > 29 + %if 0%{?fedora} > 29 -DBUILD_SHARED_LIBS:BOOL=OFF \ . -%else + %else -DBUILD_SHARED_LIBS:BOOL=OFF -%endif + %endif %endif -%if 0%{?rhel} == 9 -pushd redhat-linux-build -%endif - -%if 0%{?fedora} >= 35 -pushd redhat-linux-build +%if 0%{?rhel} == 9 || 0%{?fedora} >= 35 || 0%{?eln} + pushd redhat-linux-build %else -%if 0%{?fedora} >= 33 -pushd %{_target_platform} -%endif -%endif + %if 0%{?fedora} >= 33 + pushd %{_target_platform} + %endif -%if 0%{?mageia} > 7 -pushd build + %if 0%{?mageia} > 7 + pushd build + %endif %endif make %{?_smp_mflags} -%if 0%{?rhel} == 9 -popd +%if 0%{?rhel} == 9 || 0%{?fedora} >= 33 || 0%{?mageia} > 7 + popd %endif -%if 0%{?fedora} >= 33 -popd -%endif - -%if 0%{?mageia} > 7 -popd -%endif %install pushd build -%if 0%{?rhel} == 9 -pushd redhat-linux-build -%endif - -%if 0%{?fedora} >= 35 -pushd redhat-linux-build +%if 0%{?rhel} == 9 || 0%{?fedora} >= 35 || 0%{?eln} + pushd redhat-linux-build %else -%if 0%{?fedora} >= 33 -pushd %{_target_platform} -%endif -%endif + %if 0%{?fedora} >= 33 + pushd %{_target_platform} + %endif -%if 0%{?mageia} -pushd build + %if 0%{?mageia} + pushd build + %endif %endif chrpath -d i2pd From 1e7feae0df17eb26cd4d843fcbf1afb26bae95f7 Mon Sep 17 00:00:00 2001 From: r4sas Date: Sun, 10 Sep 2023 13:08:00 +0300 Subject: [PATCH 0196/1171] [rpm] remove BuildRequires tabulation Signed-off-by: r4sas --- contrib/rpm/i2pd-git.spec | 4 ++-- contrib/rpm/i2pd.spec | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index ff46bc0f..cebc15a4 100644 --- a/contrib/rpm/i2pd-git.spec +++ b/contrib/rpm/i2pd-git.spec @@ -11,9 +11,9 @@ URL: https://github.com/PurpleI2P/i2pd Source0: https://github.com/PurpleI2P/i2pd/archive/openssl/i2pd-openssl.tar.gz %if 0%{?rhel} == 7 - BuildRequires: cmake3 +BuildRequires: cmake3 %else - BuildRequires: cmake +BuildRequires: cmake %endif BuildRequires: chrpath diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 5d1adfb7..cc826928 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -9,9 +9,9 @@ URL: https://github.com/PurpleI2P/i2pd Source0: https://github.com/PurpleI2P/i2pd/archive/%{version}/%name-%version.tar.gz %if 0%{?rhel} == 7 - BuildRequires: cmake3 +BuildRequires: cmake3 %else - BuildRequires: cmake +BuildRequires: cmake %endif BuildRequires: chrpath From 918aa556ef93272464ca396ae485b30b24b42b36 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 15 Sep 2023 11:37:45 -0400 Subject: [PATCH 0197/1171] fixed non-x86 build --- libi2pd/CPU.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/CPU.cpp b/libi2pd/CPU.cpp index 106882eb..5d5fc6b3 100644 --- a/libi2pd/CPU.cpp +++ b/libi2pd/CPU.cpp @@ -13,7 +13,7 @@ #define bit_AES (1 << 25) #endif -#if (defined(__GNUC__) && __GNUC__ < 5) +#if (defined(__GNUC__) && __GNUC__ < 5 && (defined(__x86_64__) || defined(__i386__))) #include #endif From df6bb6d9b8b33d9a7db81386fd8771c5b7b8bc57 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 17 Sep 2023 10:19:57 -0400 Subject: [PATCH 0198/1171] 2.49.0 --- ChangeLog | 27 +++++++++++++++++++++++++++ contrib/rpm/i2pd-git.spec | 5 ++++- contrib/rpm/i2pd.spec | 5 ++++- debian/changelog | 6 ++++++ libi2pd/version.h | 4 ++-- 5 files changed, 43 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 881e05d7..17ec98d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,33 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog +## [2.49.0] - 2023-09-18 +### Added +- Handle SOCK5 authrozation with empty user/password +- Drop incoming transport sessions from too old or from future routers +- Memory pool for router profiles +- Allow 0 hops in explicitPeers +### Changed +- Separate network and testing status +- Remove AVX code +- Improve NTCP2 transport session logging +- Select router with ipv4 for tunnel endpoint +- Consider all addresses non-published for U and H routers even if they have host/port +- Don't pick completely unreachable routers for tunnels +- Exclude SSU1 introducers from SSU2 addresses +- Don't create paired inbound tunnel if length is different +- Remove introducer from RouterInfo after 60 minutes +- Reduce SSU2 keep alive interval and add peer test interval variance +- Don't pick too old sessions for introducer +### Fixed +- Version of the subnegotiation in user/password SOCKS5 response +- Send keepalive for existing session with introducer +- Buffer offset for EVP_EncryptFinal_ex() to include outlen +- Termination block size processing for transport sessions +- Crash if deleted BOB destination was shared between few BOB sessions +- Introducers with zero tag +- Padding for SSU2 path response + ## [2.48.0] - 2023-06-12 ### Added - Allow user/password authentication method for SOCK5 proxy diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index cebc15a4..c745e05f 100644 --- a/contrib/rpm/i2pd-git.spec +++ b/contrib/rpm/i2pd-git.spec @@ -1,7 +1,7 @@ %define git_hash %(git rev-parse HEAD | cut -c -7) Name: i2pd-git -Version: 2.48.0 +Version: 2.49.0 Release: git%{git_hash}%{?dist} Summary: I2P router written in C++ Conflicts: i2pd @@ -144,6 +144,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Mon Sep 18 2023 orignal - 2.49.0 +- update to 2.49.0 + * Mon Jun 12 2023 orignal - 2.48.0 - update to 2.48.0 diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index cc826928..b88f21b2 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,5 +1,5 @@ Name: i2pd -Version: 2.48.0 +Version: 2.49.0 Release: 2%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git @@ -142,6 +142,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Mon Sep 18 2023 orignal - 2.49.0 +- update to 2.49.0 + * Mon Jun 12 2023 orignal - 2.48.0 - update to 2.48.0 diff --git a/debian/changelog b/debian/changelog index 91b0abdf..613bc7c9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i2pd (2.49.0-1) unstable; urgency=high + + * updated to version 2.49.0/0.9.60 + + -- orignal Mon, 18 Sep 2023 16:00:00 +0000 + i2pd (2.48.0-1) unstable; urgency=high * updated to version 2.48.0/0.9.59 diff --git a/libi2pd/version.h b/libi2pd/version.h index 903ceebc..9854995e 100644 --- a/libi2pd/version.h +++ b/libi2pd/version.h @@ -18,7 +18,7 @@ #define MAKE_VERSION_NUMBER(a,b,c) ((a*100+b)*100+c) #define I2PD_VERSION_MAJOR 2 -#define I2PD_VERSION_MINOR 48 +#define I2PD_VERSION_MINOR 49 #define I2PD_VERSION_MICRO 0 #define I2PD_VERSION_PATCH 0 #ifdef GITVER @@ -33,7 +33,7 @@ #define I2P_VERSION_MAJOR 0 #define I2P_VERSION_MINOR 9 -#define I2P_VERSION_MICRO 59 +#define I2P_VERSION_MICRO 60 #define I2P_VERSION_PATCH 0 #define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO) #define I2P_VERSION_NUMBER MAKE_VERSION_NUMBER(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO) From 3a4238729a103baef76ab677d555ae55a4833a9b Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 17 Sep 2023 10:41:31 -0400 Subject: [PATCH 0199/1171] 2.49.0 --- ChangeLog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 17ec98d7..69d5c4c9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,7 +3,7 @@ ## [2.49.0] - 2023-09-18 ### Added -- Handle SOCK5 authrozation with empty user/password +- Handle SOCK5 authorization with empty user/password - Drop incoming transport sessions from too old or from future routers - Memory pool for router profiles - Allow 0 hops in explicitPeers @@ -17,7 +17,7 @@ - Exclude SSU1 introducers from SSU2 addresses - Don't create paired inbound tunnel if length is different - Remove introducer from RouterInfo after 60 minutes -- Reduce SSU2 keep alive interval and add peer test interval variance +- Reduce SSU2 keep alive interval and add keep alive interval variance - Don't pick too old sessions for introducer ### Fixed - Version of the subnegotiation in user/password SOCKS5 response From 4d573f6655c37cc13022157c1e2d043debca7512 Mon Sep 17 00:00:00 2001 From: r4sas Date: Sun, 17 Sep 2023 15:36:15 +0000 Subject: [PATCH 0200/1171] 2.49.0 Signed-off-by: r4sas --- ChangeLog | 16 ++++++++-------- Win32/mask.bmp | Bin 25818 -> 0 bytes contrib/rpm/i2pd.spec | 2 +- debian/changelog | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) delete mode 100644 Win32/mask.bmp diff --git a/ChangeLog b/ChangeLog index 69d5c4c9..4dd49a24 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,20 +4,20 @@ ## [2.49.0] - 2023-09-18 ### Added - Handle SOCK5 authorization with empty user/password -- Drop incoming transport sessions from too old or from future routers -- Memory pool for router profiles +- Drop incoming transport sessions from too old or from future routers +- Memory pool for router profiles - Allow 0 hops in explicitPeers ### Changed - Separate network and testing status - Remove AVX code -- Improve NTCP2 transport session logging -- Select router with ipv4 for tunnel endpoint +- Improve NTCP2 transport session logging +- Select router with ipv4 for tunnel endpoint - Consider all addresses non-published for U and H routers even if they have host/port - Don't pick completely unreachable routers for tunnels -- Exclude SSU1 introducers from SSU2 addresses +- Exclude SSU1 introducers from SSU2 addresses - Don't create paired inbound tunnel if length is different -- Remove introducer from RouterInfo after 60 minutes -- Reduce SSU2 keep alive interval and add keep alive interval variance +- Remove introducer from RouterInfo after 60 minutes +- Reduce SSU2 keep alive interval and add keep alive interval variance - Don't pick too old sessions for introducer ### Fixed - Version of the subnegotiation in user/password SOCKS5 response @@ -26,7 +26,7 @@ - Termination block size processing for transport sessions - Crash if deleted BOB destination was shared between few BOB sessions - Introducers with zero tag -- Padding for SSU2 path response +- Padding for SSU2 path response ## [2.48.0] - 2023-06-12 ### Added diff --git a/Win32/mask.bmp b/Win32/mask.bmp deleted file mode 100644 index cc2aeda75c6139ef81b479bb01f726996e756050..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25818 zcmeHPcUV(d7I**Holl+FZ)cRENUT(c0qHF?=@v#o1*5{yl8}(lLJd7gCv+kfK#^WV zDHae0>{1kz8O8283JR!L#x}brJm;AS9S1~t?|aF2bKkk`_shBWoO5rYx8|z-jQ&d* z-X-Cc3NJNy{bPnOyd&4rA7;$pzW%)aH_fhh@80!2d-lg4e@wG+e@VmT)YN`kce1qM zI_r;84v;%>;)K*jf{FyVOEr7{QMFf1!37%^K znHJ&gZNH4NrHaC0X8{S4ki@mC9iuFQiA^v9zumj*1jlteHw(FwsbXMl;*RO|yVpnWD5D2&by3OD&@`+u)eMhAHNIn+G;lpK; zK7uw9)!n^u@eI+JC~5*YAA>f`qPV#9b4XLt8OY(Kj*f3QnGwg14_X$>oOlFUFSOc= zdLcAM(~<^K1UYspI*1>>3yWJ@Tc13A3RLq_1WjFP zyJS1x(+kHoUqV(}9bo3ZBP=1K=g){vN>mI&AiRThdgkm|zTRag=LeX?@MU5j$B4j% z%k2$~Ef<N;ItzdJh4%WTso!6gu4K}kRp+_;Odl(Vd6EXk#+csuy+H zIK3BWG)nD+gz=6Z6R$jWR5VFIjHi@DWquKF2alE4zzm%1y^}W+OaHA1ba!{>W$v|6 z(jxLufpUT*OqVJGb-?Rn)(_GF^!4&ZZ2ynOkxG{1l#qf8axy6U{QrHC}%=O~b-6LQ*Qg{l4`71g!DKqlm@jJu{x z-t*&9WnTHBoqN!cr?Peefpm$Go>2sQ&{9}pya>Re2j+iLcqBno3Y}evLXs+*!+|dC z&~viO71x-W{bXTjB(Owfy&s~AD$Y50n>eb_d)lGkfxY{o3t$+P=9W1v2mos~${`sl zA8)^~a$`jRz`k|s7GsNzy?_`HqOG{bi1Sc`Su4C^l@h%`!C{BGYoY2UZ=BFV4WGkY zRgC#nopE6OA~{4AA@W^)kn6f^D+#j&816hF_d7zuGYM0i=~kd-Tk_5Dvk&$jRRCZ0Z+$Q1d8T8FNL2ma9t7 zha4?dle8swnuY09hgnM$mI4}onzM``;_QWsLkOfVW?gQ*{OJZX&X)Ou6yvOBl8g2B z_7lq&54$*_dt78gV4DfWo{9_B za614j^=n|KZp204P~D?Ug_;dHa2q7vQFh9LdxbR{&#Yb5o!}BtRAMIDNyU{~~ntzxN;rs!xpwW@p#KorfyHvl&qm6Zk6vuFuQVRQSSZT%|{cOK1VHu8evx>ul=OJ`)A7U1++|G5sCTotCs58DA=cgCjlOYpcEcRo&C+f7weNC*7kwP9o^>QRH)h4C>&<#q51&% zFbfN-qS)8i2!1Q)`V38`=CP|r4>+I-Tv!;LC$20c0xJrL3?|k+bJ4w+feYNJq?9pi$GnaVvghQ9&Vux`7|$g0Ij0 z`}gzrWd~V1*e(76>>iqi;V*5Mc$>!3LnDx1f8wjss&#RklAN-p#wIx9G?XkL?Xhw- zD51?fDNsNC_#0eK{AyHPi|_&UsxE~Z-c{gRz$3VUG~MtPRksrG7*PU2UUxME+zW@f zVw;4;?Bq2mT1HN4dbZ;7)^nF4r{0M3q|yReuqQoKH?aHx2t0rOqVQM^y5TVcnV9Uz6l*Tgh~e9 zupQ!QYTkC?BA@bq=mD1cCS5;LUL|+M#D*Jp_IrJOlG5EQ8u+UO!4`YC3=t z?o=Y~f~PR4A_Rh>LPCYQ-yrF(vHYrm?7`&eu5Eg}yb=u2kLo2>csK;AD=M7?#1Z(n z%$L>)YlI0CHY6a(tWqW1rw=h3WlA<|Awu|6)Ay*R zUo~MqR}8(0!V*CiTN{qmjOb?!*SSye>~lM-4gk}&O;F&Sg(S62UGyT_v;ymOSxx#1 zYia!iA_Dqq8$cDo)`2LSR`4lJW(}g2kg2`a6DCsF(|4FJDNGU&5B2au*0H;H@6vHdOqI=v*bO{n$0hMOe%mA! zAQ%H$*LHhee8QH;Bz{#@9b0^0 zVn#C!YlT=FQ2~!A71%UPA_d~52o8{NlK1J?F81y??qN~j%5Uu^UR8u5IT;_$kpj;U zP-{7Ru{`&1USe@pcwPo8XJ1r)UTX1?lIqr$ww|7zwksXgO)alpVP4|j@^u5qcf}?k z@h>L<35K;Du!PnOPg5Bg$P5Xa#7KVUg9mWto0mp=8P%coC!hx8LhHm5e>VbGuUxSf z;riob0dapv3M`C#Ez}=9f$ZkSxFw^HAW%(O_LrYlggLtbSEvA%m@EWf7NzQQy*@ZW z8toSV#>c>xpY=VXNe6){23ke(K5c7mAuV}-loV=k5D+WbpUW$Nr6(Q%U@VwSg9!B2 z#WH321;c0&+nEE_i90@+&tY%B*h-fAa5&#ibUF6dLKDv$(gM)+=GB|z&~SpV7>nu( zCdlwDpF7dWSQz6Z!36u0Px9`q+cXtDbZxYgRt5*3Pv*1!I3>^10D);Wb&HSGI{f6& zarNpj>W5+vR*tJ?5M@Eo_3PKsOf&(T^?{Z)h*bn+I_s{&eyWXvGcgGuZF^DackHyI zr}=-RJ4}NmnFkrTn9}^gJvtycEqFV*|JO1=W}rQpZ`K{AX6(_p5P+4iv#V<~8i-a8 z=WJ-QfvI6b{`?batF5SVT($yK5uyY+>ATUgSYm1*02J+t%!(u>4&R-dH*QeW^&yaB zi(7vC_U++?v8R)cK-;BD#&%vKp5_2&-;ZDmTlPLyHe*utNgvQOY_PDd{+}n$JC{|A z$P6rx2>~IS1(w2}Ym6v74UznGL+zVg6&8WZD=w)&fzdb`#HOT7 jeqH_7=~>Zb Date: Sun, 17 Sep 2023 15:59:11 +0000 Subject: [PATCH 0201/1171] [i18n] update translations Signed-off-by: r4sas --- i18n/French.cpp | 6 +++--- i18n/Italian.cpp | 6 +++++- i18n/Portuguese.cpp | 6 +++++- i18n/Ukrainian.cpp | 6 +++++- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/i18n/French.cpp b/i18n/French.cpp index 8bec887c..0a5b147e 100644 --- a/i18n/French.cpp +++ b/i18n/French.cpp @@ -96,7 +96,7 @@ namespace french // language namespace {"Address", "Adresse"}, {"Type", "Type"}, {"EncType", "EncType"}, - {"Expire LeaseSet", "Expiration du LeaseSet"}, + {"Expire LeaseSet", "Expirer le jeu de baux"}, {"Inbound tunnels", "Tunnels entrants"}, {"%dms", "%dms"}, {"Outbound tunnels", "Tunnels sortants"}, @@ -153,8 +153,8 @@ namespace french // language namespace {"StreamID can't be null", "StreamID ne peut pas être vide"}, {"Return to destination page", "Retourner à la page de destination"}, {"You will be redirected in %d seconds", "Vous serez redirigé dans %d secondes"}, - {"LeaseSet expiration time updated", "Temps d'expiration du LeaseSet mis à jour"}, - {"LeaseSet is not found or already expired", "Le LeaseSet est introuvable ou a déjà expirée"}, + {"LeaseSet expiration time updated", "Temps d'expiration du jeu de baux mis à jour"}, + {"LeaseSet is not found or already expired", "Le jeu de baux est introuvable ou a déjà expiré"}, {"Transit tunnels count must not exceed %d", "Le nombre de tunnels de transit ne doit pas excéder %d"}, {"Back to commands list", "Retour à la liste des commandes"}, {"Register at reg.i2p", "Inscription à reg.i2p"}, diff --git a/i18n/Italian.cpp b/i18n/Italian.cpp index 386372d5..2dcaab5e 100644 --- a/i18n/Italian.cpp +++ b/i18n/Italian.cpp @@ -69,6 +69,7 @@ namespace italian // language namespace {"Stopping in", "Arresto in"}, {"Family", "Famiglia"}, {"Tunnel creation success rate", "Percentuale di tunnel creati con successo"}, + {"Total tunnel creation success rate", "Percentuale di successo totale nella creazione del tunnel"}, {"Received", "Ricevuti"}, {"%.2f KiB/s", "%.2f KiB/s"}, {"Sent", "Inviati"}, @@ -95,6 +96,7 @@ namespace italian // language namespace {"Address", "Indirizzo"}, {"Type", "Tipologia"}, {"EncType", "Tipo di crittografia"}, + {"Expire LeaseSet", "Scadenza LeaseSet"}, {"Inbound tunnels", "Tunnel in entrata"}, {"%dms", "%dms"}, {"Outbound tunnels", "Tunnel in uscita"}, @@ -109,6 +111,7 @@ namespace italian // language namespace {"Local Destination", "Destinazione locale"}, {"Streams", "Flussi"}, {"Close stream", "Interrompi il flusso"}, + {"Such destination is not found", "Questa destinazione non è stata trovata"}, {"I2CP session not found", "Sessione I2CP non trovata"}, {"I2CP is not enabled", "I2CP non è abilitato"}, {"Invalid", "Invalido"}, @@ -150,6 +153,8 @@ namespace italian // language namespace {"StreamID can't be null", "Lo StreamID non può essere null"}, {"Return to destination page", "Ritorna alla pagina di destinazione"}, {"You will be redirected in %d seconds", "Sarai reindirizzato tra %d secondi"}, + {"LeaseSet expiration time updated", "Tempo di scadenza LeaseSet aggiornato"}, + {"LeaseSet is not found or already expired", "LeaseSet non trovato o già scaduto"}, {"Transit tunnels count must not exceed %d", "Il conteggio dei tunnel di transito non deve superare %d"}, {"Back to commands list", "Ritorna alla lista dei comandi"}, {"Register at reg.i2p", "Registra a reg.i2p"}, @@ -158,7 +163,6 @@ namespace italian // language namespace {"Submit", "Invia"}, {"Domain can't end with .b32.i2p", "I domini non possono terminare con .b32.i2p"}, {"Domain must end with .i2p", "I domini devono terminare con .i2p"}, - {"Such destination is not found", "Questa destinazione non è stata trovata"}, {"Unknown command", "Comando sconosciuto"}, {"Command accepted", "Comando accettato"}, {"Proxy error", "Errore del proxy"}, diff --git a/i18n/Portuguese.cpp b/i18n/Portuguese.cpp index 8ba7f0cd..4c6d749f 100644 --- a/i18n/Portuguese.cpp +++ b/i18n/Portuguese.cpp @@ -69,6 +69,7 @@ namespace portuguese // language namespace {"Stopping in", "Parando em"}, {"Family", "Família"}, {"Tunnel creation success rate", "Taxa de sucesso na criação de túneis"}, + {"Total tunnel creation success rate", "Taxa total de sucesso na criação de túneis"}, {"Received", "Recebido"}, {"%.2f KiB/s", "%.2f KiB/s"}, {"Sent", "Enviado"}, @@ -95,6 +96,7 @@ namespace portuguese // language namespace {"Address", "Endereço"}, {"Type", "Tipo"}, {"EncType", "Tipo de Criptografia"}, + {"Expire LeaseSet", "Expirar LeaseSet"}, {"Inbound tunnels", "Túneis de Entrada"}, {"%dms", "%dms"}, {"Outbound tunnels", "Túneis de Saída"}, @@ -109,6 +111,7 @@ namespace portuguese // language namespace {"Local Destination", "Destinos Locais"}, {"Streams", "Fluxos"}, {"Close stream", "Fechar fluxo"}, + {"Such destination is not found", "Tal destino não foi encontrado"}, {"I2CP session not found", "Sessão do I2CP não encontrada"}, {"I2CP is not enabled", "I2CP não está ativado"}, {"Invalid", "Inválido"}, @@ -150,6 +153,8 @@ namespace portuguese // language namespace {"StreamID can't be null", "StreamID não pode ser nulo"}, {"Return to destination page", "Retornar para à página de destino"}, {"You will be redirected in %d seconds", "Você será redirecionado em %d segundos"}, + {"LeaseSet expiration time updated", "Tempo de validade do LeaseSet atualizado"}, + {"LeaseSet is not found or already expired", "LeaseSet não foi encontrado ou já expirou"}, {"Transit tunnels count must not exceed %d", "A contagem de túneis de trânsito não deve exceder %d"}, {"Back to commands list", "Voltar para a lista de comandos"}, {"Register at reg.i2p", "Registrar na reg.i2p"}, @@ -158,7 +163,6 @@ namespace portuguese // language namespace {"Submit", "Enviar"}, {"Domain can't end with .b32.i2p", "O domínio não pode terminar com .b32.i2p"}, {"Domain must end with .i2p", "O domínio não pode terminar com .i2p"}, - {"Such destination is not found", "Tal destino não foi encontrado"}, {"Unknown command", "Comando desconhecido"}, {"Command accepted", "Comando aceito"}, {"Proxy error", "Erro no proxy"}, diff --git a/i18n/Ukrainian.cpp b/i18n/Ukrainian.cpp index c1e222ea..d089c142 100644 --- a/i18n/Ukrainian.cpp +++ b/i18n/Ukrainian.cpp @@ -69,6 +69,7 @@ namespace ukrainian // language namespace {"Stopping in", "Зупинка через"}, {"Family", "Сімейство"}, {"Tunnel creation success rate", "Успішно побудованих тунелів"}, + {"Total tunnel creation success rate", "Загальна кількість створених тунелів"}, {"Received", "Отримано"}, {"%.2f KiB/s", "%.2f КіБ/с"}, {"Sent", "Відправлено"}, @@ -95,6 +96,7 @@ namespace ukrainian // language namespace {"Address", "Адреса"}, {"Type", "Тип"}, {"EncType", "ТипШифр"}, + {"Expire LeaseSet", "Завершити LeaseSet"}, {"Inbound tunnels", "Вхідні тунелі"}, {"%dms", "%dмс"}, {"Outbound tunnels", "Вихідні тунелі"}, @@ -109,6 +111,7 @@ namespace ukrainian // language namespace {"Local Destination", "Локальні Призначення"}, {"Streams", "Потоки"}, {"Close stream", "Закрити потік"}, + {"Such destination is not found", "Така точка призначення не знайдена"}, {"I2CP session not found", "I2CP сесія не знайдена"}, {"I2CP is not enabled", "I2CP не увікнуто"}, {"Invalid", "Некоректний"}, @@ -150,6 +153,8 @@ namespace ukrainian // language namespace {"StreamID can't be null", "Ідентифікатор потоку не може бути порожнім"}, {"Return to destination page", "Повернутися на сторінку точки призначення"}, {"You will be redirected in %d seconds", "Ви будете переадресовані через %d секунд"}, + {"LeaseSet expiration time updated", "Час закінчення LeaseSet оновлено"}, + {"LeaseSet is not found or already expired", "LeaseSet не знайдено або вже закінчився"}, {"Transit tunnels count must not exceed %d", "Кількість транзитних тунелів не повинна перевищувати %d"}, {"Back to commands list", "Повернутися до списку команд"}, {"Register at reg.i2p", "Зареєструвати на reg.i2p"}, @@ -158,7 +163,6 @@ namespace ukrainian // language namespace {"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", "Команда прийнята"}, {"Proxy error", "Помилка проксі"}, From 9c25a88707294f93843c2fead9cd4768776d6078 Mon Sep 17 00:00:00 2001 From: r4sas Date: Sun, 17 Sep 2023 16:21:36 +0000 Subject: [PATCH 0202/1171] [i18n] update translations Signed-off-by: r4sas --- i18n/Uzbek.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/i18n/Uzbek.cpp b/i18n/Uzbek.cpp index 9d798be4..cf94a489 100644 --- a/i18n/Uzbek.cpp +++ b/i18n/Uzbek.cpp @@ -69,6 +69,7 @@ namespace uzbek // language namespace {"Stopping in", "Ichida to'xtatish"}, {"Family", "Oila"}, {"Tunnel creation success rate", "Tunnel yaratish muvaffaqiyat darajasi"}, + {"Total tunnel creation success rate", "Tunnel yaratishning umumiy muvaffaqiyat darajasi"}, {"Received", "Qabul qilindi"}, {"%.2f KiB/s", "%.2f KiB/s"}, {"Sent", "Yuborilgan"}, @@ -95,6 +96,7 @@ namespace uzbek // language namespace {"Address", "Manzil"}, {"Type", "Turi"}, {"EncType", "ShifrlashTuri"}, + {"Expire LeaseSet", "LeaseSet muddati tugaydi"}, {"Inbound tunnels", "Kirish tunnellari"}, {"%dms", "%dms"}, {"Outbound tunnels", "Chiquvchi tunnellar"}, @@ -109,6 +111,7 @@ namespace uzbek // language namespace {"Local Destination", "Mahalliy joylanish"}, {"Streams", "Strim"}, {"Close stream", "Strimni o'chirish"}, + {"Such destination is not found", "Bunday yo'nalish topilmadi"}, {"I2CP session not found", "I2CP sessiyasi topilmadi"}, {"I2CP is not enabled", "I2CP yoqilmagan"}, {"Invalid", "Noto'g'ri"}, @@ -150,6 +153,8 @@ namespace uzbek // language namespace {"StreamID can't be null", "StreamID bo'sh bo'lishi mumkin emas"}, {"Return to destination page", "Manzilgoh sahifasiga qaytish"}, {"You will be redirected in %d seconds", "Siz %d soniyadan so‘ng boshqa yo‘nalishga yo‘naltirilasiz"}, + {"LeaseSet expiration time updated", "LeaseSet amal qilish muddati yangilandi"}, + {"LeaseSet is not found or already expired", "LeaseSet topilmadi yoki muddati tugagan"}, {"Transit tunnels count must not exceed %d", "Tranzit tunnellar soni %d dan oshmasligi kerak"}, {"Back to commands list", "Buyruqlar ro'yxatiga qaytish"}, {"Register at reg.i2p", "Reg.i2p-da ro'yxatdan o'ting"}, @@ -158,7 +163,6 @@ namespace uzbek // language namespace {"Submit", "Yuborish"}, {"Domain can't end with .b32.i2p", "Domen .b32.i2p bilan tugashi mumkin emas"}, {"Domain must end with .i2p", "Domen .i2p bilan tugashi kerak"}, - {"Such destination is not found", "Bunday yo'nalish topilmadi"}, {"Unknown command", "Noma'lum buyruq"}, {"Command accepted", "Buyruq qabul qilindi"}, {"Proxy error", "Proksi xatosi"}, From 1857f14be86aa360c90f7baab0d7013f10f22632 Mon Sep 17 00:00:00 2001 From: r4sas Date: Sun, 17 Sep 2023 18:33:42 +0000 Subject: [PATCH 0203/1171] [cpu] use short defines instead of long checks Signed-off-by: r4sas --- libi2pd/CPU.cpp | 4 ++-- libi2pd/CPU.h | 18 ++++++++++++++++++ libi2pd/Crypto.cpp | 15 +++++---------- libi2pd/Crypto.h | 8 ++++---- 4 files changed, 29 insertions(+), 16 deletions(-) diff --git a/libi2pd/CPU.cpp b/libi2pd/CPU.cpp index 5d5fc6b3..4c522987 100644 --- a/libi2pd/CPU.cpp +++ b/libi2pd/CPU.cpp @@ -13,7 +13,7 @@ #define bit_AES (1 << 25) #endif -#if (defined(__GNUC__) && __GNUC__ < 5 && (defined(__x86_64__) || defined(__i386__))) +#if defined(__GNUC__) && __GNUC__ < 5 && IS_X86 #include #endif @@ -29,7 +29,7 @@ namespace cpu inline bool cpu_support_aes() { -#if (defined(_M_AMD64) || defined(__x86_64__)) || (defined(_M_IX86) || defined(__i386__)) +#if IS_X86 #if defined(__clang__) # if (__clang_major__ >= 6) __builtin_cpu_init(); diff --git a/libi2pd/CPU.h b/libi2pd/CPU.h index a0695884..1c30db48 100644 --- a/libi2pd/CPU.h +++ b/libi2pd/CPU.h @@ -9,6 +9,24 @@ #ifndef LIBI2PD_CPU_H #define LIBI2PD_CPU_H +#if defined(_M_AMD64) || defined(__x86_64__) || defined(_M_IX86) || defined(__i386__) +# define IS_X86 1 +# if defined(_M_AMD64) || defined(__x86_64__) +# define IS_X86_64 1 +# else +# define IS_X86_64 0 +# endif +#else +# define IS_X86 0 +# define IS_X86_64 0 +#endif + +#if defined(__AES__) && !defined(_MSC_VER) && IS_X86 +# define SUPPORTS_AES 1 +#else +# define SUPPORTS_AES 0 +#endif + namespace i2p { namespace cpu diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index b5bc33d1..3e5bdd35 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -28,11 +28,6 @@ #include "I2PEndian.h" #include "Log.h" -#if defined(__AES__) && !defined(_MSC_VER) && ((defined(_M_AMD64) || defined(__x86_64__)) || (defined(_M_IX86) || defined(__i386__))) - #define SUPPORTS_AES 1 -#else - #define SUPPORTS_AES 0 -#endif namespace i2p { @@ -165,7 +160,7 @@ namespace crypto // DH/ElGamal -#if !defined(__x86_64__) +#if !IS_X86_64 const int ELGAMAL_SHORT_EXPONENT_NUM_BITS = 226; const int ELGAMAL_SHORT_EXPONENT_NUM_BYTES = ELGAMAL_SHORT_EXPONENT_NUM_BITS/8+1; #endif @@ -367,7 +362,7 @@ namespace crypto BIGNUM * b1 = BN_CTX_get (ctx); BIGNUM * b = BN_CTX_get (ctx); // select random k -#if (defined(_M_AMD64) || defined(__x86_64__)) +#if IS_X86_64 BN_rand (k, ELGAMAL_FULL_EXPONENT_NUM_BITS, -1, 1); // full exponent for x64 #else BN_rand (k, ELGAMAL_SHORT_EXPONENT_NUM_BITS, -1, 1); // short exponent of 226 bits @@ -434,7 +429,7 @@ namespace crypto void GenerateElGamalKeyPair (uint8_t * priv, uint8_t * pub) { -#if (defined(_M_AMD64) || defined(__x86_64__)) || (defined(_M_IX86) || defined(__i386__)) || defined(_MSC_VER) +#if IS_X86 || defined(_MSC_VER) RAND_bytes (priv, 256); #else // lower 226 bits (28 bytes and 2 bits) only. short exponent @@ -1309,7 +1304,7 @@ namespace crypto CRYPTO_set_locking_callback (OpensslLockingCallback);*/ if (precomputation) { -#if (defined(_M_AMD64) || defined(__x86_64__)) +#if IS_X86_64 g_ElggTable = new BIGNUM * [ELGAMAL_FULL_EXPONENT_NUM_BYTES][255]; PrecalculateElggTable (g_ElggTable, ELGAMAL_FULL_EXPONENT_NUM_BYTES); #else @@ -1324,7 +1319,7 @@ namespace crypto if (g_ElggTable) { DestroyElggTable (g_ElggTable, -#if (defined(_M_AMD64) || defined(__x86_64__)) +#if IS_X86_64 ELGAMAL_FULL_EXPONENT_NUM_BYTES #else ELGAMAL_SHORT_EXPONENT_NUM_BYTES diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index 1419293b..816d79fd 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -150,7 +150,7 @@ namespace crypto }; -#ifdef __AES__ +#if SUPPORTS_AES class ECBCryptoAESNI { public: @@ -167,7 +167,7 @@ namespace crypto }; #endif -#ifdef __AES__ +#if SUPPORTS_AES class ECBEncryption: public ECBCryptoAESNI #else class ECBEncryption @@ -183,7 +183,7 @@ namespace crypto AES_KEY m_Key; }; -#ifdef __AES__ +#if SUPPORTS_AES class ECBDecryption: public ECBCryptoAESNI #else class ECBDecryption From 3da50614264f2bb93bc7bad9425772d92b01a973 Mon Sep 17 00:00:00 2001 From: r4sas Date: Mon, 18 Sep 2023 17:11:45 +0000 Subject: [PATCH 0204/1171] [cpu] Increase GCC version for use of builtin CPU extensions checker Signed-off-by: r4sas --- libi2pd/CPU.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/CPU.cpp b/libi2pd/CPU.cpp index 4c522987..e434dd57 100644 --- a/libi2pd/CPU.cpp +++ b/libi2pd/CPU.cpp @@ -13,7 +13,7 @@ #define bit_AES (1 << 25) #endif -#if defined(__GNUC__) && __GNUC__ < 5 && IS_X86 +#if defined(__GNUC__) && __GNUC__ < 6 && IS_X86 #include #endif From fb420bb563a3ebf8803faaa390ba6b2bb840d872 Mon Sep 17 00:00:00 2001 From: r4sas Date: Mon, 18 Sep 2023 18:12:26 +0000 Subject: [PATCH 0205/1171] [cpu] more builtin version check changes Signed-off-by: r4sas --- libi2pd/CPU.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/CPU.cpp b/libi2pd/CPU.cpp index e434dd57..77820c88 100644 --- a/libi2pd/CPU.cpp +++ b/libi2pd/CPU.cpp @@ -35,10 +35,10 @@ namespace cpu __builtin_cpu_init(); # endif return __builtin_cpu_supports("aes"); -#elif (defined(__GNUC__) && __GNUC__ >= 5) +#elif (defined(__GNUC__) && __GNUC__ >= 6) __builtin_cpu_init(); return __builtin_cpu_supports("aes"); -#elif (defined(__GNUC__) && __GNUC__ < 5) +#elif (defined(__GNUC__) && __GNUC__ < 6) int cpu_info[4]; bool flag = false; __cpuid(0, cpu_info[0], cpu_info[1], cpu_info[2], cpu_info[3]); From 0cf656cd7687fce461f644820066afc36be312b3 Mon Sep 17 00:00:00 2001 From: hfsfox Date: Thu, 28 Sep 2023 22:30:38 +0300 Subject: [PATCH 0206/1171] Add Haiku OS support (#1970) --- Makefile | 3 +++ Makefile.haiku | 10 ++++++++++ build/CMakeLists.txt | 4 ++++ libi2pd/FS.cpp | 8 ++++++++ libi2pd/I2PEndian.h | 2 +- libi2pd/util.cpp | 11 +++++++++++ 6 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 Makefile.haiku diff --git a/Makefile b/Makefile index 0861ec0b..86ea0aa8 100644 --- a/Makefile +++ b/Makefile @@ -67,6 +67,9 @@ else ifneq (, $(findstring linux, $(SYS))$(findstring gnu, $(SYS))) else ifneq (, $(findstring freebsd, $(SYS))$(findstring openbsd, $(SYS))) DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp include Makefile.bsd +else ifneq (, $(findstring haiku, $(SYS))) + DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp + include Makefile.haiku else # not supported $(error Not supported platform) endif diff --git a/Makefile.haiku b/Makefile.haiku new file mode 100644 index 00000000..85c2835d --- /dev/null +++ b/Makefile.haiku @@ -0,0 +1,10 @@ +CXX = g++ +CXXFLAGS := -Wall -std=c++11 +INCFLAGS = -I/system/develop/headers +DEFINES = -D_DEFAULT_SOURCE -D_GNU_SOURCE +LDLIBS = -lbe -lbsd -lnetwork -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread + +ifeq ($(USE_UPNP),yes) + DEFINES += -DUSE_UPNP + LDLIBS += -lminiupnpc +endif diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 3185ffab..abfadfca 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -139,6 +139,10 @@ if(APPLE) add_definitions(-DMAC_OSX) endif() +if(HAIKU) + add_definitions(-D_DEFAULT_SOURCE -D_GNU_SOURCE) +endif() + if(MSVC) add_definitions(-DWINVER=0x0600) add_definitions(-D_WIN32_WINNT=0x0600) diff --git a/libi2pd/FS.cpp b/libi2pd/FS.cpp index 7334550f..d38bcc2f 100644 --- a/libi2pd/FS.cpp +++ b/libi2pd/FS.cpp @@ -136,6 +136,14 @@ namespace fs { dataDir = (home != NULL && strlen(home) > 0) ? home : ""; dataDir += "/Library/Application Support/" + appName; return; +#elif defined(__HAIKU__) + char *home = getenv("HOME"); + if (home != NULL && strlen(home) > 0) { + dataDir = std::string(home) + "/config/settings/" + appName; + } else { + dataDir = "/tmp/" + appName; + } + return; #else /* other unix */ #if defined(ANDROID) const char * ext = getenv("EXTERNAL_STORAGE"); diff --git a/libi2pd/I2PEndian.h b/libi2pd/I2PEndian.h index 06abf29a..681a4999 100644 --- a/libi2pd/I2PEndian.h +++ b/libi2pd/I2PEndian.h @@ -14,7 +14,7 @@ #if defined(__FreeBSD__) || defined(__NetBSD__) #include -#elif defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__GLIBC__) +#elif defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__GLIBC__) || defined(__HAIKU__) #include #elif defined(__APPLE__) && defined(__MACH__) diff --git a/libi2pd/util.cpp b/libi2pd/util.cpp index 088a7af5..a7afdce8 100644 --- a/libi2pd/util.cpp +++ b/libi2pd/util.cpp @@ -27,6 +27,17 @@ # include #endif +#if defined(__HAIKU__) +#include +#include +#include +#include +#ifndef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE +#include +#endif +#endif + #ifdef _WIN32 #include #include From 1e6edf06a29a0af8ac09f12c227f6b9ed76d75df Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 28 Sep 2023 16:05:13 -0400 Subject: [PATCH 0207/1171] send already accepting error response --- libi2pd_client/SAM.cpp | 49 ++++++++++++++++++++++++++++-------------- libi2pd_client/SAM.h | 5 +++-- 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index bb9d6a6b..1a281c57 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -360,7 +360,7 @@ namespace client if (type == eSAMSessionTypeUnknown) { // unknown style - SendI2PError("Unknown STYLE"); + SendSessionI2PError("Unknown STYLE"); return; } @@ -375,14 +375,14 @@ namespace client if (e) { // not an ip address - SendI2PError("Invalid IP Address in HOST"); + SendSessionI2PError("Invalid IP Address in HOST"); return; } auto port = std::stoi(params[SAM_PARAM_PORT]); if (port == -1) { - SendI2PError("Invalid port"); + SendSessionI2PError("Invalid port"); return; } forward = std::make_shared(addr, port); @@ -484,7 +484,7 @@ namespace client LogPrint (eLogDebug, "SAM: Stream connect: ", buf); if ( m_SocketType != eSAMSocketTypeUnknown) { - SendI2PError ("Socket already in use"); + SendSessionI2PError ("Socket already in use"); return; } std::map params; @@ -582,7 +582,7 @@ namespace client LogPrint (eLogDebug, "SAM: Stream accept: ", buf); if ( m_SocketType != eSAMSocketTypeUnknown) { - SendI2PError ("Socket already in use"); + SendSessionI2PError ("Socket already in use"); return; } std::map params; @@ -598,9 +598,15 @@ namespace client if (!session->GetLocalDestination ()->IsAcceptingStreams ()) { m_IsAccepting = true; + SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); session->GetLocalDestination ()->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, shared_from_this (), std::placeholders::_1)); } - SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); + else // already accepting + { + // TODO: implement queue + LogPrint (eLogInfo, "SAM: Session ", m_ID, " is already accepting"); + SendStreamI2PError ("Already accepting"); + } } else SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); @@ -620,26 +626,26 @@ namespace client } if (session->GetLocalDestination ()->IsAcceptingStreams ()) { - SendI2PError ("Already accepting"); + SendSessionI2PError ("Already accepting"); return; } auto it = params.find (SAM_PARAM_PORT); if (it == params.end ()) { - SendI2PError ("PORT is missing"); + SendSessionI2PError ("PORT is missing"); return; } auto port = std::stoi (it->second); if (port <= 0 || port >= 0xFFFF) { - SendI2PError ("Invalid PORT"); + SendSessionI2PError ("Invalid PORT"); return; } boost::system::error_code ec; auto ep = m_Socket.remote_endpoint (ec); if (ec) { - SendI2PError ("Socket error"); + SendSessionI2PError ("Socket error"); return; } ep.port (port); @@ -791,13 +797,13 @@ namespace client if (type == eSAMSessionTypeUnknown) { // unknown style - SendI2PError("Unsupported STYLE"); + SendSessionI2PError("Unsupported STYLE"); return; } auto fromPort = std::stoi(params[SAM_PARAM_FROM_PORT]); if (fromPort == -1) { - SendI2PError("Invalid from port"); + SendSessionI2PError("Invalid from port"); return; } auto subsession = std::make_shared(masterSession, id, type, fromPort); @@ -810,7 +816,7 @@ namespace client SendMessageReply (SAM_SESSION_CREATE_DUPLICATED_ID, strlen(SAM_SESSION_CREATE_DUPLICATED_ID), false); } else - SendI2PError ("Wrong session type"); + SendSessionI2PError ("Wrong session type"); } void SAMSocket::ProcessSessionRemove (char * buf, size_t len) @@ -832,12 +838,12 @@ namespace client SendSessionCreateReplyOk (); } else - SendI2PError ("Wrong session type"); + SendSessionI2PError ("Wrong session type"); } - void SAMSocket::SendI2PError(const std::string & msg) + void SAMSocket::SendSessionI2PError(const std::string & msg) { - LogPrint (eLogError, "SAM: I2P error: ", msg); + LogPrint (eLogError, "SAM: Session I2P error: ", msg); #ifdef _MSC_VER size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_STATUS_I2P_ERROR, msg.c_str()); #else @@ -846,6 +852,17 @@ namespace client SendMessageReply (m_Buffer, len, true); } + void SAMSocket::SendStreamI2PError(const std::string & msg) + { + LogPrint (eLogError, "SAM: Stream I2P error: ", msg); +#ifdef _MSC_VER + size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_STREAM_STATUS_I2P_ERROR, msg.c_str()); +#else + size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_STREAM_STATUS_I2P_ERROR, msg.c_str()); +#endif + SendMessageReply (m_Buffer, len, true); + } + void SAMSocket::HandleNamingLookupLeaseSetRequestComplete (std::shared_ptr leaseSet, std::string name) { if (leaseSet) diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index b4c72754..736c0945 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -49,7 +49,7 @@ namespace client const char SAM_STREAM_STATUS_INVALID_ID[] = "STREAM STATUS RESULT=INVALID_ID\n"; const char SAM_STREAM_STATUS_INVALID_KEY[] = "STREAM STATUS RESULT=INVALID_KEY\n"; const char SAM_STREAM_STATUS_CANT_REACH_PEER[] = "STREAM STATUS RESULT=CANT_REACH_PEER\n"; - const char SAM_STREAM_STATUS_I2P_ERROR[] = "STREAM STATUS RESULT=I2P_ERROR\n"; + const char SAM_STREAM_STATUS_I2P_ERROR[] = "STREAM STATUS RESULT=I2P_ERROR MESSAGE=\"%s\"\n"; const char SAM_STREAM_ACCEPT[] = "STREAM ACCEPT"; const char SAM_STREAM_FORWARD[] = "STREAM FORWARD"; const char SAM_DATAGRAM_SEND[] = "DATAGRAM SEND"; @@ -141,7 +141,8 @@ namespace client void ProcessNamingLookup (char * buf, size_t len); void ProcessSessionAdd (char * buf, size_t len); void ProcessSessionRemove (char * buf, size_t len); - void SendI2PError(const std::string & msg); + void SendSessionI2PError(const std::string & msg); + void SendStreamI2PError(const std::string & msg); size_t ProcessDatagramSend (char * buf, size_t len, const char * data); // from SAM 1.0 void ExtractParams (char * buf, std::map& params); From efdbe267554bfa03bcb51097f8e19e9d335e3a9f Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 28 Sep 2023 18:40:51 -0400 Subject: [PATCH 0208/1171] try peer test again if Unknown --- libi2pd/Transports.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index b452c05e..45284e24 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -833,8 +833,12 @@ namespace transport } } bool ipv4Testing = i2p::context.GetTesting (); + if (!ipv4Testing) + ipv4Testing = i2p::context.GetRouterInfo ().IsSSU2V4 () && (i2p::context.GetStatus() == eRouterStatusUnknown); bool ipv6Testing = i2p::context.GetTestingV6 (); - // if still testing, repeat peer test + if (!ipv6Testing) + ipv6Testing = i2p::context.GetRouterInfo ().IsSSU2V6 () && (i2p::context.GetStatusV6() == eRouterStatusUnknown); + // if still testing or unknown, repeat peer test if (ipv4Testing || ipv6Testing) PeerTest (ipv4Testing, ipv6Testing); m_PeerCleanupTimer->expires_from_now (boost::posix_time::seconds(3 * SESSION_CREATION_TIMEOUT)); From 9980bfa0e7f03a3849eca4e2e771593cc64419a5 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 30 Sep 2023 14:10:45 -0400 Subject: [PATCH 0209/1171] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e7fb7318..ce25c8f2 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ Current status: [![Crowdin](https://badges.crowdin.net/i2pd/localized.svg)](http Donations --------- -**E-Mail**: ```i2porignal at yandex.ru``` +**E-Mail**: ```i2porignal at yandex.com``` **BTC**: ```3MDoGJW9TLMTCDGrR9bLgWXfm6sjmgy86f``` From e926b0392f3458a1c8af15a4baba0185a56eea09 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 7 Oct 2023 14:22:53 -0400 Subject: [PATCH 0210/1171] reseed.is.prestium.org reseed added --- .../reheatedburger_at_protonmail.com.crt | 34 +++++++++++++++++++ libi2pd/Config.cpp | 3 +- 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 contrib/certificates/reseed/reheatedburger_at_protonmail.com.crt diff --git a/contrib/certificates/reseed/reheatedburger_at_protonmail.com.crt b/contrib/certificates/reseed/reheatedburger_at_protonmail.com.crt new file mode 100644 index 00000000..d14c5fe1 --- /dev/null +++ b/contrib/certificates/reseed/reheatedburger_at_protonmail.com.crt @@ -0,0 +1,34 @@ +-----BEGIN CERTIFICATE----- +MIIF7zCCA9egAwIBAgIRANVB/+wEuXS0Ttoh5teJt90wDQYJKoZIhvcNAQELBQAw +fTELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJYWDEeMBwGA1UE +ChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxJjAkBgNVBAMM +HXJlaGVhdGVkYnVyZ2VyQHByb3Rvbm1haWwuY29tMB4XDTIzMDkyMTE4MDAyOVoX +DTMzMDkyMTE4MDAyOVowfTELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYD +VQQJEwJYWDEeMBwGA1UEChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQL +EwNJMlAxJjAkBgNVBAMMHXJlaGVhdGVkYnVyZ2VyQHByb3Rvbm1haWwuY29tMIIC +IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuNwmiIY3MLSBS5sL5PXRDVK6 +MoSNw4qx0o8nDHvVBxNtzgc0/qjYvsuUggY0tZbPpxhML6GHd4qo7Z3Ip1x0MxhI +Ao5MJaflaEdm4+HeMy0IE3aU73KRUwp+nF3cUHZdlps+9mtYs4oncVEWkFQwGsgt +4yrLtXf6PmPWfFH28ffeaev90e+hdhQpTvr54Ewx6NTaMQr8mkhXL2utvPpjnPM5 +UAhOeJCMgfhLzgS4rahG0O8CQMtH5gKZ+6zjoSRatnjj0j1mBO7+e1TL5O7dVS9k +P83tmkIDDl4tXBzXr9aXQMJstbM2CEvinVcCsR74GjPcg4iB0Ift71Dx7oGKI06t +3bSvll0GZm2mFhIba/4q6f4oAJ2aeq6ejt1Kcm8g5cxtwrRZnXv5JXHZqba3y8J5 +zWaRHzhc9tyEqRBRkc6c7xMdZQ31iJ6TlxUT8vAJ1N7OnX87oHrCjwyikpyOen4r +Uvv1Ge054XPTeoHz+Jyt34t71ty1W13uPHpuvtPVR9MfgGrxd4Z9+LWvAjmMbFsZ +lC3Ll+94nUk+O0puU6KisuCGP4hCtdEtebkIqT8zo8LicLAYUMjX7KwnS7681Cu1 +sY2mB2oZAytN9Zy42oOoNeY5x39kxfwuut/2E1kxKX75O0bwfIXr611abCKc3bbz +euMrIsaB/2VFp9nAah8CAwEAAaNqMGgwDgYDVR0PAQH/BAQDAgKEMB0GA1UdJQQW +MBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MCYGA1UdDgQf +BB1yZWhlYXRlZGJ1cmdlckBwcm90b25tYWlsLmNvbTANBgkqhkiG9w0BAQsFAAOC +AgEATuHi2Yz52OK7e+sKVdHu2KrSLCGm98BG1UIMHFi3WRBTOFyp+lZ519bJ1rFj +tmP9E1a+k/vlbc7FbV4PcV6HJYfGEv/ImtJsEnrzbhrQphC1zMFv7q6JCTUbAzl6 +ySlJ++mVxQ6AzPNH3TQgL1wPKuLh76/Y4053fg+NI3PmzzhkTUheVDkg0/a9ENSf +xMnCa3fIm869735qHk67QlikFvAfWwc4zT1Ncwodh8G4+oX0GFzIl+OZaM1GTMuD +UCcFKoqwtjyLCr22xNk8CfyiExPJXQG1HzEvDcxyoxQtnh9occR9PgqXySz26/NM +XDyM+l4utLMGBcVY4x9fksRiaWEfxiygYOxY9zDl6clh6S10b3CLut4UMiS1RTtE +Mjx2BZN3p0nxpT2leJdGxtBPGrvxuiCOEmTbOMLc3DQtppXO97B3dVMtJ5Ee8Y6p +Tq/8eiHI6eQXat6dgFT5X16vzF7w7XO7fAxuqk4Kx1D1aTVyikdo+Fcdg44dWOjq +NZu8VcCzZij/Dfjlce6t6h8D+wvDD8AkiivaDljpvbNDx/QQlQXFgH98TZA8Rnvr +QcyNNATfz+1yQUiyO6Lrjaw64OJwXYX/llgnDC+qQpP6kqZabi2TsG0EVPukVvr9 +0HyAUu4lnXtTIDq2yPNenegCloqDL1ZQdaYd2XIItnfZdTY= +-----END CERTIFICATE----- diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 5551b010..0f101e64 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -221,7 +221,8 @@ namespace config { "https://reseed-pl.i2pd.xyz/," "https://www2.mk16.de/," "https://i2p.ghativega.in/," - "https://i2p.novg.net/" + "https://i2p.novg.net/," + "https://reseed.is.prestium.org/" ), "Reseed URLs, separated by comma") ("reseed.yggurls", value()->default_value( "http://[324:71e:281a:9ed3::ace]:7070/," From 606e35eec1efd02480f85bac9b8d47706aca8dbe Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 10 Oct 2023 12:59:40 -0400 Subject: [PATCH 0211/1171] reseed.us.prestium.org reseed added --- .../reseed/null_at_i2pmail.org.crt | 33 +++++++++++++++++++ libi2pd/Config.cpp | 3 +- 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 contrib/certificates/reseed/null_at_i2pmail.org.crt diff --git a/contrib/certificates/reseed/null_at_i2pmail.org.crt b/contrib/certificates/reseed/null_at_i2pmail.org.crt new file mode 100644 index 00000000..d736a95e --- /dev/null +++ b/contrib/certificates/reseed/null_at_i2pmail.org.crt @@ -0,0 +1,33 @@ +-----BEGIN CERTIFICATE----- +MIIFyDCCA7CgAwIBAgIRAO8lBnTo+hlvglQwug2jHZkwDQYJKoZIhvcNAQELBQAw +cDELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJYWDEeMBwGA1UE +ChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxGTAXBgNVBAMM +EG51bGxAaTJwbWFpbC5vcmcwHhcNMjMwOTIxMjIzMTM2WhcNMzMwOTIxMjIzMTM2 +WjBwMQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYD +VQQKExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEZMBcGA1UE +AwwQbnVsbEBpMnBtYWlsLm9yZzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC +ggIBAMMpAvaHwzuZZ6qelRU4jcgpuAIZFH++F1Te4b1t02pRfnQ0Eeh04VC1JxO0 +XjUr1/iszEyvrI4+AdxaobDyRFPylkOLtfec4d2ciDc1cupj6y2vyYhMVN31rrvE +ve7sKoTHJ5Dx+UPGOVZZsSsmK9TXIU23W2bo7k2VnjVBXdWZyNE4twfTYCosDnYA +1HIEaIUFVv+COqw2pktxkMmfUAlnDLeVSfsAzEr37K+x0Xk5hO8m6GWQx0NRjjYp +gyEcFhWAJjAYaF3gUVR9rVVky1OeFhZgxE/KzVrW7uc84ZCMKITEPwT0qqIpsTJp +486YXzuPSc+ef78cKSQf5992l7imySJ24I/5H73HkovGAFGZdwvl6V6Ta5YqO7RR +gVDOL1EIVUnMCqFBCE6RmyZqXBVrv4Cacdc6lZ4fj42SRtWZfe6rNCpJzTRtbOyW +DBmYpK6q/jddfqI1sX0PXIn9U+Rod5Z4uz82PAjhamqyr5fpAnoQxKppBvQ3tNfn +KQhmP73Hdpvl24pRyQLBIRUL86i7TPBBn7n3XZlQfXP7lp8+KJYLkL2/zCVDrwLX +kC9hRIxCU9bZbXlkRE2R/PrK53LZecjk2KcgINA4ZlguNgze/Qj8BXelUF4izbpV +bTSvniTM46AECvjDcICAOky9Ku4RnmUJxQVf3ahDEuso7/N7AgMBAAGjXTBbMA4G +A1UdDwEB/wQEAwIChDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDwYD +VR0TAQH/BAUwAwEB/zAZBgNVHQ4EEgQQbnVsbEBpMnBtYWlsLm9yZzANBgkqhkiG +9w0BAQsFAAOCAgEAEUfYJTdDH7uCojnpF0Gs2tXxPJ22UhdqEsXfqR7KhhmmApss +q5kiiPIYoy5T/4IM7NVyeeJAMYwQsdJjwZ4QyxLBb9EqMS2krREcPZNRfFzBr2Wj +EBhJEYTnbIn4docwJWyXsJVG0CqFXPF1qGd0Sc2u87yj2xZNTnloWKAEQAO7DE39 +gWfDH6slM/3h3WD3Mjuk7JoYSYmBfvvm2hkBbC6lzD7XY7rdSmIUwJ050e9UrJaV +La51dd5r4q8d1cHrVUwLiACAaXJ15AEqUDLHQcvKvyfhkabwRy+v0wsodSMgSMEH +xA+kGhkIW7yV7o2exYOYypHCca3IA+pimMpEseNNrHSwbHOMfauiN7jiZLEPg6D6 +a8XwK7qmMYUq7j6QWuIqI81o29WZRf4LZ0GFoVce+e5VxkVKSItKcJoedIAp1ML8 +NhFwd9s/nqWidu/StscEEbGzz6ZuDXwshERXC0QR8HjHEPi4U8220juf4cxUahxK +heEU91l7VksSZYRUN98h28vovGcukLcnVoLj5H/+Z4r/BgxMrOUJKetxf8fU7FjO +j1U6XV36tGi+IOwYQb9D5fTVafC3hHkuUIjlOdUGYadse98ILhn9kaNtqkBtk/EU +vK+McnrEv7tcKrbvYEop/KaUayhjFiL+wGWnpxt7gLhIiavnIeUyD7acltw= +-----END CERTIFICATE----- diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 0f101e64..cd78727f 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -222,7 +222,8 @@ namespace config { "https://www2.mk16.de/," "https://i2p.ghativega.in/," "https://i2p.novg.net/," - "https://reseed.is.prestium.org/" + "https://reseed.is.prestium.org/," + "https://reseed.us.prestium.org/" ), "Reseed URLs, separated by comma") ("reseed.yggurls", value()->default_value( "http://[324:71e:281a:9ed3::ace]:7070/," From 0cc91dd2d2225b7e4690fc4fb7a39106d018ebf8 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 15 Oct 2023 08:31:55 -0400 Subject: [PATCH 0212/1171] don't pick too active peer --- libi2pd/NTCP2.cpp | 20 +++++++------- libi2pd/RouterContext.cpp | 14 +++++----- libi2pd/RouterInfo.h | 8 ++++-- libi2pd/SSU2Session.cpp | 18 ++++++------- libi2pd/TransportSession.h | 55 +++++++++++++++++++++++++++++++++----- libi2pd/Transports.cpp | 2 +- 6 files changed, 80 insertions(+), 37 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index bbd93435..0a23f07e 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -374,7 +374,7 @@ namespace transport transports.PeerDisconnected (shared_from_this ()); m_Server.RemoveNTCP2Session (shared_from_this ()); m_SendQueue.clear (); - m_SendQueueSize = 0; + SetSendQueueSize (0); auto remoteIdentity = GetRemoteIdentity (); if (remoteIdentity) { @@ -433,7 +433,7 @@ namespace transport void NTCP2Session::DeleteNextReceiveBuffer (uint64_t ts) { if (m_NextReceivedBuffer && !m_IsReceiving && - ts > m_LastActivityTimestamp + NTCP2_RECEIVE_BUFFER_DELETION_TIMEOUT) + ts > GetLastActivityTimestamp () + NTCP2_RECEIVE_BUFFER_DELETION_TIMEOUT) { delete[] m_NextReceivedBuffer; m_NextReceivedBuffer = nullptr; @@ -789,7 +789,7 @@ namespace transport void NTCP2Session::ServerLogin () { SetTerminationTimeout (NTCP2_ESTABLISH_TIMEOUT); - m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); + SetLastActivityTimestamp (i2p::util::GetSecondsSinceEpoch ()); m_Establisher->CreateEphemeralKey (); boost::asio::async_read (m_Socket, boost::asio::buffer(m_Establisher->m_SessionRequestBuffer, 64), boost::asio::transfer_all (), std::bind(&NTCP2Session::HandleSessionRequestReceived, shared_from_this (), @@ -872,9 +872,8 @@ namespace transport } else { - m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); - m_NumReceivedBytes += bytes_transferred + 2; // + length - i2p::transport::transports.UpdateReceivedBytes (bytes_transferred); + UpdateNumReceivedBytes (bytes_transferred + 2); + i2p::transport::transports.UpdateReceivedBytes (bytes_transferred + 2); uint8_t nonce[12]; CreateNonce (m_ReceiveSequenceNumber, nonce); m_ReceiveSequenceNumber++; if (i2p::crypto::AEADChaCha20Poly1305 (m_NextReceivedBuffer, m_NextReceivedLen-16, nullptr, 0, m_ReceiveKey, nonce, m_NextReceivedBuffer, m_NextReceivedLen, false)) @@ -1095,11 +1094,10 @@ namespace transport } else { - m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); - m_NumSentBytes += bytes_transferred; + UpdateNumSentBytes (bytes_transferred); i2p::transport::transports.UpdateSentBytes (bytes_transferred); LogPrint (eLogDebug, "NTCP2: Next frame sent ", bytes_transferred); - if (m_LastActivityTimestamp > m_NextRouterInfoResendTime) + if (GetLastActivityTimestamp () > m_NextRouterInfoResendTime) { m_NextRouterInfoResendTime += NTCP2_ROUTERINFO_RESEND_INTERVAL + rand ()%NTCP2_ROUTERINFO_RESEND_INTERVAL_THRESHOLD; @@ -1108,7 +1106,7 @@ namespace transport else { SendQueue (); - m_SendQueueSize = m_SendQueue.size (); + SetSendQueueSize (m_SendQueue.size ()); } } } @@ -1231,7 +1229,7 @@ namespace transport GetIdentHashBase64(), " exceeds ", NTCP2_MAX_OUTGOING_QUEUE_SIZE); Terminate (); } - m_SendQueueSize = m_SendQueue.size (); + SetSendQueueSize (m_SendQueue.size ()); } void NTCP2Session::SendLocalRouterInfo (bool update) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index fa3ba7bd..f21c0592 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -594,15 +594,15 @@ namespace i2p /* detect parameters */ switch (L) { - case i2p::data::CAPS_FLAG_LOW_BANDWIDTH1 : limit = 12; type = low; break; - case i2p::data::CAPS_FLAG_LOW_BANDWIDTH2 : limit = 48; type = low; break; - case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH1 : limit = 64; type = high; break; - case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH2 : limit = 128; type = high; break; - case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH3 : limit = 256; type = high; break; - case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH1 : limit = 2048; type = extra; break; + case i2p::data::CAPS_FLAG_LOW_BANDWIDTH1 : limit = 12; type = low; break; + case i2p::data::CAPS_FLAG_LOW_BANDWIDTH2 : limit = i2p::data::LOW_BANDWIDTH_LIMIT; type = low; break; // 48 + case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH1 : limit = 64; type = high; break; + case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH2 : limit = 128; type = high; break; + case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH3 : limit = i2p::data::HIGH_BANDWIDTH_LIMIT; type = high; break; // 256 + case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH1 : limit = i2p::data::EXTRA_BANDWIDTH_LIMIT; type = extra; break; // 2048 case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH2 : limit = 1000000; type = unlim; break; // 1Gbyte/s default: - limit = 48; type = low; + limit = i2p::data::LOW_BANDWIDTH_LIMIT; type = low; // 48 } /* update caps & flags in RI */ auto caps = m_RouterInfo.GetCaps (); diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 9aff2240..a95119ed 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -42,8 +42,12 @@ namespace data const char CAPS_FLAG_HIGH_BANDWIDTH1 = 'M'; /* 48-64 KBps */ const char CAPS_FLAG_HIGH_BANDWIDTH2 = 'N'; /* 64-128 KBps */ const char CAPS_FLAG_HIGH_BANDWIDTH3 = 'O'; /* 128-256 KBps */ - const char CAPS_FLAG_EXTRA_BANDWIDTH1 = 'P'; /* 256-2000 KBps */ - const char CAPS_FLAG_EXTRA_BANDWIDTH2 = 'X'; /* > 2000 KBps */ + const char CAPS_FLAG_EXTRA_BANDWIDTH1 = 'P'; /* 256-2048 KBps */ + const char CAPS_FLAG_EXTRA_BANDWIDTH2 = 'X'; /* > 2048 KBps */ + // bandwidth limits in kBps + const uint32_t LOW_BANDWIDTH_LIMIT = 48; + const uint32_t HIGH_BANDWIDTH_LIMIT = 256; + const uint32_t EXTRA_BANDWIDTH_LIMIT = 2048; // congesion flags const char CAPS_FLAG_MEDIUM_CONGESTION = 'D'; const char CAPS_FLAG_HIGH_CONGESTION = 'E'; diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index f0e539c7..487d5549 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -263,7 +263,7 @@ namespace transport m_SessionConfirmedFragment.reset (nullptr); m_PathChallenge.reset (nullptr); m_SendQueue.clear (); - m_SendQueueSize = 0; + SetSendQueueSize (0); m_SentPackets.clear (); m_IncompleteMessages.clear (); m_RelaySessions.clear (); @@ -364,7 +364,7 @@ namespace transport RequestTermination (eSSU2TerminationReasonTimeout); } } - m_SendQueueSize = m_SendQueue.size (); + SetSendQueueSize (m_SendQueue.size ()); } bool SSU2Session::SendQueue () @@ -524,7 +524,7 @@ namespace transport LogPrint (eLogInfo, "SSU2: Packet was not Acked after ", it->second->numResends, " attempts. Terminate session"); m_SentPackets.clear (); m_SendQueue.clear (); - m_SendQueueSize = 0; + SetSendQueueSize (0); RequestTermination (eSSU2TerminationReasonTimeout); return resentPackets.size (); } @@ -1452,8 +1452,7 @@ namespace transport header.ll[1] ^= CreateHeaderMask (m_KeyDataSend + 32, payload + (len + 4)); m_Server.Send (header.buf, 16, payload, len + 16, m_RemoteEndpoint); m_SendPacketNum++; - m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); - m_NumSentBytes += len + 32; + UpdateNumSentBytes (len + 32); return m_SendPacketNum - 1; } @@ -1494,8 +1493,7 @@ namespace transport LogPrint (eLogWarning, "SSU2: Data AEAD verification failed "); return; } - m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); - m_NumReceivedBytes += len; + UpdateNumReceivedBytes (len); if (!packetNum || UpdateReceivePacketNum (packetNum)) HandlePayload (payload, payloadSize); } @@ -2357,7 +2355,7 @@ namespace transport if (!msg->IsExpired ()) { // m_LastActivityTimestamp is updated in ProcessData before - if (m_ReceivedI2NPMsgIDs.emplace (msgID, (uint32_t)m_LastActivityTimestamp).second) + if (m_ReceivedI2NPMsgIDs.emplace (msgID, (uint32_t)GetLastActivityTimestamp ()).second) m_Handler.PutNextMessage (std::move (msg)); else LogPrint (eLogDebug, "SSU2: Message ", msgID, " already received"); @@ -2943,7 +2941,7 @@ namespace transport else ++it; } - if (m_ReceivedI2NPMsgIDs.size () > SSU2_MAX_NUM_RECEIVED_I2NP_MSGIDS || ts > m_LastActivityTimestamp + SSU2_DECAY_INTERVAL) + if (m_ReceivedI2NPMsgIDs.size () > SSU2_MAX_NUM_RECEIVED_I2NP_MSGIDS || ts > GetLastActivityTimestamp () + SSU2_DECAY_INTERVAL) // decay m_ReceivedI2NPMsgIDs.clear (); else @@ -3015,7 +3013,7 @@ namespace transport { bool sent = SendQueue (); // if we have something to send if (sent) - m_SendQueueSize = m_SendQueue.size (); + SetSendQueueSize (m_SendQueue.size ()); if (m_IsDataReceived) { if (!sent) SendQuickAck (); diff --git a/libi2pd/TransportSession.h b/libi2pd/TransportSession.h index 7d2f2653..e298fdb2 100644 --- a/libi2pd/TransportSession.h +++ b/libi2pd/TransportSession.h @@ -71,15 +71,17 @@ namespace transport const int64_t TRANSPORT_SESSION_SLOWNESS_THRESHOLD = 500; // in milliseconds const int64_t TRANSPORT_SESSION_MAX_HANDSHAKE_INTERVAL = 10000; // in milliseconds + const uint64_t TRANSPORT_SESSION_BANDWIDTH_UPDATE_MIN_INTERVAL = 5; // in seconds class TransportSession { public: TransportSession (std::shared_ptr router, int terminationTimeout): - m_NumSentBytes (0), m_NumReceivedBytes (0), m_SendQueueSize (0), - m_IsOutgoing (router), m_TerminationTimeout (terminationTimeout), - m_LastActivityTimestamp (i2p::util::GetSecondsSinceEpoch ()), - m_HandshakeInterval (0) + m_IsOutgoing (router), m_TerminationTimeout (terminationTimeout), m_HandshakeInterval (0), + m_SendQueueSize (0), m_NumSentBytes (0), m_NumReceivedBytes (0), + m_LastBandWidthUpdateNumSentBytes (0), m_LastBandWidthUpdateNumReceivedBytes (0), + m_LastActivityTimestamp (i2p::util::GetSecondsSinceEpoch ()), + m_LastBandwidthUpdateTimestamp (m_LastActivityTimestamp), m_InBandwidth (0), m_OutBandwidth (0) { if (router) m_RemoteIdentity = router->GetRouterIdentity (); @@ -103,11 +105,29 @@ namespace transport } size_t GetNumSentBytes () const { return m_NumSentBytes; }; + void UpdateNumSentBytes (size_t len) + { + m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); + m_NumSentBytes += len; + UpdateBandwidth (); + } size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; }; + void UpdateNumReceivedBytes (size_t len) + { + m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); + m_NumReceivedBytes += len; + UpdateBandwidth (); + } size_t GetSendQueueSize () const { return m_SendQueueSize; }; + void SetSendQueueSize (size_t s) { m_SendQueueSize = s; }; bool IsOutgoing () const { return m_IsOutgoing; }; bool IsSlow () const { return m_HandshakeInterval > TRANSPORT_SESSION_SLOWNESS_THRESHOLD && m_HandshakeInterval < TRANSPORT_SESSION_MAX_HANDSHAKE_INTERVAL; }; + bool IsBandwidthExceeded (bool isHighBandwidth) const + { + auto limit = isHighBandwidth ? i2p::data::HIGH_BANDWIDTH_LIMIT*1024 : i2p::data::LOW_BANDWIDTH_LIMIT*1024; // convert to bytes + return std::max (m_InBandwidth, m_OutBandwidth) > limit; + } int GetTerminationTimeout () const { return m_TerminationTimeout; }; void SetTerminationTimeout (int terminationTimeout) { m_TerminationTimeout = terminationTimeout; }; @@ -120,21 +140,44 @@ namespace transport uint32_t GetCreationTime () const { return m_CreationTime; }; void SetCreationTime (uint32_t ts) { m_CreationTime = ts; }; // for introducers + uint64_t GetLastActivityTimestamp () const { return m_LastActivityTimestamp; }; + void SetLastActivityTimestamp (uint64_t ts) { m_LastActivityTimestamp = ts; }; + virtual uint32_t GetRelayTag () const { return 0; }; virtual void SendLocalRouterInfo (bool update = false) { SendI2NPMessages ({ CreateDatabaseStoreMsg () }); }; virtual void SendI2NPMessages (const std::vector >& msgs) = 0; virtual bool IsEstablished () const = 0; + private: + + void UpdateBandwidth () + { + uint64_t interval = m_LastActivityTimestamp - m_LastBandwidthUpdateTimestamp; + if (interval > TRANSPORT_SESSION_BANDWIDTH_UPDATE_MIN_INTERVAL) + { + m_OutBandwidth = (m_NumSentBytes - m_LastBandWidthUpdateNumSentBytes)/interval; + m_LastBandWidthUpdateNumSentBytes = m_NumSentBytes; + m_InBandwidth = (m_NumReceivedBytes - m_LastBandWidthUpdateNumReceivedBytes)/interval; + m_LastBandWidthUpdateNumReceivedBytes = m_NumReceivedBytes; + m_LastBandwidthUpdateTimestamp = m_LastActivityTimestamp; + } + } + protected: std::shared_ptr m_RemoteIdentity; mutable std::mutex m_RemoteIdentityMutex; - size_t m_NumSentBytes, m_NumReceivedBytes, m_SendQueueSize; bool m_IsOutgoing; int m_TerminationTimeout; - uint64_t m_LastActivityTimestamp; uint32_t m_CreationTime; // seconds since epoch int64_t m_HandshakeInterval; // in milliseconds between SessionRequest->SessionCreated or SessionCreated->SessionConfirmed + + private: + + size_t m_SendQueueSize, m_NumSentBytes, m_NumReceivedBytes, + m_LastBandWidthUpdateNumSentBytes, m_LastBandWidthUpdateNumReceivedBytes; + uint64_t m_LastActivityTimestamp, m_LastBandwidthUpdateTimestamp; + uint32_t m_InBandwidth, m_OutBandwidth; }; // SOCKS5 proxy diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 45284e24..53a13410 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -951,7 +951,7 @@ namespace transport // connected, not overloaded and not slow return !peer.router && !peer.sessions.empty () && peer.isReachable && peer.sessions.front ()->GetSendQueueSize () <= PEER_ROUTER_INFO_OVERLOAD_QUEUE_SIZE && - !peer.sessions.front ()->IsSlow () && + !peer.sessions.front ()->IsSlow () && !peer.sessions.front ()->IsBandwidthExceeded (peer.isHighBandwidth) && (!isHighBandwidth || peer.isHighBandwidth); }); } From 0a519d8072423c978a6ea1a788c20976580a5d2c Mon Sep 17 00:00:00 2001 From: Vort Date: Sun, 15 Oct 2023 18:08:15 +0300 Subject: [PATCH 0213/1171] Fix MSVC compilation for std::max --- build/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index abfadfca..6a2aa99b 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -121,7 +121,7 @@ if(WIN32) ) file(GLOB WIN32_RC ${WIN32_SRC_DIR}/*.rc) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWIN32_APP -DWIN32_LEAN_AND_MEAN") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWIN32_APP -DWIN32_LEAN_AND_MEAN -DNOMINMAX") endif() From 04adc14b769da541b07dfddb6a6a0c7b269f15e3 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 16 Oct 2023 18:46:59 -0400 Subject: [PATCH 0214/1171] ls@mail.i2p yggdrasil reseed added --- .../certificates/reseed/ls_at_mail.i2p.crt | 32 +++++++++++++++++++ libi2pd/Config.cpp | 3 +- 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 contrib/certificates/reseed/ls_at_mail.i2p.crt diff --git a/contrib/certificates/reseed/ls_at_mail.i2p.crt b/contrib/certificates/reseed/ls_at_mail.i2p.crt new file mode 100644 index 00000000..8e0902d7 --- /dev/null +++ b/contrib/certificates/reseed/ls_at_mail.i2p.crt @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFdTCCA12gAwIBAgIEQ5vCxzANBgkqhkiG9w0BAQ0FADBrMQswCQYDVQQGEwJY +WDELMAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMR4wHAYDVQQKDBVJMlAgQW5vbnlt +b3VzIE5ldHdvcmsxDDAKBgNVBAsMA0kyUDEUMBIGA1UEAwwLbHNAbWFpbC5pMnAw +HhcNMjMxMDE2MjAwNTA5WhcNMzMxMDEzMjAwNTA5WjBrMQswCQYDVQQGEwJYWDEL +MAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMR4wHAYDVQQKDBVJMlAgQW5vbnltb3Vz +IE5ldHdvcmsxDDAKBgNVBAsMA0kyUDEUMBIGA1UEAwwLbHNAbWFpbC5pMnAwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDPcbKRtf4PzrDa0iRit0XrwnmA +2c1fJhkBipdPor7gMOAlkR82H1lkZSizR7kTZnr7vYqjDrOQr7bl5Dy3qo8/YCbZ +jsnUCTIIgIJQUxUlR40RjaSXphqzUEiXKHR6b0RahhFisQ3hlbbgzSch5YgSLKws +hOLi+eDSXw+HlwHlWFlT1XOKxSTJ/F3Bv40gxqZVC2pbxiPOeRZHQ6Ojw75lxTSF +gww2WzgztiWt4X9BO1yepnVqhAVRPmTfGUMfKzq9jkMzZKeQFV4uZSP9nCqzEpYd +WNDUfpTWiAQ9F+BwFXGusXXA3tGVwS7s6IEoiJFM5fsoJYfRoWGh3/1eirhBXW7U +M6oubMSTADyrvfjLfJBMmMnc2hNblRlKr0ZKUjMfv8cnyT4kQxlXLAHHXY2P89TM +TEVODkU48gnv6tC4t1JCb1/Da+3yVMjNX6rCzQfUwnLFrWthrwiI0NivAKFtiZjq +w1/ZQcYke2YyeqcfXMn+NTUA22Sm2mJoMo7jUf+rbM9Pi27/DncJgRGj5qwY0D3S +gc7829EjuZNPttGBmae1EmO7WQMB32cqdmItnV2FXpMhnn9h0u5H52kYqwn+mdtc +dTJRcbfKG1RTr3UjFISaTwL8qigMIkVXIzcpnr/R/sSeEs8xCqfsJ6rb4dCyFx+M +hqQcOCL5tumyd4W/LQIDAQABoyEwHzAdBgNVHQ4EFgQUgfaOG5HCnlW82wZ5BahL +GRO06igwDQYJKoZIhvcNAQENBQADggIBAKdVpqS9qF7gGotgXaVA1iP5YNsWlTvG +daGqeA/87//U21W6gpq82FhzsmsvUtXZfIeVIlDPI7WNDzS+A3K/KKrwM7dLgSie +r9eMl3D8WYPU95QF4mAlRyl7PCCsYoVjyvfro0iq3/iudIA5476rjfLdTXRi5hAT +qemPj0S+6sRjKEldRtGXrQATFlvLIWVYpgHijdDDx5M2hAz2y0mFxlDZTlA4BhL4 +DwtGlVKmbc2x5MvIQM4UhbQqkxYS4gXnzf5Qx9QIytHfTr/hmbrkhKR1GCO31BSk +x9LhZxdI8LlwKSo6YgwXEB9E0M/tplaK9iZJFv4HPYLZrVJpb4IklMumyLMrgW5P +fR0dgKn+R9lk0emJ1Cu+qyyzf1vsLycYBwaEztINn4VK+/HfDFpnVCvJOyNuDmj5 +KBLIoGdGoVfylmnc+e8zAXe+DY41fgniHMISOO78P8Bx9vTB+rhqnOUr9MzlUxPB +sKGjbXy2YynEqiGb+9g344v/+ukTSDenqTPHVzJ5uOi0iedy+3ASzUNN6GJocovP +167VOhwaETM0FwiKe0VdZRLLbbZ79CtJC0tmgcgPQPRa9Ldr6KN7u1J3D6lUp6zl +byPom10ueKONRb36t7ai79l2SEUZRSMkx6AXIU0JJ1SMtQtav7b5LkpYJfdL7+vO +dDx2/Za0VmdD +-----END CERTIFICATE----- diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index cd78727f..3d3c5c2a 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -230,7 +230,8 @@ namespace config { "http://[301:65b9:c7cd:9a36::1]:18801/," "http://[320:8936:ec1a:31f1::216]/," "http://[306:3834:97b9:a00a::1]/," - "http://[316:f9e0:f22e:a74f::216]/" + "http://[316:f9e0:f22e:a74f::216]/," + "http://[300:e097:2621:79e3::add1]:7170" ), "Reseed URLs through the Yggdrasil, separated by comma") ; From d04b19d77ce03a973f4e83668fa3e79be574bcdb Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 18 Oct 2023 18:09:41 -0400 Subject: [PATCH 0215/1171] don't recalculate badwidth if clock was adjusted too much --- libi2pd/TransportSession.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libi2pd/TransportSession.h b/libi2pd/TransportSession.h index e298fdb2..f4668116 100644 --- a/libi2pd/TransportSession.h +++ b/libi2pd/TransportSession.h @@ -152,8 +152,16 @@ namespace transport void UpdateBandwidth () { - uint64_t interval = m_LastActivityTimestamp - m_LastBandwidthUpdateTimestamp; - if (interval > TRANSPORT_SESSION_BANDWIDTH_UPDATE_MIN_INTERVAL) + int64_t interval = m_LastActivityTimestamp - m_LastBandwidthUpdateTimestamp; + if (interval < 0 || interval > 60*10) // 10 minutes + { + // clock was adjusted, copy new values + m_LastBandWidthUpdateNumSentBytes = m_NumSentBytes; + m_LastBandWidthUpdateNumReceivedBytes = m_NumReceivedBytes; + m_LastBandwidthUpdateTimestamp = m_LastActivityTimestamp; + return; + } + if ((uint64_t)interval > TRANSPORT_SESSION_BANDWIDTH_UPDATE_MIN_INTERVAL) { m_OutBandwidth = (m_NumSentBytes - m_LastBandWidthUpdateNumSentBytes)/interval; m_LastBandWidthUpdateNumSentBytes = m_NumSentBytes; From 0ef9c083264ba00227383b921a2f4459a8afa290 Mon Sep 17 00:00:00 2001 From: Dex Date: Fri, 27 Oct 2023 15:06:24 +1100 Subject: [PATCH 0216/1171] fix manpage typo for ipv4 flag --- debian/i2pd.1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/i2pd.1 b/debian/i2pd.1 index 5145321f..42c282d9 100644 --- a/debian/i2pd.1 +++ b/debian/i2pd.1 @@ -64,7 +64,7 @@ The network interface to bind to for IPv4 connections The network interface to bind to for IPv6 connections .TP \fB\-\-ipv4=\fR -Enable communication through ipv6 (\fIenabled\fR by default) +Enable communication through ipv4 (\fIenabled\fR by default) .TP \fB\-\-ipv6\fR Enable communication through ipv6 (\fIdisabled\fR by default) From e090b9052a15c57ab6bf2aebfbdd43a845bb97f8 Mon Sep 17 00:00:00 2001 From: acetone <63557806+freeacetone@users.noreply.github.com> Date: Sun, 29 Oct 2023 11:57:14 +0300 Subject: [PATCH 0217/1171] Yggdrasil reseed address replaced by address for 4.X+ version --- contrib/i2pd.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/i2pd.conf b/contrib/i2pd.conf index 545973a3..be4a6719 100644 --- a/contrib/i2pd.conf +++ b/contrib/i2pd.conf @@ -225,7 +225,7 @@ verify = true ## Default: "mainline" I2P Network reseeds # urls = https://reseed.i2p-projekt.de/,https://i2p.mooo.com/netDb/,https://netdb.i2p2.no/ ## Reseed URLs through the Yggdrasil, separated by comma -# yggurls = http://[324:9de3:fea4:f6ac::ace]:7070/ +# yggurls = http://[324:71e:281a:9ed3::ace]:7070/ ## Path to local reseed data file (.su3) for manual reseeding # file = /path/to/i2pseeds.su3 ## or HTTPS URL to reseed from From 3286bdb4a771fb1cb8bd33bb03a4d4ff695ac39a Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 29 Oct 2023 22:11:38 -0400 Subject: [PATCH 0218/1171] verify jump link for valid characters --- libi2pd/Base.cpp | 12 ++++++++++- libi2pd/Base.h | 4 +++- libi2pd_client/AddressBook.cpp | 20 +++++++++++++----- libi2pd_client/HTTPProxy.cpp | 37 ++++++++++++++++++++++++++++------ 4 files changed, 60 insertions(+), 13 deletions(-) diff --git a/libi2pd/Base.cpp b/libi2pd/Base.cpp index e979c5b4..02ad5f9f 100644 --- a/libi2pd/Base.cpp +++ b/libi2pd/Base.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -28,6 +28,11 @@ namespace data return T32; } + bool IsBase32 (char ch) + { + return (ch >= 'a' && ch <= 'z') || (ch >= '2' && ch <= '7'); + } + static void iT64Build(void); /* @@ -55,6 +60,11 @@ namespace data return T64; } + bool IsBase64 (char ch) + { + return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || ch == '-' || ch == '~'; + } + /* * Reverse Substitution Table (built in run time) */ diff --git a/libi2pd/Base.h b/libi2pd/Base.h index 79152e02..a163435c 100644 --- a/libi2pd/Base.h +++ b/libi2pd/Base.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -19,9 +19,11 @@ namespace data { size_t Base64ToByteStream (const char * InBuffer, size_t InCount, uint8_t * OutBuffer, size_t len ); const char * GetBase32SubstitutionTable (); const char * GetBase64SubstitutionTable (); + bool IsBase64 (char ch); size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen); size_t ByteStreamToBase32 (const uint8_t * InBuf, size_t len, char * outBuf, size_t outLen); + bool IsBase32 (char ch); /** * Compute the size for a buffer to contain encoded base64 given that the size of the input is input_size bytes diff --git a/libi2pd_client/AddressBook.cpp b/libi2pd_client/AddressBook.cpp index 055311a9..8f2117a7 100644 --- a/libi2pd_client/AddressBook.cpp +++ b/libi2pd_client/AddressBook.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -403,10 +403,20 @@ namespace client if (!addr) return false; - i2p::data::IdentityEx ident; - if (ident.FromBase64 (jump) && ident.GetIdentHash () == addr->identHash) - return true; - + auto pos = jump.find(".b32.i2p"); + if (pos != std::string::npos) + { + i2p::data::IdentHash identHash; + if (identHash.FromBase32(jump.substr (0, pos)) && identHash == addr->identHash) + return true; + } + else + { + i2p::data::IdentityEx ident; + if (ident.FromBase64 (jump) && ident.GetIdentHash () == addr->identHash) + return true; + } + return false; } diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index 26b47d8b..76d37a1e 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -75,8 +75,9 @@ namespace proxy { void HandleSockRecv(const boost::system::error_code & ecode, std::size_t bytes_transfered); void Terminate(); void AsyncSockRead(); - bool ExtractAddressHelper(i2p::http::URL & url, std::string & b64, bool & confirm); - void SanitizeHTTPRequest(i2p::http::HTTPReq & req); + static bool ExtractAddressHelper(i2p::http::URL& url, std::string& jump, bool& confirm); + static bool VerifyAddressHelper (const std::string& jump); + static void SanitizeHTTPRequest(i2p::http::HTTPReq& req); void SentHTTPFailed(const boost::system::error_code & ecode); void HandleStreamRequestComplete (std::shared_ptr stream); /* error helpers */ @@ -221,7 +222,7 @@ namespace proxy { std::bind(&HTTPReqHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1)); } - bool HTTPReqHandler::ExtractAddressHelper(i2p::http::URL & url, std::string & b64, bool & confirm) + bool HTTPReqHandler::ExtractAddressHelper(i2p::http::URL& url, std::string& jump, bool& confirm) { confirm = false; const char *param = "i2paddresshelper="; @@ -237,8 +238,13 @@ namespace proxy { std::string value = params["i2paddresshelper"]; len += value.length(); - b64 = i2p::http::UrlDecode(value); - + jump = i2p::http::UrlDecode(value); + if (!VerifyAddressHelper (jump)) + { + LogPrint (eLogError, "HTTPProxy: Malformed jump link ", jump); + return false; + } + // if we need update exists, request formed with update param if (params["update"] == "true") { @@ -269,7 +275,26 @@ namespace proxy { return true; } - void HTTPReqHandler::SanitizeHTTPRequest(i2p::http::HTTPReq & req) + bool HTTPReqHandler::VerifyAddressHelper (const std::string& jump) + { + auto pos = jump.find(".b32.i2p"); + if (pos != std::string::npos) + { + auto b32 = jump.substr (0, pos); + for (auto& ch: b32) + if (!i2p::data::IsBase32(ch)) return false; + return true; + } + else + { + for (auto& ch: jump) + if (!i2p::data::IsBase64(ch)) return false; + return true; + } + return false; + } + + void HTTPReqHandler::SanitizeHTTPRequest(i2p::http::HTTPReq& req) { /* drop common headers */ req.RemoveHeader("Via"); From e1b4feb618ecd7ab9fc81c462646182224384e8c Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 30 Oct 2023 08:10:17 -0400 Subject: [PATCH 0219/1171] correct base64 check --- libi2pd/Base.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Base.cpp b/libi2pd/Base.cpp index 02ad5f9f..b8de571b 100644 --- a/libi2pd/Base.cpp +++ b/libi2pd/Base.cpp @@ -62,7 +62,7 @@ namespace data bool IsBase64 (char ch) { - return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || ch == '-' || ch == '~'; + return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '-' || ch == '~'; } /* From 69b0bef206c23046e3ace953db5ecf8af35ebff6 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 30 Oct 2023 10:09:47 -0400 Subject: [PATCH 0220/1171] fixed possible invalid pointer when send error response --- libi2pd_client/HTTPProxy.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index 76d37a1e..88de602b 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -109,7 +109,7 @@ namespace proxy { std::shared_ptr m_sock; std::shared_ptr m_proxysock; boost::asio::ip::tcp::resolver m_proxy_resolver; - std::string m_OutproxyUrl; + std::string m_OutproxyUrl, m_Response; bool m_Addresshelper; i2p::http::URL m_ProxyURL; i2p::http::URL m_RequestURL; @@ -206,8 +206,8 @@ namespace proxy { << "" << content << "\r\n" << "\r\n"; res.body = ss.str(); - std::string response = res.to_string(); - boost::asio::async_write(*m_sock, boost::asio::buffer(response), boost::asio::transfer_all(), + m_Response = res.to_string(); + boost::asio::async_write(*m_sock, boost::asio::buffer(m_Response), boost::asio::transfer_all(), std::bind(&HTTPReqHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1)); } @@ -217,8 +217,8 @@ namespace proxy { res.code = 302; res.add_header("Location", address); res.add_header("Connection", "close"); - std::string response = res.to_string(); - boost::asio::async_write(*m_sock, boost::asio::buffer(response), boost::asio::transfer_all(), + m_Response = res.to_string(); + boost::asio::async_write(*m_sock, boost::asio::buffer(m_Response), boost::asio::transfer_all(), std::bind(&HTTPReqHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1)); } From 575268d36093928d48491cf85e007504732bbf2d Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 30 Oct 2023 20:02:48 -0400 Subject: [PATCH 0221/1171] reduce expiration time for low bandwidth and far routers --- libi2pd/NetDb.cpp | 11 +++++++++-- libi2pd/NetDb.hpp | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 02d4dfd8..12817ad1 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -654,13 +654,20 @@ namespace data // find & mark expired routers if (!it.second->GetCompatibleTransports (true)) // non reachable by any transport it.second->SetUnreachable (true); - else if (checkForExpiration && ts > it.second->GetTimestamp () + expirationTimeout) - it.second->SetUnreachable (true); else if (ts + NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < it.second->GetTimestamp ()) { LogPrint (eLogWarning, "NetDb: RouterInfo is from future for ", (it.second->GetTimestamp () - ts)/1000LL, " seconds"); it.second->SetUnreachable (true); } + else if (checkForExpiration) + { + uint64_t t = expirationTimeout; + if (total > NETDB_NUM_ROUTERS_THRESHOLD && !it.second->IsHighBandwidth () && // low bandwidth router + ((it.second->GetIdentHash()[0] & 0xFE) != (i2p::context.GetIdentHash ()[0] & 0xFE))) // different first 7 bits + t >>= 1; // reduce expiration time by 2 times + if (ts > it.second->GetTimestamp () + t) + it.second->SetUnreachable (true); + } if (it.second->IsUnreachable () && i2p::transport::transports.IsConnected (it.second->GetIdentHash ())) it.second->SetUnreachable (false); // don't expire connected router } diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index 44dff3b8..8edc94d6 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -39,6 +39,7 @@ namespace data const int NETDB_MIN_ROUTERS = 90; const int NETDB_MIN_FLOODFILLS = 5; const int NETDB_NUM_FLOODFILLS_THRESHOLD = 1500; + const int NETDB_NUM_ROUTERS_THRESHOLD = 4*NETDB_NUM_FLOODFILLS_THRESHOLD; const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60 * 60; // 1 hour, in seconds const int NETDB_MIN_EXPIRATION_TIMEOUT = 90 * 60; // 1.5 hours const int NETDB_MAX_EXPIRATION_TIMEOUT = 27 * 60 * 60; // 27 hours From a6ee1e648e0724d7798986d1f490c22b80105dd9 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 31 Oct 2023 09:10:56 -0400 Subject: [PATCH 0222/1171] recognize trailing padding as part of base64 address --- libi2pd_client/HTTPProxy.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index 88de602b..a0fc8f07 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -287,8 +287,17 @@ namespace proxy { } else { + bool padding = false; for (auto& ch: jump) - if (!i2p::data::IsBase64(ch)) return false; + { + if (ch == '=') + padding = true; + else + { + if (padding) return false; // other chars after padding + if (!i2p::data::IsBase64(ch)) return false; + } + } return true; } return false; From a3f62e1d7150cd6d1b5195019a8f3a0caf201548 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 31 Oct 2023 13:20:04 -0400 Subject: [PATCH 0223/1171] check actual distance with router to reduce expiration time --- libi2pd/NetDb.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 12817ad1..54b7b7c1 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -661,12 +661,13 @@ namespace data } else if (checkForExpiration) { - uint64_t t = expirationTimeout; - if (total > NETDB_NUM_ROUTERS_THRESHOLD && !it.second->IsHighBandwidth () && // low bandwidth router - ((it.second->GetIdentHash()[0] & 0xFE) != (i2p::context.GetIdentHash ()[0] & 0xFE))) // different first 7 bits - t >>= 1; // reduce expiration time by 2 times - if (ts > it.second->GetTimestamp () + t) + if (ts > it.second->GetTimestamp () + expirationTimeout) it.second->SetUnreachable (true); + else if ((ts > it.second->GetTimestamp () + expirationTimeout/2) && // more than half of expiration + total > NETDB_NUM_ROUTERS_THRESHOLD && !it.second->IsHighBandwidth() && // low bandwidth + !it.second->IsFloodfill() && (!i2p::context.IsFloodfill () || // non floodfill + (CreateRoutingKey (it.second->GetIdentHash ()) ^ i2p::context.GetIdentHash ()).metric[0] >= 0x02)) // different first 7 bits + it.second->SetUnreachable (true); } if (it.second->IsUnreachable () && i2p::transport::transports.IsConnected (it.second->GetIdentHash ())) it.second->SetUnreachable (false); // don't expire connected router From 379be2a29e3d9298cb46e0adba1abc27f36732c1 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Tue, 31 Oct 2023 22:33:12 +0300 Subject: [PATCH 0224/1171] [gha] Update FreeBSD build action --- .github/workflows/build-freebsd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-freebsd.yml b/.github/workflows/build-freebsd.yml index 76b496ad..b4decc49 100644 --- a/.github/workflows/build-freebsd.yml +++ b/.github/workflows/build-freebsd.yml @@ -13,7 +13,7 @@ jobs: - name: Test in FreeBSD id: test - uses: vmactions/freebsd-vm@v0.3.0 + uses: vmactions/freebsd-vm@v0.3.1 with: usesh: true mem: 2048 From 0021501d750250ad0da604cc4593b5a28b442b05 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Tue, 31 Oct 2023 22:39:51 +0300 Subject: [PATCH 0225/1171] [gha] disable FreeBSD build Additional info: https://github.com/vmactions/freebsd-vm/issues/74 --- .../workflows/{build-freebsd.yml => build-freebsd.yml-disabled} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{build-freebsd.yml => build-freebsd.yml-disabled} (100%) diff --git a/.github/workflows/build-freebsd.yml b/.github/workflows/build-freebsd.yml-disabled similarity index 100% rename from .github/workflows/build-freebsd.yml rename to .github/workflows/build-freebsd.yml-disabled From 083034fa35bfdc4924294e57c08313a739cc02f4 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 9 Nov 2023 21:56:32 -0500 Subject: [PATCH 0226/1171] send peer tests with random delays --- libi2pd/Transports.cpp | 44 +++++++++++++++++++++++++++++++++++++++--- libi2pd/Transports.h | 2 ++ 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 53a13410..b6e2e261 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -645,14 +645,33 @@ namespace transport LogPrint (eLogInfo, "Transports: Started peer test IPv4"); std::set excluded; excluded.insert (i2p::context.GetIdentHash ()); // don't pick own router + int testDelay = 0; for (int i = 0; i < 5; i++) { auto router = i2p::data::netdb.GetRandomSSU2PeerTestRouter (true, excluded); // v4 if (router) { if (!i2p::context.GetTesting ()) + { i2p::context.SetTesting (true); - m_SSU2Server->StartPeerTest (router, true); + // send first peer test immediately + m_SSU2Server->StartPeerTest (router, true); + } + else + { + testDelay += PEER_TEST_DELAY_INTERVAL + rand() % PEER_TEST_DELAY_INTERVAL_VARIANCE; + if (m_Service) + { + auto delayTimer = std::make_shared(*m_Service); + delayTimer->expires_from_now (boost::posix_time::milliseconds (testDelay)); + delayTimer->async_wait ( + [this, router, delayTimer](const boost::system::error_code& ecode) + { + if (ecode != boost::asio::error::operation_aborted) + m_SSU2Server->StartPeerTest (router, true); + }); + } + } excluded.insert (router->GetIdentHash ()); } } @@ -664,14 +683,33 @@ namespace transport LogPrint (eLogInfo, "Transports: Started peer test IPv6"); std::set excluded; excluded.insert (i2p::context.GetIdentHash ()); // don't pick own router + int testDelay = 0; for (int i = 0; i < 5; i++) { auto router = i2p::data::netdb.GetRandomSSU2PeerTestRouter (false, excluded); // v6 if (router) { if (!i2p::context.GetTestingV6 ()) - i2p::context.SetTestingV6 (true); - m_SSU2Server->StartPeerTest (router, false); + { + i2p::context.SetTestingV6 (true); + // send first peer test immediately + m_SSU2Server->StartPeerTest (router, false); + } + else + { + testDelay += PEER_TEST_DELAY_INTERVAL + rand() % PEER_TEST_DELAY_INTERVAL_VARIANCE; + if (m_Service) + { + auto delayTimer = std::make_shared(*m_Service); + delayTimer->expires_from_now (boost::posix_time::milliseconds (testDelay)); + delayTimer->async_wait ( + [this, router, delayTimer](const boost::system::error_code& ecode) + { + if (ecode != boost::asio::error::operation_aborted) + m_SSU2Server->StartPeerTest (router, false); + }); + } + } excluded.insert (router->GetIdentHash ()); } } diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index a8f2a16a..cb63ca91 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -105,6 +105,8 @@ namespace transport const uint64_t SESSION_CREATION_TIMEOUT = 15; // in seconds const int PEER_TEST_INTERVAL = 71; // in minutes + const int PEER_TEST_DELAY_INTERVAL = 20; // in milliseconds + const int PEER_TEST_DELAY_INTERVAL_VARIANCE = 30; // in milliseconds const int MAX_NUM_DELAYED_MESSAGES = 150; const int CHECK_PROFILE_NUM_DELAYED_MESSAGES = 15; // check profile after class Transports From 6b33250c599f138d8834fb00bfe9f936bc9d8894 Mon Sep 17 00:00:00 2001 From: Fabrice Fontaine Date: Sat, 4 Nov 2023 12:24:33 +0100 Subject: [PATCH 0227/1171] build/CMakeLists.txt: enable C language MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Detection of libatomic is broken since version 2.47.0 and https://github.com/PurpleI2P/i2pd/commit/b7f0d87dafa8957131b496c38fbe65d8cb378a9d because C language is not enabled anymore: -- Looking for __atomic_fetch_add_4 in atomic -- Looking for __atomic_fetch_add_4 in atomic - not found CMake Error at cmake_modules/CheckAtomic.cmake:59 (message): Host compiler appears to require libatomic, but cannot find it. Call Stack (most recent call first): CMakeLists.txt:54 (include) Indeed if C language is not enabled, the test will be run with the C++ compiler resulting in the following error: Building CXX object CMakeFiles/cmTC_03d01.dir/CheckFunctionExists.cxx.o /home/fabrice/buildroot/output/host/bin/x86_64-linux-g++ --sysroot=/home/fabrice/buildroot/output/host/x86_64-buildroot-linux-gnu/sysroot -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -O1 -g0 -D_FORTIFY_SOURCE=2 -DCHECK_FUNCTION_EXISTS=__atomic_fetch_add_4 -DNDEBUG -o CMakeFiles/cmTC_03d01.dir/CheckFunctionExists.cxx.o -c /home/fabrice/buildroot/output/build/i2pd-2.49.0/build/CMakeFiles/CMakeScratch/TryCompile-NApnv9/CheckFunctionExists.cxx : error: new declaration ‘char __atomic_fetch_add_4()’ ambiguates built-in declaration ‘unsigned int __atomic_fetch_add_4(volatile void*, unsigned int, int)’ [-fpermissive] whereas with a C compiler, we'll get: Building C object CMakeFiles/cmTC_7e47b.dir/CheckFunctionExists.c.o /home/fabrice/buildroot/output/host/bin/x86_64-linux-gcc --sysroot=/home/fabrice/buildroot/output/host/x86_64-buildroot-linux-gnu/sysroot -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -O1 -g0 -D_FORTIFY_SOURCE=2 -DCHECK_FUNCTION_EXISTS=__atomic_fetch_add_4 -DNDEBUG -o CMakeFiles/cmTC_7e47b.dir/CheckFunctionExists.c.o -c /home/fabrice/buildroot/output/build/i2pd-2.49.0/build/CMakeFiles/CMakeScratch/TryCompile-e0zFMG/CheckFunctionExists.c : warning: conflicting types for built-in function ‘__atomic_fetch_add_4’; expected ‘unsigned int(volatile void *, unsigned int, int)’ [-Wbuiltin-declaration-mismatch] Fix #1908 Signed-off-by: Fabrice Fontaine --- build/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 6a2aa99b..232e427f 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -25,7 +25,7 @@ project( i2pd VERSION ${PROJECT_VERSION} HOMEPAGE_URL "https://i2pd.website/" - LANGUAGES CXX + LANGUAGES C CXX ) # configurable options From 1a02819187ea306d64e6090d7a3536bacfc76982 Mon Sep 17 00:00:00 2001 From: Dimitris Apostolou Date: Fri, 21 Jul 2023 21:43:40 +0300 Subject: [PATCH 0228/1171] Remove deprecated bind_at_load from macOS --- Makefile.osx | 1 - 1 file changed, 1 deletion(-) diff --git a/Makefile.osx b/Makefile.osx index e069aaff..467c9fdd 100644 --- a/Makefile.osx +++ b/Makefile.osx @@ -5,7 +5,6 @@ DEFINES := -DMAC_OSX LDFLAGS := -Wl,-rpath,/usr/local/lib -L/usr/local/lib LDFLAGS += -Wl,-dead_strip LDFLAGS += -Wl,-dead_strip_dylibs -LDFLAGS += -Wl,-bind_at_load ifeq ($(USE_STATIC),yes) LDLIBS = -lz /usr/local/lib/libcrypto.a /usr/local/lib/libssl.a /usr/local/lib/libboost_system.a /usr/local/lib/libboost_date_time.a /usr/local/lib/libboost_filesystem.a /usr/local/lib/libboost_program_options.a -lpthread From 9632e7ba03533533ff056ad89546bdc3441269b4 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 12 Nov 2023 18:32:57 -0500 Subject: [PATCH 0229/1171] exclude NAT64 ipv6 addresses --- libi2pd/util.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libi2pd/util.cpp b/libi2pd/util.cpp index a7afdce8..d1ed9992 100644 --- a/libi2pd/util.cpp +++ b/libi2pd/util.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -665,6 +665,7 @@ namespace net if (host.is_v6()) { static const std::vector< std::pair > reservedIPv6Ranges { + address_pair_v6("64:ff9b::", "64:ff9b:ffff:ffff:ffff:ffff:ffff:ffff"), // NAT64 address_pair_v6("2001:db8::", "2001:db8:ffff:ffff:ffff:ffff:ffff:ffff"), address_pair_v6("fc00::", "fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"), address_pair_v6("fe80::", "febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff"), From 8d6eb5b6b2c8f69627cefaa5b6eb4f1010c11631 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 13 Nov 2023 19:12:07 -0500 Subject: [PATCH 0230/1171] don't lock mutex in AsyncSend --- libi2pd/Streaming.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index c2cf3a0a..a7f932f5 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -532,14 +532,18 @@ namespace stream void Stream::AsyncSend (const uint8_t * buf, size_t len, SendHandler handler) { + std::shared_ptr buffer; if (len > 0 && buf) - { - std::unique_lock l(m_SendBufferMutex); - m_SendBuffer.Add (buf, len, handler); - } + buffer = std::make_shared(buf, len, handler); else if (handler) handler(boost::system::error_code ()); - m_Service.post (std::bind (&Stream::SendBuffer, shared_from_this ())); + auto s = shared_from_this (); + m_Service.post ([s, buffer]() + { + if (buffer) + s->m_SendBuffer.Add (buffer); + s->SendBuffer (); + }); } void Stream::SendBuffer () From 21259204b1f55e1014d088d5d7a2b1cf11048ea6 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 14 Nov 2023 09:39:36 -0500 Subject: [PATCH 0231/1171] eliminate send buffer mutex completely --- libi2pd/Streaming.cpp | 171 ++++++++++++++++++++---------------------- libi2pd/Streaming.h | 2 - 2 files changed, 80 insertions(+), 93 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index a7f932f5..629039ab 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -19,11 +19,6 @@ namespace i2p { namespace stream { - void SendBufferQueue::Add (const uint8_t * buf, size_t len, SendHandler handler) - { - Add (std::make_shared(buf, len, handler)); - } - void SendBufferQueue::Add (std::shared_ptr buf) { if (buf) @@ -115,10 +110,7 @@ namespace stream void Stream::CleanUp () { - { - std::unique_lock l(m_SendBufferMutex); - m_SendBuffer.CleanUp (); - } + m_SendBuffer.CleanUp (); while (!m_ReceiveQueue.empty ()) { auto packet = m_ReceiveQueue.front (); @@ -553,91 +545,88 @@ namespace stream bool isNoAck = m_LastReceivedSequenceNumber < 0; // first packet std::vector packets; + while ((m_Status == eStreamStatusNew) || (IsEstablished () && !m_SendBuffer.IsEmpty () && numMsgs > 0)) { - std::unique_lock l(m_SendBufferMutex); - while ((m_Status == eStreamStatusNew) || (IsEstablished () && !m_SendBuffer.IsEmpty () && numMsgs > 0)) + Packet * p = m_LocalDestination.NewPacket (); + uint8_t * packet = p->GetBuffer (); + // TODO: implement setters + size_t size = 0; + htobe32buf (packet + size, m_SendStreamID); + size += 4; // sendStreamID + htobe32buf (packet + size, m_RecvStreamID); + size += 4; // receiveStreamID + htobe32buf (packet + size, m_SequenceNumber++); + size += 4; // sequenceNum + if (isNoAck) + htobuf32 (packet + size, 0); + else + htobe32buf (packet + size, m_LastReceivedSequenceNumber); + size += 4; // ack Through + if (m_Status == eStreamStatusNew && !m_SendStreamID && m_RemoteIdentity) { - Packet * p = m_LocalDestination.NewPacket (); - uint8_t * packet = p->GetBuffer (); - // TODO: implement setters - size_t size = 0; - htobe32buf (packet + size, m_SendStreamID); - size += 4; // sendStreamID - htobe32buf (packet + size, m_RecvStreamID); - size += 4; // receiveStreamID - htobe32buf (packet + size, m_SequenceNumber++); - size += 4; // sequenceNum - if (isNoAck) - htobuf32 (packet + size, 0); - else - htobe32buf (packet + size, m_LastReceivedSequenceNumber); - size += 4; // ack Through - if (m_Status == eStreamStatusNew && !m_SendStreamID && m_RemoteIdentity) - { - // first SYN packet - packet[size] = 8; - size++; // NACK count - memcpy (packet + size, m_RemoteIdentity->GetIdentHash (), 32); - size += 32; - } - else - { - packet[size] = 0; - size++; // NACK count - } - packet[size] = m_RTO/1000; - size++; // resend delay - if (m_Status == eStreamStatusNew) - { - // initial packet - m_Status = eStreamStatusOpen; - if (!m_RemoteLeaseSet) m_RemoteLeaseSet = m_LocalDestination.GetOwner ()->FindLeaseSet (m_RemoteIdentity->GetIdentHash ());; - if (m_RemoteLeaseSet) - { - m_RoutingSession = m_LocalDestination.GetOwner ()->GetRoutingSession (m_RemoteLeaseSet, true); - m_MTU = m_RoutingSession->IsRatchets () ? STREAMING_MTU_RATCHETS : STREAMING_MTU; - } - uint16_t flags = PACKET_FLAG_SYNCHRONIZE | PACKET_FLAG_FROM_INCLUDED | - PACKET_FLAG_SIGNATURE_INCLUDED | PACKET_FLAG_MAX_PACKET_SIZE_INCLUDED; - if (isNoAck) flags |= PACKET_FLAG_NO_ACK; - bool isOfflineSignature = m_LocalDestination.GetOwner ()->GetPrivateKeys ().IsOfflineSignature (); - if (isOfflineSignature) flags |= PACKET_FLAG_OFFLINE_SIGNATURE; - htobe16buf (packet + size, flags); - size += 2; // flags - size_t identityLen = m_LocalDestination.GetOwner ()->GetIdentity ()->GetFullLen (); - size_t signatureLen = m_LocalDestination.GetOwner ()->GetPrivateKeys ().GetSignatureLen (); - uint8_t * optionsSize = packet + size; // set options size later - size += 2; // options size - m_LocalDestination.GetOwner ()->GetIdentity ()->ToBuffer (packet + size, identityLen); - size += identityLen; // from - htobe16buf (packet + size, m_MTU); - size += 2; // max packet size - if (isOfflineSignature) - { - const auto& offlineSignature = m_LocalDestination.GetOwner ()->GetPrivateKeys ().GetOfflineSignature (); - memcpy (packet + size, offlineSignature.data (), offlineSignature.size ()); - size += offlineSignature.size (); // offline signature - } - uint8_t * signature = packet + size; // set it later - memset (signature, 0, signatureLen); // zeroes for now - size += signatureLen; // signature - htobe16buf (optionsSize, packet + size - 2 - optionsSize); // actual options size - size += m_SendBuffer.Get (packet + size, m_MTU); // payload - m_LocalDestination.GetOwner ()->Sign (packet, size, signature); - } - else - { - // follow on packet - htobuf16 (packet + size, 0); - size += 2; // flags - htobuf16 (packet + size, 0); // no options - size += 2; // options size - size += m_SendBuffer.Get(packet + size, m_MTU); // payload - } - p->len = size; - packets.push_back (p); - numMsgs--; + // first SYN packet + packet[size] = 8; + size++; // NACK count + memcpy (packet + size, m_RemoteIdentity->GetIdentHash (), 32); + size += 32; } + else + { + packet[size] = 0; + size++; // NACK count + } + packet[size] = m_RTO/1000; + size++; // resend delay + if (m_Status == eStreamStatusNew) + { + // initial packet + m_Status = eStreamStatusOpen; + if (!m_RemoteLeaseSet) m_RemoteLeaseSet = m_LocalDestination.GetOwner ()->FindLeaseSet (m_RemoteIdentity->GetIdentHash ());; + if (m_RemoteLeaseSet) + { + m_RoutingSession = m_LocalDestination.GetOwner ()->GetRoutingSession (m_RemoteLeaseSet, true); + m_MTU = m_RoutingSession->IsRatchets () ? STREAMING_MTU_RATCHETS : STREAMING_MTU; + } + uint16_t flags = PACKET_FLAG_SYNCHRONIZE | PACKET_FLAG_FROM_INCLUDED | + PACKET_FLAG_SIGNATURE_INCLUDED | PACKET_FLAG_MAX_PACKET_SIZE_INCLUDED; + if (isNoAck) flags |= PACKET_FLAG_NO_ACK; + bool isOfflineSignature = m_LocalDestination.GetOwner ()->GetPrivateKeys ().IsOfflineSignature (); + if (isOfflineSignature) flags |= PACKET_FLAG_OFFLINE_SIGNATURE; + htobe16buf (packet + size, flags); + size += 2; // flags + size_t identityLen = m_LocalDestination.GetOwner ()->GetIdentity ()->GetFullLen (); + size_t signatureLen = m_LocalDestination.GetOwner ()->GetPrivateKeys ().GetSignatureLen (); + uint8_t * optionsSize = packet + size; // set options size later + size += 2; // options size + m_LocalDestination.GetOwner ()->GetIdentity ()->ToBuffer (packet + size, identityLen); + size += identityLen; // from + htobe16buf (packet + size, m_MTU); + size += 2; // max packet size + if (isOfflineSignature) + { + const auto& offlineSignature = m_LocalDestination.GetOwner ()->GetPrivateKeys ().GetOfflineSignature (); + memcpy (packet + size, offlineSignature.data (), offlineSignature.size ()); + size += offlineSignature.size (); // offline signature + } + uint8_t * signature = packet + size; // set it later + memset (signature, 0, signatureLen); // zeroes for now + size += signatureLen; // signature + htobe16buf (optionsSize, packet + size - 2 - optionsSize); // actual options size + size += m_SendBuffer.Get (packet + size, m_MTU); // payload + m_LocalDestination.GetOwner ()->Sign (packet, size, signature); + } + else + { + // follow on packet + htobuf16 (packet + size, 0); + size += 2; // flags + htobuf16 (packet + size, 0); // no options + size += 2; // options size + size += m_SendBuffer.Get(packet + size, m_MTU); // payload + } + p->len = size; + packets.push_back (p); + numMsgs--; } if (packets.size () > 0) { diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 3609df92..1db59118 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -135,7 +135,6 @@ namespace stream SendBufferQueue (): m_Size (0) {}; ~SendBufferQueue () { CleanUp (); }; - void Add (const uint8_t * buf, size_t len, SendHandler handler); void Add (std::shared_ptr buf); size_t Get (uint8_t * buf, size_t len); size_t GetSize () const { return m_Size; }; @@ -251,7 +250,6 @@ namespace stream size_t m_NumSentBytes, m_NumReceivedBytes; uint16_t m_Port; - std::mutex m_SendBufferMutex; SendBufferQueue m_SendBuffer; int m_WindowSize, m_RTT, m_RTO, m_AckDelay; uint64_t m_LastWindowSizeIncreaseTime; From 94255ebaf40236f224bcd45be89c18d0747ce591 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 17 Nov 2023 13:44:30 -0500 Subject: [PATCH 0232/1171] STREAM ACCEPT queue --- libi2pd_client/SAM.cpp | 29 +++++++++++++++++------------ libi2pd_client/SAM.h | 5 ++++- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 1a281c57..54da4654 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -601,10 +601,15 @@ namespace client SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); session->GetLocalDestination ()->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, shared_from_this (), std::placeholders::_1)); } - else // already accepting + else if (session->acceptQueue.size () < SAM_SESSION_MAX_ACCEPT_QUEUE_SIZE) + { + // already accepting, queue up + SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); + session->acceptQueue.push_back (shared_from_this()); + } + else { - // TODO: implement queue - LogPrint (eLogInfo, "SAM: Session ", m_ID, " is already accepting"); + LogPrint (eLogInfo, "SAM: Session ", m_ID, " accept queue is full ", session->acceptQueue.size ()); SendStreamI2PError ("Already accepting"); } } @@ -1057,16 +1062,16 @@ namespace client m_Stream = stream; context.GetAddressBook ().InsertFullAddress (stream->GetRemoteIdentity ()); auto session = m_Owner.FindSession (m_ID); - if (session) + if (session && !session->acceptQueue.empty ()) { - // find more pending acceptors - for (auto & it: m_Owner.ListSockets (m_ID)) - if (it->m_SocketType == eSAMSocketTypeAcceptor) - { - it->m_IsAccepting = true; - session->GetLocalDestination ()->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, it, std::placeholders::_1)); - break; - } + // pending acceptors + auto socket = session->acceptQueue.front (); + session->acceptQueue.pop_front (); + if (socket && socket->GetSocketType () == eSAMSocketTypeAcceptor) + { + socket->m_IsAccepting = true; + session->GetLocalDestination ()->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, socket, std::placeholders::_1)); + } } if (!m_IsSilent) { diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index 736c0945..2841afb9 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -31,6 +31,8 @@ namespace client const size_t SAM_SOCKET_BUFFER_SIZE = 8192; const int SAM_SOCKET_CONNECTION_MAX_IDLE = 3600; // in seconds const int SAM_SESSION_READINESS_CHECK_INTERVAL = 3; // in seconds + const size_t SAM_SESSION_MAX_ACCEPT_QUEUE_SIZE = 64; + const char SAM_HANDSHAKE[] = "HELLO VERSION"; const char SAM_HANDSHAKE_REPLY[] = "HELLO REPLY RESULT=OK VERSION=%s\n"; const char SAM_HANDSHAKE_NOVERSION[] = "HELLO REPLY RESULT=NOVERSION\n"; @@ -189,7 +191,8 @@ namespace client std::string Name; SAMSessionType Type; std::shared_ptr UDPEndpoint; // TODO: move - + std::list > acceptQueue; + SAMSession (SAMBridge & parent, const std::string & name, SAMSessionType type); virtual ~SAMSession () {}; From d327533b56d5a7f88d9d5004670fa5274d333dfc Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 17 Nov 2023 18:50:52 -0500 Subject: [PATCH 0233/1171] close unclaimed acceptors after 3 seconds --- libi2pd_client/SAM.cpp | 52 ++++++++++++++++++++++++++++++------------ libi2pd_client/SAM.h | 5 ++-- 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 54da4654..ffdeb5ac 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -601,16 +601,27 @@ namespace client SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); session->GetLocalDestination ()->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, shared_from_this (), std::placeholders::_1)); } - else if (session->acceptQueue.size () < SAM_SESSION_MAX_ACCEPT_QUEUE_SIZE) - { - // already accepting, queue up - SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); - session->acceptQueue.push_back (shared_from_this()); - } - else + else { - LogPrint (eLogInfo, "SAM: Session ", m_ID, " accept queue is full ", session->acceptQueue.size ()); - SendStreamI2PError ("Already accepting"); + auto ts = i2p::util::GetSecondsSinceEpoch (); + while (!session->acceptQueue.empty () && session->acceptQueue.front ().second + SAM_SESSION_MAX_ACCEPT_INTERVAL > ts) + { + auto socket = session->acceptQueue.front ().first; + session->acceptQueue.pop_front (); + if (socket) + m_Owner.GetService ().post (std::bind(&SAMSocket::TerminateClose, socket)); + } + if (session->acceptQueue.size () < SAM_SESSION_MAX_ACCEPT_QUEUE_SIZE) + { + // already accepting, queue up + SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); + session->acceptQueue.push_back (std::make_pair(shared_from_this(), ts)); + } + else + { + LogPrint (eLogInfo, "SAM: Session ", m_ID, " accept queue is full ", session->acceptQueue.size ()); + SendStreamI2PError ("Already accepting"); + } } } else @@ -1065,12 +1076,23 @@ namespace client if (session && !session->acceptQueue.empty ()) { // pending acceptors - auto socket = session->acceptQueue.front (); - session->acceptQueue.pop_front (); - if (socket && socket->GetSocketType () == eSAMSocketTypeAcceptor) - { - socket->m_IsAccepting = true; - session->GetLocalDestination ()->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, socket, std::placeholders::_1)); + auto ts = i2p::util::GetSecondsSinceEpoch (); + while (!session->acceptQueue.empty () && session->acceptQueue.front ().second + SAM_SESSION_MAX_ACCEPT_INTERVAL > ts) + { + auto socket = session->acceptQueue.front ().first; + session->acceptQueue.pop_front (); + if (socket) + m_Owner.GetService ().post (std::bind(&SAMSocket::TerminateClose, socket)); + } + if (!session->acceptQueue.empty ()) + { + auto socket = session->acceptQueue.front ().first; + session->acceptQueue.pop_front (); + if (socket && socket->GetSocketType () == eSAMSocketTypeAcceptor) + { + socket->m_IsAccepting = true; + session->GetLocalDestination ()->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, socket, std::placeholders::_1)); + } } } if (!m_IsSilent) diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index 2841afb9..34af5a62 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -31,7 +31,8 @@ namespace client const size_t SAM_SOCKET_BUFFER_SIZE = 8192; const int SAM_SOCKET_CONNECTION_MAX_IDLE = 3600; // in seconds const int SAM_SESSION_READINESS_CHECK_INTERVAL = 3; // in seconds - const size_t SAM_SESSION_MAX_ACCEPT_QUEUE_SIZE = 64; + const size_t SAM_SESSION_MAX_ACCEPT_QUEUE_SIZE = 50; + const size_t SAM_SESSION_MAX_ACCEPT_INTERVAL = 3; // in seconds const char SAM_HANDSHAKE[] = "HELLO VERSION"; const char SAM_HANDSHAKE_REPLY[] = "HELLO REPLY RESULT=OK VERSION=%s\n"; @@ -191,7 +192,7 @@ namespace client std::string Name; SAMSessionType Type; std::shared_ptr UDPEndpoint; // TODO: move - std::list > acceptQueue; + std::list, uint64_t> > acceptQueue; // socket, receive time in seconds SAMSession (SAMBridge & parent, const std::string & name, SAMSessionType type); virtual ~SAMSession () {}; From c215f2e8d19f07b95163fdfecd974fa5eec2dce1 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 23 Nov 2023 13:06:50 -0500 Subject: [PATCH 0234/1171] check router for null pointer --- libi2pd/NetDb.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 54b7b7c1..07f0f341 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -628,7 +628,7 @@ namespace data auto own = i2p::context.GetSharedRouterInfo (); for (auto& it: m_RouterInfos) { - if (it.second == own) continue; // skip own + if (!it.second || it.second == own) continue; // skip own std::string ident = it.second->GetIdentHashBase64(); if (it.second->IsUpdated ()) { @@ -698,7 +698,7 @@ namespace data std::unique_lock l(m_RouterInfosMutex); for (auto it = m_RouterInfos.begin (); it != m_RouterInfos.end ();) { - if (it->second->IsUnreachable ()) + if (!it->second || it->second->IsUnreachable ()) it = m_RouterInfos.erase (it); else { From c802c2deb0eac4e8b012939f0da6128d40bf6b8c Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 5 Dec 2023 15:48:26 -0500 Subject: [PATCH 0235/1171] update yggdrasil ressed address --- libi2pd/Config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 3d3c5c2a..4deb59ac 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -231,7 +231,7 @@ namespace config { "http://[320:8936:ec1a:31f1::216]/," "http://[306:3834:97b9:a00a::1]/," "http://[316:f9e0:f22e:a74f::216]/," - "http://[300:e097:2621:79e3::add1]:7170" + "http://[300:eaff:7fab:181b::e621]:7170" ), "Reseed URLs through the Yggdrasil, separated by comma") ; From 9b82265cd87e8bd4b329733713b50c6c7f85b6ba Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 17 Dec 2023 11:07:10 -0500 Subject: [PATCH 0236/1171] 2.50.0 --- ChangeLog | 15 +++++++++++++++ contrib/rpm/i2pd-git.spec | 5 ++++- contrib/rpm/i2pd.spec | 5 ++++- debian/changelog | 6 ++++++ libi2pd/version.h | 4 ++-- 5 files changed, 31 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4dd49a24..1e5156f9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,21 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog +## [2.50.0] - 2023-12-18 +### Added +- Support of concurrent ACCEPTs on SAM 3.1 +- Haiku OS support +- Low bandwidth and far routers can expire before 1 hour +### Changed +- Don't pick too active peer for first hop +- Try peer test again if status is Unknown +- Send peer tests with random delay +- Reseeds list +### Fixed +- XSS vulnerability in addresshelper +- Publishing NAT64 ipv6 addresses +- Deadlock in AsyncSend callback + ## [2.49.0] - 2023-09-18 ### Added - Handle SOCK5 authorization with empty user/password diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index c745e05f..f0344a34 100644 --- a/contrib/rpm/i2pd-git.spec +++ b/contrib/rpm/i2pd-git.spec @@ -1,7 +1,7 @@ %define git_hash %(git rev-parse HEAD | cut -c -7) Name: i2pd-git -Version: 2.49.0 +Version: 2.50.0 Release: git%{git_hash}%{?dist} Summary: I2P router written in C++ Conflicts: i2pd @@ -144,6 +144,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Mon Dec 18 2023 orignal - 2.50.0 +- update to 2.50.0 + * Mon Sep 18 2023 orignal - 2.49.0 - update to 2.49.0 diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 56a7f6e1..9b662f6e 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,5 +1,5 @@ Name: i2pd -Version: 2.49.0 +Version: 2.50.0 Release: 1%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git @@ -142,6 +142,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Mon Dec 18 2023 orignal - 2.50.0 +- update to 2.50.0 + * Mon Sep 18 2023 orignal - 2.49.0 - update to 2.49.0 diff --git a/debian/changelog b/debian/changelog index 4c8ed6bb..55566573 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i2pd (2.50.0-1) unstable; urgency=medium + + * updated to version 2.50.0/0.9.61 + + -- orignal Mon, 18 Dec 2023 16:00:00 +0000 + i2pd (2.49.0-1) unstable; urgency=medium * updated to version 2.49.0/0.9.60 diff --git a/libi2pd/version.h b/libi2pd/version.h index 9854995e..03d6b963 100644 --- a/libi2pd/version.h +++ b/libi2pd/version.h @@ -18,7 +18,7 @@ #define MAKE_VERSION_NUMBER(a,b,c) ((a*100+b)*100+c) #define I2PD_VERSION_MAJOR 2 -#define I2PD_VERSION_MINOR 49 +#define I2PD_VERSION_MINOR 50 #define I2PD_VERSION_MICRO 0 #define I2PD_VERSION_PATCH 0 #ifdef GITVER @@ -33,7 +33,7 @@ #define I2P_VERSION_MAJOR 0 #define I2P_VERSION_MINOR 9 -#define I2P_VERSION_MICRO 60 +#define I2P_VERSION_MICRO 61 #define I2P_VERSION_PATCH 0 #define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO) #define I2P_VERSION_NUMBER MAKE_VERSION_NUMBER(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO) From c2d71331749ac3500d20d19038c29d7d8d4d2eed Mon Sep 17 00:00:00 2001 From: r4sas Date: Sun, 17 Dec 2023 19:30:55 +0000 Subject: [PATCH 0237/1171] [make] fix windows msys2 build Signed-off-by: r4sas --- Makefile | 2 +- Makefile.mingw | 26 ++++++++++++-------------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index 86ea0aa8..3998beb0 100644 --- a/Makefile +++ b/Makefile @@ -121,7 +121,7 @@ obj/%.o: %.cpp | mk_obj_dir -include $(DEPS) $(I2PD): $(DAEMON_OBJS) $(ARLIB) $(ARLIB_CLIENT) $(ARLIB_LANG) - $(CXX) -o $@ $(DEFINES) $(LDFLAGS) $^ $(LDLIBS) + $(CXX) $(DEFINES) $(LDFLAGS) -o $@ $^ $(LDLIBS) $(SHLIB): $(LIB_OBJS) ifneq ($(USE_STATIC),yes) diff --git a/Makefile.mingw b/Makefile.mingw index 6cd19080..157f49c1 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -5,14 +5,11 @@ WINDRES = windres CXXFLAGS := $(CXX_DEBUG) -fPIC -msse INCFLAGS := -I$(DAEMON_SRC_DIR) -IWin32 -LDFLAGS := ${LD_DEBUG} -static +LDFLAGS := ${LD_DEBUG} -static -fPIC -msse NEEDED_CXXFLAGS += -std=c++17 DEFINES += -DWIN32_LEAN_AND_MEAN -# Boost libraries suffix -BOOST_SUFFIX = -mt - # UPNP Support ifeq ($(USE_UPNP),yes) DEFINES += -DUSE_UPNP -DMINIUPNP_STATICLIB @@ -20,20 +17,20 @@ ifeq ($(USE_UPNP),yes) endif LDLIBS += \ - -lboost_system$(BOOST_SUFFIX) \ - -lboost_date_time$(BOOST_SUFFIX) \ - -lboost_filesystem$(BOOST_SUFFIX) \ - -lboost_program_options$(BOOST_SUFFIX) \ - -lssl \ - -lcrypto \ - -lz \ + $(MINGW_PREFIX)/lib/libboost_system-mt.a \ + $(MINGW_PREFIX)/lib/libboost_date_time-mt.a \ + $(MINGW_PREFIX)/lib/libboost_filesystem-mt.a \ + $(MINGW_PREFIX)/lib/libboost_program_options-mt.a \ + $(MINGW_PREFIX)/lib/libssl.a \ + $(MINGW_PREFIX)/lib/libcrypto.a \ + $(MINGW_PREFIX)/lib/libz.a \ -lwsock32 \ -lws2_32 \ - -lgdi32 \ -liphlpapi \ + -lcrypt32 \ + -lgdi32 \ -lole32 \ - -luuid \ - -lpthread + -luuid ifeq ($(USE_WIN32_APP), yes) DEFINES += -DWIN32_APP @@ -48,6 +45,7 @@ endif ifeq ($(USE_AESNI),yes) NEEDED_CXXFLAGS += -maes + LDFLAGS += -maes DEFINES += -D__AES__ endif From 53c6b10177b85f510dd0e67a9d6dbb5ccaa0bbcf Mon Sep 17 00:00:00 2001 From: r4sas Date: Sun, 17 Dec 2023 19:41:28 +0000 Subject: [PATCH 0238/1171] [make] get the mistakenly deleted pthread back Signed-off-by: r4sas --- Makefile.mingw | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile.mingw b/Makefile.mingw index 157f49c1..38da225a 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -30,7 +30,8 @@ LDLIBS += \ -lcrypt32 \ -lgdi32 \ -lole32 \ - -luuid + -luuid \ + -lpthread ifeq ($(USE_WIN32_APP), yes) DEFINES += -DWIN32_APP From c3429bb1a935f8c637cae422a2b85d0f3508d1aa Mon Sep 17 00:00:00 2001 From: r4sas Date: Mon, 18 Dec 2023 09:38:08 +0000 Subject: [PATCH 0239/1171] [gha] return freebsd build back Signed-off-by: r4sas --- .github/workflows/build-freebsd.yml | 32 +++++++++++++++++++++++++++++ ChangeLog | 2 +- 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/build-freebsd.yml diff --git a/.github/workflows/build-freebsd.yml b/.github/workflows/build-freebsd.yml new file mode 100644 index 00000000..6dc46a39 --- /dev/null +++ b/.github/workflows/build-freebsd.yml @@ -0,0 +1,32 @@ +name: Build on FreeBSD + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-latest + name: with UPnP + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Test in FreeBSD + id: test + uses: vmactions/freebsd-vm@v1 + with: + usesh: true + mem: 2048 + sync: rsync + copyback: true + prepare: pkg install -y devel/cmake devel/gmake devel/boost-libs security/openssl net/miniupnpc + run: | + cd build + cmake -DWITH_UPNP=ON -DCMAKE_BUILD_TYPE=Release . + gmake -j2 + + - name: Upload artifacts + uses: actions/upload-artifact@v3 + with: + name: i2pd-freebsd + path: build/i2pd diff --git a/ChangeLog b/ChangeLog index 1e5156f9..31e8718b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,7 +9,7 @@ ### Changed - Don't pick too active peer for first hop - Try peer test again if status is Unknown -- Send peer tests with random delay +- Send peer tests with random delay - Reseeds list ### Fixed - XSS vulnerability in addresshelper From 05eda2bc9eed9a816f6668c9b06a62d7a42d98d5 Mon Sep 17 00:00:00 2001 From: r4sas Date: Mon, 18 Dec 2023 09:55:10 +0000 Subject: [PATCH 0240/1171] [gha] build docker containers only on specific paths changes Signed-off-by: r4sas --- .github/workflows/build-freebsd.yml-disabled | 32 -------------------- .github/workflows/docker.yml | 10 ++++++ 2 files changed, 10 insertions(+), 32 deletions(-) delete mode 100644 .github/workflows/build-freebsd.yml-disabled diff --git a/.github/workflows/build-freebsd.yml-disabled b/.github/workflows/build-freebsd.yml-disabled deleted file mode 100644 index b4decc49..00000000 --- a/.github/workflows/build-freebsd.yml-disabled +++ /dev/null @@ -1,32 +0,0 @@ -name: Build on FreeBSD - -on: [push, pull_request] - -jobs: - build: - runs-on: macos-12 - name: with UPnP - - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Test in FreeBSD - id: test - uses: vmactions/freebsd-vm@v0.3.1 - with: - usesh: true - mem: 2048 - sync: rsync - copyback: true - prepare: pkg install -y devel/cmake devel/gmake devel/boost-libs security/openssl net/miniupnpc - run: | - cd build - cmake -DWITH_UPNP=ON -DCMAKE_BUILD_TYPE=Release . - gmake -j2 - - - name: Upload artifacts - uses: actions/upload-artifact@v3 - with: - name: i2pd-freebsd - path: build/i2pd diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 28e4e8b0..41fe859e 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -5,6 +5,16 @@ on: branches: - openssl - docker + paths: + - .github/workflows/docker.yml + - contrib/docker/** + - contrib/certificates/** + - daemon/** + - i18n/** + - libi2pd/** + - libi2pd_client/** + - Makefile + - Makefile.linux tags: - '*' From beffdb9fe175a93164bd88ee0fafe1a22595ed15 Mon Sep 17 00:00:00 2001 From: r4sas Date: Mon, 18 Dec 2023 10:06:49 +0000 Subject: [PATCH 0241/1171] [apparmor] add profile for docker container Author: corona@mail.i2p Signed-off-by: r4sas --- contrib/apparmor/docker-i2pd | 42 ++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 contrib/apparmor/docker-i2pd diff --git a/contrib/apparmor/docker-i2pd b/contrib/apparmor/docker-i2pd new file mode 100644 index 00000000..8e34298a --- /dev/null +++ b/contrib/apparmor/docker-i2pd @@ -0,0 +1,42 @@ +# _________________________________________ +# / Copy this file to the right location \ +# | then load with: | +# | | +# | apparmor_parser -r -W | +# | /etc/apparmor.d/docker-i2pd | +# | | +# | docker run --security-opt | +# | "apparmor=docker-i2pd" ... | +# | purplei2p/i2pd | +# | | +# \ And "aa-status" to verify it's loaded. / +# ----------------------------------------- +# \ ^__^ +# \ (oo)\_______ +# (__)\ )\/\ +# ||----w | +# || || + +#include + +profile docker-i2pd flags=(attach_disconnected,mediate_deleted) { + #include + #include + #include + + /bin/busybox ix, + /usr/local/bin/i2pd ix, + /entrypoint.sh ixr, + + /i2pd_certificates/** r, + + /home/i2pd/data/** rw, + + /home/i2pd/data/i2pd.pid k, + + deny /home/i2pd/data/i2pd.conf w, + deny /home/i2pd/data/tunnels.conf w, + deny /home/i2pd/data/tunnels.d/** w, + deny /home/i2pd/data/certificates/** w, + deny /home/i2pd/data/i2pd.log r, +} From 0e98dd5c7049d79bdcdba341357c504e562eb61f Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 18 Dec 2023 07:40:40 -0500 Subject: [PATCH 0242/1171] use fallback EdDSA implementation with openssl 3.2.0 due to regression in EVP_DigestSign (#23075) --- libi2pd/Crypto.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index 816d79fd..5b31cdd4 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -39,7 +39,9 @@ # define LEGACY_OPENSSL 0 # if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1 # define OPENSSL_HKDF 1 -# define OPENSSL_EDDSA 1 +# if (OPENSSL_VERSION_NUMBER < 0x030200000) // 3.2.0, regression in EVP_DigestSign +# define OPENSSL_EDDSA 1 +# endif # define OPENSSL_X25519 1 # if (OPENSSL_VERSION_NUMBER != 0x030000000) // 3.0.0, regression in SipHash # define OPENSSL_SIPHASH 1 From 8ffc1486a4cbacb774fd5b8834f9a6022ed2044b Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 18 Dec 2023 09:32:12 -0500 Subject: [PATCH 0243/1171] test-eddsa added --- tests/CMakeLists.txt | 7 +++++ tests/Makefile | 6 +++- tests/test-eddsa.cpp | 68 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 tests/test-eddsa.cpp diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 21daadd9..de319f5d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -65,6 +65,10 @@ SET(test-elligator_SRCS test-elligator.cpp ) +set(test-eddsa_SRCS + test-eddsa.cpp +) + add_executable(test-http-merge_chunked ${test-http-merge_chunked_SRCS}) add_executable(test-http-req ${test-http-req_SRCS}) add_executable(test-http-res ${test-http-res_SRCS}) @@ -77,6 +81,7 @@ add_executable(test-x25519 ${test-x25519_SRCS}) add_executable(test-aeadchacha20poly1305 ${test-aeadchacha20poly1305_SRCS}) add_executable(test-blinding ${test-blinding_SRCS}) add_executable(test-elligator ${test-elligator_SRCS}) +add_executable(test-eddsa ${test-eddsa_SRCS}) set(LIBS libi2pd @@ -101,6 +106,7 @@ target_link_libraries(test-x25519 ${LIBS}) target_link_libraries(test-aeadchacha20poly1305 ${LIBS}) target_link_libraries(test-blinding ${LIBS}) target_link_libraries(test-elligator ${LIBS}) +target_link_libraries(test-eddsa ${LIBS}) add_test(test-http-merge_chunked ${TEST_PATH}/test-http-merge_chunked) add_test(test-http-req ${TEST_PATH}/test-http-req) @@ -114,3 +120,4 @@ add_test(test-x25519 ${TEST_PATH}/test-x25519) add_test(test-aeadchacha20poly1305 ${TEST_PATH}/test-aeadchacha20poly1305) add_test(test-blinding ${TEST_PATH}/test-blinding) add_test(test-elligator ${TEST_PATH}/test-elligator) +add_test(test-eddsa ${TEST_PATH}/test-eddsa) diff --git a/tests/Makefile b/tests/Makefile index 9c5711e2..7c44e467 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -7,7 +7,8 @@ LIBI2PD = ../libi2pd.a TESTS = \ test-http-merge_chunked test-http-req test-http-res test-http-url test-http-url_decode \ - test-gost test-gost-sig test-base-64 test-x25519 test-aeadchacha20poly1305 test-blinding test-elligator + test-gost test-gost-sig test-base-64 test-x25519 test-aeadchacha20poly1305 test-blinding \ + test-elligator test-eddsa ifneq (, $(findstring mingw, $(SYS))$(findstring windows-gnu, $(SYS))$(findstring cygwin, $(SYS))) CXXFLAGS += -DWIN32_LEAN_AND_MEAN @@ -55,6 +56,9 @@ test-blinding: test-blinding.cpp $(LIBI2PD) test-elligator: test-elligator.cpp $(LIBI2PD) $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) +test-eddsa: test-eddsa.cpp $(LIBI2PD) + $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) + run: $(TESTS) @for TEST in $(TESTS); do echo Running $$TEST; ./$$TEST ; done diff --git a/tests/test-eddsa.cpp b/tests/test-eddsa.cpp new file mode 100644 index 00000000..b3895e2b --- /dev/null +++ b/tests/test-eddsa.cpp @@ -0,0 +1,68 @@ +#include +#include +#include + +#include "Signature.h" + +// TEST 1024 from RFC-8032 + +int main () +{ + uint8_t key[32], pub[32], msg[1024], sig[64]; + BIGNUM * input = BN_new(); + BN_hex2bn(&input, "f5e5767cf153319517630f226876b86c8160cc583bc013744c6bf255f5cc0ee5"); + BN_bn2bin(input, key); + BN_hex2bn(&input, + "08b8b2b733424243760fe426a4b54908632110a66c2f6591eabd3345e3e4eb98" + "fa6e264bf09efe12ee50f8f54e9f77b1e355f6c50544e23fb1433ddf73be84d8" + "79de7c0046dc4996d9e773f4bc9efe5738829adb26c81b37c93a1b270b20329d" + "658675fc6ea534e0810a4432826bf58c941efb65d57a338bbd2e26640f89ffbc" + "1a858efcb8550ee3a5e1998bd177e93a7363c344fe6b199ee5d02e82d522c4fe" + "ba15452f80288a821a579116ec6dad2b3b310da903401aa62100ab5d1a36553e" + "06203b33890cc9b832f79ef80560ccb9a39ce767967ed628c6ad573cb116dbef" + "efd75499da96bd68a8a97b928a8bbc103b6621fcde2beca1231d206be6cd9ec7" + "aff6f6c94fcd7204ed3455c68c83f4a41da4af2b74ef5c53f1d8ac70bdcb7ed1" + "85ce81bd84359d44254d95629e9855a94a7c1958d1f8ada5d0532ed8a5aa3fb2" + "d17ba70eb6248e594e1a2297acbbb39d502f1a8c6eb6f1ce22b3de1a1f40cc24" + "554119a831a9aad6079cad88425de6bde1a9187ebb6092cf67bf2b13fd65f270" + "88d78b7e883c8759d2c4f5c65adb7553878ad575f9fad878e80a0c9ba63bcbcc" + "2732e69485bbc9c90bfbd62481d9089beccf80cfe2df16a2cf65bd92dd597b07" + "07e0917af48bbb75fed413d238f5555a7a569d80c3414a8d0859dc65a46128ba" + "b27af87a71314f318c782b23ebfe808b82b0ce26401d2e22f04d83d1255dc51a" + "ddd3b75a2b1ae0784504df543af8969be3ea7082ff7fc9888c144da2af58429e" + "c96031dbcad3dad9af0dcbaaaf268cb8fcffead94f3c7ca495e056a9b47acdb7" + "51fb73e666c6c655ade8297297d07ad1ba5e43f1bca32301651339e22904cc8c" + "42f58c30c04aafdb038dda0847dd988dcda6f3bfd15c4b4c4525004aa06eeff8" + "ca61783aacec57fb3d1f92b0fe2fd1a85f6724517b65e614ad6808d6f6ee34df" + "f7310fdc82aebfd904b01e1dc54b2927094b2db68d6f903b68401adebf5a7e08" + "d78ff4ef5d63653a65040cf9bfd4aca7984a74d37145986780fc0b16ac451649" + "de6188a7dbdf191f64b5fc5e2ab47b57f7f7276cd419c17a3ca8e1b939ae49e4" + "88acba6b965610b5480109c8b17b80e1b7b750dfc7598d5d5011fd2dcc5600a3" + "2ef5b52a1ecc820e308aa342721aac0943bf6686b64b2579376504ccc493d97e" + "6aed3fb0f9cd71a43dd497f01f17c0e2cb3797aa2a2f256656168e6c496afc5f" + "b93246f6b1116398a346f1a641f3b041e989f7914f90cc2c7fff357876e506b5" + "0d334ba77c225bc307ba537152f3f1610e4eafe595f6d9d90d11faa933a15ef1" + "369546868a7f3a45a96768d40fd9d03412c091c6315cf4fde7cb68606937380d" + "b2eaaa707b4c4185c32eddcdd306705e4dc1ffc872eeee475a64dfac86aba41c" + "0618983f8741c5ef68d3a101e8a3b8cac60c905c15fc910840b94c00a0b9d0" + ); + BN_bn2bin(input, msg); + BN_hex2bn(&input, + "0aab4c900501b3e24d7cdf4663326a3a87df5e4843b2cbdb67cbf6e460fec350" + "aa5371b1508f9f4528ecea23c436d94b5e8fcd4f681e30a6ac00a9704a188a03"); + BN_bn2bin(input, sig); + BN_hex2bn(&input, + "278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e"); + BN_bn2bin(input, pub); + + uint8_t s[64]; + i2p::crypto::EDDSA25519Signer signer (key); + signer.Sign (msg, 1023, s); +#if OPENSSL_EDDSA + assert(memcmp (s, sig, 64) == 0); +#endif + + i2p::crypto::EDDSA25519Verifier verifier; + verifier.SetPublicKey (pub); + assert(verifier.Verify (msg, 1023, s)); +} From 43e130ee347c9aea7a840ebfa242ec897f906886 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 19 Dec 2023 19:29:08 -0500 Subject: [PATCH 0244/1171] reinitialize context before each Sign/Verify call to make it working with openssl 3.2 --- libi2pd/Crypto.h | 4 +--- libi2pd/Signature.cpp | 27 ++++++++++++++------------- libi2pd/Signature.h | 4 +++- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index 5b31cdd4..816d79fd 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -39,9 +39,7 @@ # define LEGACY_OPENSSL 0 # if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1 # define OPENSSL_HKDF 1 -# if (OPENSSL_VERSION_NUMBER < 0x030200000) // 3.2.0, regression in EVP_DigestSign -# define OPENSSL_EDDSA 1 -# endif +# define OPENSSL_EDDSA 1 # define OPENSSL_X25519 1 # if (OPENSSL_VERSION_NUMBER != 0x030000000) // 3.0.0, regression in SipHash # define OPENSSL_SIPHASH 1 diff --git a/libi2pd/Signature.cpp b/libi2pd/Signature.cpp index ebc188a9..60cdbec2 100644 --- a/libi2pd/Signature.cpp +++ b/libi2pd/Signature.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2021, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -15,7 +15,8 @@ namespace i2p namespace crypto { #if OPENSSL_EDDSA - EDDSA25519Verifier::EDDSA25519Verifier () + EDDSA25519Verifier::EDDSA25519Verifier (): + m_Pkey (nullptr) { m_MDCtx = EVP_MD_CTX_create (); } @@ -23,17 +24,18 @@ namespace crypto EDDSA25519Verifier::~EDDSA25519Verifier () { EVP_MD_CTX_destroy (m_MDCtx); + EVP_PKEY_free (m_Pkey); } void EDDSA25519Verifier::SetPublicKey (const uint8_t * signingKey) { - EVP_PKEY * pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_ED25519, NULL, signingKey, 32); - EVP_DigestVerifyInit (m_MDCtx, NULL, NULL, NULL, pkey); - EVP_PKEY_free (pkey); + if (m_Pkey) EVP_PKEY_free (m_Pkey); + m_Pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_ED25519, NULL, signingKey, 32); } bool EDDSA25519Verifier::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const { + EVP_DigestVerifyInit (m_MDCtx, NULL, NULL, NULL, m_Pkey); return EVP_DigestVerify (m_MDCtx, signature, 64, buf, len); } @@ -99,29 +101,26 @@ namespace crypto #if OPENSSL_EDDSA EDDSA25519Signer::EDDSA25519Signer (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey): - m_MDCtx (nullptr), m_Fallback (nullptr) + m_MDCtx (nullptr), m_Pkey (nullptr), m_Fallback (nullptr) { - EVP_PKEY * pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_ED25519, NULL, signingPrivateKey, 32); + m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_ED25519, NULL, signingPrivateKey, 32); uint8_t publicKey[EDDSA25519_PUBLIC_KEY_LENGTH]; size_t len = EDDSA25519_PUBLIC_KEY_LENGTH; - EVP_PKEY_get_raw_public_key (pkey, publicKey, &len); + EVP_PKEY_get_raw_public_key (m_Pkey, publicKey, &len); if (signingPublicKey && memcmp (publicKey, signingPublicKey, EDDSA25519_PUBLIC_KEY_LENGTH)) { LogPrint (eLogWarning, "EdDSA public key mismatch. Fallback"); m_Fallback = new EDDSA25519SignerCompat (signingPrivateKey, signingPublicKey); } else - { m_MDCtx = EVP_MD_CTX_create (); - EVP_DigestSignInit (m_MDCtx, NULL, NULL, NULL, pkey); - } - EVP_PKEY_free (pkey); } EDDSA25519Signer::~EDDSA25519Signer () { if (m_Fallback) delete m_Fallback; EVP_MD_CTX_destroy (m_MDCtx); + EVP_PKEY_free (m_Pkey); } void EDDSA25519Signer::Sign (const uint8_t * buf, int len, uint8_t * signature) const @@ -131,7 +130,9 @@ namespace crypto { size_t l = 64; uint8_t sig[64]; // temporary buffer for signature. openssl issue #7232 - EVP_DigestSign (m_MDCtx, sig, &l, buf, len); + EVP_DigestSignInit (m_MDCtx, NULL, NULL, NULL, m_Pkey); + if (!EVP_DigestSign (m_MDCtx, sig, &l, buf, len)) + LogPrint (eLogError, "EdDSA signing failed"); memcpy (signature, sig, 64); } } diff --git a/libi2pd/Signature.h b/libi2pd/Signature.h index e153e66d..671ebfb7 100644 --- a/libi2pd/Signature.h +++ b/libi2pd/Signature.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2021, The PurpleI2P Project +* Copyright (c) 2013-2023, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -305,6 +305,7 @@ namespace crypto #if OPENSSL_EDDSA EVP_MD_CTX * m_MDCtx; + EVP_PKEY * m_Pkey; #else EDDSAPoint m_PublicKey; uint8_t m_PublicKeyEncoded[EDDSA25519_PUBLIC_KEY_LENGTH]; @@ -342,6 +343,7 @@ namespace crypto private: EVP_MD_CTX * m_MDCtx; + EVP_PKEY * m_Pkey; EDDSA25519SignerCompat * m_Fallback; }; #else From 816a58f292228fb72ca9383023cba817acfad56d Mon Sep 17 00:00:00 2001 From: r4sas Date: Sat, 23 Dec 2023 18:13:31 +0000 Subject: [PATCH 0245/1171] 2.50.1 Signed-off-by: r4sas --- ChangeLog | 4 ++++ contrib/rpm/i2pd-git.spec | 5 ++++- contrib/rpm/i2pd.spec | 5 ++++- debian/changelog | 6 ++++++ libi2pd/version.h | 2 +- 5 files changed, 19 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 31e8718b..87329bf8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,10 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog +## [2.50.0] - 2023-12-23 +###Fixed +- Support for new EdDSA usage behavior in OpenSSL 3.2.0 + ## [2.50.0] - 2023-12-18 ### Added - Support of concurrent ACCEPTs on SAM 3.1 diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index f0344a34..ab5b4190 100644 --- a/contrib/rpm/i2pd-git.spec +++ b/contrib/rpm/i2pd-git.spec @@ -1,7 +1,7 @@ %define git_hash %(git rev-parse HEAD | cut -c -7) Name: i2pd-git -Version: 2.50.0 +Version: 2.50.1 Release: git%{git_hash}%{?dist} Summary: I2P router written in C++ Conflicts: i2pd @@ -144,6 +144,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Sat Dec 23 2023 r4sas - 2.50.1 +- update to 2.50.1 + * Mon Dec 18 2023 orignal - 2.50.0 - update to 2.50.0 diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 9b662f6e..74cc826d 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,5 +1,5 @@ Name: i2pd -Version: 2.50.0 +Version: 2.50.1 Release: 1%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git @@ -142,6 +142,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Sat Dec 23 2023 r4sas - 2.50.1 +- update to 2.50.1 + * Mon Dec 18 2023 orignal - 2.50.0 - update to 2.50.0 diff --git a/debian/changelog b/debian/changelog index 55566573..5484fd92 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i2pd (2.50.1-1) unstable; urgency=medium + + * updated to version 2.50.1/0.9.61 + + -- r4sas Sat, 23 Dec 2023 18:30:00 +0000 + i2pd (2.50.0-1) unstable; urgency=medium * updated to version 2.50.0/0.9.61 diff --git a/libi2pd/version.h b/libi2pd/version.h index 03d6b963..c79e3a2b 100644 --- a/libi2pd/version.h +++ b/libi2pd/version.h @@ -19,7 +19,7 @@ #define I2PD_VERSION_MAJOR 2 #define I2PD_VERSION_MINOR 50 -#define I2PD_VERSION_MICRO 0 +#define I2PD_VERSION_MICRO 1 #define I2PD_VERSION_PATCH 0 #ifdef GITVER #define I2PD_VERSION XSTRINGIZE(GITVER) From 69ee6112b3b134c40e4446999ede613d985a9122 Mon Sep 17 00:00:00 2001 From: r4sas Date: Sat, 23 Dec 2023 19:53:39 +0000 Subject: [PATCH 0246/1171] [changelog] fix version Signed-off-by: r4sas --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 87329bf8..0778cd70 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,7 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog -## [2.50.0] - 2023-12-23 +## [2.50.1] - 2023-12-23 ###Fixed - Support for new EdDSA usage behavior in OpenSSL 3.2.0 From 302af823a3509e5faa0e5cfcacdef2e480250d88 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 30 Dec 2023 15:55:53 -0500 Subject: [PATCH 0247/1171] fixed race condition with openssl 3.2.0 --- libi2pd/Signature.cpp | 38 +++++++++++++++++++++++++------------- libi2pd/Signature.h | 2 -- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/libi2pd/Signature.cpp b/libi2pd/Signature.cpp index 60cdbec2..342b6d03 100644 --- a/libi2pd/Signature.cpp +++ b/libi2pd/Signature.cpp @@ -18,12 +18,10 @@ namespace crypto EDDSA25519Verifier::EDDSA25519Verifier (): m_Pkey (nullptr) { - m_MDCtx = EVP_MD_CTX_create (); } EDDSA25519Verifier::~EDDSA25519Verifier () { - EVP_MD_CTX_destroy (m_MDCtx); EVP_PKEY_free (m_Pkey); } @@ -35,8 +33,17 @@ namespace crypto bool EDDSA25519Verifier::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const { - EVP_DigestVerifyInit (m_MDCtx, NULL, NULL, NULL, m_Pkey); - return EVP_DigestVerify (m_MDCtx, signature, 64, buf, len); + if (m_Pkey) + { + EVP_MD_CTX * ctx = EVP_MD_CTX_create (); + EVP_DigestVerifyInit (ctx, NULL, NULL, NULL, m_Pkey); + auto ret = EVP_DigestVerify (ctx, signature, 64, buf, len); + EVP_MD_CTX_destroy (ctx); + return ret; + } + else + LogPrint (eLogError, "EdDSA verification key is not set"); + return false; } #else @@ -101,7 +108,7 @@ namespace crypto #if OPENSSL_EDDSA EDDSA25519Signer::EDDSA25519Signer (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey): - m_MDCtx (nullptr), m_Pkey (nullptr), m_Fallback (nullptr) + m_Pkey (nullptr), m_Fallback (nullptr) { m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_ED25519, NULL, signingPrivateKey, 32); uint8_t publicKey[EDDSA25519_PUBLIC_KEY_LENGTH]; @@ -111,30 +118,35 @@ namespace crypto { LogPrint (eLogWarning, "EdDSA public key mismatch. Fallback"); m_Fallback = new EDDSA25519SignerCompat (signingPrivateKey, signingPublicKey); + EVP_PKEY_free (m_Pkey); + m_Pkey = nullptr; } - else - m_MDCtx = EVP_MD_CTX_create (); } EDDSA25519Signer::~EDDSA25519Signer () { if (m_Fallback) delete m_Fallback; - EVP_MD_CTX_destroy (m_MDCtx); - EVP_PKEY_free (m_Pkey); + if (m_Pkey) EVP_PKEY_free (m_Pkey); } void EDDSA25519Signer::Sign (const uint8_t * buf, int len, uint8_t * signature) const { - if (m_Fallback) return m_Fallback->Sign (buf, len, signature); - else + if (m_Fallback) + return m_Fallback->Sign (buf, len, signature); + else if (m_Pkey) { + + EVP_MD_CTX * ctx = EVP_MD_CTX_create (); size_t l = 64; uint8_t sig[64]; // temporary buffer for signature. openssl issue #7232 - EVP_DigestSignInit (m_MDCtx, NULL, NULL, NULL, m_Pkey); - if (!EVP_DigestSign (m_MDCtx, sig, &l, buf, len)) + EVP_DigestSignInit (ctx, NULL, NULL, NULL, m_Pkey); + if (!EVP_DigestSign (ctx, sig, &l, buf, len)) LogPrint (eLogError, "EdDSA signing failed"); memcpy (signature, sig, 64); + EVP_MD_CTX_destroy (ctx); } + else + LogPrint (eLogError, "EdDSA signing key is not set"); } #endif } diff --git a/libi2pd/Signature.h b/libi2pd/Signature.h index 671ebfb7..8bd94357 100644 --- a/libi2pd/Signature.h +++ b/libi2pd/Signature.h @@ -304,7 +304,6 @@ namespace crypto private: #if OPENSSL_EDDSA - EVP_MD_CTX * m_MDCtx; EVP_PKEY * m_Pkey; #else EDDSAPoint m_PublicKey; @@ -342,7 +341,6 @@ namespace crypto private: - EVP_MD_CTX * m_MDCtx; EVP_PKEY * m_Pkey; EDDSA25519SignerCompat * m_Fallback; }; From d4c47d90cb308c9845888fcc746b30dcb1c96fdd Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 30 Dec 2023 17:16:28 -0500 Subject: [PATCH 0248/1171] adjust time offset after second time discrepancy --- libi2pd/SSU2.cpp | 21 ++++++++++++++++++++- libi2pd/SSU2.h | 2 ++ libi2pd/SSU2Session.cpp | 7 +++---- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 7099ba0c..4448c1df 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -24,7 +24,8 @@ namespace transport m_AddressV4 (boost::asio::ip::address_v4()), m_AddressV6 (boost::asio::ip::address_v6()), m_TerminationTimer (GetService ()), m_CleanupTimer (GetService ()), m_ResendTimer (GetService ()), m_IntroducersUpdateTimer (GetService ()), m_IntroducersUpdateTimerV6 (GetService ()), - m_IsPublished (true), m_IsSyncClockFromPeers (true), m_IsThroughProxy (false) + m_IsPublished (true), m_IsSyncClockFromPeers (true), m_PendingTimeOffset (0), + m_IsThroughProxy (false) { } @@ -209,6 +210,24 @@ namespace transport return ep.port (); } + void SSU2Server::AdjustTimeOffset (int64_t offset) + { + if (offset) + { + if (m_PendingTimeOffset) // one more + { + offset = (m_PendingTimeOffset + offset)/2; // average + LogPrint (eLogWarning, "SSU2: Clock adjusted by ", -offset, " seconds"); + i2p::util::AdjustTimeOffset (-offset); + m_PendingTimeOffset = 0; + } + else + m_PendingTimeOffset = offset; // first + } + else + m_PendingTimeOffset = 0; // reset + } + boost::asio::ip::udp::socket& SSU2Server::OpenSocket (const boost::asio::ip::udp::endpoint& localEndpoint) { boost::asio::ip::udp::socket& socket = localEndpoint.address ().is_v6 () ? m_SocketV6 : m_SocketV4; diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index a1fafc63..03e22245 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -66,6 +66,7 @@ namespace transport bool IsSupported (const boost::asio::ip::address& addr) const; uint16_t GetPort (bool v4) const; bool IsSyncClockFromPeers () const { return m_IsSyncClockFromPeers; }; + void AdjustTimeOffset (int64_t offset); void AddSession (std::shared_ptr session); void RemoveSession (uint64_t connID); @@ -161,6 +162,7 @@ namespace transport std::shared_ptr m_LastSession; bool m_IsPublished; // if we maintain introducers bool m_IsSyncClockFromPeers; + int64_t m_PendingTimeOffset; // during peer test // proxy bool m_IsThroughProxy; diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 487d5549..bab9f2bb 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1668,10 +1668,7 @@ namespace transport if (m_Server.IsSyncClockFromPeers ()) { if (std::abs (offset) > SSU2_CLOCK_THRESHOLD) - { - LogPrint (eLogWarning, "SSU2: Clock adjusted by ", -offset, " seconds"); - i2p::util::AdjustTimeOffset (-offset); - } + m_Server.AdjustTimeOffset (-offset); } else if (std::abs (offset) > SSU2_CLOCK_SKEW) { @@ -2481,6 +2478,8 @@ namespace transport else if (m_Address->IsV6 ()) i2p::context.SetTestingV6 (testing); } + if (!testing) + m_Server.AdjustTimeOffset (0); // reset time offset when testing is over } size_t SSU2Session::CreateAddressBlock (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& ep) From 8319dd6b25b62b085d3f9b2867e438cd204ed7fb Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 30 Dec 2023 19:49:16 -0500 Subject: [PATCH 0249/1171] drop exploratory and leaseset lookups for non-floodfill router --- libi2pd/NetDb.cpp | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 07f0f341..9f186659 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -1019,6 +1019,11 @@ namespace data std::shared_ptr replyMsg; if (lookupType == DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP) { + if (!context.IsFloodfill ()) + { + LogPrint (eLogWarning, "NetDb: Exploratory lookup to non-floodfill dropped"); + return; + } LogPrint (eLogInfo, "NetDb: Exploratory close to ", key, " ", numExcluded, " excluded"); std::set excludedRouters; const uint8_t * excluded_ident = excluded; @@ -1044,6 +1049,7 @@ namespace data if (lookupType == DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP || lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP) { + // try to find router auto router = FindRouter (ident); if (router && !router->IsUnreachable ()) { @@ -1056,17 +1062,26 @@ namespace data if (!replyMsg && (lookupType == DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP || lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP)) { - auto leaseSet = FindLeaseSet (ident); - if (!leaseSet) + // try to find leaseset + if (context.IsFloodfill ()) + { + auto leaseSet = FindLeaseSet (ident); + if (!leaseSet) + { + // no leaseset found + LogPrint(eLogDebug, "NetDb: Requested LeaseSet not found for ", ident.ToBase32()); + } + else if (!leaseSet->IsExpired ()) // we don't send back expired leasesets + { + LogPrint (eLogDebug, "NetDb: Requested LeaseSet ", key, " found"); + replyMsg = CreateDatabaseStoreMsg (ident, leaseSet); + } + } + else if (lookupType == DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP) { - // no lease set found - LogPrint(eLogDebug, "NetDb: Requested LeaseSet not found for ", ident.ToBase32()); - } - else if (!leaseSet->IsExpired ()) // we don't send back our LeaseSets - { - LogPrint (eLogDebug, "NetDb: Requested LeaseSet ", key, " found"); - replyMsg = CreateDatabaseStoreMsg (ident, leaseSet); - } + LogPrint (eLogWarning, "NetDb: Explicit LeaseSet lookup to non-floodfill dropped"); + return; + } } if (!replyMsg) From 21f41a2b2a39461a480b8539beb2f1c141bb8fe7 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 31 Dec 2023 10:14:24 -0500 Subject: [PATCH 0250/1171] correct time offset direction --- libi2pd/SSU2.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 4448c1df..55eb0567 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -217,8 +217,8 @@ namespace transport if (m_PendingTimeOffset) // one more { offset = (m_PendingTimeOffset + offset)/2; // average - LogPrint (eLogWarning, "SSU2: Clock adjusted by ", -offset, " seconds"); - i2p::util::AdjustTimeOffset (-offset); + LogPrint (eLogWarning, "SSU2: Clock adjusted by ", offset, " seconds"); + i2p::util::AdjustTimeOffset (offset); m_PendingTimeOffset = 0; } else From b855c7189111a30ed5acdffe8d2d584c35b2fc61 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 31 Dec 2023 14:39:59 -0500 Subject: [PATCH 0251/1171] don't adjust clock if time offsets are too different --- libi2pd/SSU2.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 55eb0567..6a8615d5 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -216,9 +216,14 @@ namespace transport { if (m_PendingTimeOffset) // one more { - offset = (m_PendingTimeOffset + offset)/2; // average - LogPrint (eLogWarning, "SSU2: Clock adjusted by ", offset, " seconds"); - i2p::util::AdjustTimeOffset (offset); + if (std::abs (m_PendingTimeOffset - offset) < SSU2_CLOCK_SKEW) + { + offset = (m_PendingTimeOffset + offset)/2; // average + LogPrint (eLogWarning, "SSU2: Clock adjusted by ", offset, " seconds"); + i2p::util::AdjustTimeOffset (offset); + } + else + LogPrint (eLogWarning, "SSU2: Time offsets are too different. Clock not adjusted"); m_PendingTimeOffset = 0; } else From c5cab05a6b8690f3fd2442054c1475e06dc43640 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 2 Jan 2024 19:42:49 -0500 Subject: [PATCH 0252/1171] reset peding time offset if correct time was received --- libi2pd/SSU2Session.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index bab9f2bb..e5261622 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022-2023, The PurpleI2P Project +* Copyright (c) 2022-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -1668,7 +1668,12 @@ namespace transport if (m_Server.IsSyncClockFromPeers ()) { if (std::abs (offset) > SSU2_CLOCK_THRESHOLD) + { + LogPrint (eLogWarning, "SSU2: Time offset ", offset, " from ", m_RemoteEndpoint); m_Server.AdjustTimeOffset (-offset); + } + else + m_Server.AdjustTimeOffset (0); } else if (std::abs (offset) > SSU2_CLOCK_SKEW) { From 577c71b930dddcc0ca74dcb4368aa2aea07486da Mon Sep 17 00:00:00 2001 From: Dimitris Apostolou Date: Thu, 4 Jan 2024 21:35:25 +0200 Subject: [PATCH 0253/1171] Fix typos --- libi2pd/Datagram.h | 2 +- libi2pd/NTCP2.cpp | 2 +- libi2pd/RouterInfo.cpp | 2 +- libi2pd/TunnelPool.cpp | 2 +- libi2pd_client/UDPTunnel.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libi2pd/Datagram.h b/libi2pd/Datagram.h index 8f3d5ceb..e6d1f7b6 100644 --- a/libi2pd/Datagram.h +++ b/libi2pd/Datagram.h @@ -150,7 +150,7 @@ namespace datagram void HandleDatagram (uint16_t fromPort, uint16_t toPort, uint8_t *const& buf, size_t len); void HandleRawDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); - /** find a receiver by port, if none by port is found try default receiever, otherwise returns nullptr */ + /** find a receiver by port, if none by port is found try default receiver, otherwise returns nullptr */ Receiver FindReceiver(uint16_t port); private: diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 0a23f07e..f1a5e241 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1234,7 +1234,7 @@ namespace transport void NTCP2Session::SendLocalRouterInfo (bool update) { - if (update || !IsOutgoing ()) // we send it in SessionConfirmed for ougoing session + if (update || !IsOutgoing ()) // we send it in SessionConfirmed for outgoing session m_Server.GetService ().post (std::bind (&NTCP2Session::SendRouterInfo, shared_from_this ())); } diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 63cb79ef..60f9a518 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -995,7 +995,7 @@ namespace data bool RouterInfo::IsPublished (bool v4) const { - if (m_Caps & (eUnreachable | eHidden)) return false; // if router sets U or H we assume that all addreses are not published + if (m_Caps & (eUnreachable | eHidden)) return false; // if router sets U or H we assume that all addresses are not published auto addr = GetAddresses (); if (v4) return ((*addr)[eNTCP2V4Idx] && ((*addr)[eNTCP2V4Idx])->published) || diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index 23cc53e3..5339c9be 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -301,7 +301,7 @@ namespace tunnel { for (auto it: m_OutboundTunnels) { - // try to create inbound tunnel through the same path as succesive outbound + // try to create inbound tunnel through the same path as successive outbound CreatePairedInboundTunnel (it); num++; if (num >= m_NumInboundTunnels) break; diff --git a/libi2pd_client/UDPTunnel.h b/libi2pd_client/UDPTunnel.h index 862ce216..3233c3f0 100644 --- a/libi2pd_client/UDPTunnel.h +++ b/libi2pd_client/UDPTunnel.h @@ -72,7 +72,7 @@ namespace client boost::asio::ip::udp::endpoint LocalEndpoint; /** client's udp endpoint */ boost::asio::ip::udp::endpoint RemoteEndpoint; - /** how long has this converstation been idle in ms */ + /** how long has this conversation been idle in ms */ uint64_t idle; }; From 5cf1961fa4910ad7b5bd1298bfe723af50b5ccb5 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 6 Jan 2024 11:31:01 -0500 Subject: [PATCH 0254/1171] drop updated routers from future --- libi2pd/NetDb.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 9f186659..6e023c45 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -247,9 +247,10 @@ namespace data m_Requests.RequestComplete (ident, r); return r; } - if (r->IsUnreachable ()) + if (r->IsUnreachable () || + i2p::util::GetMillisecondsSinceEpoch () + NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < r->GetTimestamp ()) { - // delete router as invalid after update + // delete router as invalid or from future after update m_RouterInfos.erase (ident); if (wasFloodfill) { From a8135b8d1820281d18d96cf2fa87e65c55350356 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 6 Jan 2024 14:51:42 -0500 Subject: [PATCH 0255/1171] 2.50.2 --- libi2pd/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/version.h b/libi2pd/version.h index c79e3a2b..7b9e20c8 100644 --- a/libi2pd/version.h +++ b/libi2pd/version.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -19,7 +19,7 @@ #define I2PD_VERSION_MAJOR 2 #define I2PD_VERSION_MINOR 50 -#define I2PD_VERSION_MICRO 1 +#define I2PD_VERSION_MICRO 2 #define I2PD_VERSION_PATCH 0 #ifdef GITVER #define I2PD_VERSION XSTRINGIZE(GITVER) From 3b97feb89fdc310ab43cc9336e1817f5b17f4b82 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 6 Jan 2024 15:07:51 -0500 Subject: [PATCH 0256/1171] 2.50.2 --- ChangeLog | 5 +++++ contrib/rpm/i2pd-git.spec | 5 ++++- contrib/rpm/i2pd.spec | 5 ++++- debian/changelog | 6 ++++++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0778cd70..6534a9b5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,11 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog +## [2.50.2] - 2024-01-06 +###Fixed +- Crash with OpenSSL 3.2.0 +- False positive clock skew detection + ## [2.50.1] - 2023-12-23 ###Fixed - Support for new EdDSA usage behavior in OpenSSL 3.2.0 diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index ab5b4190..0bc46eab 100644 --- a/contrib/rpm/i2pd-git.spec +++ b/contrib/rpm/i2pd-git.spec @@ -1,7 +1,7 @@ %define git_hash %(git rev-parse HEAD | cut -c -7) Name: i2pd-git -Version: 2.50.1 +Version: 2.50.2 Release: git%{git_hash}%{?dist} Summary: I2P router written in C++ Conflicts: i2pd @@ -144,6 +144,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Sat Jan 06 2024 orignal - 2.50.2 +- update to 2.50.2 + * Sat Dec 23 2023 r4sas - 2.50.1 - update to 2.50.1 diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 74cc826d..1de4076e 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,5 +1,5 @@ Name: i2pd -Version: 2.50.1 +Version: 2.50.2 Release: 1%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git @@ -142,6 +142,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Sat Jan 06 2024 orignal - 2.50.2 +- update to 2.50.2 + * Sat Dec 23 2023 r4sas - 2.50.1 - update to 2.50.1 diff --git a/debian/changelog b/debian/changelog index 5484fd92..56ab7c16 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i2pd (2.50.2) unstable; urgency=medium + + * updated to version 2.50.2/0.9.61 + +-- orignal Sat, 06 Jan 2024 16:00:00 +0000 + i2pd (2.50.1-1) unstable; urgency=medium * updated to version 2.50.1/0.9.61 From 8bc58daa5a63a12f88b3fb454ee297e37e1ec48a Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 7 Jan 2024 18:42:34 -0500 Subject: [PATCH 0257/1171] fixed #2004. Check supported crypto --- libi2pd_client/SAM.cpp | 56 +++++++++++++++++++++++++----------------- libi2pd_client/SAM.h | 6 +++-- 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index ffdeb5ac..775b9411 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -550,17 +550,22 @@ namespace client if (!session) session = m_Owner.FindSession(m_ID); if (session) { - m_SocketType = eSAMSocketTypeStream; - m_Stream = session->GetLocalDestination ()->CreateStream (remote); - if (m_Stream) - { - m_Stream->Send ((uint8_t *)m_Buffer, m_BufferOffset); // connect and send - m_BufferOffset = 0; - I2PReceive (); - SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); + if (session->GetLocalDestination ()->SupportsEncryptionType (remote->GetEncryptionType ())) + { + m_SocketType = eSAMSocketTypeStream; + m_Stream = session->GetLocalDestination ()->CreateStream (remote); + if (m_Stream) + { + m_Stream->Send ((uint8_t *)m_Buffer, m_BufferOffset); // connect and send + m_BufferOffset = 0; + I2PReceive (); + SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); + } + else + SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); } else - SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); + SendStreamCantReachPeer ("Incompatible crypto"); } else SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); @@ -573,7 +578,7 @@ namespace client else { LogPrint (eLogError, "SAM: Destination to connect not found"); - SendMessageReply (SAM_STREAM_STATUS_CANT_REACH_PEER, strlen(SAM_STREAM_STATUS_CANT_REACH_PEER), true); + SendStreamCantReachPeer ("LeaseSet not found"); } } @@ -857,27 +862,32 @@ namespace client SendSessionI2PError ("Wrong session type"); } + void SAMSocket::SendReplyWithMessage (const char * reply, const std::string & msg) + { +#ifdef _MSC_VER + size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, reply, msg.c_str()); +#else + size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, reply, msg.c_str()); +#endif + SendMessageReply (m_Buffer, len, true); + } + void SAMSocket::SendSessionI2PError(const std::string & msg) { LogPrint (eLogError, "SAM: Session I2P error: ", msg); -#ifdef _MSC_VER - size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_STATUS_I2P_ERROR, msg.c_str()); -#else - size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_STATUS_I2P_ERROR, msg.c_str()); -#endif - SendMessageReply (m_Buffer, len, true); + SendReplyWithMessage (SAM_SESSION_STATUS_I2P_ERROR, msg); } void SAMSocket::SendStreamI2PError(const std::string & msg) { LogPrint (eLogError, "SAM: Stream I2P error: ", msg); -#ifdef _MSC_VER - size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_STREAM_STATUS_I2P_ERROR, msg.c_str()); -#else - size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_STREAM_STATUS_I2P_ERROR, msg.c_str()); -#endif - SendMessageReply (m_Buffer, len, true); + SendReplyWithMessage (SAM_STREAM_STATUS_I2P_ERROR, msg); } + + void SAMSocket::SendStreamCantReachPeer(const std::string & msg) + { + SendReplyWithMessage (SAM_STREAM_STATUS_CANT_REACH_PEER, msg); + } void SAMSocket::HandleNamingLookupLeaseSetRequestComplete (std::shared_ptr leaseSet, std::string name) { diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index 34af5a62..3ed8f00c 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -51,7 +51,7 @@ namespace client const char SAM_STREAM_STATUS_OK[] = "STREAM STATUS RESULT=OK\n"; const char SAM_STREAM_STATUS_INVALID_ID[] = "STREAM STATUS RESULT=INVALID_ID\n"; const char SAM_STREAM_STATUS_INVALID_KEY[] = "STREAM STATUS RESULT=INVALID_KEY\n"; - const char SAM_STREAM_STATUS_CANT_REACH_PEER[] = "STREAM STATUS RESULT=CANT_REACH_PEER\n"; + const char SAM_STREAM_STATUS_CANT_REACH_PEER[] = "STREAM STATUS RESULT=CANT_REACH_PEER MESSAGE=\"%s\"\n"; const char SAM_STREAM_STATUS_I2P_ERROR[] = "STREAM STATUS RESULT=I2P_ERROR MESSAGE=\"%s\"\n"; const char SAM_STREAM_ACCEPT[] = "STREAM ACCEPT"; const char SAM_STREAM_FORWARD[] = "STREAM FORWARD"; @@ -144,8 +144,10 @@ namespace client void ProcessNamingLookup (char * buf, size_t len); void ProcessSessionAdd (char * buf, size_t len); void ProcessSessionRemove (char * buf, size_t len); + void SendReplyWithMessage (const char * reply, const std::string & msg); void SendSessionI2PError(const std::string & msg); void SendStreamI2PError(const std::string & msg); + void SendStreamCantReachPeer(const std::string & msg); size_t ProcessDatagramSend (char * buf, size_t len, const char * data); // from SAM 1.0 void ExtractParams (char * buf, std::map& params); From 1e9bcd6b8b228aeed713f1d1714809409e97633a Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 8 Jan 2024 16:36:14 +0300 Subject: [PATCH 0258/1171] [gha] MSVC: Switch to direct Boost and OpenSSL installation --- .github/workflows/build-windows-msvc.yml | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-windows-msvc.yml b/.github/workflows/build-windows-msvc.yml index 172e0596..a077d626 100644 --- a/.github/workflows/build-windows-msvc.yml +++ b/.github/workflows/build-windows-msvc.yml @@ -26,15 +26,27 @@ jobs: ./install_zlib.bat del install_zlib.bat + #- name: Install Boost + # uses: crazy-max/ghaction-chocolatey@v2 + # with: + # args: install boost-msvc-14.3 --version=1.81.0 + + #- name: Install OpenSSL + # uses: crazy-max/ghaction-chocolatey@v2 + # with: + # args: install openssl + - name: Install Boost - uses: crazy-max/ghaction-chocolatey@v2 - with: - args: install boost-msvc-14.3 --version=1.81.0 + run: | + powershell -Command "(Invoke-WebRequest -UserAgent "Wget" -Uri https://sourceforge.net/projects/boost/files/boost-binaries/1.84.0/boost_1_84_0-msvc-14.3-64.exe/download -OutFile boost_1_84_0-msvc-14.3-64.exe)" + ./boost_1_84_0-msvc-14.3-64.exe /VERYSILENT + del boost_1_84_0-msvc-14.3-64.exe - name: Install OpenSSL - uses: crazy-max/ghaction-chocolatey@v2 - with: - args: install openssl + run: | + powershell -Command "(Invoke-WebRequest -UserAgent "Wget" -Uri https://slproweb.com/download/Win64OpenSSL-3_2_0.exe -OutFile Win64OpenSSL-3_2_0.exe)" + ./Win64OpenSSL-3_2_0.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- + del Win64OpenSSL-3_2_0.exe - name: Configure working-directory: build From dfe8b25e5ec2d0533584bf03cf0d1289bc1ca71d Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 8 Jan 2024 17:05:36 +0300 Subject: [PATCH 0259/1171] [gha] MSVC: remove deletion of installation files --- .github/workflows/build-windows-msvc.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/build-windows-msvc.yml b/.github/workflows/build-windows-msvc.yml index a077d626..5af526e2 100644 --- a/.github/workflows/build-windows-msvc.yml +++ b/.github/workflows/build-windows-msvc.yml @@ -40,13 +40,11 @@ jobs: run: | powershell -Command "(Invoke-WebRequest -UserAgent "Wget" -Uri https://sourceforge.net/projects/boost/files/boost-binaries/1.84.0/boost_1_84_0-msvc-14.3-64.exe/download -OutFile boost_1_84_0-msvc-14.3-64.exe)" ./boost_1_84_0-msvc-14.3-64.exe /VERYSILENT - del boost_1_84_0-msvc-14.3-64.exe - name: Install OpenSSL run: | powershell -Command "(Invoke-WebRequest -UserAgent "Wget" -Uri https://slproweb.com/download/Win64OpenSSL-3_2_0.exe -OutFile Win64OpenSSL-3_2_0.exe)" ./Win64OpenSSL-3_2_0.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- - del Win64OpenSSL-3_2_0.exe - name: Configure working-directory: build From cd087568b55161767c6094f86054d4976e137209 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 9 Jan 2024 21:02:11 -0500 Subject: [PATCH 0260/1171] reply with CANT_REACH_PEER if connect to outselves --- libi2pd_client/SAM.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 775b9411..1a3afb58 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -523,15 +523,20 @@ namespace client { if (addr->IsIdentHash ()) { - auto leaseSet = session->GetLocalDestination ()->FindLeaseSet(addr->identHash); - if (leaseSet) - Connect(leaseSet, session); - else - { - session->GetLocalDestination ()->RequestDestination(addr->identHash, - std::bind(&SAMSocket::HandleConnectLeaseSetRequestComplete, - shared_from_this(), std::placeholders::_1)); + if (session->GetLocalDestination ()->GetIdentHash () != addr->identHash) + { + auto leaseSet = session->GetLocalDestination ()->FindLeaseSet(addr->identHash); + if (leaseSet) + Connect(leaseSet, session); + else + { + session->GetLocalDestination ()->RequestDestination(addr->identHash, + std::bind(&SAMSocket::HandleConnectLeaseSetRequestComplete, + shared_from_this(), std::placeholders::_1)); + } } + else + SendStreamCantReachPeer ("Can't connect to myself"); } else // B33 session->GetLocalDestination ()->RequestDestinationWithEncryptedLeaseSet (addr->blindedPublicKey, From 2ad26dd4c9def4cf05e144f65793323187a2b830 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 11 Jan 2024 14:09:08 -0500 Subject: [PATCH 0261/1171] fixed race condition in ECIESx25519 tags table --- libi2pd/RouterContext.cpp | 22 +++++++++++++++++++++- libi2pd/RouterContext.h | 1 + libi2pd/Tunnel.cpp | 2 +- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index f21c0592..10d33bf5 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -1199,7 +1199,27 @@ namespace i2p else i2p::garlic::GarlicDestination::ProcessDeliveryStatusMessage (msg); } - + + void RouterContext::SubmitECIESx25519Key (const uint8_t * key, uint64_t tag) + { + if (m_Service) + { + struct + { + uint8_t k[32]; + uint64_t t; + } data; + memcpy (data.k, key, 32); + data.t = tag; + m_Service->GetService ().post ([this,data](void) + { + AddECIESx25519Key (data.k, data.t); + }); + } + else + LogPrint (eLogError, "Router: service is NULL"); + } + void RouterContext::CleanupDestination () { if (m_Service) diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index d49b5523..91a553ba 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -136,6 +136,7 @@ namespace garlic void SetNetID (int netID) { m_NetID = netID; }; bool DecryptTunnelBuildRecord (const uint8_t * encrypted, uint8_t * data); bool DecryptTunnelShortRequestRecord (const uint8_t * encrypted, uint8_t * data); + void SubmitECIESx25519Key (const uint8_t * key, uint64_t tag); void UpdatePort (int port); // called from Daemon void UpdateAddress (const boost::asio::ip::address& host); // called from SSU2 or Daemon diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 6234ceb4..b8e17920 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -116,7 +116,7 @@ namespace tunnel if (m_Pool && m_Pool->GetLocalDestination ()) m_Pool->GetLocalDestination ()->SubmitECIESx25519Key (key, tag); else - i2p::context.AddECIESx25519Key (key, tag); + i2p::context.SubmitECIESx25519Key (key, tag); } i2p::transport::transports.SendMessage (GetNextIdentHash (), msg); } From ca9782dd0d4ad8116035352f22524b4f3ee77633 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 11 Jan 2024 15:39:42 -0500 Subject: [PATCH 0262/1171] handle 'reservedrange' param properly --- daemon/Daemon.cpp | 4 +--- libi2pd/NTCP2.cpp | 4 ++-- libi2pd/Reseed.cpp | 24 +++++++++++------------- libi2pd/RouterInfo.cpp | 5 +++-- libi2pd/SSU2.cpp | 8 ++++---- libi2pd/SSU2Session.cpp | 4 ++-- libi2pd/Transports.cpp | 13 ++++++++++--- libi2pd/Transports.h | 5 +++-- 8 files changed, 36 insertions(+), 31 deletions(-) diff --git a/daemon/Daemon.cpp b/daemon/Daemon.cpp index f04236fe..308daa4c 100644 --- a/daemon/Daemon.cpp +++ b/daemon/Daemon.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -298,12 +298,10 @@ namespace util bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2); - bool checkInReserved; i2p::config::GetOption("reservedrange", checkInReserved); LogPrint(eLogInfo, "Daemon: Starting Transports"); if(!ssu2) LogPrint(eLogInfo, "Daemon: SSU2 disabled"); if(!ntcp2) LogPrint(eLogInfo, "Daemon: NTCP2 disabled"); - i2p::transport::transports.SetCheckReserved(checkInReserved); i2p::transport::transports.Start(ntcp2, ssu2); if (i2p::transport::transports.IsBoundSSU2() || i2p::transport::transports.IsBoundNTCP2()) LogPrint(eLogInfo, "Daemon: Transports started"); diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index f1a5e241..efc317c2 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1490,7 +1490,7 @@ namespace transport if (!ec) { LogPrint (eLogDebug, "NTCP2: Connected from ", ep); - if (!i2p::util::net::IsInReservedRange(ep.address ())) + if (!i2p::transport::transports.IsInReservedRange(ep.address ())) { if (m_PendingIncomingSessions.emplace (ep.address (), conn).second) { @@ -1537,7 +1537,7 @@ namespace transport if (!ec) { LogPrint (eLogDebug, "NTCP2: Connected from ", ep); - if (!i2p::util::net::IsInReservedRange(ep.address ()) || + if (!i2p::transport::transports.IsInReservedRange(ep.address ()) || i2p::util::net::IsYggdrasilAddress (ep.address ())) { if (m_PendingIncomingSessions.emplace (ep.address (), conn).second) diff --git a/libi2pd/Reseed.cpp b/libi2pd/Reseed.cpp index 28e4db24..5fdc2fae 100644 --- a/libi2pd/Reseed.cpp +++ b/libi2pd/Reseed.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -687,18 +687,16 @@ namespace data while (it != end) { boost::asio::ip::tcp::endpoint ep = *it; - if ( - ( - !i2p::util::net::IsInReservedRange(ep.address ()) && ( - (ep.address ().is_v4 () && i2p::context.SupportsV4 ()) || - (ep.address ().is_v6 () && i2p::context.SupportsV6 ()) - ) - ) || - ( - i2p::util::net::IsYggdrasilAddress (ep.address ()) && - i2p::context.SupportsMesh () - ) - ) + bool supported = false; + if (!ep.address ().is_unspecified ()) + { + if (ep.address ().is_v4 ()) + supported = i2p::context.SupportsV4 (); + else if (ep.address ().is_v6 ()) + supported = i2p::util::net::IsYggdrasilAddress (ep.address ()) ? + i2p::context.SupportsMesh () : i2p::context.SupportsV6 (); + } + if (supported) { s.lowest_layer().connect (ep, ecode); if (!ecode) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 60f9a518..7cde7c33 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -21,6 +21,7 @@ #include "Base.h" #include "Timestamp.h" #include "Log.h" +#include "Transports.h" #include "NetDb.hpp" #include "RouterContext.h" #include "RouterInfo.h" @@ -253,7 +254,7 @@ namespace data address->host = boost::asio::ip::address::from_string (value, ecode); if (!ecode && !address->host.is_unspecified ()) { - if (!i2p::util::net::IsInReservedRange (address->host) || + if (!i2p::transport::transports.IsInReservedRange (address->host) || i2p::util::net::IsYggdrasilAddress (address->host)) isHost = true; else diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 6a8615d5..1503b404 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022-2023, The PurpleI2P Project +* Copyright (c) 2022-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -566,7 +566,7 @@ namespace transport else it1->second->ProcessRetry (buf, len); } - else if (!i2p::util::net::IsInReservedRange(senderEndpoint.address ()) && senderEndpoint.port ()) + else if (!i2p::transport::transports.IsInReservedRange(senderEndpoint.address ()) && senderEndpoint.port ()) { // assume new incoming session auto session = std::make_shared (*this); @@ -666,7 +666,7 @@ namespace transport bool isValidEndpoint = !address->host.is_unspecified () && address->port; if (isValidEndpoint) { - if (i2p::util::net::IsInReservedRange(address->host)) return false; + if (i2p::transport::transports.IsInReservedRange(address->host)) return false; auto s = FindPendingOutgoingSession (boost::asio::ip::udp::endpoint (address->host, address->port)); if (s) { @@ -753,7 +753,7 @@ namespace transport if (addr) { bool isValidEndpoint = !addr->host.is_unspecified () && addr->port && - !i2p::util::net::IsInReservedRange(addr->host); + !i2p::transport::transports.IsInReservedRange(addr->host); if (isValidEndpoint) { auto s = FindPendingOutgoingSession (boost::asio::ip::udp::endpoint (addr->host, addr->port)); diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index e5261622..8cb39102 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1471,7 +1471,7 @@ namespace transport ResendHandshakePacket (); // assume we receive return; } - if (from != m_RemoteEndpoint && !i2p::util::net::IsInReservedRange (from.address ())) + if (from != m_RemoteEndpoint && !i2p::transport::transports.IsInReservedRange (from.address ())) { LogPrint (eLogInfo, "SSU2: Remote endpoint update ", m_RemoteEndpoint, "->", from); m_RemoteEndpoint = from; @@ -1753,7 +1753,7 @@ namespace transport if (ExtractEndpoint (buf, len, ep)) { LogPrint (eLogInfo, "SSU2: Our external address is ", ep); - if (!i2p::util::net::IsInReservedRange (ep.address ())) + if (!i2p::transport::transports.IsInReservedRange (ep.address ())) { i2p::context.UpdateAddress (ep.address ()); // check our port diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index b6e2e261..318d410f 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -505,7 +505,7 @@ namespace transport if (!m_NTCP2Server) continue; std::shared_ptr address = (tr == i2p::data::RouterInfo::eNTCP2V6) ? peer.router->GetPublishedNTCP2V6Address () : peer.router->GetPublishedNTCP2V4Address (); - if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host)) + if (address && IsInReservedRange(address->host)) address = nullptr; if (address) { @@ -524,7 +524,7 @@ namespace transport if (!m_SSU2Server) continue; std::shared_ptr address = (tr == i2p::data::RouterInfo::eSSU2V6) ? peer.router->GetSSU2V6Address () : peer.router->GetSSU2V4Address (); - if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host)) + if (address && IsInReservedRange(address->host)) address = nullptr; if (address && address->IsReachableSSU ()) { @@ -1084,6 +1084,11 @@ namespace transport } } + bool Transports::IsInReservedRange (const boost::asio::ip::address& host) const + { + return IsCheckReserved () && i2p::util::net::IsInReservedRange (host); + } + void InitAddressFromIface () { bool ipv6; i2p::config::GetOption("ipv6", ipv6); @@ -1196,6 +1201,8 @@ namespace transport i2p::context.PublishSSU2Address (ssu2port, false, ipv4, ipv6); // unpublish } + bool checkReserved; i2p::config::GetOption("reservedrange", checkReserved); + transports.SetCheckReserved (checkReserved); } } } diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index cb63ca91..7ef7f9b2 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -167,7 +167,8 @@ namespace transport void PeerTest (bool ipv4 = true, bool ipv6 = true); void SetCheckReserved (bool check) { m_CheckReserved = check; }; - bool IsCheckReserved () { return m_CheckReserved; }; + bool IsCheckReserved () const { return m_CheckReserved; }; + bool IsInReservedRange (const boost::asio::ip::address& host) const; private: From 34d75b08ddac5a3655dab2f89793528562af30d2 Mon Sep 17 00:00:00 2001 From: Vort Date: Fri, 12 Jan 2024 17:13:07 +0200 Subject: [PATCH 0263/1171] handle 'reservedrange' param properly --- daemon/Daemon.cpp | 4 ++++ libi2pd/Transports.cpp | 3 --- libi2pd/api.cpp | 5 ++++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/daemon/Daemon.cpp b/daemon/Daemon.cpp index 308daa4c..17d17f72 100644 --- a/daemon/Daemon.cpp +++ b/daemon/Daemon.cpp @@ -160,6 +160,10 @@ namespace util int netID; i2p::config::GetOption("netid", netID); i2p::context.SetNetID (netID); + + bool checkReserved; i2p::config::GetOption("reservedrange", checkReserved); + i2p::transport::transports.SetCheckReserved(checkReserved); + i2p::context.Init (); i2p::transport::InitTransports (); diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 318d410f..0bd17104 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -1200,9 +1200,6 @@ namespace transport else i2p::context.PublishSSU2Address (ssu2port, false, ipv4, ipv6); // unpublish } - - bool checkReserved; i2p::config::GetOption("reservedrange", checkReserved); - transports.SetCheckReserved (checkReserved); } } } diff --git a/libi2pd/api.cpp b/libi2pd/api.cpp index ad24519f..05f962f3 100644 --- a/libi2pd/api.cpp +++ b/libi2pd/api.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -44,6 +44,9 @@ namespace api int netID; i2p::config::GetOption("netid", netID); i2p::context.SetNetID (netID); + bool checkReserved; i2p::config::GetOption("reservedrange", checkReserved); + i2p::transport::transports.SetCheckReserved(checkReserved); + i2p::context.Init (); } From d8f6c4a93dc1722463754eb5c1670a4bab2f2304 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 14 Jan 2024 17:16:31 -0500 Subject: [PATCH 0264/1171] correct encryption and path for follow on lookup request --- libi2pd/NetDb.cpp | 42 +++-------------- libi2pd/NetDbRequests.cpp | 94 +++++++++++++++++++++++++-------------- libi2pd/NetDbRequests.h | 24 ++++++---- 3 files changed, 83 insertions(+), 77 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 6e023c45..8eb5d653 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -721,7 +721,7 @@ namespace data void NetDb::RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete, bool direct) { - auto dest = m_Requests.CreateRequest (destination, false, requestComplete); // non-exploratory + auto dest = m_Requests.CreateRequest (destination, false, direct, requestComplete); // non-exploratory if (!dest) { LogPrint (eLogWarning, "NetDb: Destination ", destination.ToBase64(), " is requested already"); @@ -761,10 +761,10 @@ namespace data } } - void NetDb::RequestDestinationFrom (const IdentHash& destination, const IdentHash & from, bool exploritory, RequestedDestination::RequestComplete requestComplete) + void NetDb::RequestDestinationFrom (const IdentHash& destination, const IdentHash & from, bool exploratory, RequestedDestination::RequestComplete requestComplete) { - auto dest = m_Requests.CreateRequest (destination, exploritory, requestComplete); // non-exploratory + auto dest = m_Requests.CreateRequest (destination, exploratory, true, requestComplete); // non-exploratory if (!dest) { LogPrint (eLogWarning, "NetDb: Destination ", destination.ToBase64(), " is requested already"); @@ -919,39 +919,9 @@ namespace data auto dest = m_Requests.FindRequest (ident); if (dest) { - bool deleteDest = true; if (num > 0) - { - auto pool = i2p::tunnel::tunnels.GetExploratoryPool (); - auto outbound = pool ? pool->GetNextOutboundTunnel () : nullptr; - auto inbound = pool ? pool->GetNextInboundTunnel () : nullptr; - if (!dest->IsExploratory ()) - { - // reply to our destination. Try other floodfills - if (outbound && inbound) - { - auto count = dest->GetExcludedPeers ().size (); - if (count < 7) - { - auto nextFloodfill = GetClosestFloodfill (dest->GetDestination (), dest->GetExcludedPeers ()); - if (nextFloodfill) - { - // request destination - LogPrint (eLogDebug, "NetDb: Try ", key, " at ", count, " floodfill ", nextFloodfill->GetIdentHash ().ToBase64 ()); - outbound->SendTunnelDataMsgTo (nextFloodfill->GetIdentHash (), 0, - dest->CreateRequestMessage (nextFloodfill, inbound)); - deleteDest = false; - } - } - else - LogPrint (eLogWarning, "NetDb: ", key, " was not found on ", count, " floodfills"); - } - } - - if (deleteDest) - // no more requests for the destinationation. delete it - m_Requests.RequestComplete (ident, nullptr); - } + // try to send next requests + m_Requests.SendNextRequest (dest); else // no more requests for destination possible. delete it m_Requests.RequestComplete (ident, nullptr); @@ -1156,7 +1126,7 @@ namespace data for (int i = 0; i < numDestinations; i++) { RAND_bytes (randomHash, 32); - auto dest = m_Requests.CreateRequest (randomHash, true); // exploratory + auto dest = m_Requests.CreateRequest (randomHash, true, !throughTunnels); // exploratory if (!dest) { LogPrint (eLogWarning, "NetDb: Exploratory destination is requested already"); diff --git a/libi2pd/NetDbRequests.cpp b/libi2pd/NetDbRequests.cpp index 4011b8aa..2cb578e2 100644 --- a/libi2pd/NetDbRequests.cpp +++ b/libi2pd/NetDbRequests.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -11,6 +11,7 @@ #include "Transports.h" #include "NetDb.hpp" #include "NetDbRequests.h" +#include "ECIESX25519AEADRatchetSession.h" namespace i2p { @@ -74,14 +75,15 @@ namespace data } - std::shared_ptr NetDbRequests::CreateRequest (const IdentHash& destination, bool isExploratory, RequestedDestination::RequestComplete requestComplete) + std::shared_ptr NetDbRequests::CreateRequest (const IdentHash& destination, + bool isExploratory, bool direct, RequestedDestination::RequestComplete requestComplete) { // request RouterInfo directly - auto dest = std::make_shared (destination, isExploratory); + auto dest = std::make_shared (destination, isExploratory, direct); dest->SetRequestComplete (requestComplete); { - std::unique_lock l(m_RequestedDestinationsMutex); - if (!m_RequestedDestinations.insert (std::make_pair (destination, dest)).second) // not inserted + std::unique_lock l(m_RequestedDestinationsMutex); + if (!m_RequestedDestinations.emplace (destination, dest).second) // not inserted return nullptr; } return dest; @@ -125,35 +127,10 @@ namespace data { auto& dest = it->second; bool done = false; - if (ts < dest->GetCreationTime () + 60) // request is worthless after 1 minute + if (ts < dest->GetCreationTime () + MAX_REQUEST_TIME) // request becomes worthless { - if (ts > dest->GetCreationTime () + 5) // no response for 5 seconds - { - auto count = dest->GetExcludedPeers ().size (); - if (!dest->IsExploratory () && count < 7) - { - auto pool = i2p::tunnel::tunnels.GetExploratoryPool (); - auto outbound = pool->GetNextOutboundTunnel (); - auto inbound = pool->GetNextInboundTunnel (); - auto nextFloodfill = netdb.GetClosestFloodfill (dest->GetDestination (), dest->GetExcludedPeers ()); - if (nextFloodfill && outbound && inbound) - outbound->SendTunnelDataMsgTo (nextFloodfill->GetIdentHash (), 0, - dest->CreateRequestMessage (nextFloodfill, inbound)); - else - { - done = true; - if (!inbound) LogPrint (eLogWarning, "NetDbReq: No inbound tunnels"); - if (!outbound) LogPrint (eLogWarning, "NetDbReq: No outbound tunnels"); - if (!nextFloodfill) LogPrint (eLogWarning, "NetDbReq: No more floodfills"); - } - } - else - { - if (!dest->IsExploratory ()) - LogPrint (eLogWarning, "NetDbReq: ", dest->GetDestination ().ToBase64 (), " not found after 7 attempts"); - done = true; - } - } + if (ts > dest->GetCreationTime () + MIN_REQUEST_TIME) // retry in no response after min interval + done = !SendNextRequest (dest); } else // delete obsolete request done = true; @@ -164,5 +141,56 @@ namespace data ++it; } } + + bool NetDbRequests::SendNextRequest (std::shared_ptr dest) + { + if (!dest) return false; + bool ret = true; + auto count = dest->GetExcludedPeers ().size (); + if (!dest->IsExploratory () && count < MAX_NUM_REQUEST_ATTEMPTS) + { + auto nextFloodfill = netdb.GetClosestFloodfill (dest->GetDestination (), dest->GetExcludedPeers ()); + if (nextFloodfill) + { + bool direct = dest->IsDirect (); + if (direct && !nextFloodfill->IsReachableFrom (i2p::context.GetRouterInfo ()) && + !i2p::transport::transports.IsConnected (nextFloodfill->GetIdentHash ())) + direct = false; // floodfill can't be reached directly + if (direct) + i2p::transport::transports.SendMessage (nextFloodfill->GetIdentHash (), dest->CreateRequestMessage (nextFloodfill->GetIdentHash ())); + else + { + auto pool = i2p::tunnel::tunnels.GetExploratoryPool (); + auto outbound = pool->GetNextOutboundTunnel (); + auto inbound = pool->GetNextInboundTunnel (); + if (nextFloodfill && outbound && inbound) + { + LogPrint (eLogDebug, "NetDbReq: Try ", dest->GetDestination (), " at ", count, " floodfill ", nextFloodfill->GetIdentHash ().ToBase64 ()); + auto msg = dest->CreateRequestMessage (nextFloodfill, inbound); + outbound->SendTunnelDataMsgTo (nextFloodfill->GetIdentHash (), 0, + i2p::garlic::WrapECIESX25519MessageForRouter (msg, nextFloodfill->GetIdentity ()->GetEncryptionPublicKey ())); + } + else + { + ret = false; + if (!inbound) LogPrint (eLogWarning, "NetDbReq: No inbound tunnels"); + if (!outbound) LogPrint (eLogWarning, "NetDbReq: No outbound tunnels"); + } + } + } + else + { + ret = false; + if (!nextFloodfill) LogPrint (eLogWarning, "NetDbReq: No more floodfills"); + } + } + else + { + if (!dest->IsExploratory ()) + LogPrint (eLogWarning, "NetDbReq: ", dest->GetDestination ().ToBase64 (), " not found after 7 attempts"); + ret = false; + } + return ret; + } } } diff --git a/libi2pd/NetDbRequests.h b/libi2pd/NetDbRequests.h index cf2f0915..a4d1cf21 100644 --- a/libi2pd/NetDbRequests.h +++ b/libi2pd/NetDbRequests.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -9,9 +9,10 @@ #ifndef NETDB_REQUESTS_H__ #define NETDB_REQUESTS_H__ +#include #include #include -#include +#include #include "Identity.h" #include "RouterInfo.h" @@ -19,14 +20,18 @@ namespace i2p { namespace data { + const size_t MAX_NUM_REQUEST_ATTEMPTS = 7; + const uint64_t MIN_REQUEST_TIME = 5; // in seconds + const uint64_t MAX_REQUEST_TIME = 60; // in seconds + class RequestedDestination { public: typedef std::function)> RequestComplete; - RequestedDestination (const IdentHash& destination, bool isExploratory = false): - m_Destination (destination), m_IsExploratory (isExploratory), m_CreationTime (0) {}; + RequestedDestination (const IdentHash& destination, bool isExploratory = false, bool direct = true): + m_Destination (destination), m_IsExploratory (isExploratory), m_IsDirect (direct), m_CreationTime (0) {}; ~RequestedDestination () { if (m_RequestComplete) m_RequestComplete (nullptr); }; const IdentHash& GetDestination () const { return m_Destination; }; @@ -34,6 +39,7 @@ namespace data const std::set& GetExcludedPeers () { return m_ExcludedPeers; }; void ClearExcludedPeers (); bool IsExploratory () const { return m_IsExploratory; }; + bool IsDirect () const { return m_IsDirect; }; bool IsExcluded (const IdentHash& ident) const { return m_ExcludedPeers.count (ident); }; uint64_t GetCreationTime () const { return m_CreationTime; }; std::shared_ptr CreateRequestMessage (std::shared_ptr, std::shared_ptr replyTunnel); @@ -47,7 +53,7 @@ namespace data private: IdentHash m_Destination; - bool m_IsExploratory; + bool m_IsExploratory, m_IsDirect; std::set m_ExcludedPeers; uint64_t m_CreationTime; RequestComplete m_RequestComplete; @@ -60,15 +66,17 @@ namespace data void Start (); void Stop (); - std::shared_ptr CreateRequest (const IdentHash& destination, bool isExploratory, RequestedDestination::RequestComplete requestComplete = nullptr); + std::shared_ptr CreateRequest (const IdentHash& destination, bool isExploratory, + bool direct = false, RequestedDestination::RequestComplete requestComplete = nullptr); void RequestComplete (const IdentHash& ident, std::shared_ptr r); std::shared_ptr FindRequest (const IdentHash& ident) const; void ManageRequests (); - + bool SendNextRequest (std::shared_ptr dest); + private: mutable std::mutex m_RequestedDestinationsMutex; - std::map > m_RequestedDestinations; + std::unordered_map > m_RequestedDestinations; }; } } From 4afdca090d33ba2d2bb390e46637ba42aa42fc5d Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 14 Jan 2024 18:54:21 -0500 Subject: [PATCH 0265/1171] support multiple RouterInfo request callbacks --- libi2pd/NetDbRequests.cpp | 20 +++++++++++++++++++- libi2pd/NetDbRequests.h | 1 + 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/libi2pd/NetDbRequests.cpp b/libi2pd/NetDbRequests.cpp index 2cb578e2..167095d7 100644 --- a/libi2pd/NetDbRequests.cpp +++ b/libi2pd/NetDbRequests.cpp @@ -83,8 +83,26 @@ namespace data dest->SetRequestComplete (requestComplete); { std::unique_lock l(m_RequestedDestinationsMutex); - if (!m_RequestedDestinations.emplace (destination, dest).second) // not inserted + auto ret = m_RequestedDestinations.emplace (destination, dest); + if (!ret.second) // not inserted + { + dest->SetRequestComplete (nullptr); // don't call requestComplete in destructor + if (requestComplete) + { + auto prev = ret.first->second->GetRequestComplete (); + if (prev) // if already set + ret.first->second->SetRequestComplete ( + [requestComplete, prev](std::shared_ptr r) + { + prev (r); // call previous + requestComplete (r); // then new + }); + else + ret.first->second->SetRequestComplete (requestComplete); + } + return nullptr; + } } return dest; } diff --git a/libi2pd/NetDbRequests.h b/libi2pd/NetDbRequests.h index a4d1cf21..001b0f07 100644 --- a/libi2pd/NetDbRequests.h +++ b/libi2pd/NetDbRequests.h @@ -46,6 +46,7 @@ namespace data std::shared_ptr CreateRequestMessage (const IdentHash& floodfill); void SetRequestComplete (const RequestComplete& requestComplete) { m_RequestComplete = requestComplete; }; + RequestComplete GetRequestComplete () const { return m_RequestComplete; }; bool IsRequestComplete () const { return m_RequestComplete != nullptr; }; void Success (std::shared_ptr r); void Fail (); From 49f4dc53adf1c3d464f4d9baaae3c49dfe6ae8af Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 15 Jan 2024 19:32:17 -0500 Subject: [PATCH 0266/1171] try next floodfill for router request on demand --- libi2pd/NetDbRequests.cpp | 21 +++++++++++++++++---- libi2pd/NetDbRequests.h | 8 ++++---- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/libi2pd/NetDbRequests.cpp b/libi2pd/NetDbRequests.cpp index 167095d7..92e5a7b8 100644 --- a/libi2pd/NetDbRequests.cpp +++ b/libi2pd/NetDbRequests.cpp @@ -17,6 +17,17 @@ namespace i2p { namespace data { + RequestedDestination::RequestedDestination (const IdentHash& destination, bool isExploratory, bool direct): + m_Destination (destination), m_IsExploratory (isExploratory), m_IsDirect (direct), + m_CreationTime (i2p::util::GetSecondsSinceEpoch ()), m_LastRequestTime (0) + { + } + + RequestedDestination::~RequestedDestination () + { + if (m_RequestComplete) m_RequestComplete (nullptr); + } + std::shared_ptr RequestedDestination::CreateRequestMessage (std::shared_ptr router, std::shared_ptr replyTunnel) { @@ -29,7 +40,7 @@ namespace data msg = i2p::CreateRouterInfoDatabaseLookupMsg(m_Destination, i2p::context.GetIdentHash(), 0, m_IsExploratory, &m_ExcludedPeers); if(router) m_ExcludedPeers.insert (router->GetIdentHash ()); - m_CreationTime = i2p::util::GetSecondsSinceEpoch (); + m_LastRequestTime = i2p::util::GetSecondsSinceEpoch (); return msg; } @@ -38,7 +49,7 @@ namespace data auto msg = i2p::CreateRouterInfoDatabaseLookupMsg (m_Destination, i2p::context.GetRouterInfo ().GetIdentHash () , 0, false, &m_ExcludedPeers); m_ExcludedPeers.insert (floodfill); - m_CreationTime = i2p::util::GetSecondsSinceEpoch (); + m_LastRequestTime = i2p::util::GetSecondsSinceEpoch (); return msg; } @@ -100,7 +111,9 @@ namespace data else ret.first->second->SetRequestComplete (requestComplete); } - + if (i2p::util::GetSecondsSinceEpoch () > ret.first->second->GetLastRequestTime () + MIN_REQUEST_TIME) + if (!SendNextRequest (ret.first->second)) // try next floodfill + m_RequestedDestinations.erase (ret.first); // delete request if failed return nullptr; } } @@ -147,7 +160,7 @@ namespace data bool done = false; if (ts < dest->GetCreationTime () + MAX_REQUEST_TIME) // request becomes worthless { - if (ts > dest->GetCreationTime () + MIN_REQUEST_TIME) // retry in no response after min interval + if (ts > dest->GetLastRequestTime () + MIN_REQUEST_TIME) // try next floodfill if no response after min interval done = !SendNextRequest (dest); } else // delete obsolete request diff --git a/libi2pd/NetDbRequests.h b/libi2pd/NetDbRequests.h index 001b0f07..47a5d481 100644 --- a/libi2pd/NetDbRequests.h +++ b/libi2pd/NetDbRequests.h @@ -30,9 +30,8 @@ namespace data typedef std::function)> RequestComplete; - RequestedDestination (const IdentHash& destination, bool isExploratory = false, bool direct = true): - m_Destination (destination), m_IsExploratory (isExploratory), m_IsDirect (direct), m_CreationTime (0) {}; - ~RequestedDestination () { if (m_RequestComplete) m_RequestComplete (nullptr); }; + RequestedDestination (const IdentHash& destination, bool isExploratory = false, bool direct = true); + ~RequestedDestination (); const IdentHash& GetDestination () const { return m_Destination; }; int GetNumExcludedPeers () const { return m_ExcludedPeers.size (); }; @@ -42,6 +41,7 @@ namespace data bool IsDirect () const { return m_IsDirect; }; bool IsExcluded (const IdentHash& ident) const { return m_ExcludedPeers.count (ident); }; uint64_t GetCreationTime () const { return m_CreationTime; }; + uint64_t GetLastRequestTime () const { return m_LastRequestTime; }; std::shared_ptr CreateRequestMessage (std::shared_ptr, std::shared_ptr replyTunnel); std::shared_ptr CreateRequestMessage (const IdentHash& floodfill); @@ -56,7 +56,7 @@ namespace data IdentHash m_Destination; bool m_IsExploratory, m_IsDirect; std::set m_ExcludedPeers; - uint64_t m_CreationTime; + uint64_t m_CreationTime, m_LastRequestTime; // in seconds RequestComplete m_RequestComplete; }; From 7cfcb12c7b0f3e9c3f6408c404b22e0a3e3e53bf Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 16 Jan 2024 14:33:36 -0500 Subject: [PATCH 0267/1171] don't create peer for unreachable router --- libi2pd/Transports.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 0bd17104..eb836354 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -436,6 +436,10 @@ namespace transport auto it = m_Peers.find (ident); if (it == m_Peers.end ()) { + // check if not known as unreachable + auto profile = i2p::data::GetRouterProfile (ident); + if (profile && profile->IsUnreachable ()) return; // don't create peer to unreachable router + // try to connect bool connected = false; try { From 39e378a03dda77cb380182c1c0c192478caa44e9 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 17 Jan 2024 18:15:49 -0500 Subject: [PATCH 0268/1171] check received data size --- libi2pd/NTCP2.cpp | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index efc317c2..c52c5cc2 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -809,10 +809,15 @@ namespace transport void NTCP2Session::HandleReceivedLength (const boost::system::error_code& ecode, std::size_t bytes_transferred) { - if (ecode) + if (ecode || bytes_transferred != 2) { if (ecode != boost::asio::error::operation_aborted) - LogPrint (eLogWarning, "NTCP2: Receive length read error: ", ecode.message ()); + { + if (ecode) + LogPrint (eLogWarning, "NTCP2: Receive length read error: ", ecode.message ()); + else if (bytes_transferred != 2) + LogPrint (eLogError, "NTCP2: Receive length of ", bytes_transferred, " bytes"); + } Terminate (); } else @@ -833,14 +838,19 @@ namespace transport CreateNextReceivedBuffer (m_NextReceivedLen); boost::system::error_code ec; size_t moreBytes = m_Socket.available(ec); - if (!ec && moreBytes >= m_NextReceivedLen) - { - // read and process message immediately if available - moreBytes = boost::asio::read (m_Socket, boost::asio::buffer(m_NextReceivedBuffer, m_NextReceivedLen), boost::asio::transfer_all (), ec); - HandleReceived (ec, moreBytes); - } + if (!ec) + { + if (moreBytes >= m_NextReceivedLen) + { + // read and process message immediately if available + moreBytes = boost::asio::read (m_Socket, boost::asio::buffer(m_NextReceivedBuffer, m_NextReceivedLen), boost::asio::transfer_all (), ec); + HandleReceived (ec, moreBytes); + } + else + Receive (); + } else - Receive (); + LogPrint (eLogWarning, "NTCP2: Socket error: ", ec.message ()); } else { @@ -864,10 +874,15 @@ namespace transport void NTCP2Session::HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred) { - if (ecode) + if (ecode || bytes_transferred != m_NextReceivedLen) { - if (ecode != boost::asio::error::operation_aborted) - LogPrint (eLogWarning, "NTCP2: Receive read error: ", ecode.message ()); + if (ecode != boost::asio::error::operation_aborted) + { + if (ecode) + LogPrint (eLogWarning, "NTCP2: Receive read error: ", ecode.message ()); + else if (bytes_transferred != m_NextReceivedLen) + LogPrint (eLogError, "NTCP2: Received ", bytes_transferred, " bytes. Instead ", m_NextReceivedLen); + } Terminate (); } else From 1e5604ed4373dcea18a8353df188451d592bd864 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 18 Jan 2024 19:18:51 -0500 Subject: [PATCH 0269/1171] check if peer is connected before trying to connect --- libi2pd/Transports.cpp | 15 ++++++++------- libi2pd/Transports.h | 2 ++ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index eb836354..5d3027a9 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -458,7 +458,7 @@ namespace transport } if (!connected) return; } - if (!it->second.sessions.empty ()) + if (it->second.IsConnected ()) it->second.sessions.front ()->SendI2NPMessages (msgs); else { @@ -616,7 +616,8 @@ namespace transport { LogPrint (eLogDebug, "Transports: RouterInfo for ", ident.ToBase64 (), " found, trying to connect"); it->second.SetRouter (r); - ConnectToPeer (ident, it->second); + if (!it->second.IsConnected ()) + ConnectToPeer (ident, it->second); } else { @@ -810,13 +811,13 @@ namespace transport auto it = m_Peers.find (ident); if (it != m_Peers.end ()) { - auto before = it->second.sessions.size (); + bool wasConnected = it->second.IsConnected (); it->second.sessions.remove (session); - if (it->second.sessions.empty ()) + if (!it->second.IsConnected ()) { if (it->second.delayedMessages.size () > 0) { - if (before > 0) // we had an active session before + if (wasConnected) // we had an active session before it->second.numAttempts = 0; // start over ConnectToPeer (ident, it->second); } @@ -849,7 +850,7 @@ namespace transport { return !session || !session->IsEstablished (); }); - if (it->second.sessions.empty () && ts > it->second.creationTime + SESSION_CREATION_TIMEOUT) + if (!it->second.IsConnected () && ts > it->second.creationTime + SESSION_CREATION_TIMEOUT) { LogPrint (eLogWarning, "Transports: Session to peer ", it->first.ToBase64 (), " has not been created in ", SESSION_CREATION_TIMEOUT, " seconds"); /* if (!it->second.router) @@ -991,7 +992,7 @@ namespace transport [isHighBandwidth](const Peer& peer)->bool { // connected, not overloaded and not slow - return !peer.router && !peer.sessions.empty () && peer.isReachable && + return !peer.router && peer.IsConnected () && peer.isReachable && peer.sessions.front ()->GetSendQueueSize () <= PEER_ROUTER_INFO_OVERLOAD_QUEUE_SIZE && !peer.sessions.front ()->IsSlow () && !peer.sessions.front ()->IsBandwidthExceeded (peer.isHighBandwidth) && (!isHighBandwidth || peer.isHighBandwidth); diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index 7ef7f9b2..0e5518b1 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -101,6 +101,8 @@ namespace transport isReachable = (bool)router->GetCompatibleTransports (true); } } + + bool IsConnected () const { return !sessions.empty (); } }; const uint64_t SESSION_CREATION_TIMEOUT = 15; // in seconds From b4484c8e8f7615b6beeab872515c3f9ff1dc3bc9 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Fri, 19 Jan 2024 21:54:10 +0300 Subject: [PATCH 0270/1171] [gha] msvc: switch back to boost 1.81.0 --- .github/workflows/build-windows-msvc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-windows-msvc.yml b/.github/workflows/build-windows-msvc.yml index 5af526e2..dea64644 100644 --- a/.github/workflows/build-windows-msvc.yml +++ b/.github/workflows/build-windows-msvc.yml @@ -38,7 +38,7 @@ jobs: - name: Install Boost run: | - powershell -Command "(Invoke-WebRequest -UserAgent "Wget" -Uri https://sourceforge.net/projects/boost/files/boost-binaries/1.84.0/boost_1_84_0-msvc-14.3-64.exe/download -OutFile boost_1_84_0-msvc-14.3-64.exe)" + powershell -Command "(Invoke-WebRequest -UserAgent "Wget" -Uri https://sourceforge.net/projects/boost/files/boost-binaries/1.81.0/boost_1_81_0-msvc-14.3-64.exe/download -OutFile boost_1_84_0-msvc-14.3-64.exe)" ./boost_1_84_0-msvc-14.3-64.exe /VERYSILENT - name: Install OpenSSL From 140146e433a83eb9137d668baedc13282a5a03c0 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 19 Jan 2024 14:09:48 -0500 Subject: [PATCH 0271/1171] limit mininal received packet size to 40 bytes --- libi2pd/SSU2.cpp | 9 ++++++++- libi2pd/SSU2.h | 3 ++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 1503b404..1fb10927 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -283,8 +283,15 @@ namespace transport // but better to find out which host were sent it and mark that router as unreachable { i2p::transport::transports.UpdateReceivedBytes (bytes_transferred); + if (bytes_transferred < SSU2_MIN_RECEIVED_PACKET_SIZE) + { + // drop too short packets + m_PacketsPool.ReleaseMt (packet); + Receive (socket); + return; + } packet->len = bytes_transferred; - + boost::system::error_code ec; size_t moreBytes = socket.available (ec); if (!ec && moreBytes) diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index 03e22245..6d07f7fa 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022-2023, The PurpleI2P Project +* Copyright (c) 2022-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -27,6 +27,7 @@ namespace transport const size_t SSU2_SOCKET_RECEIVE_BUFFER_SIZE = 0x1FFFF; // 128K const size_t SSU2_SOCKET_SEND_BUFFER_SIZE = 0x1FFFF; // 128K const size_t SSU2_MAX_NUM_INTRODUCERS = 3; + const size_t SSU2_MIN_RECEIVED_PACKET_SIZE = 40; // 16 byte short header + 8 byte minimum payload + 16 byte MAC const int SSU2_TO_INTRODUCER_SESSION_DURATION = 3600; // 1 hour const int SSU2_TO_INTRODUCER_SESSION_EXPIRATION = 4800; // 80 minutes const int SSU2_KEEP_ALIVE_INTERVAL = 15; // in seconds From 0b47f65b069e47187efed3707c90866d0b036f39 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 19 Jan 2024 18:29:17 -0500 Subject: [PATCH 0272/1171] don't remove another NTCP2 session with same address --- libi2pd/NTCP2.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index c52c5cc2..a58ab0a2 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1415,7 +1415,11 @@ namespace transport void NTCP2Server::RemoveNTCP2Session (std::shared_ptr session) { if (session && session->GetRemoteIdentity ()) - m_NTCP2Sessions.erase (session->GetRemoteIdentity ()->GetIdentHash ()); + { + auto it = m_NTCP2Sessions.find (session->GetRemoteIdentity ()->GetIdentHash ()); + if (it != m_NTCP2Sessions.end () && it->second == session) + m_NTCP2Sessions.erase (it); + } } std::shared_ptr NTCP2Server::FindNTCP2Session (const i2p::data::IdentHash& ident) From 5e19e361e7ececd3008615a623e48f7f2f351e8b Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 20 Jan 2024 17:33:28 -0500 Subject: [PATCH 0273/1171] check max frame sizebefore sending --- libi2pd/NTCP2.cpp | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index a58ab0a2..45968f7d 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -809,15 +809,10 @@ namespace transport void NTCP2Session::HandleReceivedLength (const boost::system::error_code& ecode, std::size_t bytes_transferred) { - if (ecode || bytes_transferred != 2) + if (ecode) { if (ecode != boost::asio::error::operation_aborted) - { - if (ecode) - LogPrint (eLogWarning, "NTCP2: Receive length read error: ", ecode.message ()); - else if (bytes_transferred != 2) - LogPrint (eLogError, "NTCP2: Receive length of ", bytes_transferred, " bytes"); - } + LogPrint (eLogWarning, "NTCP2: Receive length read error: ", ecode.message ()); Terminate (); } else @@ -874,15 +869,10 @@ namespace transport void NTCP2Session::HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred) { - if (ecode || bytes_transferred != m_NextReceivedLen) + if (ecode) { if (ecode != boost::asio::error::operation_aborted) - { - if (ecode) - LogPrint (eLogWarning, "NTCP2: Receive read error: ", ecode.message ()); - else if (bytes_transferred != m_NextReceivedLen) - LogPrint (eLogError, "NTCP2: Received ", bytes_transferred, " bytes. Instead ", m_NextReceivedLen); - } + LogPrint (eLogWarning, "NTCP2: Receive read error: ", ecode.message ()); Terminate (); } else @@ -1061,6 +1051,11 @@ namespace transport macBuf = m_NextSendBuffer + paddingLen; totalLen += paddingLen; } + if (totalLen > NTCP2_UNENCRYPTED_FRAME_MAX_SIZE) + { + LogPrint (eLogError, "NTCP2: Frame to send is too long ", totalLen); + return; + } uint8_t nonce[12]; CreateNonce (m_SendSequenceNumber, nonce); m_SendSequenceNumber++; i2p::crypto::AEADChaCha20Poly1305Encrypt (encryptBufs, m_SendKey, nonce, macBuf); // encrypt buffers @@ -1085,6 +1080,12 @@ namespace transport delete[] m_NextSendBuffer; m_NextSendBuffer = nullptr; return; } + if (payloadLen > NTCP2_UNENCRYPTED_FRAME_MAX_SIZE) + { + LogPrint (eLogError, "NTCP2: Buffer to send is too long ", payloadLen); + delete[] m_NextSendBuffer; m_NextSendBuffer = nullptr; + return; + } // encrypt uint8_t nonce[12]; CreateNonce (m_SendSequenceNumber, nonce); m_SendSequenceNumber++; @@ -1160,7 +1161,12 @@ namespace transport len -= 3; if (msgLen < 256) msgLen = 256; // for short message padding should not be always zero size_t paddingSize = (msgLen*NTCP2_MAX_PADDING_RATIO)/100; - if (msgLen + paddingSize + 3 > NTCP2_UNENCRYPTED_FRAME_MAX_SIZE) paddingSize = NTCP2_UNENCRYPTED_FRAME_MAX_SIZE - msgLen -3; + if (msgLen + paddingSize + 3 > NTCP2_UNENCRYPTED_FRAME_MAX_SIZE) + { + ssize_t l = NTCP2_UNENCRYPTED_FRAME_MAX_SIZE - msgLen -3; + if (l <= 0) return 0; + paddingSize = l; + } if (paddingSize > len) paddingSize = len; if (paddingSize) { @@ -1169,7 +1175,7 @@ namespace transport RAND_bytes ((uint8_t *)m_PaddingSizes, sizeof (m_PaddingSizes)); m_NextPaddingSize = 0; } - paddingSize = m_PaddingSizes[m_NextPaddingSize++] % paddingSize; + paddingSize = m_PaddingSizes[m_NextPaddingSize++] % (paddingSize + 1); } buf[0] = eNTCP2BlkPadding; // blk htobe16buf (buf + 1, paddingSize); // size From 9f217f8a117089e7a4e3d9eeb732f7a741f11edf Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 21 Jan 2024 18:59:04 -0500 Subject: [PATCH 0274/1171] don't send expired I2NP messages --- libi2pd/I2NPProtocol.cpp | 10 +++++++--- libi2pd/I2NPProtocol.h | 3 ++- libi2pd/NTCP2.cpp | 7 +++++++ libi2pd/SSU2Session.cpp | 3 ++- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index b8147555..ebd5f8d6 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -72,11 +72,15 @@ namespace i2p SetExpiration (i2p::util::GetMillisecondsSinceEpoch () + I2NP_MESSAGE_EXPIRATION_TIMEOUT); } - bool I2NPMessage::IsExpired () const + bool I2NPMessage::IsExpired (uint64_t ts) const { - auto ts = i2p::util::GetMillisecondsSinceEpoch (); auto exp = GetExpiration (); return (ts > exp + I2NP_MESSAGE_CLOCK_SKEW) || (ts < exp - 3*I2NP_MESSAGE_CLOCK_SKEW); // check if expired or too far in future + } + + bool I2NPMessage::IsExpired () const + { + return IsExpired (i2p::util::GetMillisecondsSinceEpoch ()); } std::shared_ptr CreateI2NPMessage (I2NPMessageType msgType, const uint8_t * buf, size_t len, uint32_t replyMsgID) diff --git a/libi2pd/I2NPProtocol.h b/libi2pd/I2NPProtocol.h index 6c64f2ab..e86f4f32 100644 --- a/libi2pd/I2NPProtocol.h +++ b/libi2pd/I2NPProtocol.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -252,6 +252,7 @@ namespace tunnel void FillI2NPMessageHeader (I2NPMessageType msgType, uint32_t replyMsgID = 0, bool checksum = true); void RenewI2NPMessageHeader (); bool IsExpired () const; + bool IsExpired (uint64_t ts) const; // in milliseconds }; template diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 45968f7d..925c89dd 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1132,10 +1132,17 @@ namespace transport if (!m_SendQueue.empty ()) { std::vector > msgs; + auto ts = i2p::util::GetMillisecondsSinceEpoch (); size_t s = 0; while (!m_SendQueue.empty ()) { auto msg = m_SendQueue.front (); + if (!msg || msg->IsExpired (ts)) + { + // drop null or expired message + m_SendQueue.pop_front (); + continue; + } size_t len = msg->GetNTCP2Length (); if (s + len + 3 <= NTCP2_UNENCRYPTED_FRAME_MAX_SIZE) // 3 bytes block header { diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 8cb39102..3ea07629 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -379,8 +379,9 @@ namespace transport while (!m_SendQueue.empty () && m_SentPackets.size () <= m_WindowSize) { auto msg = m_SendQueue.front (); - if (!msg) + if (!msg || msg->IsExpired (ts)) { + // drop null or expired message m_SendQueue.pop_front (); continue; } From a2249f0a82ca29215b039e15e7755be9f6012735 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 24 Jan 2024 13:52:13 -0500 Subject: [PATCH 0275/1171] identify server tunnel session but from ant to ports --- libi2pd_client/UDPTunnel.cpp | 57 +++++++++++++++++++++++++----------- libi2pd_client/UDPTunnel.h | 7 +++-- 2 files changed, 44 insertions(+), 20 deletions(-) diff --git a/libi2pd_client/UDPTunnel.cpp b/libi2pd_client/UDPTunnel.cpp index 1e4b3d7c..3fcf8b35 100644 --- a/libi2pd_client/UDPTunnel.cpp +++ b/libi2pd_client/UDPTunnel.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -27,8 +27,17 @@ namespace client m_LastSession->LastActivity = i2p::util::GetMillisecondsSinceEpoch(); } - void I2PUDPServerTunnel::HandleRecvFromI2PRaw (uint16_t, uint16_t, const uint8_t * buf, size_t len) + void I2PUDPServerTunnel::HandleRecvFromI2PRaw (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) { + if (m_LastSession && (fromPort != m_LastSession->RemotePort || toPort != m_LastSession->LocalPort)) + { + std::lock_guard lock(m_SessionsMutex); + auto it = m_Sessions.find (GetSessionIndex (fromPort, toPort)); + if (it != m_Sessions.end ()) + m_LastSession = it->second; + else + m_LastSession = nullptr; + } if (m_LastSession) { m_LastSession->IPSocket.send_to(boost::asio::buffer(buf, len), m_RemoteEndpoint); @@ -41,11 +50,12 @@ namespace client std::lock_guard lock(m_SessionsMutex); uint64_t now = i2p::util::GetMillisecondsSinceEpoch(); auto itr = m_Sessions.begin(); - while(itr != m_Sessions.end()) { - if(now - (*itr)->LastActivity >= delta ) + while(itr != m_Sessions.end()) + { + if(now - itr->second->LastActivity >= delta ) itr = m_Sessions.erase(itr); else - ++itr; + itr++; } } @@ -66,15 +76,25 @@ namespace client UDPSessionPtr I2PUDPServerTunnel::ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort) { auto ih = from.GetIdentHash(); - for (auto & s : m_Sessions ) + auto idx = GetSessionIndex (remotePort, localPort); { - if (s->Identity.GetLL()[0] == ih.GetLL()[0] && remotePort == s->RemotePort) + std::lock_guard lock(m_SessionsMutex); + auto it = m_Sessions.find (idx); + if (it != m_Sessions.end ()) { - /** found existing session */ - LogPrint(eLogDebug, "UDPServer: Found session ", s->IPSocket.local_endpoint(), " ", ih.ToBase32()); - return s; - } - } + if (it->second->Identity.GetLL()[0] == ih.GetLL()[0]) + { + LogPrint(eLogDebug, "UDPServer: Found session ", it->second->IPSocket.local_endpoint(), " ", ih.ToBase32()); + return it->second; + } + else + { + LogPrint(eLogWarning, "UDPServer: Session with from ", remotePort, " and to ", localPort, " ports already exists. But from differend address. Removed"); + m_Sessions.erase (it); + } + } + } + boost::asio::ip::address addr; /** create new udp session */ if(m_IsUniqueLocal && m_LocalAddress.is_loopback()) @@ -84,10 +104,12 @@ namespace client } else addr = m_LocalAddress; - boost::asio::ip::udp::endpoint ep(addr, 0); - m_Sessions.push_back(std::make_shared(ep, m_LocalDest, m_RemoteEndpoint, ih, localPort, remotePort)); - auto & back = m_Sessions.back(); - return back; + + auto s = std::make_shared(boost::asio::ip::udp::endpoint(addr, 0), + m_LocalDest, m_RemoteEndpoint, ih, localPort, remotePort); + std::lock_guard lock(m_SessionsMutex); + m_Sessions.emplace (idx, s); + return s; } UDPSession::UDPSession(boost::asio::ip::udp::endpoint localEndpoint, @@ -175,8 +197,9 @@ namespace client std::vector > sessions; std::lock_guard lock (m_SessionsMutex); - for (UDPSessionPtr s: m_Sessions) + for (auto it: m_Sessions) { + auto s = it.second; if (!s->m_Destination) continue; auto info = s->m_Destination->GetInfoForRemote (s->Identity); if (!info) continue; diff --git a/libi2pd_client/UDPTunnel.h b/libi2pd_client/UDPTunnel.h index 3233c3f0..6dff41ea 100644 --- a/libi2pd_client/UDPTunnel.h +++ b/libi2pd_client/UDPTunnel.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -104,7 +104,8 @@ namespace client void HandleRecvFromI2P (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); void HandleRecvFromI2PRaw (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); UDPSessionPtr ObtainUDPSession (const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort); - + uint32_t GetSessionIndex (uint16_t fromPort, uint16_t toPort) const { return ((uint32_t)fromPort << 16) + toPort; } + private: bool m_IsUniqueLocal; @@ -112,7 +113,7 @@ namespace client boost::asio::ip::address m_LocalAddress; boost::asio::ip::udp::endpoint m_RemoteEndpoint; std::mutex m_SessionsMutex; - std::vector m_Sessions; + std::unordered_map m_Sessions; // (from port, to port)->session std::shared_ptr m_LocalDest; UDPSessionPtr m_LastSession; bool m_Gzip; From c5a18065281e45469518d6db032264971252199b Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 24 Jan 2024 13:58:42 -0500 Subject: [PATCH 0276/1171] fixed possible deadlock --- libi2pd_client/UDPTunnel.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/libi2pd_client/UDPTunnel.cpp b/libi2pd_client/UDPTunnel.cpp index 3fcf8b35..0bf3202f 100644 --- a/libi2pd_client/UDPTunnel.cpp +++ b/libi2pd_client/UDPTunnel.cpp @@ -19,10 +19,7 @@ namespace client void I2PUDPServerTunnel::HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) { if (!m_LastSession || m_LastSession->Identity.GetLL()[0] != from.GetIdentHash ().GetLL()[0] || fromPort != m_LastSession->RemotePort) - { - std::lock_guard lock(m_SessionsMutex); m_LastSession = ObtainUDPSession(from, toPort, fromPort); - } m_LastSession->IPSocket.send_to(boost::asio::buffer(buf, len), m_RemoteEndpoint); m_LastSession->LastActivity = i2p::util::GetMillisecondsSinceEpoch(); } From 70639f11396ad514d3bf358b8dccdd9aee7aff80 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 24 Jan 2024 19:05:38 -0500 Subject: [PATCH 0277/1171] don't adjust clock if offsets came from same router --- libi2pd/SSU2.cpp | 29 +++++++++++++++++++++-------- libi2pd/SSU2.h | 3 ++- libi2pd/SSU2Session.cpp | 6 +++--- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 1fb10927..0ebeab6d 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -210,27 +210,40 @@ namespace transport return ep.port (); } - void SSU2Server::AdjustTimeOffset (int64_t offset) + void SSU2Server::AdjustTimeOffset (int64_t offset, std::shared_ptr from) { if (offset) { if (m_PendingTimeOffset) // one more { - if (std::abs (m_PendingTimeOffset - offset) < SSU2_CLOCK_SKEW) + if (m_PendingTimeOffsetFrom && from && + m_PendingTimeOffsetFrom->GetIdentHash ().GetLL()[0] != from->GetIdentHash ().GetLL()[0]) // from different routers { - offset = (m_PendingTimeOffset + offset)/2; // average - LogPrint (eLogWarning, "SSU2: Clock adjusted by ", offset, " seconds"); - i2p::util::AdjustTimeOffset (offset); - } + if (std::abs (m_PendingTimeOffset - offset) < SSU2_CLOCK_SKEW) + { + offset = (m_PendingTimeOffset + offset)/2; // average + LogPrint (eLogWarning, "SSU2: Clock adjusted by ", offset, " seconds"); + i2p::util::AdjustTimeOffset (offset); + } + else + LogPrint (eLogWarning, "SSU2: Time offsets are too different. Clock not adjusted"); + m_PendingTimeOffset = 0; + m_PendingTimeOffsetFrom = nullptr; + } else - LogPrint (eLogWarning, "SSU2: Time offsets are too different. Clock not adjusted"); - m_PendingTimeOffset = 0; + LogPrint (eLogWarning, "SSU2: Time offsets from same router. Clock not adjusted"); } else + { m_PendingTimeOffset = offset; // first + m_PendingTimeOffsetFrom = from; + } } else + { m_PendingTimeOffset = 0; // reset + m_PendingTimeOffsetFrom = nullptr; + } } boost::asio::ip::udp::socket& SSU2Server::OpenSocket (const boost::asio::ip::udp::endpoint& localEndpoint) diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index 6d07f7fa..da682746 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -67,7 +67,7 @@ namespace transport bool IsSupported (const boost::asio::ip::address& addr) const; uint16_t GetPort (bool v4) const; bool IsSyncClockFromPeers () const { return m_IsSyncClockFromPeers; }; - void AdjustTimeOffset (int64_t offset); + void AdjustTimeOffset (int64_t offset, std::shared_ptr from); void AddSession (std::shared_ptr session); void RemoveSession (uint64_t connID); @@ -164,6 +164,7 @@ namespace transport bool m_IsPublished; // if we maintain introducers bool m_IsSyncClockFromPeers; int64_t m_PendingTimeOffset; // during peer test + std::shared_ptr m_PendingTimeOffsetFrom; // proxy bool m_IsThroughProxy; diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 3ea07629..5c951391 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1671,10 +1671,10 @@ namespace transport if (std::abs (offset) > SSU2_CLOCK_THRESHOLD) { LogPrint (eLogWarning, "SSU2: Time offset ", offset, " from ", m_RemoteEndpoint); - m_Server.AdjustTimeOffset (-offset); + m_Server.AdjustTimeOffset (-offset, GetRemoteIdentity ()); } else - m_Server.AdjustTimeOffset (0); + m_Server.AdjustTimeOffset (0, nullptr); } else if (std::abs (offset) > SSU2_CLOCK_SKEW) { @@ -2485,7 +2485,7 @@ namespace transport i2p::context.SetTestingV6 (testing); } if (!testing) - m_Server.AdjustTimeOffset (0); // reset time offset when testing is over + m_Server.AdjustTimeOffset (0, nullptr); // reset time offset when testing is over } size_t SSU2Session::CreateAddressBlock (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& ep) From 5b93558bd0d7b46bf004a198f15282d217e5c7d8 Mon Sep 17 00:00:00 2001 From: weko Date: Thu, 25 Jan 2024 01:05:58 +0000 Subject: [PATCH 0278/1171] Add support for multiple udp server tunnels on one destionation --- libi2pd/Datagram.cpp | 68 ++++++++++++++++++++++++++++++-- libi2pd/Datagram.h | 28 +++++++------ libi2pd_client/ClientContext.cpp | 2 +- libi2pd_client/SAM.cpp | 53 ++++++++++++++----------- libi2pd_client/UDPTunnel.cpp | 46 ++++++++++++++------- libi2pd_client/UDPTunnel.h | 3 +- 6 files changed, 143 insertions(+), 57 deletions(-) diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp index 64738ebe..c99db584 100644 --- a/libi2pd/Datagram.cpp +++ b/libi2pd/Datagram.cpp @@ -19,7 +19,7 @@ namespace i2p namespace datagram { DatagramDestination::DatagramDestination (std::shared_ptr owner, bool gzip): - m_Owner (owner), m_Receiver (nullptr), m_RawReceiver (nullptr), m_Gzip (gzip) + m_Owner (owner), m_DefaultReceiver (nullptr), m_DefaultRawReceiver (nullptr), m_Gzip (gzip) { if (m_Gzip) m_Deflator.reset (new i2p::data::GzipDeflator); @@ -119,19 +119,79 @@ namespace datagram void DatagramDestination::HandleRawDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) { - if (m_RawReceiver) - m_RawReceiver (fromPort, toPort, buf, len); + auto r = FindRawReceiver(toPort); + + if (r) + r (fromPort, toPort, buf, len); else LogPrint (eLogWarning, "DatagramDestination: no receiver for raw datagram"); } + void DatagramDestination::SetReceiver (const Receiver& receiver, uint16_t port) + { + std::lock_guard lock(m_ReceiversMutex); + m_ReceiversByPorts[port] = receiver; + if (!m_DefaultReceiver) { + m_DefaultReceiver = receiver; + m_DefaultReceiverPort = port; + } + } + + void DatagramDestination::ResetReceiver (uint16_t port) + { + std::lock_guard lock(m_ReceiversMutex); + m_ReceiversByPorts.erase (port); + if (m_DefaultReceiverPort == port) { + m_DefaultReceiver = nullptr; + m_DefaultReceiverPort = 0; + } + } + + + void DatagramDestination::SetRawReceiver (const RawReceiver& receiver, uint16_t port) + { + std::lock_guard lock(m_RawReceiversMutex); + m_RawReceiversByPorts[port] = receiver; + if (!m_DefaultRawReceiver) { + m_DefaultRawReceiver = receiver; + m_DefaultRawReceiverPort = port; + } + }; + + void DatagramDestination::ResetRawReceiver (uint16_t port) + { + std::lock_guard lock(m_RawReceiversMutex); + m_RawReceiversByPorts.erase (port); + if (m_DefaultRawReceiverPort == port) { + m_DefaultRawReceiver = nullptr; + m_DefaultRawReceiverPort = 0; + } + } + + DatagramDestination::Receiver DatagramDestination::FindReceiver(uint16_t port) { std::lock_guard lock(m_ReceiversMutex); - Receiver r = m_Receiver; + Receiver r = nullptr; auto itr = m_ReceiversByPorts.find(port); if (itr != m_ReceiversByPorts.end()) r = itr->second; + else { + r = m_DefaultReceiver; + } + return r; + } + + DatagramDestination::RawReceiver DatagramDestination::FindRawReceiver(uint16_t port) + { + std::lock_guard lock(m_RawReceiversMutex); + RawReceiver r = nullptr; + auto itr = m_RawReceiversByPorts.find(port); + if (itr != m_RawReceiversByPorts.end()) + r = itr->second; + else { + r = m_DefaultRawReceiver; + } return r; } diff --git a/libi2pd/Datagram.h b/libi2pd/Datagram.h index e6d1f7b6..fd6af909 100644 --- a/libi2pd/Datagram.h +++ b/libi2pd/Datagram.h @@ -126,14 +126,12 @@ namespace datagram void HandleDataMessagePayload (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len, bool isRaw = false); - void SetReceiver (const Receiver& receiver) { m_Receiver = receiver; }; - void ResetReceiver () { m_Receiver = nullptr; }; - void SetReceiver (const Receiver& receiver, uint16_t port) { std::lock_guard lock(m_ReceiversMutex); m_ReceiversByPorts[port] = receiver; }; - void ResetReceiver (uint16_t port) { std::lock_guard lock(m_ReceiversMutex); m_ReceiversByPorts.erase (port); }; + void SetReceiver (const Receiver& receiver, uint16_t port); + void ResetReceiver (uint16_t port); - void SetRawReceiver (const RawReceiver& receiver) { m_RawReceiver = receiver; }; - void ResetRawReceiver () { m_RawReceiver = nullptr; }; + void SetRawReceiver (const RawReceiver& receiver, uint16_t port); + void ResetRawReceiver (uint16_t port); std::shared_ptr GetInfoForRemote(const i2p::data::IdentHash & remote); @@ -150,20 +148,26 @@ namespace datagram void HandleDatagram (uint16_t fromPort, uint16_t toPort, uint8_t *const& buf, size_t len); void HandleRawDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); - /** find a receiver by port, if none by port is found try default receiver, otherwise returns nullptr */ Receiver FindReceiver(uint16_t port); + RawReceiver FindRawReceiver(uint16_t port); private: std::shared_ptr m_Owner; - Receiver m_Receiver; // default - RawReceiver m_RawReceiver; // default - bool m_Gzip; // gzip compression of data messages + std::mutex m_SessionsMutex; std::map m_Sessions; - std::mutex m_ReceiversMutex; - std::map m_ReceiversByPorts; + Receiver m_DefaultReceiver; + RawReceiver m_DefaultRawReceiver; + uint16_t m_DefaultReceiverPort; + uint16_t m_DefaultRawReceiverPort; + std::mutex m_ReceiversMutex; + std::mutex m_RawReceiversMutex; + std::unordered_map m_ReceiversByPorts; + std::unordered_map m_RawReceiversByPorts; + + bool m_Gzip; // gzip compression of data messages i2p::data::GzipInflator m_Inflator; std::unique_ptr m_Deflator; std::vector m_From, m_Signature; diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index d8c0bd2d..4efe252d 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -775,7 +775,7 @@ namespace client address = "127.0.0.1"; } auto localAddress = boost::asio::ip::address::from_string(address); - auto serverTunnel = std::make_shared(name, localDestination, localAddress, endpoint, port, gzip); + auto serverTunnel = std::make_shared(name, localDestination, localAddress, endpoint, inPort, gzip); if(!isUniqueLocal) { LogPrint(eLogInfo, "Clients: Disabling loopback address mapping"); diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 1a3afb58..e4cbae8a 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -415,12 +415,17 @@ namespace client { session->UDPEndpoint = forward; auto dest = session->GetLocalDestination ()->CreateDatagramDestination (); + auto port = std::stoi(params[SAM_PARAM_PORT]); if (type == eSAMSessionTypeDatagram) dest->SetReceiver (std::bind (&SAMSocket::HandleI2PDatagramReceive, shared_from_this (), - std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5)); + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5), + port + ); else // raw dest->SetRawReceiver (std::bind (&SAMSocket::HandleI2PRawDatagramReceive, shared_from_this (), - std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), + port + ); } if (session->GetLocalDestination ()->IsReady ()) @@ -524,7 +529,7 @@ namespace client if (addr->IsIdentHash ()) { if (session->GetLocalDestination ()->GetIdentHash () != addr->identHash) - { + { auto leaseSet = session->GetLocalDestination ()->FindLeaseSet(addr->identHash); if (leaseSet) Connect(leaseSet, session); @@ -556,7 +561,7 @@ namespace client if (session) { if (session->GetLocalDestination ()->SupportsEncryptionType (remote->GetEncryptionType ())) - { + { m_SocketType = eSAMSocketTypeStream; m_Stream = session->GetLocalDestination ()->CreateStream (remote); if (m_Stream) @@ -570,7 +575,7 @@ namespace client SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); } else - SendStreamCantReachPeer ("Incompatible crypto"); + SendStreamCantReachPeer ("Incompatible crypto"); } else SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); @@ -583,7 +588,7 @@ namespace client else { LogPrint (eLogError, "SAM: Destination to connect not found"); - SendStreamCantReachPeer ("LeaseSet not found"); + SendStreamCantReachPeer ("LeaseSet not found"); } } @@ -612,27 +617,27 @@ namespace client session->GetLocalDestination ()->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, shared_from_this (), std::placeholders::_1)); } else - { + { auto ts = i2p::util::GetSecondsSinceEpoch (); while (!session->acceptQueue.empty () && session->acceptQueue.front ().second + SAM_SESSION_MAX_ACCEPT_INTERVAL > ts) - { + { auto socket = session->acceptQueue.front ().first; session->acceptQueue.pop_front (); if (socket) m_Owner.GetService ().post (std::bind(&SAMSocket::TerminateClose, socket)); - } + } if (session->acceptQueue.size () < SAM_SESSION_MAX_ACCEPT_QUEUE_SIZE) { // already accepting, queue up SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); session->acceptQueue.push_back (std::make_pair(shared_from_this(), ts)); - } - else - { + } + else + { LogPrint (eLogInfo, "SAM: Session ", m_ID, " accept queue is full ", session->acceptQueue.size ()); SendStreamI2PError ("Already accepting"); - } - } + } + } } else SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); @@ -875,8 +880,8 @@ namespace client size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, reply, msg.c_str()); #endif SendMessageReply (m_Buffer, len, true); - } - + } + void SAMSocket::SendSessionI2PError(const std::string & msg) { LogPrint (eLogError, "SAM: Session I2P error: ", msg); @@ -886,14 +891,14 @@ namespace client void SAMSocket::SendStreamI2PError(const std::string & msg) { LogPrint (eLogError, "SAM: Stream I2P error: ", msg); - SendReplyWithMessage (SAM_STREAM_STATUS_I2P_ERROR, msg); + SendReplyWithMessage (SAM_STREAM_STATUS_I2P_ERROR, msg); } void SAMSocket::SendStreamCantReachPeer(const std::string & msg) { - SendReplyWithMessage (SAM_STREAM_STATUS_CANT_REACH_PEER, msg); - } - + SendReplyWithMessage (SAM_STREAM_STATUS_CANT_REACH_PEER, msg); + } + void SAMSocket::HandleNamingLookupLeaseSetRequestComplete (std::shared_ptr leaseSet, std::string name) { if (leaseSet) @@ -1093,14 +1098,14 @@ namespace client // pending acceptors auto ts = i2p::util::GetSecondsSinceEpoch (); while (!session->acceptQueue.empty () && session->acceptQueue.front ().second + SAM_SESSION_MAX_ACCEPT_INTERVAL > ts) - { + { auto socket = session->acceptQueue.front ().first; session->acceptQueue.pop_front (); if (socket) m_Owner.GetService ().post (std::bind(&SAMSocket::TerminateClose, socket)); - } + } if (!session->acceptQueue.empty ()) - { + { auto socket = session->acceptQueue.front ().first; session->acceptQueue.pop_front (); if (socket && socket->GetSocketType () == eSAMSocketTypeAcceptor) @@ -1108,7 +1113,7 @@ namespace client socket->m_IsAccepting = true; session->GetLocalDestination ()->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, socket, std::placeholders::_1)); } - } + } } if (!m_IsSilent) { diff --git a/libi2pd_client/UDPTunnel.cpp b/libi2pd_client/UDPTunnel.cpp index 0bf3202f..cd17bbf0 100644 --- a/libi2pd_client/UDPTunnel.cpp +++ b/libi2pd_client/UDPTunnel.cpp @@ -32,7 +32,7 @@ namespace client auto it = m_Sessions.find (GetSessionIndex (fromPort, toPort)); if (it != m_Sessions.end ()) m_LastSession = it->second; - else + else m_LastSession = nullptr; } if (m_LastSession) @@ -47,7 +47,7 @@ namespace client std::lock_guard lock(m_SessionsMutex); uint64_t now = i2p::util::GetMillisecondsSinceEpoch(); auto itr = m_Sessions.begin(); - while(itr != m_Sessions.end()) + while(itr != m_Sessions.end()) { if(now - itr->second->LastActivity >= delta ) itr = m_Sessions.erase(itr); @@ -88,10 +88,10 @@ namespace client { LogPrint(eLogWarning, "UDPServer: Session with from ", remotePort, " and to ", localPort, " ports already exists. But from differend address. Removed"); m_Sessions.erase (it); - } - } - } - + } + } + } + boost::asio::ip::address addr; /** create new udp session */ if(m_IsUniqueLocal && m_LocalAddress.is_loopback()) @@ -102,7 +102,7 @@ namespace client else addr = m_LocalAddress; - auto s = std::make_shared(boost::asio::ip::udp::endpoint(addr, 0), + auto s = std::make_shared(boost::asio::ip::udp::endpoint(addr, 0), m_LocalDest, m_RemoteEndpoint, ih, localPort, remotePort); std::lock_guard lock(m_SessionsMutex); m_Sessions.emplace (idx, s); @@ -163,9 +163,9 @@ namespace client } I2PUDPServerTunnel::I2PUDPServerTunnel (const std::string & name, std::shared_ptr localDestination, - const boost::asio::ip::address& localAddress, const boost::asio::ip::udp::endpoint& forwardTo, uint16_t port, bool gzip) : + const boost::asio::ip::address& localAddress, const boost::asio::ip::udp::endpoint& forwardTo, uint16_t inPort, bool gzip) : m_IsUniqueLocal (true), m_Name (name), m_LocalAddress (localAddress), - m_RemoteEndpoint (forwardTo), m_LocalDest (localDestination), m_Gzip (gzip) + m_RemoteEndpoint (forwardTo), m_LocalDest (localDestination), m_inPort(inPort), m_Gzip (gzip) { } @@ -179,14 +179,23 @@ namespace client m_LocalDest->Start (); auto dgram = m_LocalDest->CreateDatagramDestination (m_Gzip); - dgram->SetReceiver (std::bind (&I2PUDPServerTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5)); - dgram->SetRawReceiver (std::bind (&I2PUDPServerTunnel::HandleRecvFromI2PRaw, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); + dgram->SetReceiver ( + std::bind (&I2PUDPServerTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5), + m_inPort + ); + dgram->SetRawReceiver ( + std::bind (&I2PUDPServerTunnel::HandleRecvFromI2PRaw, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), + m_inPort + ); } void I2PUDPServerTunnel::Stop () { auto dgram = m_LocalDest->GetDatagramDestination (); - if (dgram) dgram->ResetReceiver (); + if (dgram) { + dgram->ResetReceiver (m_inPort); + dgram->ResetRawReceiver (m_inPort); + } } std::vector > I2PUDPServerTunnel::GetSessions () @@ -240,9 +249,13 @@ namespace client dgram->SetReceiver (std::bind (&I2PUDPClientTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, - std::placeholders::_5)); + std::placeholders::_5), + RemotePort + ); dgram->SetRawReceiver (std::bind (&I2PUDPClientTunnel::HandleRecvFromI2PRaw, this, - std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), + RemotePort + ); m_LocalDest->Start (); if (m_ResolveThread == nullptr) @@ -253,7 +266,10 @@ namespace client void I2PUDPClientTunnel::Stop () { auto dgram = m_LocalDest->GetDatagramDestination (); - if (dgram) dgram->ResetReceiver (); + if (dgram) { + dgram->ResetReceiver (RemotePort); + dgram->ResetRawReceiver (RemotePort); + } m_cancel_resolve = true; m_Sessions.clear(); diff --git a/libi2pd_client/UDPTunnel.h b/libi2pd_client/UDPTunnel.h index 6dff41ea..5650124c 100644 --- a/libi2pd_client/UDPTunnel.h +++ b/libi2pd_client/UDPTunnel.h @@ -105,7 +105,7 @@ namespace client void HandleRecvFromI2PRaw (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); UDPSessionPtr ObtainUDPSession (const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort); uint32_t GetSessionIndex (uint16_t fromPort, uint16_t toPort) const { return ((uint32_t)fromPort << 16) + toPort; } - + private: bool m_IsUniqueLocal; @@ -116,6 +116,7 @@ namespace client std::unordered_map m_Sessions; // (from port, to port)->session std::shared_ptr m_LocalDest; UDPSessionPtr m_LastSession; + uint16_t m_inPort; bool m_Gzip; public: From 4b167fdbafe577bca8b745e64ed0b15140c90b34 Mon Sep 17 00:00:00 2001 From: weko Date: Thu, 25 Jan 2024 01:57:24 +0000 Subject: [PATCH 0279/1171] Update copyright year --- libi2pd/Datagram.cpp | 2 +- libi2pd/Datagram.h | 2 +- libi2pd_client/ClientContext.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp index c99db584..717e3312 100644 --- a/libi2pd/Datagram.cpp +++ b/libi2pd/Datagram.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * diff --git a/libi2pd/Datagram.h b/libi2pd/Datagram.h index fd6af909..45edecab 100644 --- a/libi2pd/Datagram.h +++ b/libi2pd/Datagram.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index 4efe252d..c27ce625 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * From 67c4d4bcaafbe67ee5dd7bbd4fda44eb1d91a6e4 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 25 Jan 2024 09:09:44 -0500 Subject: [PATCH 0280/1171] fixed VS build error --- libi2pd/NTCP2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 925c89dd..fff2fdc7 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1170,7 +1170,7 @@ namespace transport size_t paddingSize = (msgLen*NTCP2_MAX_PADDING_RATIO)/100; if (msgLen + paddingSize + 3 > NTCP2_UNENCRYPTED_FRAME_MAX_SIZE) { - ssize_t l = NTCP2_UNENCRYPTED_FRAME_MAX_SIZE - msgLen -3; + int l = (int)NTCP2_UNENCRYPTED_FRAME_MAX_SIZE - msgLen -3; if (l <= 0) return 0; paddingSize = l; } From 75c2cb751f493c4bf96249e1b1e800868806943c Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 25 Jan 2024 18:51:46 -0500 Subject: [PATCH 0281/1171] lock mutex before deleting RouterInfo's buffer --- libi2pd/NetDb.cpp | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 8eb5d653..f1be7520 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -240,7 +240,7 @@ namespace data { bool wasFloodfill = r->IsFloodfill (); { - std::unique_lock l(m_RouterInfosMutex); + std::lock_guard l(m_RouterInfosMutex); if (!r->Update (buf, len)) { updated = false; @@ -254,7 +254,7 @@ namespace data m_RouterInfos.erase (ident); if (wasFloodfill) { - std::unique_lock l(m_FloodfillsMutex); + std::lock_guard l(m_FloodfillsMutex); m_Floodfills.Remove (r->GetIdentHash ()); } m_Requests.RequestComplete (ident, nullptr); @@ -265,7 +265,7 @@ namespace data if (wasFloodfill != r->IsFloodfill ()) // if floodfill status updated { LogPrint (eLogDebug, "NetDb: RouterInfo floodfill status updated: ", ident.ToBase64()); - std::unique_lock l(m_FloodfillsMutex); + std::lock_guard l(m_FloodfillsMutex); if (wasFloodfill) m_Floodfills.Remove (r->GetIdentHash ()); else if (r->IsEligibleFloodfill ()) @@ -291,7 +291,7 @@ namespace data { bool inserted = false; { - std::unique_lock l(m_RouterInfosMutex); + std::lock_guard l(m_RouterInfosMutex); inserted = m_RouterInfos.insert ({r->GetIdentHash (), r}).second; } if (inserted) @@ -302,7 +302,7 @@ namespace data if (m_Floodfills.GetSize () < NETDB_NUM_FLOODFILLS_THRESHOLD || r->GetProfile ()->IsReal ()) // don't insert floodfill until it's known real if we have enough { - std::unique_lock l(m_FloodfillsMutex); + std::lock_guard l(m_FloodfillsMutex); m_Floodfills.Insert (r); } else @@ -325,7 +325,7 @@ namespace data bool NetDb::AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len) { - std::unique_lock lock(m_LeaseSetsMutex); + std::lock_guard lock(m_LeaseSetsMutex); bool updated = false; auto it = m_LeaseSets.find(ident); if (it != m_LeaseSets.end () && it->second->GetStoreType () == i2p::data::NETDB_STORE_TYPE_LEASESET) @@ -366,7 +366,7 @@ namespace data auto leaseSet = std::make_shared (storeType, buf, len, false); // we don't need leases in netdb if (leaseSet->IsValid ()) { - std::unique_lock lock(m_LeaseSetsMutex); + std::lock_guard lock(m_LeaseSetsMutex); auto it = m_LeaseSets.find(ident); if (it == m_LeaseSets.end () || it->second->GetStoreType () != storeType || leaseSet->GetPublishedTimestamp () > it->second->GetPublishedTimestamp ()) @@ -393,7 +393,7 @@ namespace data std::shared_ptr NetDb::FindRouter (const IdentHash& ident) const { - std::unique_lock l(m_RouterInfosMutex); + std::lock_guard l(m_RouterInfosMutex); auto it = m_RouterInfos.find (ident); if (it != m_RouterInfos.end ()) return it->second; @@ -403,7 +403,7 @@ namespace data std::shared_ptr NetDb::FindLeaseSet (const IdentHash& destination) const { - std::unique_lock lock(m_LeaseSetsMutex); + std::lock_guard lock(m_LeaseSetsMutex); auto it = m_LeaseSets.find (destination); if (it != m_LeaseSets.end ()) return it->second; @@ -437,7 +437,7 @@ namespace data auto r = FindRouter (ident); if (r) { - std::unique_lock l(m_RouterInfosMutex); + std::lock_guard l(m_RouterInfosMutex); r->ExcludeReachableTransports (transports); } } @@ -527,7 +527,7 @@ namespace data void NetDb::VisitLeaseSets(LeaseSetVisitor v) { - std::unique_lock lock(m_LeaseSetsMutex); + std::lock_guard lock(m_LeaseSetsMutex); for ( auto & entry : m_LeaseSets) v(entry.first, entry.second); } @@ -543,7 +543,7 @@ namespace data void NetDb::VisitRouterInfos(RouterInfoVisitor v) { - std::unique_lock lock(m_RouterInfosMutex); + std::lock_guard lock(m_RouterInfosMutex); for ( const auto & item : m_RouterInfos ) v(item.second); } @@ -555,7 +555,7 @@ namespace data size_t iters = max_iters_per_cyle; while(n > 0) { - std::unique_lock lock(m_RouterInfosMutex); + std::lock_guard lock(m_RouterInfosMutex); uint32_t idx = rand () % m_RouterInfos.size (); uint32_t i = 0; for (const auto & it : m_RouterInfos) { @@ -638,6 +638,7 @@ namespace data // we have something to save it.second->SaveToFile (m_Storage.Path(ident)); it.second->SetUnreachable (false); + std::lock_guard l(m_RouterInfosMutex); // possible collision between DeleteBuffer and Update it.second->DeleteBuffer (); } it.second->SetUpdated (false); @@ -696,7 +697,7 @@ namespace data LogPrint (eLogInfo, "NetDb: Deleting ", deletedCount, " unreachable routers"); // clean up RouterInfos table { - std::unique_lock l(m_RouterInfosMutex); + std::lock_guard l(m_RouterInfosMutex); for (auto it = m_RouterInfos.begin (); it != m_RouterInfos.end ();) { if (!it->second || it->second->IsUnreachable ()) @@ -710,7 +711,7 @@ namespace data } // clean up expired floodfills or not floodfills anymore { - std::unique_lock l(m_FloodfillsMutex); + std::lock_guard l(m_FloodfillsMutex); m_Floodfills.Cleanup ([](const std::shared_ptr& r)->bool { return r && r->IsFloodfill () && !r->IsUnreachable (); @@ -1249,7 +1250,7 @@ namespace data return 0; uint16_t inds[3]; RAND_bytes ((uint8_t *)inds, sizeof (inds)); - std::unique_lock l(m_RouterInfosMutex); + std::lock_guard l(m_RouterInfosMutex); auto count = m_RouterInfos.size (); if(count == 0) return nullptr; inds[0] %= count; @@ -1311,7 +1312,7 @@ namespace data const std::set& excluded) const { IdentHash destKey = CreateRoutingKey (destination); - std::unique_lock l(m_FloodfillsMutex); + std::lock_guard l(m_FloodfillsMutex); return m_Floodfills.FindClosest (destKey, [&excluded](const std::shared_ptr& r)->bool { return r && !r->IsUnreachable () && !r->GetProfile ()->IsUnreachable () && @@ -1326,7 +1327,7 @@ namespace data IdentHash destKey = CreateRoutingKey (destination); std::vector > v; { - std::unique_lock l(m_FloodfillsMutex); + std::lock_guard l(m_FloodfillsMutex); v = m_Floodfills.FindClosest (destKey, num, [&excluded](const std::shared_ptr& r)->bool { return r && !r->IsUnreachable () && !r->GetProfile ()->IsUnreachable () && @@ -1381,7 +1382,7 @@ namespace data { auto ts = i2p::util::GetSecondsSinceEpoch (); { - std::unique_lock l(m_RouterInfosMutex); + std::lock_guard l(m_RouterInfosMutex); for (auto& it: m_RouterInfos) it.second->UpdateIntroducers (ts); } From 530c353b00f73dcc497cf13206d50051b0748615 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 27 Jan 2024 12:17:59 -0500 Subject: [PATCH 0282/1171] don't send Ack with NACK immediately but after 2 milliseconds --- libi2pd/Streaming.cpp | 37 ++++++++++++++++--------------------- libi2pd/Streaming.h | 3 ++- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 629039ab..c43f99ad 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -179,13 +179,9 @@ namespace stream { if (!m_IsAckSendScheduled) { - m_IsAckSendScheduled = true; auto ackTimeout = m_RTT/10; if (ackTimeout > m_AckDelay) ackTimeout = m_AckDelay; - else if (ackTimeout < MIN_SEND_ACK_TIMEOUT) ackTimeout = MIN_SEND_ACK_TIMEOUT; - m_AckSendTimer.expires_from_now (boost::posix_time::milliseconds(ackTimeout)); - m_AckSendTimer.async_wait (std::bind (&Stream::HandleAckSendTimer, - shared_from_this (), std::placeholders::_1)); + ScheduleAck (ackTimeout); } } else if (packet->IsSYN ()) @@ -207,23 +203,11 @@ namespace stream // save message and wait for missing message again SavePacket (packet); if (m_LastReceivedSequenceNumber >= 0) - { - // send NACKs for missing messages ASAP - if (m_IsAckSendScheduled) - { - m_IsAckSendScheduled = false; - m_AckSendTimer.cancel (); - } - SendQuickAck (); - } + // send NACKs for missing messages with minimal timeout + ScheduleAck (MIN_SEND_ACK_TIMEOUT); else - { // wait for SYN - m_IsAckSendScheduled = true; - m_AckSendTimer.expires_from_now (boost::posix_time::milliseconds(SYN_TIMEOUT)); - m_AckSendTimer.async_wait (std::bind (&Stream::HandleAckSendTimer, - shared_from_this (), std::placeholders::_1)); - } + ScheduleAck (SYN_TIMEOUT); } } } @@ -1029,6 +1013,17 @@ namespace stream } } + void Stream::ScheduleAck (int timeout) + { + if (m_IsAckSendScheduled) + m_AckSendTimer.cancel (); + m_IsAckSendScheduled = true; + if (timeout < MIN_SEND_ACK_TIMEOUT) timeout = MIN_SEND_ACK_TIMEOUT; + m_AckSendTimer.expires_from_now (boost::posix_time::milliseconds(timeout)); + m_AckSendTimer.async_wait (std::bind (&Stream::HandleAckSendTimer, + shared_from_this (), std::placeholders::_1)); + } + void Stream::HandleAckSendTimer (const boost::system::error_code& ecode) { if (m_IsAckSendScheduled) diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 1db59118..ed79edc9 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -227,6 +227,7 @@ namespace stream void ScheduleResend (); void HandleResendTimer (const boost::system::error_code& ecode); + void ScheduleAck (int timeout); void HandleAckSendTimer (const boost::system::error_code& ecode); private: From a3246cd9dc92f91219801e6ef8c6fa22f0056616 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 27 Jan 2024 17:57:50 -0500 Subject: [PATCH 0283/1171] doen't send Ack packet too often if missing packets --- libi2pd/Streaming.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index c43f99ad..a4604892 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -203,8 +203,11 @@ namespace stream // save message and wait for missing message again SavePacket (packet); if (m_LastReceivedSequenceNumber >= 0) - // send NACKs for missing messages with minimal timeout - ScheduleAck (MIN_SEND_ACK_TIMEOUT); + { + if (!m_IsAckSendScheduled) + // send NACKs for missing messages + ScheduleAck (MIN_SEND_ACK_TIMEOUT*m_SavedPackets.size ()); + } else // wait for SYN ScheduleAck (SYN_TIMEOUT); From 81015a52285651e0c6fe2a8bf33d7dd0b2c96b83 Mon Sep 17 00:00:00 2001 From: Vort Date: Sun, 28 Jan 2024 15:37:14 +0200 Subject: [PATCH 0284/1171] log changes of network status --- libi2pd/RouterContext.cpp | 4 ++++ libi2pd/RouterContext.h | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 10d33bf5..b3c51ca6 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -303,6 +303,8 @@ namespace i2p SetTesting (false); if (status != m_Status) { + LogPrint(eLogInfo, "Router: network status v4 changed ", + ROUTER_STATUS_NAMES[m_Status], " -> ", ROUTER_STATUS_NAMES[status]); m_Status = status; switch (m_Status) { @@ -323,6 +325,8 @@ namespace i2p SetTestingV6 (false); if (status != m_StatusV6) { + LogPrint(eLogInfo, "Router: network status v6 changed ", + ROUTER_STATUS_NAMES[m_StatusV6], " -> ", ROUTER_STATUS_NAMES[status]); m_StatusV6 = status; switch (m_StatusV6) { diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index 91a553ba..ddfc65de 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -48,6 +48,15 @@ namespace garlic eRouterStatusMesh = 4 }; + const char* const ROUTER_STATUS_NAMES[] = + { + "OK", // 0 + "Firewalled", // 1 + "Unknown", // 2 + "Proxy", // 3 + "Mesh" // 4 + }; + enum RouterError { eRouterErrorNone = 0, From 822cb35efe35b95c269329275b1d00f3b7f3b7c8 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 28 Jan 2024 18:12:40 -0500 Subject: [PATCH 0285/1171] limit send Ack timeout by Ack delay interval --- libi2pd/Streaming.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index a4604892..74fb3d97 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -205,8 +205,12 @@ namespace stream if (m_LastReceivedSequenceNumber >= 0) { if (!m_IsAckSendScheduled) + { // send NACKs for missing messages - ScheduleAck (MIN_SEND_ACK_TIMEOUT*m_SavedPackets.size ()); + int ackTimeout = MIN_SEND_ACK_TIMEOUT*m_SavedPackets.size (); + if (ackTimeout > m_AckDelay) ackTimeout = m_AckDelay; + ScheduleAck (ackTimeout); + } } else // wait for SYN From d926a310645d9778848f8fadb710a70dc66ebd34 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 29 Jan 2024 18:01:41 -0500 Subject: [PATCH 0286/1171] fixed warning --- libi2pd/Datagram.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp index 717e3312..f87f9653 100644 --- a/libi2pd/Datagram.cpp +++ b/libi2pd/Datagram.cpp @@ -156,7 +156,7 @@ namespace datagram m_DefaultRawReceiver = receiver; m_DefaultRawReceiverPort = port; } - }; + } void DatagramDestination::ResetRawReceiver (uint16_t port) { From f0084785059b8e78acef3301e1fd818ec6b0c73b Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 29 Jan 2024 19:54:43 -0500 Subject: [PATCH 0287/1171] handle I2NP messages drops --- libi2pd/I2NPProtocol.h | 7 +++++-- libi2pd/NTCP2.cpp | 1 + libi2pd/NetDb.cpp | 6 +++++- libi2pd/NetDbRequests.cpp | 6 +++++- libi2pd/SSU2Session.cpp | 1 + libi2pd/Transports.h | 7 +++++++ 6 files changed, 24 insertions(+), 4 deletions(-) diff --git a/libi2pd/I2NPProtocol.h b/libi2pd/I2NPProtocol.h index e86f4f32..a2877a08 100644 --- a/libi2pd/I2NPProtocol.h +++ b/libi2pd/I2NPProtocol.h @@ -13,6 +13,7 @@ #include #include #include +#include #include "Crypto.h" #include "I2PEndian.h" #include "Identity.h" @@ -149,7 +150,8 @@ namespace tunnel uint8_t * buf; size_t len, offset, maxLen; std::shared_ptr from; - + std::function onDrop; + I2NPMessage (): buf (nullptr),len (I2NP_HEADER_SIZE + 2), offset(2), maxLen (0), from (nullptr) {}; // reserve 2 bytes for NTCP header @@ -241,7 +243,6 @@ namespace tunnel SetSize (len - offset - I2NP_HEADER_SIZE); SetChks (0); } - void ToNTCP2 () { uint8_t * ntcp2 = GetNTCP2Header (); @@ -253,6 +254,8 @@ namespace tunnel void RenewI2NPMessageHeader (); bool IsExpired () const; bool IsExpired (uint64_t ts) const; // in milliseconds + + void Drop () { if (onDrop) { onDrop (); onDrop = nullptr; }; } }; template diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index fff2fdc7..ad8ef51d 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1140,6 +1140,7 @@ namespace transport if (!msg || msg->IsExpired (ts)) { // drop null or expired message + if (msg) msg->Drop (); m_SendQueue.pop_front (); continue; } diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index f1be7520..0bf7af9d 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -736,7 +736,11 @@ namespace data !i2p::transport::transports.IsConnected (floodfill->GetIdentHash ())) direct = false; // floodfill can't be reached directly if (direct) - transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ())); + { + auto msg = dest->CreateRequestMessage (floodfill->GetIdentHash ()); + msg->onDrop = [this, dest]() { this->m_Requests.SendNextRequest (dest); }; + transports.SendMessage (floodfill->GetIdentHash (), msg); + } else { auto pool = i2p::tunnel::tunnels.GetExploratoryPool (); diff --git a/libi2pd/NetDbRequests.cpp b/libi2pd/NetDbRequests.cpp index 92e5a7b8..4099f921 100644 --- a/libi2pd/NetDbRequests.cpp +++ b/libi2pd/NetDbRequests.cpp @@ -188,7 +188,11 @@ namespace data !i2p::transport::transports.IsConnected (nextFloodfill->GetIdentHash ())) direct = false; // floodfill can't be reached directly if (direct) - i2p::transport::transports.SendMessage (nextFloodfill->GetIdentHash (), dest->CreateRequestMessage (nextFloodfill->GetIdentHash ())); + { + auto msg = dest->CreateRequestMessage (nextFloodfill->GetIdentHash ()); + msg->onDrop = [this, dest]() { this->SendNextRequest (dest); }; + i2p::transport::transports.SendMessage (nextFloodfill->GetIdentHash (), msg); + } else { auto pool = i2p::tunnel::tunnels.GetExploratoryPool (); diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 5c951391..fa6d9eca 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -382,6 +382,7 @@ namespace transport if (!msg || msg->IsExpired (ts)) { // drop null or expired message + if (msg) msg->Drop (); m_SendQueue.pop_front (); continue; } diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index 0e5518b1..c78a8bd0 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -86,6 +86,13 @@ namespace transport } } + ~Peer () + { + // drop not sent delayed messages + for (auto& it: delayedMessages) + it->Drop (); + } + void Done () { for (auto& it: sessions) From 85f5f5b91e669d626adb1daaa98a35fbc0321245 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 30 Jan 2024 10:04:19 -0500 Subject: [PATCH 0288/1171] fixed potential deadlock --- libi2pd/Transports.h | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index c78a8bd0..540bafb4 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -85,18 +85,14 @@ namespace transport isReachable = (bool)router->GetCompatibleTransports (true); } } - - ~Peer () - { - // drop not sent delayed messages - for (auto& it: delayedMessages) - it->Drop (); - } void Done () { for (auto& it: sessions) it->Done (); + // drop not sent delayed messages + for (auto& it: delayedMessages) + it->Drop (); } void SetRouter (std::shared_ptr r) From e40b656ecf8ea4bdbb92c2c5f5c996ffae7aa2d2 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 30 Jan 2024 15:41:57 -0500 Subject: [PATCH 0289/1171] Drop for tunnel and encrypted messages --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 10 ++++++++-- libi2pd/ECIESX25519AEADRatchetSession.h | 4 ++-- libi2pd/NetDb.cpp | 1 + libi2pd/NetDbRequests.cpp | 1 + libi2pd/TunnelGateway.cpp | 11 +++++++++-- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 3b3ed485..6f56f2e5 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -1171,7 +1171,7 @@ namespace garlic return m; } - std::shared_ptr WrapECIESX25519MessageForRouter (std::shared_ptr msg, const uint8_t * routerPublicKey) + std::shared_ptr WrapECIESX25519MessageForRouter (std::shared_ptr msg, const uint8_t * routerPublicKey) { // Noise_N, we are Alice, routerPublicKey is Bob's i2p::crypto::NoiseSymmetricState noiseState; @@ -1205,6 +1205,12 @@ namespace garlic htobe32buf (m->GetPayload (), offset); m->len += offset + 4; m->FillI2NPMessageHeader (eI2NPGarlic); + if (msg->onDrop) + { + // move onDrop to the wrapping I2NP messages + m->onDrop = msg->onDrop; + msg->onDrop = nullptr; + } return m; } } diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index 301f597a..517833e8 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2021, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -246,7 +246,7 @@ namespace garlic }; std::shared_ptr WrapECIESX25519Message (std::shared_ptr msg, const uint8_t * key, uint64_t tag); - std::shared_ptr WrapECIESX25519MessageForRouter (std::shared_ptr msg, const uint8_t * routerPublicKey); + std::shared_ptr WrapECIESX25519MessageForRouter (std::shared_ptr msg, const uint8_t * routerPublicKey); } } diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 0bf7af9d..bedb19f6 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -749,6 +749,7 @@ namespace data if (outbound && inbound) { auto msg = dest->CreateRequestMessage (floodfill, inbound); + msg->onDrop = [this, dest]() { this->m_Requests.SendNextRequest (dest); }; outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0, i2p::garlic::WrapECIESX25519MessageForRouter (msg, floodfill->GetIdentity ()->GetEncryptionPublicKey ())); } diff --git a/libi2pd/NetDbRequests.cpp b/libi2pd/NetDbRequests.cpp index 4099f921..3b5f41b6 100644 --- a/libi2pd/NetDbRequests.cpp +++ b/libi2pd/NetDbRequests.cpp @@ -202,6 +202,7 @@ namespace data { LogPrint (eLogDebug, "NetDbReq: Try ", dest->GetDestination (), " at ", count, " floodfill ", nextFloodfill->GetIdentHash ().ToBase64 ()); auto msg = dest->CreateRequestMessage (nextFloodfill, inbound); + msg->onDrop = [this, dest]() { this->SendNextRequest (dest); }; outbound->SendTunnelDataMsgTo (nextFloodfill->GetIdentHash (), 0, i2p::garlic::WrapECIESX25519MessageForRouter (msg, nextFloodfill->GetIdentity ()->GetEncryptionPublicKey ())); } diff --git a/libi2pd/TunnelGateway.cpp b/libi2pd/TunnelGateway.cpp index 12e7652f..85ff224e 100644 --- a/libi2pd/TunnelGateway.cpp +++ b/libi2pd/TunnelGateway.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2021, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -35,6 +35,13 @@ namespace tunnel if (!m_CurrentTunnelDataMsg) { CreateCurrentTunnelDataMessage (); + if (block.data && block.data->onDrop) + { + // onDrop is called for the first fragment in tunnel message + // that's usually true for short TBMs or lookups + m_CurrentTunnelDataMsg->onDrop = block.data->onDrop; + block.data->onDrop = nullptr; + } messageCreated = true; } @@ -155,7 +162,6 @@ namespace tunnel void TunnelGatewayBuffer::CreateCurrentTunnelDataMessage () { - m_CurrentTunnelDataMsg = nullptr; m_CurrentTunnelDataMsg = NewI2NPTunnelMessage (true); // tunnel endpoint is at least of two tunnel messages size // we reserve space for padding m_CurrentTunnelDataMsg->offset += TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE; @@ -223,6 +229,7 @@ namespace tunnel m_Tunnel->EncryptTunnelMsg (tunnelMsg, newMsg); htobe32buf (newMsg->GetPayload (), m_Tunnel->GetNextTunnelID ()); newMsg->FillI2NPMessageHeader (eI2NPTunnelData); + if (tunnelMsg->onDrop) newMsg->onDrop = tunnelMsg->onDrop; newTunnelMsgs.push_back (newMsg); m_NumSentBytes += TUNNEL_DATA_MSG_SIZE; } From 0ca782ed717bc8ad631efd4bf252c1b78894b72b Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 30 Jan 2024 18:02:14 -0500 Subject: [PATCH 0290/1171] drop unsent messages if session disconnects --- libi2pd/NTCP2.cpp | 2 ++ libi2pd/SSU2Session.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index ad8ef51d..6fe88509 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -373,6 +373,8 @@ namespace transport m_Socket.close (); transports.PeerDisconnected (shared_from_this ()); m_Server.RemoveNTCP2Session (shared_from_this ()); + for (auto& it: m_SendQueue) + it->Drop (); m_SendQueue.clear (); SetSendQueueSize (0); auto remoteIdentity = GetRemoteIdentity (); diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index fa6d9eca..9180ccc8 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -262,6 +262,8 @@ namespace transport m_SentHandshakePacket.reset (nullptr); m_SessionConfirmedFragment.reset (nullptr); m_PathChallenge.reset (nullptr); + for (auto& it: m_SendQueue) + it->Drop (); m_SendQueue.clear (); SetSendQueueSize (0); m_SentPackets.clear (); From 2e9f2d4a3b1513797a73f94b1b661d4f9b76bb9b Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 30 Jan 2024 21:52:18 -0500 Subject: [PATCH 0291/1171] Drop for LeaseSet request --- libi2pd/Destination.cpp | 67 ++++++++++++++++++++++++----------------- libi2pd/Destination.h | 3 +- 2 files changed, 42 insertions(+), 28 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index b9555abe..9b173f24 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -502,38 +502,43 @@ namespace client if (it != m_LeaseSetRequests.end ()) { auto request = it->second; - bool found = false; - if (request->excluded.size () < MAX_NUM_FLOODFILLS_PER_REQUEST) + for (int i = 0; i < num; i++) { - for (int i = 0; i < num; i++) + i2p::data::IdentHash peerHash (buf + 33 + i*32); + if (!request->excluded.count (peerHash) && !i2p::data::netdb.FindRouter (peerHash)) { - i2p::data::IdentHash peerHash (buf + 33 + i*32); - if (!request->excluded.count (peerHash) && !i2p::data::netdb.FindRouter (peerHash)) - { - LogPrint (eLogInfo, "Destination: Found new floodfill, request it"); - i2p::data::netdb.RequestDestination (peerHash, nullptr, false); // through exploratory - } - } - - auto floodfill = i2p::data::netdb.GetClosestFloodfill (key, request->excluded); - if (floodfill) - { - LogPrint (eLogInfo, "Destination: Requesting ", key.ToBase64 (), " at ", floodfill->GetIdentHash ().ToBase64 ()); - if (SendLeaseSetRequest (key, floodfill, request)) - found = true; + LogPrint (eLogInfo, "Destination: Found new floodfill, request it"); + i2p::data::netdb.RequestDestination (peerHash, nullptr, false); // through exploratory } } - if (!found) - { - LogPrint (eLogInfo, "Destination: ", key.ToBase64 (), " was not found on ", MAX_NUM_FLOODFILLS_PER_REQUEST, " floodfills"); - request->Complete (nullptr); - m_LeaseSetRequests.erase (key); - } + SendNextLeaseSetRequest (key, request); } else LogPrint (eLogWarning, "Destination: Request for ", key.ToBase64 (), " not found"); } + void LeaseSetDestination::SendNextLeaseSetRequest (const i2p::data::IdentHash& key, + std::shared_ptr request) + { + bool found = false; + if (request->excluded.size () < MAX_NUM_FLOODFILLS_PER_REQUEST) + { + auto floodfill = i2p::data::netdb.GetClosestFloodfill (key, request->excluded); + if (floodfill) + { + LogPrint (eLogInfo, "Destination: Requesting ", key.ToBase64 (), " at ", floodfill->GetIdentHash ().ToBase64 ()); + if (SendLeaseSetRequest (key, floodfill, request)) + found = true; + } + } + if (!found) + { + LogPrint (eLogInfo, "Destination: ", key.ToBase64 (), " was not found on ", MAX_NUM_FLOODFILLS_PER_REQUEST, " floodfills"); + request->Complete (nullptr); + m_LeaseSetRequests.erase (key); + } + } + void LeaseSetDestination::HandleDeliveryStatusMessage (uint32_t msgID) { if (msgID == m_PublishReplyToken) @@ -822,14 +827,22 @@ namespace client AddECIESx25519Key (replyKey, replyTag); else AddSessionKey (replyKey, replyTag); - auto msg = WrapMessageForRouter (nextFloodfill, CreateLeaseSetDatabaseLookupMsg (dest, - request->excluded, request->replyTunnel, replyKey, replyTag, isECIES)); + auto msg = CreateLeaseSetDatabaseLookupMsg (dest, request->excluded, request->replyTunnel, replyKey, replyTag, isECIES); + auto s = shared_from_this (); + msg->onDrop = [s, dest, request]() + { + s->GetService ().post([s, dest, request]() + { + s->SendNextLeaseSetRequest (dest, request); + }); + }; + auto encryptedMsg = WrapMessageForRouter (nextFloodfill, msg); request->outboundTunnel->SendTunnelDataMsgs ( { i2p::tunnel::TunnelMessageBlock { i2p::tunnel::eDeliveryTypeRouter, - nextFloodfill->GetIdentHash (), 0, msg + nextFloodfill->GetIdentHash (), 0, encryptedMsg } }); request->requestTimeoutTimer.expires_from_now (boost::posix_time::seconds(LEASESET_REQUEST_TIMEOUT)); diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 3b395f4d..a066c64c 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -176,6 +176,7 @@ namespace client void RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete, std::shared_ptr requestedBlindedKey = nullptr); bool SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr nextFloodfill, std::shared_ptr request); + void SendNextLeaseSetRequest (const i2p::data::IdentHash& key, std::shared_ptr request); void HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest); void HandleCleanupTimer (const boost::system::error_code& ecode); void CleanupRemoteLeaseSets (); From ffdd5935e90e65300da10164ca72a0de64a52b4a Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 31 Jan 2024 11:46:01 -0500 Subject: [PATCH 0292/1171] Handle drop of own RouterInfo publishing message --- libi2pd/RouterContext.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index b3c51ca6..40949891 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -1378,10 +1378,19 @@ namespace i2p uint32_t replyToken; RAND_bytes ((uint8_t *)&replyToken, 4); LogPrint (eLogInfo, "Router: Publishing our RouterInfo to ", i2p::data::GetIdentHashAbbreviation(floodfill->GetIdentHash ()), ". reply token=", replyToken); + auto onDrop = [this]() + { + if (m_Service) + m_Service->GetService ().post ([this]() { HandlePublishResendTimer (boost::system::error_code ()); }); + }; if (floodfill->IsReachableFrom (i2p::context.GetRouterInfo ()) || // are we able to connect? i2p::transport::transports.IsConnected (floodfill->GetIdentHash ())) // already connected ? + { // send directly - i2p::transport::transports.SendMessage (floodfill->GetIdentHash (), CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken)); + auto msg = CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken); + msg->onDrop = onDrop; + i2p::transport::transports.SendMessage (floodfill->GetIdentHash (), msg); + } else { // otherwise through exploratory @@ -1392,6 +1401,7 @@ namespace i2p { // encrypt for floodfill auto msg = CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken, inbound); + msg->onDrop = onDrop; outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0, i2p::garlic::WrapECIESX25519MessageForRouter (msg, floodfill->GetIdentity ()->GetEncryptionPublicKey ())); } From 83cb3a1820802a5ddf01fb3de1f0654f9f56e237 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 31 Jan 2024 15:41:21 -0500 Subject: [PATCH 0293/1171] reduce router unreachable interval --- libi2pd/Profiling.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/Profiling.h b/libi2pd/Profiling.h index 6531e060..ed23fb12 100644 --- a/libi2pd/Profiling.h +++ b/libi2pd/Profiling.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -35,7 +35,7 @@ namespace data const int PEER_PROFILE_AUTOCLEAN_VARIANCE = 3600; // in seconds (1 hour) const int PEER_PROFILE_DECLINED_RECENTLY_INTERVAL = 150; // in seconds (2.5 minutes) const int PEER_PROFILE_PERSIST_INTERVAL = 3300; // in seconds (55 minutes) - const int PEER_PROFILE_UNREACHABLE_INTERVAL = 2*3600; // on seconds (2 hours) + const int PEER_PROFILE_UNREACHABLE_INTERVAL = 480; // in seconds (8 minutes) const int PEER_PROFILE_USEFUL_THRESHOLD = 3; class RouterProfile From 96cf6ca531289328aeda9c8ea7f6eae06b338c57 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 1 Feb 2024 18:14:45 -0500 Subject: [PATCH 0294/1171] drop earlier if outgoing queue is semi-full --- libi2pd/NTCP2.cpp | 7 ++++++- libi2pd/SSU2Session.cpp | 6 +++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 6fe88509..76f3a940 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1250,8 +1250,13 @@ namespace transport void NTCP2Session::PostI2NPMessages (std::vector > msgs) { if (m_IsTerminated) return; + bool isSemiFull = m_SendQueue.size () > NTCP2_MAX_OUTGOING_QUEUE_SIZE/2; for (auto it: msgs) - m_SendQueue.push_back (std::move (it)); + if (isSemiFull && it->onDrop) + it->Drop (); // drop earlier because we can handle it + else + m_SendQueue.push_back (std::move (it)); + if (!m_IsSending) SendQueue (); else if (m_SendQueue.size () > NTCP2_MAX_OUTGOING_QUEUE_SIZE) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 9180ccc8..12671f4f 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -351,8 +351,12 @@ namespace transport void SSU2Session::PostI2NPMessages (std::vector > msgs) { if (m_State == eSSU2SessionStateTerminated) return; + bool isSemiFull = m_SendQueue.size () > SSU2_MAX_OUTGOING_QUEUE_SIZE/2; for (auto it: msgs) - m_SendQueue.push_back (std::move (it)); + if (isSemiFull && it->onDrop) + it->Drop (); // drop earlier because we can handle it + else + m_SendQueue.push_back (std::move (it)); SendQueue (); if (m_SendQueue.size () > 0) // windows is full From 8f28cee32fa76c87d8b2930a6197732a21f84852 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 1 Feb 2024 18:55:10 -0500 Subject: [PATCH 0295/1171] drop earlier if delayed queue is semi-full --- libi2pd/Transports.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 5d3027a9..a70e77b4 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -477,7 +477,10 @@ namespace transport } } for (auto& it1: msgs) - it->second.delayedMessages.push_back (it1); + if (sz > MAX_NUM_DELAYED_MESSAGES/2 && it1->onDrop) + it1->Drop (); // drop earlier because we can handle it + else + it->second.delayedMessages.push_back (it1); } else { From 47578b69c621a6d8b6a812530b8a6da31bbd9a9a Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 1 Feb 2024 19:38:12 -0500 Subject: [PATCH 0296/1171] handle drop of tunnel test message --- libi2pd/TunnelPool.cpp | 74 +++++++++++++++++++++++++++--------------- libi2pd/TunnelPool.h | 4 +-- 2 files changed, 50 insertions(+), 28 deletions(-) diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index 5339c9be..93df99be 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -360,36 +360,58 @@ namespace tunnel } // new tests - std::unique_lock l1(m_OutboundTunnelsMutex); - auto it1 = m_OutboundTunnels.begin (); - std::unique_lock l2(m_InboundTunnelsMutex); - auto it2 = m_InboundTunnels.begin (); - while (it1 != m_OutboundTunnels.end () && it2 != m_InboundTunnels.end ()) + std::vector, std::shared_ptr > > newTests; { - bool failed = false; - if ((*it1)->IsFailed ()) + std::unique_lock l1(m_OutboundTunnelsMutex); + auto it1 = m_OutboundTunnels.begin (); + std::unique_lock l2(m_InboundTunnelsMutex); + auto it2 = m_InboundTunnels.begin (); + while (it1 != m_OutboundTunnels.end () && it2 != m_InboundTunnels.end ()) { - failed = true; - ++it1; - } - if ((*it2)->IsFailed ()) - { - failed = true; - ++it2; - } - if (!failed) - { - uint32_t msgID; - RAND_bytes ((uint8_t *)&msgID, 4); + bool failed = false; + if ((*it1)->IsFailed ()) { - std::unique_lock l(m_TestsMutex); - m_Tests[msgID] = std::make_pair (*it1, *it2); + failed = true; + ++it1; + } + if ((*it2)->IsFailed ()) + { + failed = true; + ++it2; + } + if (!failed) + { + newTests.push_back(std::make_pair (*it1, *it2)); + ++it1; ++it2; } - (*it1)->SendTunnelDataMsgTo ((*it2)->GetNextIdentHash (), (*it2)->GetNextTunnelID (), - CreateDeliveryStatusMsg (msgID)); - ++it1; ++it2; } - } + } + for (auto& it: newTests) + { + uint32_t msgID; + RAND_bytes ((uint8_t *)&msgID, 4); + { + std::unique_lock l(m_TestsMutex); + m_Tests[msgID] = it; + } + auto msg = CreateDeliveryStatusMsg (msgID); + auto outbound = it.first; + auto s = shared_from_this (); + msg->onDrop = [msgID, outbound, s]() + { + // if test msg dropped locally it's outbound tunnel to blame + outbound->SetState (eTunnelStateFailed); + { + std::unique_lock l(s->m_TestsMutex); + s->m_Tests.erase (msgID); + } + { + std::unique_lock l(s->m_OutboundTunnelsMutex); + s->m_OutboundTunnels.erase (outbound); + } + }; + outbound->SendTunnelDataMsgTo (it.second->GetNextIdentHash (), it.second->GetNextTunnelID (), msg); + } } void TunnelPool::ManageTunnels (uint64_t ts) diff --git a/libi2pd/TunnelPool.h b/libi2pd/TunnelPool.h index c1fd19cd..7cb1f5c9 100644 --- a/libi2pd/TunnelPool.h +++ b/libi2pd/TunnelPool.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -30,7 +30,7 @@ namespace tunnel const int TUNNEL_POOL_MANAGE_INTERVAL = 10; // in seconds const int TUNNEL_POOL_MAX_INBOUND_TUNNELS_QUANTITY = 16; const int TUNNEL_POOL_MAX_OUTBOUND_TUNNELS_QUANTITY = 16; - const int TUNNEL_POOL_MAX_NUM_BUILD_REQUESTS = 2; + const int TUNNEL_POOL_MAX_NUM_BUILD_REQUESTS = 3; class Tunnel; class InboundTunnel; From 7b776666a3dcec3e7237a064c2ce97139e7a86ea Mon Sep 17 00:00:00 2001 From: StormyCloudInc <64628149+WaxySteelWorm@users.noreply.github.com> Date: Sat, 3 Feb 2024 10:21:19 -0600 Subject: [PATCH 0297/1171] Add files via upload --- .../reseed/admin_at_stormycloud.org.crt | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 contrib/certificates/reseed/admin_at_stormycloud.org.crt diff --git a/contrib/certificates/reseed/admin_at_stormycloud.org.crt b/contrib/certificates/reseed/admin_at_stormycloud.org.crt new file mode 100644 index 00000000..ae44521b --- /dev/null +++ b/contrib/certificates/reseed/admin_at_stormycloud.org.crt @@ -0,0 +1,34 @@ +-----BEGIN CERTIFICATE----- +MIIF1zCCA7+gAwIBAgIRAMDqFR09Xuj8ZUu+oetSvAEwDQYJKoZIhvcNAQELBQAw +dTELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJYWDEeMBwGA1UE +ChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxHjAcBgNVBAMM +FWFkbWluQHN0b3JteWNsb3VkLm9yZzAeFw0yNDAxMjUxNDE1MzBaFw0zNDAxMjUx +NDE1MzBaMHUxCzAJBgNVBAYTAlhYMQswCQYDVQQHEwJYWDELMAkGA1UECRMCWFgx +HjAcBgNVBAoTFUkyUCBBbm9ueW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMR4w +HAYDVQQDDBVhZG1pbkBzdG9ybXljbG91ZC5vcmcwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQDbGX+GikPzQXr9zvkrhfO9g0l49KHLNQhUKYqd6T+PfnGo +Fm0d3ZZVVQZ045vWgroOXDGGZZWxUIlb2inRaR2DF1TxN3pPYt59RgY9ZQ9+TL7o +isY91krCRygY8EcAmHIjlfZQ9dBVcL7CfyT0MYZA5Efee9+NDHSewTfQP9T2faIE +83Fcyd93a2mIHYjKUbJnojng/wgsy8srbsEuuTok4MIQmDj+B5nz+za2FgI0/ydh +srlMt4aGJF4/DIem9z9d0zBCOkwrmtFIzjNF1mOSA8ES4m5YnKA/y9rZlRidLPGu +prbXhPVnqHeOnHMz2QCw1wbVo504kl0bMqyEz2tVWsO9ep7iZoQs2xkFAEaegYNT +QLUpwVGlyuq3wXXwopFRffOSimGSazICwWI6j+K0pOtgefNJaWrqKYvtkj1SbK2L +LBNUIENz6VnB7KPRckuX6zxC8PpOiBK9BcftfO+xAz/wC6qq3riBPw30KKSym0nC +Zp5KciDn4Phtw9PGq8Bkl8SyWl0jtFnfTB1tzJkisf2qKcNHaFTEe2JW763YLbh/ +AU+8X8evFu40qLgvOgKoyy5DLy6i8zetX+3t9K0Fxt9+Vzzq6lm5V/RS8iIPPn+M +q1/3Z5kD0KQBG9h/Gl8BH+lB71ZxPAOZ3SMu8DJZcxBLVmDWqQPCr5CKnoz0swID +AQABo2IwYDAOBgNVHQ8BAf8EBAMCAoQwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsG +AQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHgYDVR0OBBcEFWFkbWluQHN0b3JteWNs +b3VkLm9yZzANBgkqhkiG9w0BAQsFAAOCAgEARWOJ69vTHMneSXYscha+4Ytjg0RM +faewJNEGj8qy/Qvh9si2bWYNPRK6BlbHFS7pRYBLAnhaeLBGVv1CCR6GUMMe74zQ +UuMeAoWU6qMDmB3GfYoZJh8sIxpwHqyJeTdeccRbZ4sX4F6u3IHPXYiU/AgbYqH7 +pYXQg2lCjXZYaDFAlEf5SlYUDOhhXe5kR8Edhlrsu32/JzA1DQK0JjxKCBp+DQmA +ltdOpQtAg03fHP4ssdj7VvjIDl28iIlATwBvHrdNm7T0tYWn6TWhvxbRqvfTxfaH +MvxnPdIJwNP4/9TyQkwjwHb1h+ucho3CnxI/AxspdOvT1ElMhP6Ce6rcS9pk11Rl +x0ChsqpWwDg7KYpg0qZFSKCTBp4zBq9xoMJ6BQcgMfyl736WbsCzFTEyfifp8beg +NxUa/Qk7w7cuSPGyMIKNOmOR7FLlFbtocy8sXVsUQdqnp/edelufdNe39U9uNtY6 +yoXI9//Tc6NgOwy2Oyia0slZ5qHRkB7e4USXMRzJ3p4q9eCVKjAJs81Utp7O2U+9 +vhbhwWP8CAnNTT1E5WS6EKtfrdqF7wjkV+noPGLDGmrXi01J1fSMAjMfVO+7/LOL +UN+G4ybKWnEhhOO27yidN8Xx6UrCS23DBlPPQAeA74dTsTExiOxf1o1EXzcQiMyO +LAj3/Ojbi1xkWhI= +-----END CERTIFICATE----- From de2b0f6e0986c16d394e1d9b34dcd10266d96e2f Mon Sep 17 00:00:00 2001 From: StormyCloudInc <64628149+WaxySteelWorm@users.noreply.github.com> Date: Sat, 3 Feb 2024 10:24:11 -0600 Subject: [PATCH 0298/1171] Update Config.cpp --- libi2pd/Config.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 4deb59ac..18cc69ee 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -223,7 +223,8 @@ namespace config { "https://i2p.ghativega.in/," "https://i2p.novg.net/," "https://reseed.is.prestium.org/," - "https://reseed.us.prestium.org/" + "https://reseed.us.prestium.org/", + "https://reseed.stormycloud.org/" ), "Reseed URLs, separated by comma") ("reseed.yggurls", value()->default_value( "http://[324:71e:281a:9ed3::ace]:7070/," From ce356378667fac05b192ec5e9ae1e4c7fbf7bc31 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 4 Feb 2024 15:45:22 -0500 Subject: [PATCH 0299/1171] handle drop of tunnel build message --- libi2pd/Tunnel.cpp | 14 ++++++++++---- libi2pd/Tunnel.h | 14 +++++++++++--- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index b8e17920..b578217f 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -90,7 +90,13 @@ namespace tunnel hop = hop->prev; } msg->FillI2NPMessageHeader (m_Config->IsShort () ? eI2NPShortTunnelBuild : eI2NPVariableTunnelBuild); - + auto s = shared_from_this (); + msg->onDrop = [s]() + { + LogPrint (eLogInfo, "I2NP: Tunnel ", s->GetTunnelID (), " request was not sent"); + s->SetState (i2p::tunnel::eTunnelStateBuildFailed); + }; + // send message if (outboundTunnel) { @@ -246,7 +252,7 @@ namespace tunnel { if (IsFailed ()) SetState (eTunnelStateEstablished); // incoming messages means a tunnel is alive EncryptTunnelMsg (msg, msg); - msg->from = shared_from_this (); + msg->from = GetSharedFromThis (); m_Endpoint.HandleDecryptedTunnelDataMsg (msg); } @@ -261,7 +267,7 @@ namespace tunnel if (msg) { m_NumReceivedBytes += msg->GetLength (); - msg->from = shared_from_this (); + msg->from = GetSharedFromThis (); HandleI2NPMessage (msg); } } diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index e6e3c3a5..47ff0465 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -65,7 +65,8 @@ namespace tunnel class OutboundTunnel; class InboundTunnel; - class Tunnel: public TunnelBase + class Tunnel: public TunnelBase, + public std::enable_shared_from_this { struct TunnelHop { @@ -155,7 +156,7 @@ namespace tunnel i2p::data::IdentHash m_EndpointIdentHash; }; - class InboundTunnel: public Tunnel, public std::enable_shared_from_this + class InboundTunnel: public Tunnel { public: @@ -167,6 +168,13 @@ namespace tunnel // override TunnelBase void Cleanup () override { m_Endpoint.Cleanup (); }; + protected: + + std::shared_ptr GetSharedFromThis () + { + return std::static_pointer_cast(shared_from_this ()); + } + private: TunnelEndpoint m_Endpoint; From be815804e66c878c81cb802193b589204d66005b Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 5 Feb 2024 15:44:17 -0500 Subject: [PATCH 0300/1171] expire transit tunnel is not sent further --- libi2pd/I2NPProtocol.cpp | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index ebd5f8d6..70cefbdc 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -584,13 +584,14 @@ namespace i2p memcpy (ivKey, noiseState.m_CK , 32); // check if we accept this tunnel + std::shared_ptr transitTunnel; uint8_t retCode = 0; if (!i2p::context.AcceptsTunnels () || i2p::context.IsHighCongestion ()) retCode = 30; if (!retCode) { // create new transit tunnel - auto transitTunnel = i2p::tunnel::CreateTransitTunnel ( + transitTunnel = i2p::tunnel::CreateTransitTunnel ( bufbe32toh (clearText + SHORT_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET), clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, bufbe32toh (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET), @@ -624,11 +625,22 @@ namespace i2p reply += SHORT_TUNNEL_BUILD_RECORD_SIZE; } // send reply + auto onDrop = [transitTunnel]() + { + if (transitTunnel) + { + auto t = transitTunnel->GetCreationTime (); + if (t > i2p::tunnel::TUNNEL_EXPIRATION_TIMEOUT) + // make transit tunnel expired + transitTunnel->SetCreationTime (t - i2p::tunnel::TUNNEL_EXPIRATION_TIMEOUT); + } + }; if (isEndpoint) { auto replyMsg = NewI2NPShortMessage (); replyMsg->Concat (buf, len); replyMsg->FillI2NPMessageHeader (eI2NPShortTunnelBuildReply, bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET)); + if (transitTunnel) replyMsg->onDrop = onDrop; if (memcmp ((const uint8_t *)i2p::context.GetIdentHash (), clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, 32)) // reply IBGW is not local? { @@ -652,9 +664,12 @@ namespace i2p } } else - transports.SendMessage (clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, - CreateI2NPMessage (eI2NPShortTunnelBuild, buf, len, - bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET))); + { + auto msg = CreateI2NPMessage (eI2NPShortTunnelBuild, buf, len, + bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET)); + if (transitTunnel) msg->onDrop = onDrop; + transports.SendMessage (clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, msg); + } return; } record += SHORT_TUNNEL_BUILD_RECORD_SIZE; @@ -714,7 +729,11 @@ namespace i2p return msg; } else - return CreateTunnelGatewayMsg (tunnelID, msg->GetBuffer (), msg->GetLength ()); + { + auto newMsg = CreateTunnelGatewayMsg (tunnelID, msg->GetBuffer (), msg->GetLength ()); + if (msg->onDrop) newMsg->onDrop = msg->onDrop; + return newMsg; + } } std::shared_ptr CreateTunnelGatewayMsg (uint32_t tunnelID, I2NPMessageType msgType, From f64b136f5a8426c304e38946c5cf8cfa62de5281 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 6 Feb 2024 13:37:08 -0500 Subject: [PATCH 0301/1171] remove prestium reseeds --- .../reseed/null_at_i2pmail.org.crt | 33 ------------------ .../reheatedburger_at_protonmail.com.crt | 34 ------------------- libi2pd/Config.cpp | 4 +-- 3 files changed, 1 insertion(+), 70 deletions(-) delete mode 100644 contrib/certificates/reseed/null_at_i2pmail.org.crt delete mode 100644 contrib/certificates/reseed/reheatedburger_at_protonmail.com.crt diff --git a/contrib/certificates/reseed/null_at_i2pmail.org.crt b/contrib/certificates/reseed/null_at_i2pmail.org.crt deleted file mode 100644 index d736a95e..00000000 --- a/contrib/certificates/reseed/null_at_i2pmail.org.crt +++ /dev/null @@ -1,33 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFyDCCA7CgAwIBAgIRAO8lBnTo+hlvglQwug2jHZkwDQYJKoZIhvcNAQELBQAw -cDELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJYWDEeMBwGA1UE -ChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxGTAXBgNVBAMM -EG51bGxAaTJwbWFpbC5vcmcwHhcNMjMwOTIxMjIzMTM2WhcNMzMwOTIxMjIzMTM2 -WjBwMQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYD -VQQKExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEZMBcGA1UE -AwwQbnVsbEBpMnBtYWlsLm9yZzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC -ggIBAMMpAvaHwzuZZ6qelRU4jcgpuAIZFH++F1Te4b1t02pRfnQ0Eeh04VC1JxO0 -XjUr1/iszEyvrI4+AdxaobDyRFPylkOLtfec4d2ciDc1cupj6y2vyYhMVN31rrvE -ve7sKoTHJ5Dx+UPGOVZZsSsmK9TXIU23W2bo7k2VnjVBXdWZyNE4twfTYCosDnYA -1HIEaIUFVv+COqw2pktxkMmfUAlnDLeVSfsAzEr37K+x0Xk5hO8m6GWQx0NRjjYp -gyEcFhWAJjAYaF3gUVR9rVVky1OeFhZgxE/KzVrW7uc84ZCMKITEPwT0qqIpsTJp -486YXzuPSc+ef78cKSQf5992l7imySJ24I/5H73HkovGAFGZdwvl6V6Ta5YqO7RR -gVDOL1EIVUnMCqFBCE6RmyZqXBVrv4Cacdc6lZ4fj42SRtWZfe6rNCpJzTRtbOyW -DBmYpK6q/jddfqI1sX0PXIn9U+Rod5Z4uz82PAjhamqyr5fpAnoQxKppBvQ3tNfn -KQhmP73Hdpvl24pRyQLBIRUL86i7TPBBn7n3XZlQfXP7lp8+KJYLkL2/zCVDrwLX -kC9hRIxCU9bZbXlkRE2R/PrK53LZecjk2KcgINA4ZlguNgze/Qj8BXelUF4izbpV -bTSvniTM46AECvjDcICAOky9Ku4RnmUJxQVf3ahDEuso7/N7AgMBAAGjXTBbMA4G -A1UdDwEB/wQEAwIChDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDwYD -VR0TAQH/BAUwAwEB/zAZBgNVHQ4EEgQQbnVsbEBpMnBtYWlsLm9yZzANBgkqhkiG -9w0BAQsFAAOCAgEAEUfYJTdDH7uCojnpF0Gs2tXxPJ22UhdqEsXfqR7KhhmmApss -q5kiiPIYoy5T/4IM7NVyeeJAMYwQsdJjwZ4QyxLBb9EqMS2krREcPZNRfFzBr2Wj -EBhJEYTnbIn4docwJWyXsJVG0CqFXPF1qGd0Sc2u87yj2xZNTnloWKAEQAO7DE39 -gWfDH6slM/3h3WD3Mjuk7JoYSYmBfvvm2hkBbC6lzD7XY7rdSmIUwJ050e9UrJaV -La51dd5r4q8d1cHrVUwLiACAaXJ15AEqUDLHQcvKvyfhkabwRy+v0wsodSMgSMEH -xA+kGhkIW7yV7o2exYOYypHCca3IA+pimMpEseNNrHSwbHOMfauiN7jiZLEPg6D6 -a8XwK7qmMYUq7j6QWuIqI81o29WZRf4LZ0GFoVce+e5VxkVKSItKcJoedIAp1ML8 -NhFwd9s/nqWidu/StscEEbGzz6ZuDXwshERXC0QR8HjHEPi4U8220juf4cxUahxK -heEU91l7VksSZYRUN98h28vovGcukLcnVoLj5H/+Z4r/BgxMrOUJKetxf8fU7FjO -j1U6XV36tGi+IOwYQb9D5fTVafC3hHkuUIjlOdUGYadse98ILhn9kaNtqkBtk/EU -vK+McnrEv7tcKrbvYEop/KaUayhjFiL+wGWnpxt7gLhIiavnIeUyD7acltw= ------END CERTIFICATE----- diff --git a/contrib/certificates/reseed/reheatedburger_at_protonmail.com.crt b/contrib/certificates/reseed/reheatedburger_at_protonmail.com.crt deleted file mode 100644 index d14c5fe1..00000000 --- a/contrib/certificates/reseed/reheatedburger_at_protonmail.com.crt +++ /dev/null @@ -1,34 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIF7zCCA9egAwIBAgIRANVB/+wEuXS0Ttoh5teJt90wDQYJKoZIhvcNAQELBQAw -fTELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJYWDEeMBwGA1UE -ChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxJjAkBgNVBAMM -HXJlaGVhdGVkYnVyZ2VyQHByb3Rvbm1haWwuY29tMB4XDTIzMDkyMTE4MDAyOVoX -DTMzMDkyMTE4MDAyOVowfTELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYD -VQQJEwJYWDEeMBwGA1UEChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQL -EwNJMlAxJjAkBgNVBAMMHXJlaGVhdGVkYnVyZ2VyQHByb3Rvbm1haWwuY29tMIIC -IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuNwmiIY3MLSBS5sL5PXRDVK6 -MoSNw4qx0o8nDHvVBxNtzgc0/qjYvsuUggY0tZbPpxhML6GHd4qo7Z3Ip1x0MxhI -Ao5MJaflaEdm4+HeMy0IE3aU73KRUwp+nF3cUHZdlps+9mtYs4oncVEWkFQwGsgt -4yrLtXf6PmPWfFH28ffeaev90e+hdhQpTvr54Ewx6NTaMQr8mkhXL2utvPpjnPM5 -UAhOeJCMgfhLzgS4rahG0O8CQMtH5gKZ+6zjoSRatnjj0j1mBO7+e1TL5O7dVS9k -P83tmkIDDl4tXBzXr9aXQMJstbM2CEvinVcCsR74GjPcg4iB0Ift71Dx7oGKI06t -3bSvll0GZm2mFhIba/4q6f4oAJ2aeq6ejt1Kcm8g5cxtwrRZnXv5JXHZqba3y8J5 -zWaRHzhc9tyEqRBRkc6c7xMdZQ31iJ6TlxUT8vAJ1N7OnX87oHrCjwyikpyOen4r -Uvv1Ge054XPTeoHz+Jyt34t71ty1W13uPHpuvtPVR9MfgGrxd4Z9+LWvAjmMbFsZ -lC3Ll+94nUk+O0puU6KisuCGP4hCtdEtebkIqT8zo8LicLAYUMjX7KwnS7681Cu1 -sY2mB2oZAytN9Zy42oOoNeY5x39kxfwuut/2E1kxKX75O0bwfIXr611abCKc3bbz -euMrIsaB/2VFp9nAah8CAwEAAaNqMGgwDgYDVR0PAQH/BAQDAgKEMB0GA1UdJQQW -MBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MCYGA1UdDgQf -BB1yZWhlYXRlZGJ1cmdlckBwcm90b25tYWlsLmNvbTANBgkqhkiG9w0BAQsFAAOC -AgEATuHi2Yz52OK7e+sKVdHu2KrSLCGm98BG1UIMHFi3WRBTOFyp+lZ519bJ1rFj -tmP9E1a+k/vlbc7FbV4PcV6HJYfGEv/ImtJsEnrzbhrQphC1zMFv7q6JCTUbAzl6 -ySlJ++mVxQ6AzPNH3TQgL1wPKuLh76/Y4053fg+NI3PmzzhkTUheVDkg0/a9ENSf -xMnCa3fIm869735qHk67QlikFvAfWwc4zT1Ncwodh8G4+oX0GFzIl+OZaM1GTMuD -UCcFKoqwtjyLCr22xNk8CfyiExPJXQG1HzEvDcxyoxQtnh9occR9PgqXySz26/NM -XDyM+l4utLMGBcVY4x9fksRiaWEfxiygYOxY9zDl6clh6S10b3CLut4UMiS1RTtE -Mjx2BZN3p0nxpT2leJdGxtBPGrvxuiCOEmTbOMLc3DQtppXO97B3dVMtJ5Ee8Y6p -Tq/8eiHI6eQXat6dgFT5X16vzF7w7XO7fAxuqk4Kx1D1aTVyikdo+Fcdg44dWOjq -NZu8VcCzZij/Dfjlce6t6h8D+wvDD8AkiivaDljpvbNDx/QQlQXFgH98TZA8Rnvr -QcyNNATfz+1yQUiyO6Lrjaw64OJwXYX/llgnDC+qQpP6kqZabi2TsG0EVPukVvr9 -0HyAUu4lnXtTIDq2yPNenegCloqDL1ZQdaYd2XIItnfZdTY= ------END CERTIFICATE----- diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 18cc69ee..b2ad7a17 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -222,8 +222,6 @@ namespace config { "https://www2.mk16.de/," "https://i2p.ghativega.in/," "https://i2p.novg.net/," - "https://reseed.is.prestium.org/," - "https://reseed.us.prestium.org/", "https://reseed.stormycloud.org/" ), "Reseed URLs, separated by comma") ("reseed.yggurls", value()->default_value( From c01fd3299ffb23f0497957ac6f10d8564a4fd7e4 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 6 Feb 2024 18:51:59 -0500 Subject: [PATCH 0302/1171] handle drop of destination publish msg --- libi2pd/Destination.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 9b173f24..ef0d5db3 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -626,6 +626,15 @@ namespace client LogPrint (eLogDebug, "Destination: Publish LeaseSet of ", GetIdentHash ().ToBase32 ()); RAND_bytes ((uint8_t *)&m_PublishReplyToken, 4); auto msg = WrapMessageForRouter (floodfill, i2p::CreateDatabaseStoreMsg (leaseSet, m_PublishReplyToken, inbound)); + auto s = shared_from_this (); + msg->onDrop = [s]() + { + s->GetService ().post([s]() + { + s->m_PublishConfirmationTimer.cancel (); + s->HandlePublishConfirmationTimer (boost::system::error_code()); + }); + }; m_PublishConfirmationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT)); m_PublishConfirmationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishConfirmationTimer, shared_from_this (), std::placeholders::_1)); @@ -642,7 +651,7 @@ namespace client m_PublishReplyToken = 0; if (GetIdentity ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL) { - LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds, will try again"); + LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds or failed. will try again"); Publish (); } else @@ -827,7 +836,9 @@ namespace client AddECIESx25519Key (replyKey, replyTag); else AddSessionKey (replyKey, replyTag); - auto msg = CreateLeaseSetDatabaseLookupMsg (dest, request->excluded, request->replyTunnel, replyKey, replyTag, isECIES); + + auto msg = WrapMessageForRouter (nextFloodfill, + CreateLeaseSetDatabaseLookupMsg (dest, request->excluded, request->replyTunnel, replyKey, replyTag, isECIES)); auto s = shared_from_this (); msg->onDrop = [s, dest, request]() { @@ -836,13 +847,12 @@ namespace client s->SendNextLeaseSetRequest (dest, request); }); }; - auto encryptedMsg = WrapMessageForRouter (nextFloodfill, msg); request->outboundTunnel->SendTunnelDataMsgs ( { i2p::tunnel::TunnelMessageBlock { i2p::tunnel::eDeliveryTypeRouter, - nextFloodfill->GetIdentHash (), 0, encryptedMsg + nextFloodfill->GetIdentHash (), 0, msg } }); request->requestTimeoutTimer.expires_from_now (boost::posix_time::seconds(LEASESET_REQUEST_TIMEOUT)); From c158bbe90a7c502b9a5fc23d6a8218bf7372b3d3 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 7 Feb 2024 19:43:29 -0500 Subject: [PATCH 0303/1171] send frame when it exceeds 16K --- libi2pd/NTCP2.cpp | 3 +++ libi2pd/NTCP2.h | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 76f3a940..0dbccbca 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1152,10 +1152,13 @@ namespace transport msgs.push_back (msg); s += (len + 3); m_SendQueue.pop_front (); + if (s >= NTCP2_SEND_AFTER_FRAME_SIZE) + break; // send frame right a way } else if (len + 3 > NTCP2_UNENCRYPTED_FRAME_MAX_SIZE) { LogPrint (eLogError, "NTCP2: I2NP message of size ", len, " can't be sent. Dropped"); + msg->Drop (); m_SendQueue.pop_front (); } else diff --git a/libi2pd/NTCP2.h b/libi2pd/NTCP2.h index ba1380c3..1eac23f0 100644 --- a/libi2pd/NTCP2.h +++ b/libi2pd/NTCP2.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -28,6 +28,7 @@ namespace transport { const size_t NTCP2_UNENCRYPTED_FRAME_MAX_SIZE = 65519; + const size_t NTCP2_SEND_AFTER_FRAME_SIZE = 16386; // send frame when exceeds this size const size_t NTCP2_SESSION_REQUEST_MAX_SIZE = 287; const size_t NTCP2_SESSION_CREATED_MAX_SIZE = 287; const int NTCP2_MAX_PADDING_RATIO = 6; // in % From 586695673b6b6e8fc9e6d3a17d963da196e98b71 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 8 Feb 2024 18:48:10 -0500 Subject: [PATCH 0304/1171] correct log message for next netdb request --- libi2pd/NetDbRequests.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libi2pd/NetDbRequests.cpp b/libi2pd/NetDbRequests.cpp index 3b5f41b6..4893fa1b 100644 --- a/libi2pd/NetDbRequests.cpp +++ b/libi2pd/NetDbRequests.cpp @@ -189,6 +189,7 @@ namespace data direct = false; // floodfill can't be reached directly if (direct) { + LogPrint (eLogDebug, "NetDbReq: Try ", dest->GetDestination ().ToBase64 (), " at ", count, " floodfill ", nextFloodfill->GetIdentHash ().ToBase64 (), " directly"); auto msg = dest->CreateRequestMessage (nextFloodfill->GetIdentHash ()); msg->onDrop = [this, dest]() { this->SendNextRequest (dest); }; i2p::transport::transports.SendMessage (nextFloodfill->GetIdentHash (), msg); @@ -200,7 +201,7 @@ namespace data auto inbound = pool->GetNextInboundTunnel (); if (nextFloodfill && outbound && inbound) { - LogPrint (eLogDebug, "NetDbReq: Try ", dest->GetDestination (), " at ", count, " floodfill ", nextFloodfill->GetIdentHash ().ToBase64 ()); + LogPrint (eLogDebug, "NetDbReq: Try ", dest->GetDestination ().ToBase64 (), " at ", count, " floodfill ", nextFloodfill->GetIdentHash ().ToBase64 (), " through tunnels"); auto msg = dest->CreateRequestMessage (nextFloodfill, inbound); msg->onDrop = [this, dest]() { this->SendNextRequest (dest); }; outbound->SendTunnelDataMsgTo (nextFloodfill->GetIdentHash (), 0, From f98027755281c4d168bd4843b1850ce7ceb2cfc6 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 8 Feb 2024 19:55:54 -0500 Subject: [PATCH 0305/1171] don't flood failed router --- libi2pd/NetDb.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index bedb19f6..f2166bf0 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -226,7 +226,8 @@ namespace data bool NetDb::AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len) { bool updated; - AddRouterInfo (ident, buf, len, updated); + if (!AddRouterInfo (ident, buf, len, updated)) + updated = false; return updated; } @@ -874,7 +875,7 @@ namespace data } else // RouterInfo { - LogPrint (eLogDebug, "NetDb: Store request: RouterInfo"); + LogPrint (eLogDebug, "NetDb: Store request: RouterInfo ", ident.ToBase64()); size_t size = bufbe16toh (buf + offset); offset += 2; if (size > MAX_RI_BUFFER_SIZE || size > len - offset) From 1b23aa2d7b7e4696713f7ce0a4d90e1a92baee85 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 8 Feb 2024 21:44:12 -0500 Subject: [PATCH 0306/1171] increase request timeout --- libi2pd/NetDb.cpp | 2 +- libi2pd/NetDbRequests.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index f2166bf0..f3822997 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -149,7 +149,7 @@ namespace data if (!i2p::transport::transports.IsOnline ()) continue; // don't manage netdb when offline uint64_t ts = i2p::util::GetSecondsSinceEpoch (); - if (ts - lastManageRequest >= 15 || ts + 15 < lastManageRequest) // manage requests every 15 seconds + if (ts - lastManageRequest >= MANAGE_REQUESTS_INTERVAL || ts + MANAGE_REQUESTS_INTERVAL < lastManageRequest) // manage requests every 15 seconds { m_Requests.ManageRequests (); lastManageRequest = ts; diff --git a/libi2pd/NetDbRequests.h b/libi2pd/NetDbRequests.h index 47a5d481..25c102de 100644 --- a/libi2pd/NetDbRequests.h +++ b/libi2pd/NetDbRequests.h @@ -21,8 +21,9 @@ namespace i2p namespace data { const size_t MAX_NUM_REQUEST_ATTEMPTS = 7; + const uint64_t MANAGE_REQUESTS_INTERVAL = 15; // in seconds const uint64_t MIN_REQUEST_TIME = 5; // in seconds - const uint64_t MAX_REQUEST_TIME = 60; // in seconds + const uint64_t MAX_REQUEST_TIME = MAX_NUM_REQUEST_ATTEMPTS*MANAGE_REQUESTS_INTERVAL; class RequestedDestination { From 7dd9a7a0afc0acfad81421ba681fc889ea08a8ce Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 8 Feb 2024 21:45:57 -0500 Subject: [PATCH 0307/1171] added CheckLogLevel --- libi2pd/Log.h | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/libi2pd/Log.h b/libi2pd/Log.h index 1ec0c5fe..0164ea4f 100644 --- a/libi2pd/Log.h +++ b/libi2pd/Log.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -87,8 +87,8 @@ namespace log { Log (); ~Log (); - LogType GetLogType () { return m_Destination; }; - LogLevel GetLogLevel () { return m_MinLevel; }; + LogType GetLogType () const { return m_Destination; }; + LogLevel GetLogLevel () const { return m_MinLevel; }; void Start (); void Stop (); @@ -160,6 +160,11 @@ namespace log { } // log } // i2p +inline bool CheckLogLevel (LogLevel level) noexcept +{ + return level <= i2p::log::Logger().GetLogLevel (); +} + /** internal usage only -- folding args array to single string */ template void LogPrint (std::stringstream& s, TValue&& arg) noexcept @@ -185,9 +190,7 @@ void LogPrint (std::stringstream& s, TValue&& arg, TArgs&&... args) noexcept template void LogPrint (LogLevel level, TArgs&&... args) noexcept { - i2p::log::Log &log = i2p::log::Logger(); - if (level > log.GetLogLevel ()) - return; + if (!CheckLogLevel (level)) return; // fold message to single string std::stringstream ss; @@ -200,7 +203,7 @@ void LogPrint (LogLevel level, TArgs&&... args) noexcept auto msg = std::make_shared(level, std::time(nullptr), std::move(ss).str()); msg->tid = std::this_thread::get_id(); - log.Append(msg); + i2p::log::Logger().Append(msg); } /** From 592d6ae4f47c7f1647e3b61862d28674fac882ad Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 8 Feb 2024 21:56:25 -0500 Subject: [PATCH 0308/1171] check log level before calculating base32 or base64 of ident --- libi2pd/NetDb.cpp | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index f3822997..026ae53e 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -262,10 +262,12 @@ namespace data return nullptr; } } - LogPrint (eLogInfo, "NetDb: RouterInfo updated: ", ident.ToBase64()); + if (CheckLogLevel (eLogInfo)) + LogPrint (eLogInfo, "NetDb: RouterInfo updated: ", ident.ToBase64()); if (wasFloodfill != r->IsFloodfill ()) // if floodfill status updated { - LogPrint (eLogDebug, "NetDb: RouterInfo floodfill status updated: ", ident.ToBase64()); + if (CheckLogLevel (eLogDebug)) + LogPrint (eLogDebug, "NetDb: RouterInfo floodfill status updated: ", ident.ToBase64()); std::lock_guard l(m_FloodfillsMutex); if (wasFloodfill) m_Floodfills.Remove (r->GetIdentHash ()); @@ -280,7 +282,8 @@ namespace data } else { - LogPrint (eLogDebug, "NetDb: RouterInfo is older: ", ident.ToBase64()); + if (CheckLogLevel (eLogDebug)) + LogPrint (eLogDebug, "NetDb: RouterInfo is older: ", ident.ToBase64()); updated = false; } } @@ -297,7 +300,8 @@ namespace data } if (inserted) { - LogPrint (eLogInfo, "NetDb: RouterInfo added: ", ident.ToBase64()); + if (CheckLogLevel (eLogInfo)) + LogPrint (eLogInfo, "NetDb: RouterInfo added: ", ident.ToBase64()); if (r->IsFloodfill () && r->IsEligibleFloodfill ()) { if (m_Floodfills.GetSize () < NETDB_NUM_FLOODFILLS_THRESHOLD || @@ -338,10 +342,11 @@ namespace data if(it->second->GetExpirationTime() < expires) { it->second->Update (buf, len, false); // signature is verified already - LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase32()); + if (CheckLogLevel (eLogInfo)) + LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase32()); updated = true; } - else + else if (CheckLogLevel (eLogDebug)) LogPrint(eLogDebug, "NetDb: LeaseSet is older: ", ident.ToBase32()); } else @@ -352,7 +357,8 @@ namespace data auto leaseSet = std::make_shared (buf, len, false); // we don't need leases in netdb if (leaseSet->IsValid ()) { - LogPrint (eLogInfo, "NetDb: LeaseSet added: ", ident.ToBase32()); + if (CheckLogLevel (eLogInfo)) + LogPrint (eLogInfo, "NetDb: LeaseSet added: ", ident.ToBase32()); m_LeaseSets[ident] = leaseSet; updated = true; } @@ -376,7 +382,8 @@ namespace data i2p::util::GetSecondsSinceEpoch () + NETDB_EXPIRATION_TIMEOUT_THRESHOLD > leaseSet->GetPublishedTimestamp ()) { // TODO: implement actual update - LogPrint (eLogInfo, "NetDb: LeaseSet2 updated: ", ident.ToBase32()); + if (CheckLogLevel (eLogInfo)) + LogPrint (eLogInfo, "NetDb: LeaseSet2 updated: ", ident.ToBase32()); m_LeaseSets[ident] = leaseSet; return true; } @@ -863,19 +870,22 @@ namespace data { if (storeType == NETDB_STORE_TYPE_LEASESET) // 1 { - LogPrint (eLogDebug, "NetDb: Store request: LeaseSet for ", ident.ToBase32()); + if (CheckLogLevel (eLogDebug)) + LogPrint (eLogDebug, "NetDb: Store request: LeaseSet for ", ident.ToBase32()); updated = AddLeaseSet (ident, buf + offset, len - offset); } else // all others are considered as LeaseSet2 { - LogPrint (eLogDebug, "NetDb: Store request: LeaseSet2 of type ", int(storeType), " for ", ident.ToBase32()); + if (CheckLogLevel (eLogDebug)) + LogPrint (eLogDebug, "NetDb: Store request: LeaseSet2 of type ", int(storeType), " for ", ident.ToBase32()); updated = AddLeaseSet2 (ident, buf + offset, len - offset, storeType); } } } else // RouterInfo { - LogPrint (eLogDebug, "NetDb: Store request: RouterInfo ", ident.ToBase64()); + if (CheckLogLevel (eLogDebug)) + LogPrint (eLogDebug, "NetDb: Store request: RouterInfo ", ident.ToBase64()); size_t size = bufbe16toh (buf + offset); offset += 2; if (size > MAX_RI_BUFFER_SIZE || size > len - offset) From d96803a2909a966bad9cc0599a46191c982dce84 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 9 Feb 2024 15:24:48 -0500 Subject: [PATCH 0309/1171] always request through tunnels in case of restricted routes --- libi2pd/NetDb.cpp | 1 + libi2pd/Transports.cpp | 25 ++++++++++++++++--------- libi2pd/Transports.h | 2 +- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 026ae53e..e8c92658 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -730,6 +730,7 @@ namespace data void NetDb::RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete, bool direct) { + if (direct && i2p::transport::transports.RoutesRestricted ()) direct = false; // always use tunnels for restricted routes auto dest = m_Requests.CreateRequest (destination, false, direct, requestComplete); // non-exploratory if (!dest) { diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index a70e77b4..0afe47a1 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -1015,18 +1015,25 @@ namespace transport } } - void Transports::RestrictRoutesToRouters(std::set routers) + void Transports::RestrictRoutesToRouters(const std::set& routers) { - std::unique_lock lock(m_TrustedRoutersMutex); + std::lock_guard lock(m_TrustedRoutersMutex); m_TrustedRouters.clear(); for (const auto & ri : routers ) m_TrustedRouters.push_back(ri); } - bool Transports::RoutesRestricted() const { - std::unique_lock famlock(m_FamilyMutex); - std::unique_lock routerslock(m_TrustedRoutersMutex); - return m_TrustedFamilies.size() > 0 || m_TrustedRouters.size() > 0; + bool Transports::RoutesRestricted() const + { + { + std::lock_guard routerslock(m_TrustedRoutersMutex); + if (!m_TrustedRouters.empty ()) return true; + } + { + std::lock_guard famlock(m_FamilyMutex); + if (!m_TrustedFamilies.empty ()) return true; + } + return false; } /** XXX: if routes are not restricted this dies */ @@ -1050,7 +1057,7 @@ namespace transport return i2p::data::netdb.GetRandomRouterInFamily(fam); } { - std::unique_lock l(m_TrustedRoutersMutex); + std::lock_guard l(m_TrustedRoutersMutex); auto sz = m_TrustedRouters.size(); if (sz) { @@ -1067,12 +1074,12 @@ namespace transport bool Transports::IsRestrictedPeer(const i2p::data::IdentHash & ih) const { { - std::unique_lock l(m_TrustedRoutersMutex); + std::lock_guard l(m_TrustedRoutersMutex); for (const auto & r : m_TrustedRouters ) if ( r == ih ) return true; } { - std::unique_lock l(m_FamilyMutex); + std::lock_guard l(m_FamilyMutex); auto ri = i2p::data::netdb.FindRouter(ih); for (const auto & fam : m_TrustedFamilies) if(ri->IsFamily(fam)) return true; diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index 540bafb4..206b0256 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -165,7 +165,7 @@ namespace transport /** restrict routes to use only these router families for first hops */ void RestrictRoutesToFamilies(const std::set& families); /** restrict routes to use only these routers for first hops */ - void RestrictRoutesToRouters(std::set routers); + void RestrictRoutesToRouters(const std::set& routers); bool IsRestrictedPeer(const i2p::data::IdentHash & ident) const; From 36dbc15bca1a41f7f764a15e2c272394aa06154d Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 9 Feb 2024 18:08:51 -0500 Subject: [PATCH 0310/1171] keep SSU2 socket open even if failed to bind --- libi2pd/SSU2.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 0ebeab6d..3e0583ea 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -258,13 +258,22 @@ namespace transport socket.set_option (boost::asio::ip::v6_only (true)); socket.set_option (boost::asio::socket_base::receive_buffer_size (SSU2_SOCKET_RECEIVE_BUFFER_SIZE)); socket.set_option (boost::asio::socket_base::send_buffer_size (SSU2_SOCKET_SEND_BUFFER_SIZE)); + } + catch (std::exception& ex ) + { + LogPrint (eLogCritical, "SSU2: Failed to open socket on ", localEndpoint.address (), ": ", ex.what()); + ThrowFatal ("Unable to start SSU2 transport on ", localEndpoint.address (), ": ", ex.what ()); + return socket; + } + try + { socket.bind (localEndpoint); LogPrint (eLogInfo, "SSU2: Start listening on ", localEndpoint); } catch (std::exception& ex ) { - LogPrint (eLogCritical, "SSU2: Failed to bind to ", localEndpoint, ": ", ex.what()); - ThrowFatal ("Unable to start SSU2 transport on ", localEndpoint, ": ", ex.what ()); + LogPrint (eLogWarning, "SSU2: Failed to bind to ", localEndpoint, ": ", ex.what(), ". Actual endpoint is ", socket.local_endpoint ()); + // we can continue without binding being firewalled } return socket; } From adba3987f84f67f6ab8b2be8762f51ff29154a71 Mon Sep 17 00:00:00 2001 From: Vort Date: Sat, 10 Feb 2024 17:10:21 +0200 Subject: [PATCH 0311/1171] logging fixes --- libi2pd/NTCP2.cpp | 2 +- libi2pd/RouterInfo.cpp | 2 +- libi2pd/SSU2Session.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 0dbccbca..19609b0b 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -381,7 +381,7 @@ namespace transport if (remoteIdentity) { LogPrint (eLogDebug, "NTCP2: Session with ", GetRemoteEndpoint (), - " (", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()), ") terminated"); + " (", i2p::data::GetIdentHashAbbreviation (remoteIdentity->GetIdentHash ()), ") terminated"); } else { diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 7cde7c33..a034691a 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -131,7 +131,7 @@ namespace data m_BufferLen = s.tellg (); if (m_BufferLen < 40 || m_BufferLen > MAX_RI_BUFFER_SIZE) { - LogPrint(eLogError, "RouterInfo: File", fullPath, " is malformed"); + LogPrint(eLogError, "RouterInfo: File ", fullPath, " is malformed"); return false; } s.seekg(0, std::ios::beg); diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 12671f4f..4015dcac 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -277,7 +277,7 @@ namespace transport if (remoteIdentity) { LogPrint (eLogDebug, "SSU2: Session with ", GetRemoteEndpoint (), - " (", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()), ") terminated"); + " (", i2p::data::GetIdentHashAbbreviation (remoteIdentity->GetIdentHash ()), ") terminated"); } else { From 158160f5c0256bd91bb68c5550d5fe97150dcda2 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 10 Feb 2024 20:03:36 -0500 Subject: [PATCH 0312/1171] common code for SOCKS5 proxy connectivity --- libi2pd/NTCP2.cpp | 119 ++++------------------------ libi2pd/NTCP2.h | 3 +- libi2pd/SSU2.h | 1 + libi2pd/Socks5.h | 154 +++++++++++++++++++++++++++++++++++++ libi2pd/TransportSession.h | 11 +-- 5 files changed, 170 insertions(+), 118 deletions(-) create mode 100644 libi2pd/Socks5.h diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 19609b0b..58a1c539 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -19,9 +19,10 @@ #include "RouterContext.h" #include "Transports.h" #include "NetDb.hpp" -#include "NTCP2.h" #include "HTTP.h" #include "util.h" +#include "Socks5.h" +#include "NTCP2.h" #if defined(__linux__) && !defined(_NETINET_IN_H) #include @@ -1728,47 +1729,18 @@ namespace transport case eSocksProxy: { // TODO: support username/password auth etc - static const uint8_t buff[3] = {SOCKS5_VER, 0x01, 0x00}; - boost::asio::async_write(conn->GetSocket(), boost::asio::buffer(buff, 3), boost::asio::transfer_all(), - [] (const boost::system::error_code & ec, std::size_t transferred) - { - (void) transferred; - if(ec) - { - LogPrint(eLogWarning, "NTCP2: SOCKS5 write error ", ec.message()); - } - }); - auto readbuff = std::make_shared >(2); - boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(readbuff->data (), 2), - [this, readbuff, timer, conn](const boost::system::error_code & ec, std::size_t transferred) - { - if(ec) - { - LogPrint(eLogError, "NTCP2: SOCKS5 read error ", ec.message()); - timer->cancel(); - conn->Terminate(); - return; - } - else if(transferred == 2) - { - if((*readbuff)[1] == 0x00) - { - AfterSocksHandshake(conn, timer); - return; - } - else if ((*readbuff)[1] == 0xff) - { - LogPrint(eLogError, "NTCP2: SOCKS5 proxy rejected authentication"); - timer->cancel(); - conn->Terminate(); - return; - } - LogPrint(eLogError, "NTCP2:", (int)(*readbuff)[1]); - } - LogPrint(eLogError, "NTCP2: SOCKS5 server gave invalid response"); + Socks5Handshake (conn->GetSocket(), conn->GetRemoteEndpoint (), + [conn, timer](const boost::system::error_code& ec) + { timer->cancel(); - conn->Terminate(); - }); + if (!ec) + conn->ClientLogin(); + else + { + LogPrint(eLogError, "NTCP2: SOCKS proxy handshake error ", ec.message()); + conn->Terminate(); + } + }); break; } case eHTTPProxy: @@ -1836,71 +1808,6 @@ namespace transport } } - void NTCP2Server::AfterSocksHandshake(std::shared_ptr conn, std::shared_ptr timer) - { - // build request - size_t sz = 6; // header + port - auto buff = std::make_shared >(256); - auto readbuff = std::make_shared >(256); - (*buff)[0] = SOCKS5_VER; - (*buff)[1] = SOCKS5_CMD_CONNECT; - (*buff)[2] = 0x00; - - auto& ep = conn->GetRemoteEndpoint (); - if(ep.address ().is_v4 ()) - { - (*buff)[3] = SOCKS5_ATYP_IPV4; - auto addrbytes = ep.address ().to_v4().to_bytes(); - sz += 4; - memcpy(buff->data () + 4, addrbytes.data(), 4); - } - else if (ep.address ().is_v6 ()) - { - (*buff)[3] = SOCKS5_ATYP_IPV6; - auto addrbytes = ep.address ().to_v6().to_bytes(); - sz += 16; - memcpy(buff->data () + 4, addrbytes.data(), 16); - } - else - { - // We mustn't really fall here because all connections are made to IP addresses - LogPrint(eLogError, "NTCP2: Tried to connect to unexpected address via proxy"); - return; - } - htobe16buf(buff->data () + sz - 2, ep.port ()); - boost::asio::async_write(conn->GetSocket(), boost::asio::buffer(buff->data (), sz), boost::asio::transfer_all(), - [buff](const boost::system::error_code & ec, std::size_t written) - { - if(ec) - { - LogPrint(eLogError, "NTCP2: Failed to write handshake to socks proxy ", ec.message()); - return; - } - }); - - boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(readbuff->data (), SOCKS5_UDP_IPV4_REQUEST_HEADER_SIZE), // read min reply size - boost::asio::transfer_all(), - [timer, conn, readbuff](const boost::system::error_code & e, std::size_t transferred) - { - if (e) - LogPrint(eLogError, "NTCP2: SOCKS proxy read error ", e.message()); - else if (!(*readbuff)[1]) // succeeded - { - boost::system::error_code ec; - size_t moreBytes = conn->GetSocket ().available(ec); - if (moreBytes) // read remaining portion of reply if ipv6 received - boost::asio::read (conn->GetSocket (), boost::asio::buffer(readbuff->data (), moreBytes), boost::asio::transfer_all (), ec); - timer->cancel(); - conn->ClientLogin(); - return; - } - else - LogPrint(eLogError, "NTCP2: Proxy reply error ", (int)(*readbuff)[1]); - timer->cancel(); - conn->Terminate(); - }); - } - void NTCP2Server::SetLocalAddress (const boost::asio::ip::address& localAddress) { auto addr = std::make_shared(boost::asio::ip::tcp::endpoint(localAddress, 0)); diff --git a/libi2pd/NTCP2.h b/libi2pd/NTCP2.h index 1eac23f0..a566b38d 100644 --- a/libi2pd/NTCP2.h +++ b/libi2pd/NTCP2.h @@ -267,8 +267,7 @@ namespace transport void HandleConnect (const boost::system::error_code& ecode, std::shared_ptr conn, std::shared_ptr timer); void HandleProxyConnect(const boost::system::error_code& ecode, std::shared_ptr conn, std::shared_ptr timer); - void AfterSocksHandshake(std::shared_ptr conn, std::shared_ptr timer); - + // timer void ScheduleTermination (); void HandleTerminationTimer (const boost::system::error_code& ecode); diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index da682746..da5ca317 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -13,6 +13,7 @@ #include #include "util.h" #include "SSU2Session.h" +#include "Socks5.h" namespace i2p { diff --git a/libi2pd/Socks5.h b/libi2pd/Socks5.h new file mode 100644 index 00000000..84a23997 --- /dev/null +++ b/libi2pd/Socks5.h @@ -0,0 +1,154 @@ +/* +* Copyright (c) 2024, The PurpleI2P Project +* +* This file is part of Purple i2pd project and licensed under BSD3 +* +* See full license text in LICENSE file at top of project tree +* +*/ + +#ifndef SOCKS5_H__ +#define SOCKS5_H__ + +#include +#include +#include +#include "I2PEndian.h" + +namespace i2p +{ +namespace transport +{ + // SOCKS5 constants + const uint8_t SOCKS5_VER = 0x05; + const uint8_t SOCKS5_CMD_CONNECT = 0x01; + const uint8_t SOCKS5_CMD_UDP_ASSOCIATE = 0x03; + const uint8_t SOCKS5_ATYP_IPV4 = 0x01; + const uint8_t SOCKS5_ATYP_IPV6 = 0x04; + const uint8_t SOCKS5_ATYP_NAME = 0x03; + const size_t SOCKS5_UDP_IPV4_REQUEST_HEADER_SIZE = 10; + const size_t SOCKS5_UDP_IPV6_REQUEST_HEADER_SIZE = 22; + + // SOCKS5 handshake + template + void Socks5Connect (Socket& s, Handler handler, std::shared_ptr > buff, uint16_t port) + { + if (buff && buff->size () >= 6) + { + (*buff)[0] = SOCKS5_VER; + (*buff)[1] = SOCKS5_CMD_CONNECT; + (*buff)[2] = 0x00; + htobe16buf(buff->data () + buff->size () - 2, port); + boost::asio::async_write(s, boost::asio::buffer(*buff), boost::asio::transfer_all(), + [buff, &s, handler](const boost::system::error_code& ec, std::size_t transferred) + { + (void) transferred; + if (!ec) + { + auto readbuff = std::make_shared >(262); // max possible + boost::asio::async_read(s, boost::asio::buffer(readbuff->data (), 7), boost::asio::transfer_all(), // read min reply size + [readbuff, &s, handler](const boost::system::error_code& ec, std::size_t transferred) + { + if (!ec) + { + if (!(*readbuff)[1]) // succeeded + { + boost::system::error_code ec; + size_t moreBytes = s.available(ec); + if (!ec && moreBytes) // read remaining portion of reply + boost::asio::read (s, boost::asio::buffer(readbuff->data (), moreBytes), boost::asio::transfer_all (), ec); + if (!ec) + handler (boost::system::error_code ()); + else + handler (boost::asio::error::make_error_code (boost::asio::error::connection_aborted)); + } + else + handler (boost::asio::error::make_error_code (boost::asio::error::connection_refused)); + } + else + handler (ec); + }); + } + else + handler (ec); + }); + } + else + handler (boost::asio::error::make_error_code (boost::asio::error::no_buffer_space)); + } + + template + void Socks5Connect (Socket& s, const boost::asio::ip::tcp::endpoint& ep, Handler handler) + { + std::shared_ptr > buff; + if(ep.address ().is_v4 ()) + { + buff = std::make_shared >(10); + (*buff)[3] = SOCKS5_ATYP_IPV4; + auto addrbytes = ep.address ().to_v4().to_bytes(); + memcpy(buff->data () + 4, addrbytes.data(), 4); + } + else if (ep.address ().is_v6 ()) + { + buff = std::make_shared >(22); + (*buff)[3] = SOCKS5_ATYP_IPV6; + auto addrbytes = ep.address ().to_v6().to_bytes(); + memcpy(buff->data () + 4, addrbytes.data(), 16); + } + if (buff) + Socks5Connect (s, handler, buff, ep.port ()); + else + handler (boost::asio::error::make_error_code (boost::asio::error::fault)); + } + + template + void Socks5Connect (Socket& s, const std::pair& ep, Handler handler) + { + auto& addr = ep.first; + if (addr.length () <= 255) + { + auto buff = std::make_shared >(addr.length () + 7); + (*buff)[3] = SOCKS5_ATYP_NAME; + (*buff)[4] = addr.length (); + memcpy (buff->data () + 5, addr.c_str (), addr.length ()); + Socks5Connect (s, handler, buff, ep.second); + } + else + handler (boost::asio::error::make_error_code (boost::asio::error::name_too_long)); + } + + + template + void Socks5Handshake (Socket& s, Endpoint ep, Handler handler) + { + static const uint8_t methodSelection[3] = { SOCKS5_VER, 0x01, 0x00 }; // 1 method, no auth + boost::asio::async_write(s, boost::asio::buffer(methodSelection, 3), boost::asio::transfer_all(), + [&s, ep, handler] (const boost::system::error_code& ec, std::size_t transferred) + { + (void) transferred; + if (!ec) + { + auto readbuff = std::make_shared >(2); + boost::asio::async_read(s, boost::asio::buffer(*readbuff), boost::asio::transfer_all(), + [&s, ep, handler, readbuff] (const boost::system::error_code& ec, std::size_t transferred) + { + if (!ec) + { + if (transferred == 2 && (*readbuff)[1] == 0x00) // no auth + Socks5Connect (s, ep, handler); + else + handler (boost::asio::error::make_error_code (boost::asio::error::invalid_argument)); + } + else + handler (ec); + }); + } + else + handler (ec); + }); + } + +} +} + +#endif diff --git a/libi2pd/TransportSession.h b/libi2pd/TransportSession.h index f4668116..c6bf0de3 100644 --- a/libi2pd/TransportSession.h +++ b/libi2pd/TransportSession.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -187,15 +187,6 @@ namespace transport uint64_t m_LastActivityTimestamp, m_LastBandwidthUpdateTimestamp; uint32_t m_InBandwidth, m_OutBandwidth; }; - - // SOCKS5 proxy - const uint8_t SOCKS5_VER = 0x05; - const uint8_t SOCKS5_CMD_CONNECT = 0x01; - const uint8_t SOCKS5_CMD_UDP_ASSOCIATE = 0x03; - const uint8_t SOCKS5_ATYP_IPV4 = 0x01; - const uint8_t SOCKS5_ATYP_IPV6 = 0x04; - const size_t SOCKS5_UDP_IPV4_REQUEST_HEADER_SIZE = 10; - const size_t SOCKS5_UDP_IPV6_REQUEST_HEADER_SIZE = 22; } } From 0ae7931a6f4d0299f64f95bea8249b8d6fd7b17d Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 11 Feb 2024 11:23:37 -0500 Subject: [PATCH 0313/1171] replaced SOCKS4 outproxy by SOCKS5 --- libi2pd_client/HTTPProxy.cpp | 71 ++++++++++-------------------------- 1 file changed, 19 insertions(+), 52 deletions(-) diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index a0fc8f07..5f9ee1de 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -29,6 +29,7 @@ #include "Config.h" #include "HTTP.h" #include "I18N.h" +#include "Socks5.h" namespace i2p { namespace proxy { @@ -93,9 +94,6 @@ namespace proxy { void HTTPConnect(const std::string & host, uint16_t port); void HandleHTTPConnectStreamRequestComplete(std::shared_ptr stream); - void HandleSocksProxySendHandshake(const boost::system::error_code & ec, std::size_t bytes_transfered); - void HandleSocksProxyReply(const boost::system::error_code & ec, std::size_t bytes_transfered); - typedef std::function ProxyResolvedHandler; void HandleUpstreamProxyResolved(const boost::system::error_code & ecode, boost::asio::ip::tcp::resolver::iterator itr, ProxyResolvedHandler handler); @@ -612,43 +610,30 @@ namespace proxy { void HTTPReqHandler::HandleUpstreamSocksProxyConnect(const boost::system::error_code & ec) { - if(!ec) { - if(m_RequestURL.host.size() > 255) { + if(!ec) + { + if(m_RequestURL.host.size() > 255) + { GenericProxyError(tr("Hostname is too long"), m_RequestURL.host); return; } uint16_t port = m_RequestURL.port; if(!port) port = 80; LogPrint(eLogDebug, "HTTPProxy: Connected to SOCKS upstream"); - std::string host = m_RequestURL.host; - std::size_t reqsize = 0; - m_socks_buf[0] = '\x04'; - m_socks_buf[1] = 1; - htobe16buf(m_socks_buf+2, port); - m_socks_buf[4] = 0; - m_socks_buf[5] = 0; - m_socks_buf[6] = 0; - m_socks_buf[7] = 1; - // user id - m_socks_buf[8] = 'i'; - m_socks_buf[9] = '2'; - m_socks_buf[10] = 'p'; - m_socks_buf[11] = 'd'; - m_socks_buf[12] = 0; - reqsize += 13; - memcpy(m_socks_buf+ reqsize, host.c_str(), host.size()); - reqsize += host.size(); - m_socks_buf[++reqsize] = 0; - boost::asio::async_write(*m_proxysock, boost::asio::buffer(m_socks_buf, reqsize), boost::asio::transfer_all(), std::bind(&HTTPReqHandler::HandleSocksProxySendHandshake, this, std::placeholders::_1, std::placeholders::_2)); - } else GenericProxyError(tr("Cannot connect to upstream SOCKS proxy"), ec.message()); - } - - void HTTPReqHandler::HandleSocksProxySendHandshake(const boost::system::error_code & ec, std::size_t bytes_transferred) - { - LogPrint(eLogDebug, "HTTPProxy: Upstream SOCKS handshake sent"); - if(ec) GenericProxyError(tr("Cannot negotiate with SOCKS proxy"), ec.message()); - else m_proxysock->async_read_some(boost::asio::buffer(m_socks_buf, 8), std::bind(&HTTPReqHandler::HandleSocksProxyReply, this, std::placeholders::_1, std::placeholders::_2)); + auto s = shared_from_this (); + i2p::transport::Socks5Handshake (*m_proxysock, std::make_pair(host, port), + [s](const boost::system::error_code& ec) + { + if (!ec) + s->SocksProxySuccess(); + else + s->GenericProxyError(tr("SOCKS proxy error"), ec.message ()); + }); + + } + else + GenericProxyError(tr("Cannot connect to upstream SOCKS proxy"), ec.message()); } void HTTPReqHandler::HandoverToUpstreamProxy() @@ -714,24 +699,6 @@ namespace proxy { } } - void HTTPReqHandler::HandleSocksProxyReply(const boost::system::error_code & ec, std::size_t bytes_transferred) - { - if(!ec) - { - if(m_socks_buf[1] == 90) { - // success - SocksProxySuccess(); - } else { - std::stringstream ss; - ss << "error code: "; - ss << (int) m_socks_buf[1]; - std::string msg = ss.str(); - GenericProxyError(tr("SOCKS proxy error"), msg); - } - } - else GenericProxyError(tr("No reply from SOCKS proxy"), ec.message()); - } - void HTTPReqHandler::HandleUpstreamHTTPProxyConnect(const boost::system::error_code & ec) { if(!ec) { From b07530a8a17f49745fbee0b6df6ddd6644779796 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 11 Feb 2024 11:44:15 -0500 Subject: [PATCH 0314/1171] don't print error message if operation cancelled --- libi2pd_client/I2PService.cpp | 88 ++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 37 deletions(-) diff --git a/libi2pd_client/I2PService.cpp b/libi2pd_client/I2PService.cpp index c30b7c9f..9b0b8028 100644 --- a/libi2pd_client/I2PService.cpp +++ b/libi2pd_client/I2PService.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -240,54 +240,68 @@ namespace client void TCPIPPipe::HandleDownstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered) { - LogPrint(eLogDebug, "TCPIPPipe: Downstream: ", (int) bytes_transfered, " bytes received"); - if (ecode) - { - LogPrint(eLogError, "TCPIPPipe: Downstream read error:" , ecode.message()); - if (ecode != boost::asio::error::operation_aborted) + if (ecode != boost::asio::error::operation_aborted) + { + LogPrint(eLogDebug, "TCPIPPipe: Downstream: ", (int) bytes_transfered, " bytes received"); + if (ecode) + { + LogPrint(eLogWarning, "TCPIPPipe: Downstream read error:" , ecode.message()); Terminate(); - } else { - if (bytes_transfered > 0 ) - memcpy(m_upstream_buf, m_downstream_to_up_buf, bytes_transfered); - UpstreamWrite(bytes_transfered); - } + } + else + { + if (bytes_transfered > 0 ) + memcpy(m_upstream_buf, m_downstream_to_up_buf, bytes_transfered); + UpstreamWrite(bytes_transfered); + } + } } - void TCPIPPipe::HandleDownstreamWrite(const boost::system::error_code & ecode) { - if (ecode) - { - LogPrint(eLogError, "TCPIPPipe: Downstream write error:" , ecode.message()); - if (ecode != boost::asio::error::operation_aborted) + void TCPIPPipe::HandleDownstreamWrite(const boost::system::error_code & ecode) + { + if (ecode != boost::asio::error::operation_aborted) + { + if (ecode) + { + LogPrint(eLogWarning, "TCPIPPipe: Downstream write error:" , ecode.message()); Terminate(); - } - else - AsyncReceiveUpstream(); + } + else + AsyncReceiveUpstream(); + } } - void TCPIPPipe::HandleUpstreamWrite(const boost::system::error_code & ecode) { - if (ecode) - { - LogPrint(eLogError, "TCPIPPipe: Upstream write error:" , ecode.message()); - if (ecode != boost::asio::error::operation_aborted) + void TCPIPPipe::HandleUpstreamWrite(const boost::system::error_code & ecode) + { + if (ecode != boost::asio::error::operation_aborted) + { + if (ecode) + { + LogPrint(eLogWarning, "TCPIPPipe: Upstream write error:" , ecode.message()); Terminate(); - } - else - AsyncReceiveDownstream(); + } + else + AsyncReceiveDownstream(); + } } void TCPIPPipe::HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered) { - LogPrint(eLogDebug, "TCPIPPipe: Upstream ", (int)bytes_transfered, " bytes received"); - if (ecode) - { - LogPrint(eLogError, "TCPIPPipe: Upstream read error:" , ecode.message()); - if (ecode != boost::asio::error::operation_aborted) + if (ecode != boost::asio::error::operation_aborted) + { + LogPrint(eLogDebug, "TCPIPPipe: Upstream ", (int)bytes_transfered, " bytes received"); + if (ecode) + { + LogPrint(eLogWarning, "TCPIPPipe: Upstream read error:" , ecode.message()); Terminate(); - } else { - if (bytes_transfered > 0 ) - memcpy(m_downstream_buf, m_upstream_to_down_buf, bytes_transfered); - DownstreamWrite(bytes_transfered); - } + } + else + { + if (bytes_transfered > 0 ) + memcpy(m_downstream_buf, m_upstream_to_down_buf, bytes_transfered); + DownstreamWrite(bytes_transfered); + } + } } void TCPIPAcceptor::Start () From 075f80aea23eab9b81c925c352291b73c4b34946 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 11 Feb 2024 15:33:37 -0500 Subject: [PATCH 0315/1171] use SOCK5 proxy for upstream --- libi2pd_client/SOCKS.cpp | 121 ++++++--------------------------------- 1 file changed, 18 insertions(+), 103 deletions(-) diff --git a/libi2pd_client/SOCKS.cpp b/libi2pd_client/SOCKS.cpp index 547a2da2..49a04b81 100644 --- a/libi2pd_client/SOCKS.cpp +++ b/libi2pd_client/SOCKS.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -19,6 +19,7 @@ #include "I2PTunnel.h" #include "I2PService.h" #include "util.h" +#include "Socks5.h" namespace i2p { @@ -27,10 +28,6 @@ namespace proxy static const size_t socks_buffer_size = 8192; static const size_t max_socks_hostname_size = 255; // Limit for socks5 and bad idea to traverse - //static const size_t SOCKS_FORWARDER_BUFFER_SIZE = 8192; - - static const size_t SOCKS_UPSTREAM_SOCKS4A_REPLY_SIZE = 8; - struct SOCKSDnsAddress { uint8_t size; @@ -132,7 +129,6 @@ namespace proxy boost::asio::const_buffers_1 GenerateSOCKS5SelectAuth(authMethods method); boost::asio::const_buffers_1 GenerateSOCKS4Response(errTypes error, uint32_t ip, uint16_t port); boost::asio::const_buffers_1 GenerateSOCKS5Response(errTypes error, addrTypes type, const address &addr, uint16_t port); - boost::asio::const_buffers_1 GenerateUpstreamRequest(); bool Socks5ChooseAuth(); void Socks5UserPasswdResponse (); void SocksRequestFailed(errTypes error); @@ -146,9 +142,6 @@ namespace proxy void SocksUpstreamSuccess(); void AsyncUpstreamSockRead(); void SendUpstreamRequest(); - void HandleUpstreamData(uint8_t * buff, std::size_t len); - void HandleUpstreamSockSend(const boost::system::error_code & ecode, std::size_t bytes_transfered); - void HandleUpstreamSockRecv(const boost::system::error_code & ecode, std::size_t bytes_transfered); void HandleUpstreamConnected(const boost::system::error_code & ecode, boost::asio::ip::tcp::resolver::iterator itr); void HandleUpstreamResolved(const boost::system::error_code & ecode, @@ -161,9 +154,6 @@ namespace proxy uint8_t *m_remaining_data; //Data left to be sent uint8_t *m_remaining_upstream_data; //upstream data left to be forwarded uint8_t m_response[7+max_socks_hostname_size]; - uint8_t m_upstream_response[SOCKS_UPSTREAM_SOCKS4A_REPLY_SIZE]; - uint8_t m_upstream_request[14+max_socks_hostname_size]; - std::size_t m_upstream_response_len; address m_address; //Address std::size_t m_remaining_data_len; //Size of the data left to be sent uint32_t m_4aip; //Used in 4a requests @@ -280,37 +270,6 @@ namespace proxy return boost::asio::const_buffers_1(m_response, size); } - boost::asio::const_buffers_1 SOCKSHandler::GenerateUpstreamRequest() - { - size_t upstreamRequestSize = 0; - // TODO: negotiate with upstream - // SOCKS 4a - m_upstream_request[0] = '\x04'; //version - m_upstream_request[1] = m_cmd; - htobe16buf(m_upstream_request + 2, m_port); - m_upstream_request[4] = 0; - m_upstream_request[5] = 0; - m_upstream_request[6] = 0; - m_upstream_request[7] = 1; - // user id - m_upstream_request[8] = 'i'; - m_upstream_request[9] = '2'; - m_upstream_request[10] = 'p'; - m_upstream_request[11] = 'd'; - m_upstream_request[12] = 0; - upstreamRequestSize += 13; - if (m_address.dns.size <= max_socks_hostname_size - ( upstreamRequestSize + 1) ) { - // bounds check okay - memcpy(m_upstream_request + upstreamRequestSize, m_address.dns.value, m_address.dns.size); - upstreamRequestSize += m_address.dns.size; - // null terminate - m_upstream_request[++upstreamRequestSize] = 0; - } else { - LogPrint(eLogError, "SOCKS: BUG!!! m_addr.dns.sizs > max_socks_hostname - ( upstreamRequestSize + 1 ) )"); - } - return boost::asio::const_buffers_1(m_upstream_request, upstreamRequestSize); - } - bool SOCKSHandler::Socks5ChooseAuth() { m_response[0] = '\x05'; // Version @@ -724,32 +683,6 @@ namespace proxy std::placeholders::_1, std::placeholders::_2)); } - void SOCKSHandler::AsyncUpstreamSockRead() - { - LogPrint(eLogDebug, "SOCKS: Async upstream sock read"); - if (m_upstreamSock) { - m_upstreamSock->async_read_some(boost::asio::buffer(m_upstream_response, SOCKS_UPSTREAM_SOCKS4A_REPLY_SIZE), - std::bind(&SOCKSHandler::HandleUpstreamSockRecv, shared_from_this(), std::placeholders::_1, std::placeholders::_2)); - } else { - LogPrint(eLogError, "SOCKS: No upstream socket for read"); - SocksRequestFailed(SOCKS5_GEN_FAIL); - } - } - - void SOCKSHandler::HandleUpstreamSockRecv(const boost::system::error_code & ecode, std::size_t bytes_transfered) - { - if (ecode) { - if (m_state == UPSTREAM_HANDSHAKE ) { - // we are trying to handshake but it failed - SocksRequestFailed(SOCKS5_NET_UNREACH); - } else { - LogPrint(eLogError, "SOCKS: Bad state when reading from upstream: ", (int) m_state); - } - return; - } - HandleUpstreamData(m_upstream_response, bytes_transfered); - } - void SOCKSHandler::SocksUpstreamSuccess() { LogPrint(eLogInfo, "SOCKS: Upstream success"); @@ -776,46 +709,28 @@ namespace proxy } - void SOCKSHandler::HandleUpstreamData(uint8_t * dataptr, std::size_t len) - { - if (m_state == UPSTREAM_HANDSHAKE) { - m_upstream_response_len += len; - // handle handshake data - if (m_upstream_response_len < SOCKS_UPSTREAM_SOCKS4A_REPLY_SIZE) { - // too small, continue reading - AsyncUpstreamSockRead(); - } else if (len == SOCKS_UPSTREAM_SOCKS4A_REPLY_SIZE) { - // just right - uint8_t resp = m_upstream_response[1]; - if (resp == SOCKS4_OK) { - // we have connected ! - SocksUpstreamSuccess(); - } else { - // upstream failure - LogPrint(eLogError, "SOCKS: Upstream proxy failure: ", (int) resp); - // TODO: runtime error? - SocksRequestFailed(SOCKS5_GEN_FAIL); - } - } else { - // too big - SocksRequestFailed(SOCKS5_GEN_FAIL); - } - } else { - // invalid state - LogPrint(eLogError, "SOCKS: Invalid state reading from upstream: ", (int) m_state); - } - } void SOCKSHandler::SendUpstreamRequest() { LogPrint(eLogInfo, "SOCKS: Negotiating with upstream proxy"); EnterState(UPSTREAM_HANDSHAKE); - if (m_upstreamSock) { - boost::asio::write(*m_upstreamSock, GenerateUpstreamRequest()); - AsyncUpstreamSockRead(); - } else { + if (m_upstreamSock) + { + auto s = shared_from_this (); + i2p::transport::Socks5Handshake (*m_upstreamSock, std::make_pair(m_address.dns.ToString (), m_port), + [s](const boost::system::error_code& ec) + { + if (!ec) + s->SocksUpstreamSuccess(); + else + { + s->SocksRequestFailed(SOCKS5_NET_UNREACH); + LogPrint(eLogError, "SOCKS: Upstream proxy failure: ", ec.message ()); + } + }); + } + else LogPrint(eLogError, "SOCKS: No upstream socket to send handshake to"); - } } void SOCKSHandler::HandleUpstreamConnected(const boost::system::error_code & ecode, boost::asio::ip::tcp::resolver::iterator itr) From d9b6262a6e903507697f323926ba9c5f321a234a Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 12 Feb 2024 12:10:29 -0500 Subject: [PATCH 0316/1171] removed unused field --- libi2pd_client/HTTPProxy.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index 5f9ee1de..8f9f8ada 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -111,7 +111,6 @@ namespace proxy { bool m_Addresshelper; i2p::http::URL m_ProxyURL; i2p::http::URL m_RequestURL; - uint8_t m_socks_buf[255+8]; // for socks request/response int m_req_len; i2p::http::URL m_ClientRequestURL; i2p::http::HTTPReq m_ClientRequest; From 7691a5b4a92acd72cb2b676bf921928f978cdf3b Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 12 Feb 2024 13:22:26 -0500 Subject: [PATCH 0317/1171] use common SOCK5 code for reseed --- libi2pd/Reseed.cpp | 66 +++++++++------------------------------------- 1 file changed, 13 insertions(+), 53 deletions(-) diff --git a/libi2pd/Reseed.cpp b/libi2pd/Reseed.cpp index 5fdc2fae..f8307a56 100644 --- a/libi2pd/Reseed.cpp +++ b/libi2pd/Reseed.cpp @@ -26,6 +26,7 @@ #include "HTTP.h" #include "util.h" #include "Config.h" +#include "Socks5.h" namespace i2p { @@ -615,62 +616,21 @@ namespace data { // assume socks if not http, is checked before this for other types // TODO: support username/password auth etc - uint8_t hs_writebuf[3] = {0x05, 0x01, 0x00}; - uint8_t hs_readbuf[2]; - boost::asio::write(sock, boost::asio::buffer(hs_writebuf, 3), boost::asio::transfer_all(), ecode); - if(ecode) + bool success = false; + i2p::transport::Socks5Handshake (sock, std::make_pair(url.host, url.port), + [&success](const boost::system::error_code& ec) + { + if (!ec) + success = true; + else + LogPrint (eLogError, "Reseed: SOCKS handshake failed: ", ec.message()); + }); + service.run (); // execute all async operations + if (!success) { sock.close(); - LogPrint(eLogError, "Reseed: SOCKS handshake write failed: ", ecode.message()); return ""; - } - boost::asio::read(sock, boost::asio::buffer(hs_readbuf, 2), ecode); - if(ecode) - { - sock.close(); - LogPrint(eLogError, "Reseed: SOCKS handshake read failed: ", ecode.message()); - return ""; - } - size_t sz = 0; - uint8_t buf[256]; - - buf[0] = 0x05; - buf[1] = 0x01; - buf[2] = 0x00; - buf[3] = 0x03; - sz += 4; - size_t hostsz = url.host.size(); - if(1 + 2 + hostsz + sz > sizeof(buf)) - { - sock.close(); - LogPrint(eLogError, "Reseed: SOCKS handshake failed, hostname too big: ", url.host); - return ""; - } - buf[4] = (uint8_t) hostsz; - memcpy(buf+5, url.host.c_str(), hostsz); - sz += hostsz + 1; - htobe16buf(buf+sz, url.port); - sz += 2; - boost::asio::write(sock, boost::asio::buffer(buf, sz), boost::asio::transfer_all(), ecode); - if(ecode) - { - sock.close(); - LogPrint(eLogError, "Reseed: SOCKS handshake failed writing: ", ecode.message()); - return ""; - } - boost::asio::read(sock, boost::asio::buffer(buf, 10), ecode); - if(ecode) - { - sock.close(); - LogPrint(eLogError, "Reseed: SOCKS handshake failed reading: ", ecode.message()); - return ""; - } - if(buf[1] != 0x00) - { - sock.close(); - LogPrint(eLogError, "Reseed: SOCKS handshake bad reply code: ", std::to_string(buf[1])); - return ""; - } + } } } } From 967627e58a3730d143aa0b15693a54bb93f0d0e8 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 12 Feb 2024 21:55:30 -0500 Subject: [PATCH 0318/1171] read correct reply length and handle reply codes --- libi2pd/Socks5.h | 106 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 81 insertions(+), 25 deletions(-) diff --git a/libi2pd/Socks5.h b/libi2pd/Socks5.h index 84a23997..d611bff3 100644 --- a/libi2pd/Socks5.h +++ b/libi2pd/Socks5.h @@ -29,7 +29,87 @@ namespace transport const size_t SOCKS5_UDP_IPV4_REQUEST_HEADER_SIZE = 10; const size_t SOCKS5_UDP_IPV6_REQUEST_HEADER_SIZE = 22; + const uint8_t SOCKS5_REPLY_SUCCESS = 0x00; + const uint8_t SOCKS5_REPLY_SERVER_FAILURE = 0x01; + const uint8_t SOCKS5_REPLY_CONNECTION_NOT_ALLOWED = 0x02; + const uint8_t SOCKS5_REPLY_NETWORK_UNREACHABLE = 0x03; + const uint8_t SOCKS5_REPLY_HOST_UNREACHABLE = 0x04; + const uint8_t SOCKS5_REPLY_CONNECTION_REFUSED = 0x05; + const uint8_t SOCKS5_REPLY_TTL_EXPIRED = 0x06; + const uint8_t SOCKS5_REPLY_COMMAND_NOT_SUPPORTED = 0x07; + const uint8_t SOCKS5_REPLY_ADDRESS_TYPE_NOT_SUPPORTED = 0x08; + // SOCKS5 handshake + template + void Socks5ReadReply (Socket& s, Handler handler) + { + auto readbuff = std::make_shared >(258); // max possible + boost::asio::async_read(s, boost::asio::buffer(readbuff->data (), 5), boost::asio::transfer_all(), // read 4 bytes of header + first byte of address + [readbuff, &s, handler](const boost::system::error_code& ec, std::size_t transferred) + { + if (!ec) + { + if ((*readbuff)[1] == SOCKS5_REPLY_SUCCESS) + { + size_t len = 0; + switch ((*readbuff)[3]) // ATYP + { + case SOCKS5_ATYP_IPV4: len = 3; break; // address length 4 bytes + case SOCKS5_ATYP_IPV6: len = 15; break; // address length 16 bytes + case SOCKS5_ATYP_NAME: len += (*readbuff)[4]; break; // first byte of address is length + default: ; + } + if (len) + { + len += 2; // port + boost::asio::async_read(s, boost::asio::buffer(readbuff->data (), len), boost::asio::transfer_all(), + [readbuff, &s, handler](const boost::system::error_code& ec, std::size_t transferred) + { + if (!ec) + handler (boost::system::error_code ()); // success + else + handler (boost::asio::error::make_error_code (boost::asio::error::connection_aborted)); + }); + } + else + handler (boost::asio::error::make_error_code (boost::asio::error::fault)); // unknown address type + } + else + switch ((*readbuff)[1]) // REP + { + case SOCKS5_REPLY_SERVER_FAILURE: + handler (boost::asio::error::make_error_code (boost::asio::error::access_denied )); + break; + case SOCKS5_REPLY_CONNECTION_NOT_ALLOWED: + handler (boost::asio::error::make_error_code (boost::asio::error::no_permission)); + break; + case SOCKS5_REPLY_HOST_UNREACHABLE: + handler (boost::asio::error::make_error_code (boost::asio::error::host_unreachable)); + break; + case SOCKS5_REPLY_NETWORK_UNREACHABLE: + handler (boost::asio::error::make_error_code (boost::asio::error::network_unreachable)); + break; + case SOCKS5_REPLY_CONNECTION_REFUSED: + handler (boost::asio::error::make_error_code (boost::asio::error::connection_refused)); + break; + case SOCKS5_REPLY_TTL_EXPIRED: + handler (boost::asio::error::make_error_code (boost::asio::error::timed_out)); + break; + case SOCKS5_REPLY_COMMAND_NOT_SUPPORTED: + handler (boost::asio::error::make_error_code (boost::asio::error::operation_not_supported)); + break; + case SOCKS5_REPLY_ADDRESS_TYPE_NOT_SUPPORTED: + handler (boost::asio::error::make_error_code (boost::asio::error::no_protocol_option)); + break; + default: + handler (boost::asio::error::make_error_code (boost::asio::error::connection_aborted)); + } + } + else + handler (ec); + }); + } + template void Socks5Connect (Socket& s, Handler handler, std::shared_ptr > buff, uint16_t port) { @@ -44,31 +124,7 @@ namespace transport { (void) transferred; if (!ec) - { - auto readbuff = std::make_shared >(262); // max possible - boost::asio::async_read(s, boost::asio::buffer(readbuff->data (), 7), boost::asio::transfer_all(), // read min reply size - [readbuff, &s, handler](const boost::system::error_code& ec, std::size_t transferred) - { - if (!ec) - { - if (!(*readbuff)[1]) // succeeded - { - boost::system::error_code ec; - size_t moreBytes = s.available(ec); - if (!ec && moreBytes) // read remaining portion of reply - boost::asio::read (s, boost::asio::buffer(readbuff->data (), moreBytes), boost::asio::transfer_all (), ec); - if (!ec) - handler (boost::system::error_code ()); - else - handler (boost::asio::error::make_error_code (boost::asio::error::connection_aborted)); - } - else - handler (boost::asio::error::make_error_code (boost::asio::error::connection_refused)); - } - else - handler (ec); - }); - } + Socks5ReadReply (s, handler); else handler (ec); }); From a9ad6fc31e3b733d285dcdad61dfa42bc262c13c Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 13 Feb 2024 18:52:18 -0500 Subject: [PATCH 0319/1171] renamed TCPIPPipe to SocketsPipe --- libi2pd_client/HTTPProxy.cpp | 2 +- libi2pd_client/I2PService.cpp | 52 +++++++++++++++++------------------ libi2pd_client/I2PService.h | 28 ++++++++++++------- libi2pd_client/SOCKS.cpp | 3 +- 4 files changed, 46 insertions(+), 39 deletions(-) diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index 8f9f8ada..01678f4a 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -638,7 +638,7 @@ namespace proxy { void HTTPReqHandler::HandoverToUpstreamProxy() { LogPrint(eLogDebug, "HTTPProxy: Handover to SOCKS proxy"); - auto connection = std::make_shared(GetOwner(), m_proxysock, m_sock); + auto connection = CreateSocketsPipe (GetOwner(), m_proxysock, m_sock); m_sock = nullptr; m_proxysock = nullptr; GetOwner()->AddHandler(connection); diff --git a/libi2pd_client/I2PService.cpp b/libi2pd_client/I2PService.cpp index 9b0b8028..27e34b69 100644 --- a/libi2pd_client/I2PService.cpp +++ b/libi2pd_client/I2PService.cpp @@ -148,25 +148,25 @@ namespace client } } - TCPIPPipe::TCPIPPipe(I2PService * owner, std::shared_ptr upstream, std::shared_ptr downstream) : I2PServiceHandler(owner), m_up(upstream), m_down(downstream) + SocketsPipe::SocketsPipe(I2PService * owner, std::shared_ptr upstream, std::shared_ptr downstream) : I2PServiceHandler(owner), m_up(upstream), m_down(downstream) { - boost::asio::socket_base::receive_buffer_size option(TCP_IP_PIPE_BUFFER_SIZE); + boost::asio::socket_base::receive_buffer_size option(SOCKETS_PIPE_BUFFER_SIZE); upstream->set_option(option); downstream->set_option(option); } - TCPIPPipe::~TCPIPPipe() + SocketsPipe::~SocketsPipe() { Terminate(); } - void TCPIPPipe::Start() + void SocketsPipe::Start() { AsyncReceiveUpstream(); AsyncReceiveDownstream(); } - void TCPIPPipe::Terminate() + void SocketsPipe::Terminate() { if(Kill()) return; if (m_up) @@ -184,52 +184,52 @@ namespace client Done(shared_from_this()); } - void TCPIPPipe::AsyncReceiveUpstream() + void SocketsPipe::AsyncReceiveUpstream() { if (m_up) { - m_up->async_read_some(boost::asio::buffer(m_upstream_to_down_buf, TCP_IP_PIPE_BUFFER_SIZE), - std::bind(&TCPIPPipe::HandleUpstreamReceived, shared_from_this(), + m_up->async_read_some(boost::asio::buffer(m_upstream_to_down_buf, SOCKETS_PIPE_BUFFER_SIZE), + std::bind(&SocketsPipe::HandleUpstreamReceived, shared_from_this(), std::placeholders::_1, std::placeholders::_2)); } else - LogPrint(eLogError, "TCPIPPipe: Upstream receive: No socket"); + LogPrint(eLogError, "SocketsPipe: Upstream receive: No socket"); } - void TCPIPPipe::AsyncReceiveDownstream() + void SocketsPipe::AsyncReceiveDownstream() { if (m_down) { - m_down->async_read_some(boost::asio::buffer(m_downstream_to_up_buf, TCP_IP_PIPE_BUFFER_SIZE), - std::bind(&TCPIPPipe::HandleDownstreamReceived, shared_from_this(), + m_down->async_read_some(boost::asio::buffer(m_downstream_to_up_buf, SOCKETS_PIPE_BUFFER_SIZE), + std::bind(&SocketsPipe::HandleDownstreamReceived, shared_from_this(), std::placeholders::_1, std::placeholders::_2)); } else - LogPrint(eLogError, "TCPIPPipe: Downstream receive: No socket"); + LogPrint(eLogError, "SocketsPipe: Downstream receive: No socket"); } - void TCPIPPipe::UpstreamWrite(size_t len) + void SocketsPipe::UpstreamWrite(size_t len) { if (m_up) { - LogPrint(eLogDebug, "TCPIPPipe: Upstream: ", (int) len, " bytes written"); + LogPrint(eLogDebug, "SocketsPipe: Upstream: ", (int) len, " bytes written"); boost::asio::async_write(*m_up, boost::asio::buffer(m_upstream_buf, len), boost::asio::transfer_all(), - std::bind(&TCPIPPipe::HandleUpstreamWrite, + std::bind(&SocketsPipe::HandleUpstreamWrite, shared_from_this(), std::placeholders::_1)); } else - LogPrint(eLogError, "TCPIPPipe: Upstream write: no socket"); + LogPrint(eLogError, "SocketsPipe: Upstream write: no socket"); } - void TCPIPPipe::DownstreamWrite(size_t len) + void SocketsPipe::DownstreamWrite(size_t len) { if (m_down) { LogPrint(eLogDebug, "TCPIPPipe: Downstream: ", (int) len, " bytes written"); boost::asio::async_write(*m_down, boost::asio::buffer(m_downstream_buf, len), boost::asio::transfer_all(), - std::bind(&TCPIPPipe::HandleDownstreamWrite, + std::bind(&SocketsPipe::HandleDownstreamWrite, shared_from_this(), std::placeholders::_1)); } @@ -238,7 +238,7 @@ namespace client } - void TCPIPPipe::HandleDownstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered) + void SocketsPipe::HandleDownstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered) { if (ecode != boost::asio::error::operation_aborted) { @@ -257,7 +257,7 @@ namespace client } } - void TCPIPPipe::HandleDownstreamWrite(const boost::system::error_code & ecode) + void SocketsPipe::HandleDownstreamWrite(const boost::system::error_code & ecode) { if (ecode != boost::asio::error::operation_aborted) { @@ -271,13 +271,13 @@ namespace client } } - void TCPIPPipe::HandleUpstreamWrite(const boost::system::error_code & ecode) + void SocketsPipe::HandleUpstreamWrite(const boost::system::error_code & ecode) { if (ecode != boost::asio::error::operation_aborted) { if (ecode) { - LogPrint(eLogWarning, "TCPIPPipe: Upstream write error:" , ecode.message()); + LogPrint(eLogWarning, "SocketsPipe: Upstream write error:" , ecode.message()); Terminate(); } else @@ -285,14 +285,14 @@ namespace client } } - void TCPIPPipe::HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered) + void SocketsPipe::HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered) { if (ecode != boost::asio::error::operation_aborted) { - LogPrint(eLogDebug, "TCPIPPipe: Upstream ", (int)bytes_transfered, " bytes received"); + LogPrint(eLogDebug, "SocketsPipe: Upstream ", (int)bytes_transfered, " bytes received"); if (ecode) { - LogPrint(eLogWarning, "TCPIPPipe: Upstream read error:" , ecode.message()); + LogPrint(eLogWarning, "SocketsPipe: Upstream read error:" , ecode.message()); Terminate(); } else diff --git a/libi2pd_client/I2PService.h b/libi2pd_client/I2PService.h index 4f67e19c..4be7f2ca 100644 --- a/libi2pd_client/I2PService.h +++ b/libi2pd_client/I2PService.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -99,6 +99,7 @@ namespace client virtual ~I2PServiceHandler() { } //If you override this make sure you call it from the children virtual void Handle() {}; //Start handling the socket + virtual void Start () {}; void Terminate () { Kill (); }; @@ -119,16 +120,16 @@ namespace client std::atomic m_Dead; //To avoid cleaning up multiple times }; - const size_t TCP_IP_PIPE_BUFFER_SIZE = 8192 * 8; + const size_t SOCKETS_PIPE_BUFFER_SIZE = 8192 * 8; - // bidirectional pipe for 2 tcp/ip sockets - class TCPIPPipe: public I2PServiceHandler, public std::enable_shared_from_this + // bidirectional pipe for 2 stream sockets + class SocketsPipe: public I2PServiceHandler, public std::enable_shared_from_this { public: - TCPIPPipe(I2PService * owner, std::shared_ptr upstream, std::shared_ptr downstream); - ~TCPIPPipe(); - void Start(); + SocketsPipe(I2PService * owner, std::shared_ptr upstream, std::shared_ptr downstream); + ~SocketsPipe(); + void Start() override; protected: @@ -144,11 +145,18 @@ namespace client private: - uint8_t m_upstream_to_down_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_to_up_buf[TCP_IP_PIPE_BUFFER_SIZE]; - uint8_t m_upstream_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_buf[TCP_IP_PIPE_BUFFER_SIZE]; - std::shared_ptr m_up, m_down; + uint8_t m_upstream_to_down_buf[SOCKETS_PIPE_BUFFER_SIZE], m_downstream_to_up_buf[SOCKETS_PIPE_BUFFER_SIZE]; + uint8_t m_upstream_buf[SOCKETS_PIPE_BUFFER_SIZE], m_downstream_buf[SOCKETS_PIPE_BUFFER_SIZE]; + std::shared_ptr m_up; + std::shared_ptr m_down; }; + template + std::shared_ptr CreateSocketsPipe (I2PService * owner, std::shared_ptr upstream, std::shared_ptr downstream) + { + return std::make_shared(owner, upstream, downstream); + } + /* TODO: support IPv6 too */ //This is a service that listens for connections on the IP network and interacts with I2P class TCPIPAcceptor: public I2PService diff --git a/libi2pd_client/SOCKS.cpp b/libi2pd_client/SOCKS.cpp index 49a04b81..65bad1cf 100644 --- a/libi2pd_client/SOCKS.cpp +++ b/libi2pd_client/SOCKS.cpp @@ -700,13 +700,12 @@ namespace proxy break; } m_sock->send(response); - auto forwarder = std::make_shared(GetOwner(), m_sock, m_upstreamSock); + auto forwarder = CreateSocketsPipe (GetOwner(), m_sock, m_upstreamSock); m_upstreamSock = nullptr; m_sock = nullptr; GetOwner()->AddHandler(forwarder); forwarder->Start(); Terminate(); - } From 710b27688ba03dc580839fb7b4270ecfd4943014 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 14 Feb 2024 15:35:47 -0500 Subject: [PATCH 0320/1171] generic SocketsPipe for different socket types --- libi2pd_client/I2PService.cpp | 156 ---------------------------------- libi2pd_client/I2PService.h | 99 ++++++++++++++++----- 2 files changed, 76 insertions(+), 179 deletions(-) diff --git a/libi2pd_client/I2PService.cpp b/libi2pd_client/I2PService.cpp index 27e34b69..5604f950 100644 --- a/libi2pd_client/I2PService.cpp +++ b/libi2pd_client/I2PService.cpp @@ -148,162 +148,6 @@ namespace client } } - SocketsPipe::SocketsPipe(I2PService * owner, std::shared_ptr upstream, std::shared_ptr downstream) : I2PServiceHandler(owner), m_up(upstream), m_down(downstream) - { - boost::asio::socket_base::receive_buffer_size option(SOCKETS_PIPE_BUFFER_SIZE); - upstream->set_option(option); - downstream->set_option(option); - } - - SocketsPipe::~SocketsPipe() - { - Terminate(); - } - - void SocketsPipe::Start() - { - AsyncReceiveUpstream(); - AsyncReceiveDownstream(); - } - - void SocketsPipe::Terminate() - { - if(Kill()) return; - if (m_up) - { - if (m_up->is_open()) - m_up->close(); - m_up = nullptr; - } - if (m_down) - { - if (m_down->is_open()) - m_down->close(); - m_down = nullptr; - } - Done(shared_from_this()); - } - - void SocketsPipe::AsyncReceiveUpstream() - { - if (m_up) - { - m_up->async_read_some(boost::asio::buffer(m_upstream_to_down_buf, SOCKETS_PIPE_BUFFER_SIZE), - std::bind(&SocketsPipe::HandleUpstreamReceived, shared_from_this(), - std::placeholders::_1, std::placeholders::_2)); - } - else - LogPrint(eLogError, "SocketsPipe: Upstream receive: No socket"); - } - - void SocketsPipe::AsyncReceiveDownstream() - { - if (m_down) { - m_down->async_read_some(boost::asio::buffer(m_downstream_to_up_buf, SOCKETS_PIPE_BUFFER_SIZE), - std::bind(&SocketsPipe::HandleDownstreamReceived, shared_from_this(), - std::placeholders::_1, std::placeholders::_2)); - } - else - LogPrint(eLogError, "SocketsPipe: Downstream receive: No socket"); - } - - void SocketsPipe::UpstreamWrite(size_t len) - { - if (m_up) - { - LogPrint(eLogDebug, "SocketsPipe: Upstream: ", (int) len, " bytes written"); - boost::asio::async_write(*m_up, boost::asio::buffer(m_upstream_buf, len), - boost::asio::transfer_all(), - std::bind(&SocketsPipe::HandleUpstreamWrite, - shared_from_this(), - std::placeholders::_1)); - } - else - LogPrint(eLogError, "SocketsPipe: Upstream write: no socket"); - } - - void SocketsPipe::DownstreamWrite(size_t len) - { - if (m_down) - { - LogPrint(eLogDebug, "TCPIPPipe: Downstream: ", (int) len, " bytes written"); - boost::asio::async_write(*m_down, boost::asio::buffer(m_downstream_buf, len), - boost::asio::transfer_all(), - std::bind(&SocketsPipe::HandleDownstreamWrite, - shared_from_this(), - std::placeholders::_1)); - } - else - LogPrint(eLogError, "TCPIPPipe: Downstream write: No socket"); - } - - - void SocketsPipe::HandleDownstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered) - { - if (ecode != boost::asio::error::operation_aborted) - { - LogPrint(eLogDebug, "TCPIPPipe: Downstream: ", (int) bytes_transfered, " bytes received"); - if (ecode) - { - LogPrint(eLogWarning, "TCPIPPipe: Downstream read error:" , ecode.message()); - Terminate(); - } - else - { - if (bytes_transfered > 0 ) - memcpy(m_upstream_buf, m_downstream_to_up_buf, bytes_transfered); - UpstreamWrite(bytes_transfered); - } - } - } - - void SocketsPipe::HandleDownstreamWrite(const boost::system::error_code & ecode) - { - if (ecode != boost::asio::error::operation_aborted) - { - if (ecode) - { - LogPrint(eLogWarning, "TCPIPPipe: Downstream write error:" , ecode.message()); - Terminate(); - } - else - AsyncReceiveUpstream(); - } - } - - void SocketsPipe::HandleUpstreamWrite(const boost::system::error_code & ecode) - { - if (ecode != boost::asio::error::operation_aborted) - { - if (ecode) - { - LogPrint(eLogWarning, "SocketsPipe: Upstream write error:" , ecode.message()); - Terminate(); - } - else - AsyncReceiveDownstream(); - } - } - - void SocketsPipe::HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered) - { - if (ecode != boost::asio::error::operation_aborted) - { - LogPrint(eLogDebug, "SocketsPipe: Upstream ", (int)bytes_transfered, " bytes received"); - if (ecode) - { - LogPrint(eLogWarning, "SocketsPipe: Upstream read error:" , ecode.message()); - Terminate(); - } - else - { - if (bytes_transfered > 0 ) - memcpy(m_downstream_buf, m_upstream_to_down_buf, bytes_transfered); - DownstreamWrite(bytes_transfered); - } - } - } - void TCPIPAcceptor::Start () { m_Acceptor.reset (new boost::asio::ip::tcp::acceptor (GetService (), m_LocalEndpoint)); diff --git a/libi2pd_client/I2PService.h b/libi2pd_client/I2PService.h index 4be7f2ca..b8973f9d 100644 --- a/libi2pd_client/I2PService.h +++ b/libi2pd_client/I2PService.h @@ -123,38 +123,91 @@ namespace client const size_t SOCKETS_PIPE_BUFFER_SIZE = 8192 * 8; // bidirectional pipe for 2 stream sockets - class SocketsPipe: public I2PServiceHandler, public std::enable_shared_from_this + template + class SocketsPipe: public I2PServiceHandler, + public std::enable_shared_from_this > { public: - SocketsPipe(I2PService * owner, std::shared_ptr upstream, std::shared_ptr downstream); - ~SocketsPipe(); - void Start() override; - - protected: - - void Terminate(); - void AsyncReceiveUpstream(); - void AsyncReceiveDownstream(); - void HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transferred); - void HandleDownstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transferred); - void HandleUpstreamWrite(const boost::system::error_code & ecode); - void HandleDownstreamWrite(const boost::system::error_code & ecode); - void UpstreamWrite(size_t len); - void DownstreamWrite(size_t len); + SocketsPipe(I2PService * owner, std::shared_ptr upstream, std::shared_ptr downstream): + I2PServiceHandler(owner), m_up(upstream), m_down(downstream) + { + boost::asio::socket_base::receive_buffer_size option(SOCKETS_PIPE_BUFFER_SIZE); + upstream->set_option(option); + downstream->set_option(option); + } + ~SocketsPipe() { Terminate(); } + + void Start() override + { + Transfer (m_up, m_down, m_upstream_to_down_buf, SOCKETS_PIPE_BUFFER_SIZE); // receive from upstream + Transfer (m_down, m_up, m_downstream_to_up_buf, SOCKETS_PIPE_BUFFER_SIZE); // receive from upstream + } private: - uint8_t m_upstream_to_down_buf[SOCKETS_PIPE_BUFFER_SIZE], m_downstream_to_up_buf[SOCKETS_PIPE_BUFFER_SIZE]; - uint8_t m_upstream_buf[SOCKETS_PIPE_BUFFER_SIZE], m_downstream_buf[SOCKETS_PIPE_BUFFER_SIZE]; - std::shared_ptr m_up; - std::shared_ptr m_down; + void Terminate() + { + if(Kill()) return; + if (m_up) + { + if (m_up->is_open()) + m_up->close(); + m_up = nullptr; + } + if (m_down) + { + if (m_down->is_open()) + m_down->close(); + m_down = nullptr; + } + Done(SocketsPipe::shared_from_this()); + } + + template + void Transfer (std::shared_ptr from, std::shared_ptr to, uint8_t * buf, size_t len) + { + if (!from || !to || !buf) return; + auto s = SocketsPipe::shared_from_this (); + from->async_read_some(boost::asio::buffer(buf, len), + [from, to, s, buf, len](const boost::system::error_code& ecode, std::size_t transferred) + { + if (ecode == boost::asio::error::operation_aborted) return; + if (!ecode) + { + boost::asio::async_write(*to, boost::asio::buffer(buf, transferred), boost::asio::transfer_all(), + [from, to, s, buf, len](const boost::system::error_code& ecode, std::size_t transferred) + { + (void) transferred; + if (ecode == boost::asio::error::operation_aborted) return; + if (!ecode) + s->Transfer (from, to, buf, len); + else + { + LogPrint(eLogWarning, "SocketsPipe: Write error:" , ecode.message()); + s->Terminate(); + } + }); + } + else + { + LogPrint(eLogWarning, "SocketsPipe: Read error:" , ecode.message()); + s->Terminate(); + } + }); + } + + private: + + uint8_t m_upstream_to_down_buf[SOCKETS_PIPE_BUFFER_SIZE], m_downstream_to_up_buf[SOCKETS_PIPE_BUFFER_SIZE]; + std::shared_ptr m_up; + std::shared_ptr m_down; }; - template - std::shared_ptr CreateSocketsPipe (I2PService * owner, std::shared_ptr upstream, std::shared_ptr downstream) + template + std::shared_ptr CreateSocketsPipe (I2PService * owner, std::shared_ptr upstream, std::shared_ptr downstream) { - return std::make_shared(owner, upstream, downstream); + return std::make_shared >(owner, upstream, downstream); } /* TODO: support IPv6 too */ From 0e502c49b5c8274e8c2e6d8b1b226e1002ef02de Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 14 Feb 2024 18:53:28 -0500 Subject: [PATCH 0321/1171] show correct tunnel status. restore tunnel if delivery status or data for inbound tunnel received --- daemon/HTTPServer.cpp | 18 +++++++----------- libi2pd/Tunnel.cpp | 2 +- libi2pd/TunnelPool.cpp | 4 ++-- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 2d6800b4..862d6e4a 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -133,23 +133,19 @@ namespace http { static void ShowTunnelDetails (std::stringstream& s, enum i2p::tunnel::TunnelState eState, bool explr, int bytes) { std::string state, stateText; - switch (eState) { + switch (eState) + { case i2p::tunnel::eTunnelStateBuildReplyReceived : case i2p::tunnel::eTunnelStatePending : state = "building"; break; - case i2p::tunnel::eTunnelStateBuildFailed : - case i2p::tunnel::eTunnelStateTestFailed : + case i2p::tunnel::eTunnelStateBuildFailed : state = "failed"; stateText = "declined"; break; + case i2p::tunnel::eTunnelStateTestFailed : state = "failed"; stateText = "test failed"; break; case i2p::tunnel::eTunnelStateFailed : state = "failed"; break; case i2p::tunnel::eTunnelStateExpiring : state = "expiring"; break; case i2p::tunnel::eTunnelStateEstablished : state = "established"; break; default: state = "unknown"; break; } - - if (state == "building") stateText = tr("building"); - else if (state == "failed") stateText = tr("failed"); - else if (state == "expiring") stateText = tr("expiring"); - else if (state == "established") stateText = tr("established"); - else stateText = tr("unknown"); - + if (stateText.empty ()) stateText = tr(state); + s << " " << stateText << ((explr) ? " (" + tr("exploratory") + ")" : "") << ", "; ShowTraffic(s, bytes); s << "\r\n"; diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index b578217f..d46da5b9 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -250,7 +250,7 @@ namespace tunnel void InboundTunnel::HandleTunnelDataMsg (std::shared_ptr&& msg) { - if (IsFailed ()) SetState (eTunnelStateEstablished); // incoming messages means a tunnel is alive + if (GetState () != eTunnelStateExpiring) SetState (eTunnelStateEstablished); // incoming messages means a tunnel is alive EncryptTunnelMsg (msg, msg); msg->from = GetSharedFromThis (); m_Endpoint.HandleDecryptedTunnelDataMsg (msg); diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index 93df99be..dc43a025 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -461,7 +461,7 @@ namespace tunnel // restore from test failed state if any if (test.first) { - if (test.first->GetState () == eTunnelStateTestFailed) + if (test.first->GetState () != eTunnelStateExpiring) test.first->SetState (eTunnelStateEstablished); // update latency uint64_t latency = 0; @@ -471,7 +471,7 @@ namespace tunnel } if (test.second) { - if (test.second->GetState () == eTunnelStateTestFailed) + if (test.second->GetState () != eTunnelStateExpiring) test.second->SetState (eTunnelStateEstablished); // update latency uint64_t latency = 0; From 56619caa71bdf306dbd480445d6e2835a5ec603d Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 14 Feb 2024 20:16:36 -0500 Subject: [PATCH 0322/1171] random shuffle of tunnels for peer test pairs --- libi2pd/TunnelPool.cpp | 56 +++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index dc43a025..2e306ba3 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -361,31 +361,43 @@ namespace tunnel // new tests std::vector, std::shared_ptr > > newTests; + std::random_device rd; + std::mt19937 rnd(rd()); + std::vector > outboundTunnels; { - std::unique_lock l1(m_OutboundTunnelsMutex); - auto it1 = m_OutboundTunnels.begin (); - std::unique_lock l2(m_InboundTunnelsMutex); - auto it2 = m_InboundTunnels.begin (); - while (it1 != m_OutboundTunnels.end () && it2 != m_InboundTunnels.end ()) + std::unique_lock l(m_OutboundTunnelsMutex); + for (auto& it: m_OutboundTunnels) + outboundTunnels.push_back (it); + } + std::shuffle (outboundTunnels.begin(), outboundTunnels.end(), rnd); + std::vector > inboundTunnels; + { + std::unique_lock l(m_InboundTunnelsMutex); + for (auto& it: m_InboundTunnels) + inboundTunnels.push_back (it); + } + std::shuffle (inboundTunnels.begin(), inboundTunnels.end(), rnd); + auto it1 = outboundTunnels.begin (); + auto it2 = inboundTunnels.begin (); + while (it1 != outboundTunnels.end () && it2 != inboundTunnels.end ()) + { + bool failed = false; + if ((*it1)->IsFailed ()) { - bool failed = false; - if ((*it1)->IsFailed ()) - { - failed = true; - ++it1; - } - if ((*it2)->IsFailed ()) - { - failed = true; - ++it2; - } - if (!failed) - { - newTests.push_back(std::make_pair (*it1, *it2)); - ++it1; ++it2; - } + failed = true; + ++it1; } - } + if ((*it2)->IsFailed ()) + { + failed = true; + ++it2; + } + if (!failed) + { + newTests.push_back(std::make_pair (*it1, *it2)); + ++it1; ++it2; + } + } for (auto& it: newTests) { uint32_t msgID; From dddbca6ffbd316cb4195181e955a804d17dfd2ff Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 14 Feb 2024 21:35:41 -0500 Subject: [PATCH 0323/1171] common rng for random shuffle --- libi2pd/Tunnel.cpp | 2 +- libi2pd/TunnelPool.cpp | 9 +++------ libi2pd/TunnelPool.h | 6 ++++++ 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index d46da5b9..ac0418d7 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -52,7 +52,7 @@ namespace tunnel // shuffle records std::vector recordIndicies; for (int i = 0; i < numRecords; i++) recordIndicies.push_back(i); - std::shuffle (recordIndicies.begin(), recordIndicies.end(), std::mt19937(std::random_device()())); + std::shuffle (recordIndicies.begin(), recordIndicies.end(), m_Pool ? m_Pool->GetRng () : std::mt19937(std::random_device()())); // create real records uint8_t * records = msg->GetPayload () + 1; diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index 2e306ba3..550a75c5 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -7,7 +7,6 @@ */ #include -#include #include "I2PEndian.h" #include "Crypto.h" #include "Tunnel.h" @@ -45,7 +44,7 @@ namespace tunnel m_NumInboundHops (numInboundHops), m_NumOutboundHops (numOutboundHops), m_NumInboundTunnels (numInboundTunnels), m_NumOutboundTunnels (numOutboundTunnels), m_InboundVariance (inboundVariance), m_OutboundVariance (outboundVariance), - m_IsActive (true), m_CustomPeerSelector(nullptr) + m_IsActive (true), m_CustomPeerSelector(nullptr), m_Rng(m_Rd()) { if (m_NumInboundTunnels > TUNNEL_POOL_MAX_INBOUND_TUNNELS_QUANTITY) m_NumInboundTunnels = TUNNEL_POOL_MAX_INBOUND_TUNNELS_QUANTITY; @@ -361,22 +360,20 @@ namespace tunnel // new tests std::vector, std::shared_ptr > > newTests; - std::random_device rd; - std::mt19937 rnd(rd()); std::vector > outboundTunnels; { std::unique_lock l(m_OutboundTunnelsMutex); for (auto& it: m_OutboundTunnels) outboundTunnels.push_back (it); } - std::shuffle (outboundTunnels.begin(), outboundTunnels.end(), rnd); + std::shuffle (outboundTunnels.begin(), outboundTunnels.end(), m_Rng); std::vector > inboundTunnels; { std::unique_lock l(m_InboundTunnelsMutex); for (auto& it: m_InboundTunnels) inboundTunnels.push_back (it); } - std::shuffle (inboundTunnels.begin(), inboundTunnels.end(), rnd); + std::shuffle (inboundTunnels.begin(), inboundTunnels.end(), m_Rng); auto it1 = outboundTunnels.begin (); auto it2 = inboundTunnels.begin (); while (it1 != outboundTunnels.end () && it2 != inboundTunnels.end ()) diff --git a/libi2pd/TunnelPool.h b/libi2pd/TunnelPool.h index 7cb1f5c9..3d3d4e33 100644 --- a/libi2pd/TunnelPool.h +++ b/libi2pd/TunnelPool.h @@ -15,6 +15,7 @@ #include #include #include +#include #include "Identity.h" #include "LeaseSet.h" #include "RouterInfo.h" @@ -115,6 +116,8 @@ namespace tunnel std::shared_ptr SelectNextHop (std::shared_ptr prevHop, bool reverse, bool endpoint) const; bool StandardSelectPeers(Path & path, int numHops, bool inbound, SelectHopFunc nextHop); + std::mt19937& GetRng () { return m_Rng; } + private: void TestTunnels (); @@ -148,6 +151,9 @@ namespace tunnel uint64_t m_MinLatency = 0; // if > 0 this tunnel pool will try building tunnels with minimum latency by ms uint64_t m_MaxLatency = 0; // if > 0 this tunnel pool will try building tunnels with maximum latency by ms + std::random_device m_Rd; + std::mt19937 m_Rng; + public: // for HTTP only From d8be5b8ce1876f28615e051b683c840481c1b00f Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 14 Feb 2024 21:58:03 -0500 Subject: [PATCH 0324/1171] fixed warning --- libi2pd/Socks5.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Socks5.h b/libi2pd/Socks5.h index d611bff3..8db8939b 100644 --- a/libi2pd/Socks5.h +++ b/libi2pd/Socks5.h @@ -63,7 +63,7 @@ namespace transport { len += 2; // port boost::asio::async_read(s, boost::asio::buffer(readbuff->data (), len), boost::asio::transfer_all(), - [readbuff, &s, handler](const boost::system::error_code& ec, std::size_t transferred) + [readbuff, handler](const boost::system::error_code& ec, std::size_t transferred) { if (!ec) handler (boost::system::error_code ()); // success From def404b61aceaf02ff247392f56984430b90aa6b Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 14 Feb 2024 22:19:07 -0500 Subject: [PATCH 0325/1171] skip failed and expiring tunnels for peer tests --- libi2pd/TunnelPool.cpp | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index 550a75c5..5b472232 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -364,36 +364,24 @@ namespace tunnel { std::unique_lock l(m_OutboundTunnelsMutex); for (auto& it: m_OutboundTunnels) - outboundTunnels.push_back (it); + if (it->IsEstablished () || it->GetState () == eTunnelStateTestFailed) + outboundTunnels.push_back (it); } std::shuffle (outboundTunnels.begin(), outboundTunnels.end(), m_Rng); std::vector > inboundTunnels; { std::unique_lock l(m_InboundTunnelsMutex); for (auto& it: m_InboundTunnels) - inboundTunnels.push_back (it); + if (it->IsEstablished () || it->GetState () == eTunnelStateTestFailed) + inboundTunnels.push_back (it); } std::shuffle (inboundTunnels.begin(), inboundTunnels.end(), m_Rng); auto it1 = outboundTunnels.begin (); auto it2 = inboundTunnels.begin (); while (it1 != outboundTunnels.end () && it2 != inboundTunnels.end ()) { - bool failed = false; - if ((*it1)->IsFailed ()) - { - failed = true; - ++it1; - } - if ((*it2)->IsFailed ()) - { - failed = true; - ++it2; - } - if (!failed) - { - newTests.push_back(std::make_pair (*it1, *it2)); - ++it1; ++it2; - } + newTests.push_back(std::make_pair (*it1, *it2)); + ++it1; ++it2; } for (auto& it: newTests) { From 6439e227f67d88cb9bc6ac95c04b397faa148727 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 15 Feb 2024 19:29:33 -0500 Subject: [PATCH 0326/1171] consider test failed state as established. Delete failed tunnels sooner --- libi2pd/Tunnel.cpp | 9 +++++---- libi2pd/Tunnel.h | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index ac0418d7..3e10ef1b 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -679,9 +679,10 @@ namespace tunnel for (auto it = m_OutboundTunnels.begin (); it != m_OutboundTunnels.end ();) { auto tunnel = *it; - if (ts > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) + if (tunnel->IsFailed () || ts > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT || + ts + TUNNEL_EXPIRATION_TIMEOUT < tunnel->GetCreationTime ()) { - LogPrint (eLogDebug, "Tunnel: Tunnel with id ", tunnel->GetTunnelID (), " expired"); + LogPrint (eLogDebug, "Tunnel: Tunnel with id ", tunnel->GetTunnelID (), " expired or failed"); auto pool = tunnel->GetTunnelPool (); if (pool) pool->TunnelExpired (tunnel); @@ -730,10 +731,10 @@ namespace tunnel for (auto it = m_InboundTunnels.begin (); it != m_InboundTunnels.end ();) { auto tunnel = *it; - if (ts > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT || + if (tunnel->IsFailed () || ts > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT || ts + TUNNEL_EXPIRATION_TIMEOUT < tunnel->GetCreationTime ()) { - LogPrint (eLogDebug, "Tunnel: Tunnel with id ", tunnel->GetTunnelID (), " expired"); + LogPrint (eLogDebug, "Tunnel: Tunnel with id ", tunnel->GetTunnelID (), " expired or failed"); auto pool = tunnel->GetTunnelPool (); if (pool) pool->TunnelExpired (tunnel); diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index 47ff0465..a0815cba 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -91,7 +91,7 @@ namespace tunnel i2p::data::RouterInfo::CompatibleTransports GetFarEndTransports () const { return m_FarEndTransports; }; TunnelState GetState () const { return m_State; }; void SetState (TunnelState state); - bool IsEstablished () const { return m_State == eTunnelStateEstablished; }; + bool IsEstablished () const { return m_State == eTunnelStateEstablished || m_State == eTunnelStateTestFailed; }; bool IsFailed () const { return m_State == eTunnelStateFailed; }; bool IsRecreated () const { return m_IsRecreated; }; void SetRecreated (bool recreated) { m_IsRecreated = recreated; }; From 441e847de8278d3cc9703ec9bbefec836296ff8f Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 16 Feb 2024 14:49:12 -0500 Subject: [PATCH 0327/1171] don't try to decrypt dulpicate message --- libi2pd/Garlic.cpp | 18 +++++++++++++++--- libi2pd/Garlic.h | 4 ++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 3f885186..7157052c 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -588,11 +588,17 @@ namespace garlic auto it = m_ECIESx25519Tags.find (tag); if (it != m_ECIESx25519Tags.end ()) { - if (it->second.tagset && it->second.tagset->HandleNextMessage (buf, len, it->second.index)) + if (!it->second.tagset) return true; // duplicate + if (it->second.tagset->HandleNextMessage (buf, len, it->second.index)) + { m_LastTagset = it->second.tagset; + it->second.tagset = nullptr; // mark as used + } else + { LogPrint (eLogError, "Garlic: Can't handle ECIES-X25519-AEAD-Ratchet message"); - m_ECIESx25519Tags.erase (it); + m_ECIESx25519Tags.erase (it); + } return true; } return false; @@ -879,6 +885,12 @@ namespace garlic numExpiredTags = 0; for (auto it = m_ECIESx25519Tags.begin (); it != m_ECIESx25519Tags.end ();) { + if (!it->second.tagset) + { + // delete used tag + it = m_ECIESx25519Tags.erase (it); + continue; + } if (it->second.tagset->IsExpired (ts) || it->second.tagset->IsIndexExpired (it->second.index)) { it->second.tagset->DeleteSymmKey (it->second.index); diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index b926abda..83e3b050 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -221,7 +221,7 @@ namespace garlic struct ECIESX25519AEADRatchetIndexTagset { int index; - ReceiveRatchetTagSetPtr tagset; + ReceiveRatchetTagSetPtr tagset; // null if used }; class GarlicDestination: public i2p::data::LocalDestination From 900153765abbe87101a586f9648d21ee97d7a1b3 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 16 Feb 2024 18:56:04 -0500 Subject: [PATCH 0328/1171] move router's tags cleanup to router's thread --- libi2pd/NetDb.cpp | 9 +-------- libi2pd/RouterContext.cpp | 39 ++++++++++++++++++++++++++------------- libi2pd/RouterContext.h | 8 +++++--- 3 files changed, 32 insertions(+), 24 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index e8c92658..0adeb2e7 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -106,7 +106,7 @@ namespace data { i2p::util::SetThreadName("NetDB"); - uint64_t lastManage = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0; + uint64_t lastManage = 0, lastExploratory = 0, lastManageRequest = 0; uint64_t lastProfilesCleanup = i2p::util::GetSecondsSinceEpoch (); int16_t profilesCleanupVariance = 0; @@ -165,13 +165,6 @@ namespace data lastManage = ts; } - if (ts - lastDestinationCleanup >= i2p::garlic::INCOMING_TAGS_EXPIRATION_TIMEOUT || - ts + i2p::garlic::INCOMING_TAGS_EXPIRATION_TIMEOUT < lastDestinationCleanup) - { - i2p::context.CleanupDestination (); - lastDestinationCleanup = ts; - } - if (ts - lastProfilesCleanup >= (uint64_t)(i2p::data::PEER_PROFILE_AUTOCLEAN_TIMEOUT + profilesCleanupVariance) || ts + i2p::data::PEER_PROFILE_AUTOCLEAN_TIMEOUT < lastProfilesCleanup) { diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 40949891..02ebf22c 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -61,9 +61,11 @@ namespace i2p { m_PublishTimer.reset (new boost::asio::deadline_timer (m_Service->GetService ())); ScheduleInitialPublish (); - m_CongestionUpdateTimer.reset (new boost::asio::deadline_timer (m_Service->GetService ())); - ScheduleCongestionUpdate (); } + m_CongestionUpdateTimer.reset (new boost::asio::deadline_timer (m_Service->GetService ())); + ScheduleCongestionUpdate (); + m_CleanupTimer.reset (new boost::asio::deadline_timer (m_Service->GetService ())); + ScheduleCleanupTimer (); } } @@ -1223,17 +1225,6 @@ namespace i2p else LogPrint (eLogError, "Router: service is NULL"); } - - void RouterContext::CleanupDestination () - { - if (m_Service) - m_Service->GetService ().post ([this]() - { - this->i2p::garlic::GarlicDestination::CleanupExpiredTags (); - }); - else - LogPrint (eLogError, "Router: service is NULL"); - } uint32_t RouterContext::GetUptime () const { @@ -1465,4 +1456,26 @@ namespace i2p ScheduleCongestionUpdate (); } } + + void RouterContext::ScheduleCleanupTimer () + { + if (m_CleanupTimer) + { + m_CleanupTimer->cancel (); + m_CleanupTimer->expires_from_now (boost::posix_time::minutes(ROUTER_INFO_CLEANUP_INTERVAL)); + m_CleanupTimer->async_wait (std::bind (&RouterContext::HandleCleanupTimer, + this, std::placeholders::_1)); + } + else + LogPrint (eLogError, "Router: Cleanup timer is NULL"); + } + + void RouterContext::HandleCleanupTimer (const boost::system::error_code& ecode) + { + if (ecode != boost::asio::error::operation_aborted) + { + CleanupExpiredTags (); + ScheduleCleanupTimer (); + } + } } diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index ddfc65de..d85ef282 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -38,6 +38,7 @@ namespace garlic const int ROUTER_INFO_CONFIRMATION_TIMEOUT = 5; // in seconds const int ROUTER_INFO_MAX_PUBLISH_EXCLUDED_FLOODFILLS = 15; const int ROUTER_INFO_CONGESTION_UPDATE_INTERVAL = 12*60; // in seconds + const int ROUTER_INFO_CLEANUP_INTERVAL = 5; // in minutes enum RouterStatus { @@ -181,7 +182,6 @@ namespace garlic void UpdateNTCP2V6Address (const boost::asio::ip::address& host); // called from Daemon. TODO: remove void UpdateStats (); void UpdateTimestamp (uint64_t ts); // in seconds, called from NetDb before publishing - void CleanupDestination (); // garlic destination // implements LocalDestination std::shared_ptr GetIdentity () const { return m_Keys.GetPublic (); }; @@ -230,6 +230,8 @@ namespace garlic void HandlePublishResendTimer (const boost::system::error_code& ecode); void ScheduleCongestionUpdate (); void HandleCongestionUpdateTimer (const boost::system::error_code& ecode); + void ScheduleCleanupTimer (); + void HandleCleanupTimer (const boost::system::error_code& ecode); private: @@ -253,7 +255,7 @@ namespace garlic i2p::crypto::NoiseSymmetricState m_InitialNoiseState, m_CurrentNoiseState; // publish std::unique_ptr m_Service; - std::unique_ptr m_PublishTimer, m_CongestionUpdateTimer; + std::unique_ptr m_PublishTimer, m_CongestionUpdateTimer, m_CleanupTimer; std::set m_PublishExcluded; uint32_t m_PublishReplyToken; bool m_IsHiddenMode; // not publish From 2b6a95cbee8c5216beafbac6116ade4c5230cfc2 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 16 Feb 2024 21:30:40 -0500 Subject: [PATCH 0329/1171] don't check session for symmetric key tagset. re-create tags hash if too many used tags --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 6 +++ libi2pd/ECIESX25519AEADRatchetSession.h | 10 ++-- libi2pd/Garlic.cpp | 56 +++++++++++++++-------- libi2pd/Garlic.h | 3 +- 4 files changed, 52 insertions(+), 23 deletions(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 6f56f2e5..3513b7ac 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -117,6 +117,12 @@ namespace garlic return session->HandleNextMessage (buf, len, shared_from_this (), index); } + bool ReceiveRatchetTagSet::IsSessionTerminated () const + { + return !m_Session || m_Session->IsTerminated (); + } + + SymmetricKeyTagSet::SymmetricKeyTagSet (GarlicDestination * destination, const uint8_t * key): ReceiveRatchetTagSet (nullptr), m_Destination (destination) { diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index 517833e8..030e2c45 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -86,7 +86,8 @@ namespace garlic virtual bool IsIndexExpired (int index) const; virtual bool HandleNextMessage (uint8_t * buf, size_t len, int index); - + virtual bool IsSessionTerminated () const; + private: int m_TrimBehindIndex = 0; @@ -101,9 +102,10 @@ namespace garlic SymmetricKeyTagSet (GarlicDestination * destination, const uint8_t * key); - bool IsIndexExpired (int index) const { return false; }; - bool HandleNextMessage (uint8_t * buf, size_t len, int index); - + bool IsIndexExpired (int index) const override { return false; }; + bool HandleNextMessage (uint8_t * buf, size_t len, int index) override; + bool IsSessionTerminated () const override { return false; } + private: GarlicDestination * m_Destination; diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 7157052c..ba35995f 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -431,7 +431,8 @@ namespace garlic } GarlicDestination::GarlicDestination (): m_NumTags (32), // 32 tags by default - m_PayloadBuffer (nullptr), m_NumRatchetInboundTags (0) // 0 means standard + m_PayloadBuffer (nullptr), m_NumRatchetInboundTags (0), // 0 means standard + m_NumUsedECIESx25519Tags (0) { } @@ -599,6 +600,7 @@ namespace garlic LogPrint (eLogError, "Garlic: Can't handle ECIES-X25519-AEAD-Ratchet message"); m_ECIESx25519Tags.erase (it); } + m_NumUsedECIESx25519Tags++; return true; } return false; @@ -883,24 +885,41 @@ namespace garlic } numExpiredTags = 0; - for (auto it = m_ECIESx25519Tags.begin (); it != m_ECIESx25519Tags.end ();) + if (m_NumUsedECIESx25519Tags > ECIESX25519_TAGSET_MAX_NUM_TAGS) // too many used tags { - if (!it->second.tagset) + std::unordered_map oldTags; + std::swap (m_ECIESx25519Tags, oldTags); // re-create + for (auto& it: oldTags) + if (it.second.tagset) + { + if (it.second.tagset->IsExpired (ts) || it.second.tagset->IsIndexExpired (it.second.index)) + { + it.second.tagset->DeleteSymmKey (it.second.index); + numExpiredTags++; + } + else if (it.second.tagset->IsSessionTerminated()) + numExpiredTags++; + else + m_ECIESx25519Tags.emplace (it); + } + } + else + { + for (auto it = m_ECIESx25519Tags.begin (); it != m_ECIESx25519Tags.end ();) { - // delete used tag - it = m_ECIESx25519Tags.erase (it); - continue; - } - if (it->second.tagset->IsExpired (ts) || it->second.tagset->IsIndexExpired (it->second.index)) - { - it->second.tagset->DeleteSymmKey (it->second.index); - it = m_ECIESx25519Tags.erase (it); - numExpiredTags++; - } - else - { - auto session = it->second.tagset->GetSession (); - if (!session || session->IsTerminated()) + if (!it->second.tagset) + { + // delete used tag + it = m_ECIESx25519Tags.erase (it); + continue; + } + if (it->second.tagset->IsExpired (ts) || it->second.tagset->IsIndexExpired (it->second.index)) + { + it->second.tagset->DeleteSymmKey (it->second.index); + it = m_ECIESx25519Tags.erase (it); + numExpiredTags++; + } + else if (it->second.tagset->IsSessionTerminated()) { it = m_ECIESx25519Tags.erase (it); numExpiredTags++; @@ -908,7 +927,8 @@ namespace garlic else ++it; } - } + } + m_NumUsedECIESx25519Tags = 0; if (numExpiredTags > 0) LogPrint (eLogDebug, "Garlic: ", numExpiredTags, " ECIESx25519 tags expired for ", GetIdentHash().ToBase64 ()); if (m_LastTagset && m_LastTagset->IsExpired (ts)) diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index 83e3b050..0386752b 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -291,6 +291,7 @@ namespace garlic std::unordered_map, std::hash > > m_Tags; std::unordered_map m_ECIESx25519Tags; // session tag -> session ReceiveRatchetTagSetPtr m_LastTagset; // tagset last message came for + int m_NumUsedECIESx25519Tags; // DeliveryStatus std::mutex m_DeliveryStatusSessionsMutex; std::unordered_map m_DeliveryStatusSessions; // msgID -> session @@ -299,7 +300,7 @@ namespace garlic // for HTTP only size_t GetNumIncomingTags () const { return m_Tags.size (); } - size_t GetNumIncomingECIESx25519Tags () const { return m_ECIESx25519Tags.size (); } + size_t GetNumIncomingECIESx25519Tags () const { return m_ECIESx25519Tags.size () - m_NumUsedECIESx25519Tags; } const decltype(m_Sessions)& GetSessions () const { return m_Sessions; }; const decltype(m_ECIESx25519Sessions)& GetECIESx25519Sessions () const { return m_ECIESx25519Sessions; } }; From 7e3157b162b644e8624aaea1057fb712052c4761 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 18 Feb 2024 21:28:06 -0500 Subject: [PATCH 0330/1171] don't process packet in terminated stream --- libi2pd/Streaming.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 74fb3d97..fa809c19 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -129,6 +129,11 @@ namespace stream void Stream::HandleNextPacket (Packet * packet) { + if (m_Status == eStreamStatusTerminated) + { + m_LocalDestination.DeletePacket (packet); + return; + } m_NumReceivedBytes += packet->GetLength (); if (!m_SendStreamID) { @@ -159,7 +164,8 @@ namespace stream { // we have received next in sequence message ProcessPacket (packet); - + if (m_Status == eStreamStatusTerminated) return; + // we should also try stored messages if any for (auto it = m_SavedPackets.begin (); it != m_SavedPackets.end ();) { @@ -169,6 +175,7 @@ namespace stream m_SavedPackets.erase (it++); ProcessPacket (savedPacket); + if (m_Status == eStreamStatusTerminated) return; } else break; From d677d67676eed2d84384797a6b662758878446bb Mon Sep 17 00:00:00 2001 From: Vort Date: Sun, 18 Feb 2024 22:54:43 +0200 Subject: [PATCH 0331/1171] implement medium congestion indication --- libi2pd/I2NPProtocol.cpp | 4 +- libi2pd/RouterContext.cpp | 25 +++++++---- libi2pd/RouterContext.h | 2 +- libi2pd/Transports.cpp | 87 ++++++++++++++++++++++++--------------- libi2pd/Transports.h | 26 ++++++++---- libi2pd/Tunnel.h | 2 +- 6 files changed, 92 insertions(+), 54 deletions(-) diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index 70cefbdc..78493df2 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -376,7 +376,7 @@ namespace i2p if (!i2p::context.DecryptTunnelBuildRecord (record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText)) return false; uint8_t retCode = 0; // replace record to reply - if (i2p::context.AcceptsTunnels () && !i2p::context.IsHighCongestion ()) + if (i2p::context.AcceptsTunnels () && i2p::context.GetCongestionLevel (false) < 100) { auto transitTunnel = i2p::tunnel::CreateTransitTunnel ( bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET), @@ -586,7 +586,7 @@ namespace i2p // check if we accept this tunnel std::shared_ptr transitTunnel; uint8_t retCode = 0; - if (!i2p::context.AcceptsTunnels () || i2p::context.IsHighCongestion ()) + if (!i2p::context.AcceptsTunnels () || i2p::context.GetCongestionLevel (false) >= 100) retCode = 30; if (!retCode) { diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 02ebf22c..64dd43e4 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -1137,13 +1137,14 @@ namespace i2p return i2p::tunnel::tunnels.GetExploratoryPool (); } - bool RouterContext::IsHighCongestion () const + int RouterContext::GetCongestionLevel (bool longTerm) const { - return i2p::tunnel::tunnels.IsTooManyTransitTunnels () || - i2p::transport::transports.IsBandwidthExceeded () || - i2p::transport::transports.IsTransitBandwidthExceeded (); - } - + return std::max ( + i2p::tunnel::tunnels.GetCongestionLevel (), + i2p::transport::transports.GetCongestionLevel (longTerm) + ); + } + void RouterContext::HandleI2NPMessage (const uint8_t * buf, size_t len) { i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len))); @@ -1447,10 +1448,16 @@ namespace i2p if (ecode != boost::asio::error::operation_aborted) { auto c = i2p::data::RouterInfo::eLowCongestion; - if (!AcceptsTunnels ()) + if (!AcceptsTunnels () || m_ShareRatio == 0) c = i2p::data::RouterInfo::eRejectAll; - else if (IsHighCongestion ()) - c = i2p::data::RouterInfo::eHighCongestion; + else + { + int congestionLevel = GetCongestionLevel (true); + if (congestionLevel > 90) + c = i2p::data::RouterInfo::eHighCongestion; + else if (congestionLevel > 70) + c = i2p::data::RouterInfo::eMediumCongestion; + } if (m_RouterInfo.UpdateCongestion (c)) UpdateRouterInfo (); ScheduleCongestionUpdate (); diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index d85ef282..062c187d 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -167,7 +167,7 @@ namespace garlic void SetShareRatio (int percents); // 0 - 100 bool AcceptsTunnels () const { return m_AcceptsTunnels; }; void SetAcceptsTunnels (bool acceptsTunnels) { m_AcceptsTunnels = acceptsTunnels; }; - bool IsHighCongestion () const; + int GetCongestionLevel (bool longTerm) const; bool SupportsV6 () const { return m_RouterInfo.IsV6 (); }; bool SupportsV4 () const { return m_RouterInfo.IsV4 (); }; bool SupportsMesh () const { return m_RouterInfo.IsMesh (); }; diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 0afe47a1..a3914d7c 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -140,10 +140,8 @@ namespace transport m_X25519KeysPairSupplier (15), // 15 pre-generated keys m_TotalSentBytes (0), m_TotalReceivedBytes (0), m_TotalTransitTransmittedBytes (0), m_InBandwidth (0), m_OutBandwidth (0), m_TransitBandwidth (0), - m_LastInBandwidthUpdateBytes (0), m_LastOutBandwidthUpdateBytes (0), m_LastTransitBandwidthUpdateBytes (0), m_InBandwidth15s (0), m_OutBandwidth15s (0), m_TransitBandwidth15s (0), - m_LastInBandwidth15sUpdateBytes (0), m_LastOutBandwidth15sUpdateBytes (0), m_LastTransitBandwidth15sUpdateBytes (0), - m_LastBandwidth15sUpdateTime (0) + m_InBandwidth5m (0), m_OutBandwidth5m (0), m_TransitBandwidth5m (0) { } @@ -306,6 +304,16 @@ namespace transport m_PeerCleanupTimer->expires_from_now (boost::posix_time::seconds(5 * SESSION_CREATION_TIMEOUT)); m_PeerCleanupTimer->async_wait (std::bind (&Transports::HandlePeerCleanupTimer, this, std::placeholders::_1)); + uint64_t ts = i2p::util::GetMillisecondsSinceEpoch(); + for (int i = 0; i < TRAFFIC_SAMPLE_COUNT; i++) + { + m_TrafficSamples[i].Timestamp = ts - (TRAFFIC_SAMPLE_COUNT - i - 1) * 1000; + m_TrafficSamples[i].TotalReceivedBytes = 0; + m_TrafficSamples[i].TotalSentBytes = 0; + m_TrafficSamples[i].TotalTransitTransmittedBytes = 0; + } + m_TrafficSamplePtr = TRAFFIC_SAMPLE_COUNT - 1; + m_UpdateBandwidthTimer->expires_from_now (boost::posix_time::seconds(1)); m_UpdateBandwidthTimer->async_wait (std::bind (&Transports::HandleUpdateBandwidthTimer, this, std::placeholders::_1)); @@ -364,51 +372,62 @@ namespace transport } } + void Transports::UpdateBandwidthValues(int interval, uint32_t& in, uint32_t& out, uint32_t& transit) + { + TrafficSample& sample1 = m_TrafficSamples[m_TrafficSamplePtr]; + TrafficSample& sample2 = m_TrafficSamples[(TRAFFIC_SAMPLE_COUNT + m_TrafficSamplePtr - interval) % TRAFFIC_SAMPLE_COUNT]; + auto delta = sample1.Timestamp - sample2.Timestamp; + in = (sample1.TotalReceivedBytes - sample2.TotalReceivedBytes) * 1000 / delta; + out = (sample1.TotalSentBytes - sample2.TotalSentBytes) * 1000 / delta; + transit = (sample1.TotalTransitTransmittedBytes - sample2.TotalTransitTransmittedBytes) * 1000 / delta; + } + void Transports::HandleUpdateBandwidthTimer (const boost::system::error_code& ecode) { if (ecode != boost::asio::error::operation_aborted) { - uint64_t ts = i2p::util::GetMillisecondsSinceEpoch (); + m_TrafficSamplePtr++; + if (m_TrafficSamplePtr == TRAFFIC_SAMPLE_COUNT) + m_TrafficSamplePtr = 0; - // updated every second - m_InBandwidth = m_TotalReceivedBytes - m_LastInBandwidthUpdateBytes; - m_OutBandwidth = m_TotalSentBytes - m_LastOutBandwidthUpdateBytes; - m_TransitBandwidth = m_TotalTransitTransmittedBytes - m_LastTransitBandwidthUpdateBytes; + TrafficSample& sample = m_TrafficSamples[m_TrafficSamplePtr]; + sample.Timestamp = i2p::util::GetMillisecondsSinceEpoch(); + sample.TotalReceivedBytes = m_TotalReceivedBytes; + sample.TotalSentBytes = m_TotalSentBytes; + sample.TotalTransitTransmittedBytes = m_TotalTransitTransmittedBytes; - m_LastInBandwidthUpdateBytes = m_TotalReceivedBytes; - m_LastOutBandwidthUpdateBytes = m_TotalSentBytes; - m_LastTransitBandwidthUpdateBytes = m_TotalTransitTransmittedBytes; - - // updated every 15 seconds - auto delta = ts - m_LastBandwidth15sUpdateTime; - if (delta > 15 * 1000) - { - m_InBandwidth15s = (m_TotalReceivedBytes - m_LastInBandwidth15sUpdateBytes) * 1000 / delta; - m_OutBandwidth15s = (m_TotalSentBytes - m_LastOutBandwidth15sUpdateBytes) * 1000 / delta; - m_TransitBandwidth15s = (m_TotalTransitTransmittedBytes - m_LastTransitBandwidth15sUpdateBytes) * 1000 / delta; - - m_LastBandwidth15sUpdateTime = ts; - m_LastInBandwidth15sUpdateBytes = m_TotalReceivedBytes; - m_LastOutBandwidth15sUpdateBytes = m_TotalSentBytes; - m_LastTransitBandwidth15sUpdateBytes = m_TotalTransitTransmittedBytes; - } + UpdateBandwidthValues (1, m_InBandwidth, m_OutBandwidth, m_TransitBandwidth); + UpdateBandwidthValues (15, m_InBandwidth15s, m_OutBandwidth15s, m_TransitBandwidth15s); + UpdateBandwidthValues (300, m_InBandwidth5m, m_OutBandwidth5m, m_TransitBandwidth5m); m_UpdateBandwidthTimer->expires_from_now (boost::posix_time::seconds(1)); m_UpdateBandwidthTimer->async_wait (std::bind (&Transports::HandleUpdateBandwidthTimer, this, std::placeholders::_1)); } } - bool Transports::IsBandwidthExceeded () const + int Transports::GetCongestionLevel (bool longTerm) const { - auto limit = i2p::context.GetBandwidthLimit() * 1024; // convert to bytes - auto bw = std::max (m_InBandwidth15s, m_OutBandwidth15s); - return bw > limit; - } + auto bwLimit = i2p::context.GetBandwidthLimit () * 1024; // convert to bytes + auto tbwLimit = i2p::context.GetTransitBandwidthLimit () * 1024; // convert to bytes - bool Transports::IsTransitBandwidthExceeded () const - { - auto limit = i2p::context.GetTransitBandwidthLimit() * 1024; // convert to bytes - return m_TransitBandwidth > limit; + if (tbwLimit == 0 || bwLimit == 0) + return 100; + + uint32_t bw; + uint32_t tbw; + if (longTerm) + { + bw = std::max (m_InBandwidth5m, m_OutBandwidth5m); + tbw = m_TransitBandwidth5m; + } + else + { + bw = std::max (m_InBandwidth15s, m_OutBandwidth15s); + tbw = m_TransitBandwidth; + } + auto bwCongestionLevel = 100 * bw / bwLimit; + auto tbwCongestionLevel = 100 * tbw / tbwLimit; + return std::max (bwCongestionLevel, tbwCongestionLevel); } void Transports::SendMessage (const i2p::data::IdentHash& ident, std::shared_ptr msg) diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index 206b0256..92d75efd 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -114,6 +114,17 @@ namespace transport const int PEER_TEST_DELAY_INTERVAL_VARIANCE = 30; // in milliseconds const int MAX_NUM_DELAYED_MESSAGES = 150; const int CHECK_PROFILE_NUM_DELAYED_MESSAGES = 15; // check profile after + + const int TRAFFIC_SAMPLE_COUNT = 301; // seconds + + struct TrafficSample + { + uint64_t Timestamp; + uint64_t TotalReceivedBytes; + uint64_t TotalSentBytes; + uint64_t TotalTransitTransmittedBytes; + }; + class Transports { public: @@ -153,8 +164,7 @@ namespace transport uint32_t GetInBandwidth15s () const { return m_InBandwidth15s; }; uint32_t GetOutBandwidth15s () const { return m_OutBandwidth15s; }; uint32_t GetTransitBandwidth15s () const { return m_TransitBandwidth15s; }; - bool IsBandwidthExceeded () const; - bool IsTransitBandwidthExceeded () const; + int GetCongestionLevel (bool longTerm) const; size_t GetNumPeers () const { return m_Peers.size (); }; std::shared_ptr GetRandomPeer (bool isHighBandwidth) const; @@ -186,6 +196,7 @@ namespace transport void HandlePeerCleanupTimer (const boost::system::error_code& ecode); void HandlePeerTestTimer (const boost::system::error_code& ecode); void HandleUpdateBandwidthTimer (const boost::system::error_code& ecode); + void UpdateBandwidthValues (int interval, uint32_t& in, uint32_t& out, uint32_t& transit); void DetectExternalIP (); @@ -210,14 +221,15 @@ namespace transport std::atomic m_TotalSentBytes, m_TotalReceivedBytes, m_TotalTransitTransmittedBytes; + TrafficSample m_TrafficSamples[TRAFFIC_SAMPLE_COUNT]; + int m_TrafficSamplePtr; + // Bandwidth per second uint32_t m_InBandwidth, m_OutBandwidth, m_TransitBandwidth; - uint64_t m_LastInBandwidthUpdateBytes, m_LastOutBandwidthUpdateBytes, m_LastTransitBandwidthUpdateBytes; - - // Bandwidth every 15 seconds + // Bandwidth during last 15 seconds uint32_t m_InBandwidth15s, m_OutBandwidth15s, m_TransitBandwidth15s; - uint64_t m_LastInBandwidth15sUpdateBytes, m_LastOutBandwidth15sUpdateBytes, m_LastTransitBandwidth15sUpdateBytes; - uint64_t m_LastBandwidth15sUpdateTime; + // Bandwidth during last 5 minutes + uint32_t m_InBandwidth5m, m_OutBandwidth5m, m_TransitBandwidth5m; /** which router families to trust for first hops */ std::vector m_TrustedFamilies; diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index a0815cba..0b125c70 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -240,7 +240,7 @@ namespace tunnel void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels); uint16_t GetMaxNumTransitTunnels () const { return m_MaxNumTransitTunnels; }; - bool IsTooManyTransitTunnels () const { return m_TransitTunnels.size () >= m_MaxNumTransitTunnels; }; + int GetCongestionLevel() const { return 100 * m_TransitTunnels.size() / m_MaxNumTransitTunnels; } private: From a4a3f8e96b55c83bcf3af66abf7e500cd47684b8 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 19 Feb 2024 22:04:43 -0500 Subject: [PATCH 0332/1171] support upstream proxy through local sockets --- libi2pd_client/SOCKS.cpp | 77 +++++++++++++++++++++++++++++++--------- 1 file changed, 61 insertions(+), 16 deletions(-) diff --git a/libi2pd_client/SOCKS.cpp b/libi2pd_client/SOCKS.cpp index 65bad1cf..3174bdb3 100644 --- a/libi2pd_client/SOCKS.cpp +++ b/libi2pd_client/SOCKS.cpp @@ -139,9 +139,11 @@ namespace proxy void HandleStreamRequestComplete (std::shared_ptr stream); void ForwardSOCKS(); - void SocksUpstreamSuccess(); + template + void SocksUpstreamSuccess(std::shared_ptr& upstreamSock); void AsyncUpstreamSockRead(); - void SendUpstreamRequest(); + template + void SendUpstreamRequest(std::shared_ptr& upstreamSock); void HandleUpstreamConnected(const boost::system::error_code & ecode, boost::asio::ip::tcp::resolver::iterator itr); void HandleUpstreamResolved(const boost::system::error_code & ecode, @@ -150,6 +152,9 @@ namespace proxy boost::asio::ip::tcp::resolver m_proxy_resolver; uint8_t m_sock_buff[socks_buffer_size]; std::shared_ptr m_sock, m_upstreamSock; +#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) + std::shared_ptr m_upstreamLocalSock; +#endif std::shared_ptr m_stream; uint8_t *m_remaining_data; //Data left to be sent uint8_t *m_remaining_upstream_data; //upstream data left to be forwarded @@ -212,6 +217,14 @@ namespace proxy m_upstreamSock->close(); m_upstreamSock = nullptr; } +#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) + if (m_upstreamLocalSock) + { + LogPrint(eLogDebug, "SOCKS: Closing upstream local socket"); + m_upstreamLocalSock->close(); + m_upstreamLocalSock = nullptr; + } +#endif if (m_stream) { LogPrint(eLogDebug, "SOCKS: Closing stream"); @@ -677,13 +690,45 @@ namespace proxy void SOCKSHandler::ForwardSOCKS() { LogPrint(eLogInfo, "SOCKS: Forwarding to upstream"); - EnterState(UPSTREAM_RESOLVE); - boost::asio::ip::tcp::resolver::query q(m_UpstreamProxyAddress, std::to_string(m_UpstreamProxyPort)); - m_proxy_resolver.async_resolve(q, std::bind(&SOCKSHandler::HandleUpstreamResolved, shared_from_this(), - std::placeholders::_1, std::placeholders::_2)); + if (m_UpstreamProxyPort) // TCP + { + EnterState(UPSTREAM_RESOLVE); + boost::asio::ip::tcp::resolver::query q(m_UpstreamProxyAddress, std::to_string(m_UpstreamProxyPort)); + m_proxy_resolver.async_resolve(q, std::bind(&SOCKSHandler::HandleUpstreamResolved, shared_from_this(), + std::placeholders::_1, std::placeholders::_2)); + } + else if (!m_UpstreamProxyAddress.empty ())// local + { +#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) + EnterState(UPSTREAM_CONNECT); + m_upstreamLocalSock = std::make_shared(GetOwner()->GetService()); + auto s = shared_from_this (); + m_upstreamLocalSock->async_connect(m_UpstreamProxyAddress, + [s](const boost::system::error_code& ecode) + { + if (ecode) + { + LogPrint(eLogWarning, "SOCKS: Could not connect to local upstream proxy: ", ecode.message()); + s->SocksRequestFailed(SOCKS5_NET_UNREACH); + return; + } + LogPrint(eLogInfo, "SOCKS: Connected to local upstream proxy"); + s->SendUpstreamRequest(s->m_upstreamLocalSock); + }); +#else + LogPrint(eLogError, "SOCKS: Local sockets for upstream proxy not supported"); + SocksRequestFailed(SOCKS5_ADDR_UNSUP); +#endif + } + else + { + LogPrint(eLogError, "SOCKS: Incorrect upstream proxy address"); + SocksRequestFailed(SOCKS5_ADDR_UNSUP); + } } - void SOCKSHandler::SocksUpstreamSuccess() + template + void SOCKSHandler::SocksUpstreamSuccess(std::shared_ptr& upstreamSock) { LogPrint(eLogInfo, "SOCKS: Upstream success"); boost::asio::const_buffers_1 response(nullptr, 0); @@ -700,27 +745,27 @@ namespace proxy break; } m_sock->send(response); - auto forwarder = CreateSocketsPipe (GetOwner(), m_sock, m_upstreamSock); - m_upstreamSock = nullptr; + auto forwarder = CreateSocketsPipe (GetOwner(), m_sock, upstreamSock); + upstreamSock = nullptr; m_sock = nullptr; GetOwner()->AddHandler(forwarder); forwarder->Start(); Terminate(); } - - void SOCKSHandler::SendUpstreamRequest() + template + void SOCKSHandler::SendUpstreamRequest(std::shared_ptr& upstreamSock) { LogPrint(eLogInfo, "SOCKS: Negotiating with upstream proxy"); EnterState(UPSTREAM_HANDSHAKE); - if (m_upstreamSock) + if (upstreamSock) { auto s = shared_from_this (); - i2p::transport::Socks5Handshake (*m_upstreamSock, std::make_pair(m_address.dns.ToString (), m_port), - [s](const boost::system::error_code& ec) + i2p::transport::Socks5Handshake (*upstreamSock, std::make_pair(m_address.dns.ToString (), m_port), + [s, &upstreamSock](const boost::system::error_code& ec) { if (!ec) - s->SocksUpstreamSuccess(); + s->SocksUpstreamSuccess(upstreamSock); else { s->SocksRequestFailed(SOCKS5_NET_UNREACH); @@ -740,7 +785,7 @@ namespace proxy return; } LogPrint(eLogInfo, "SOCKS: Connected to upstream proxy"); - SendUpstreamRequest(); + SendUpstreamRequest(m_upstreamSock); } void SOCKSHandler::HandleUpstreamResolved(const boost::system::error_code & ecode, boost::asio::ip::tcp::resolver::iterator itr) From 19e23b34da807476c4e1ed0dea3c1bef15df3a06 Mon Sep 17 00:00:00 2001 From: Vort Date: Tue, 20 Feb 2024 10:30:05 +0200 Subject: [PATCH 0333/1171] add constants for congestion levels --- libi2pd/I2NPProtocol.cpp | 4 ++-- libi2pd/I2NPProtocol.h | 4 ++++ libi2pd/RouterContext.cpp | 6 +++--- libi2pd/Transports.cpp | 6 +++--- libi2pd/Tunnel.h | 2 +- 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index 78493df2..a1638326 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -376,7 +376,7 @@ namespace i2p if (!i2p::context.DecryptTunnelBuildRecord (record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText)) return false; uint8_t retCode = 0; // replace record to reply - if (i2p::context.AcceptsTunnels () && i2p::context.GetCongestionLevel (false) < 100) + if (i2p::context.AcceptsTunnels () && i2p::context.GetCongestionLevel (false) < CONGESTION_LEVEL_FULL) { auto transitTunnel = i2p::tunnel::CreateTransitTunnel ( bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET), @@ -586,7 +586,7 @@ namespace i2p // check if we accept this tunnel std::shared_ptr transitTunnel; uint8_t retCode = 0; - if (!i2p::context.AcceptsTunnels () || i2p::context.GetCongestionLevel (false) >= 100) + if (!i2p::context.AcceptsTunnels () || i2p::context.GetCongestionLevel (false) >= CONGESTION_LEVEL_FULL) retCode = 30; if (!retCode) { diff --git a/libi2pd/I2NPProtocol.h b/libi2pd/I2NPProtocol.h index a2877a08..36facbe3 100644 --- a/libi2pd/I2NPProtocol.h +++ b/libi2pd/I2NPProtocol.h @@ -139,6 +139,10 @@ namespace tunnel class TunnelPool; } + const int CONGESTION_LEVEL_MEDIUM = 70; + const int CONGESTION_LEVEL_HIGH = 90; + const int CONGESTION_LEVEL_FULL = 100; + const size_t I2NP_MAX_MESSAGE_SIZE = 62708; const size_t I2NP_MAX_SHORT_MESSAGE_SIZE = 4096; const size_t I2NP_MAX_MEDIUM_MESSAGE_SIZE = 16384; diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 64dd43e4..013f4dc5 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -1448,14 +1448,14 @@ namespace i2p if (ecode != boost::asio::error::operation_aborted) { auto c = i2p::data::RouterInfo::eLowCongestion; - if (!AcceptsTunnels () || m_ShareRatio == 0) + if (!AcceptsTunnels () || !m_ShareRatio) c = i2p::data::RouterInfo::eRejectAll; else { int congestionLevel = GetCongestionLevel (true); - if (congestionLevel > 90) + if (congestionLevel > CONGESTION_LEVEL_HIGH) c = i2p::data::RouterInfo::eHighCongestion; - else if (congestionLevel > 70) + else if (congestionLevel > CONGESTION_LEVEL_MEDIUM) c = i2p::data::RouterInfo::eMediumCongestion; } if (m_RouterInfo.UpdateCongestion (c)) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index a3914d7c..bb5dcecc 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -411,7 +411,7 @@ namespace transport auto tbwLimit = i2p::context.GetTransitBandwidthLimit () * 1024; // convert to bytes if (tbwLimit == 0 || bwLimit == 0) - return 100; + return CONGESTION_LEVEL_FULL; uint32_t bw; uint32_t tbw; @@ -425,8 +425,8 @@ namespace transport bw = std::max (m_InBandwidth15s, m_OutBandwidth15s); tbw = m_TransitBandwidth; } - auto bwCongestionLevel = 100 * bw / bwLimit; - auto tbwCongestionLevel = 100 * tbw / tbwLimit; + auto bwCongestionLevel = CONGESTION_LEVEL_FULL * bw / bwLimit; + auto tbwCongestionLevel = CONGESTION_LEVEL_FULL * tbw / tbwLimit; return std::max (bwCongestionLevel, tbwCongestionLevel); } diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index 0b125c70..cc5b9461 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -240,7 +240,7 @@ namespace tunnel void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels); uint16_t GetMaxNumTransitTunnels () const { return m_MaxNumTransitTunnels; }; - int GetCongestionLevel() const { return 100 * m_TransitTunnels.size() / m_MaxNumTransitTunnels; } + int GetCongestionLevel() const { return CONGESTION_LEVEL_FULL * m_TransitTunnels.size() / m_MaxNumTransitTunnels; } private: From b092e712ec0d9616eef7d73eb2d9e2bd11afba6d Mon Sep 17 00:00:00 2001 From: Vort Date: Tue, 20 Feb 2024 17:39:48 +0200 Subject: [PATCH 0334/1171] make more attempts to select not bad hop --- libi2pd/NetDb.cpp | 2 +- libi2pd/TunnelPool.cpp | 22 +++++++++++++++++----- libi2pd/TunnelPool.h | 1 + 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 0adeb2e7..bfd07df3 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -1257,7 +1257,7 @@ namespace data std::shared_ptr NetDb::GetRandomRouter (Filter filter) const { if (m_RouterInfos.empty()) - return 0; + return nullptr; uint16_t inds[3]; RAND_bytes ((uint8_t *)inds, sizeof (inds)); std::lock_guard l(m_RouterInfosMutex); diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index 5b472232..c342d546 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -494,11 +494,23 @@ namespace tunnel std::shared_ptr TunnelPool::SelectNextHop (std::shared_ptr prevHop, bool reverse, bool endpoint) const { - auto hop = IsExploratory () ? i2p::data::netdb.GetRandomRouter (prevHop, reverse, endpoint): - i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop, reverse, endpoint); - - if (!hop || hop->GetProfile ()->IsBad ()) - hop = i2p::data::netdb.GetRandomRouter (prevHop, reverse, endpoint); + bool tryHighBandwidth = !IsExploratory (); + std::shared_ptr hop; + for (int i = 0; i < TUNNEL_POOL_MAX_HOP_SELECTION_ATTEMPTS; i++) + { + hop = tryHighBandwidth ? + i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop, reverse, endpoint) : + i2p::data::netdb.GetRandomRouter (prevHop, reverse, endpoint); + if (hop) + { + if (!hop->GetProfile ()->IsBad ()) + break; + } + else if (tryHighBandwidth) + tryHighBandwidth = false; + else + return nullptr; + } return hop; } diff --git a/libi2pd/TunnelPool.h b/libi2pd/TunnelPool.h index 3d3d4e33..d9f5966d 100644 --- a/libi2pd/TunnelPool.h +++ b/libi2pd/TunnelPool.h @@ -32,6 +32,7 @@ namespace tunnel const int TUNNEL_POOL_MAX_INBOUND_TUNNELS_QUANTITY = 16; const int TUNNEL_POOL_MAX_OUTBOUND_TUNNELS_QUANTITY = 16; const int TUNNEL_POOL_MAX_NUM_BUILD_REQUESTS = 3; + const int TUNNEL_POOL_MAX_HOP_SELECTION_ATTEMPTS = 3; class Tunnel; class InboundTunnel; From d524105727797825cf8e0310eef7120060b28c60 Mon Sep 17 00:00:00 2001 From: Vort Date: Tue, 20 Feb 2024 22:48:45 +0200 Subject: [PATCH 0335/1171] skip bandwidth updates in case of time going backwards --- libi2pd/Transports.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index bb5dcecc..04c58cf3 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -376,7 +376,12 @@ namespace transport { TrafficSample& sample1 = m_TrafficSamples[m_TrafficSamplePtr]; TrafficSample& sample2 = m_TrafficSamples[(TRAFFIC_SAMPLE_COUNT + m_TrafficSamplePtr - interval) % TRAFFIC_SAMPLE_COUNT]; - auto delta = sample1.Timestamp - sample2.Timestamp; + auto delta = (int64_t)sample1.Timestamp - (int64_t)sample2.Timestamp; + if (delta <= 0) + { + LogPrint (eLogError, "Transports: Backward clock jump detected, got ", delta, " instead of ", interval * 1000); + return; + } in = (sample1.TotalReceivedBytes - sample2.TotalReceivedBytes) * 1000 / delta; out = (sample1.TotalSentBytes - sample2.TotalSentBytes) * 1000 / delta; transit = (sample1.TotalTransitTransmittedBytes - sample2.TotalTransitTransmittedBytes) * 1000 / delta; From 2692aef53d45eb7b9a2a82a1c241a0f7ca9b175a Mon Sep 17 00:00:00 2001 From: R4SAS Date: Wed, 21 Feb 2024 01:36:32 +0300 Subject: [PATCH 0336/1171] [gha] update windows msvc action --- .github/workflows/build-windows-msvc.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-windows-msvc.yml b/.github/workflows/build-windows-msvc.yml index dea64644..36a70d5a 100644 --- a/.github/workflows/build-windows-msvc.yml +++ b/.github/workflows/build-windows-msvc.yml @@ -38,13 +38,13 @@ jobs: - name: Install Boost run: | - powershell -Command "(Invoke-WebRequest -UserAgent "Wget" -Uri https://sourceforge.net/projects/boost/files/boost-binaries/1.81.0/boost_1_81_0-msvc-14.3-64.exe/download -OutFile boost_1_84_0-msvc-14.3-64.exe)" - ./boost_1_84_0-msvc-14.3-64.exe /VERYSILENT + powershell -Command "(Invoke-WebRequest -UserAgent "Wget" -Uri https://sourceforge.net/projects/boost/files/boost-binaries/1.81.0/boost_1_81_0-msvc-14.3-64.exe/download -OutFile boost_1_81_0-msvc-14.3-64.exe)" + ./boost_1_81_0-msvc-14.3-64.exe /VERYSILENT - name: Install OpenSSL run: | - powershell -Command "(Invoke-WebRequest -UserAgent "Wget" -Uri https://slproweb.com/download/Win64OpenSSL-3_2_0.exe -OutFile Win64OpenSSL-3_2_0.exe)" - ./Win64OpenSSL-3_2_0.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- + powershell -Command "(Invoke-WebRequest -UserAgent "Wget" -Uri https://slproweb.com/download/Win64OpenSSL-3_2_1.exe -OutFile Win64OpenSSL-3_2_1.exe)" + ./Win64OpenSSL-3_2_1.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- - name: Configure working-directory: build From 695dc96a837d029999375ef80084c923d65cc4ad Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 20 Feb 2024 18:32:51 -0500 Subject: [PATCH 0337/1171] common ServiceAcceptor for all stream protocols --- libi2pd_client/I2PService.cpp | 49 ---------------- libi2pd_client/I2PService.h | 103 +++++++++++++++++++++++----------- 2 files changed, 71 insertions(+), 81 deletions(-) diff --git a/libi2pd_client/I2PService.cpp b/libi2pd_client/I2PService.cpp index 5604f950..e9513e48 100644 --- a/libi2pd_client/I2PService.cpp +++ b/libi2pd_client/I2PService.cpp @@ -147,54 +147,5 @@ namespace client m_LocalDestination->CreateStream (streamRequestComplete, address->blindedPublicKey, port); } } - - void TCPIPAcceptor::Start () - { - m_Acceptor.reset (new boost::asio::ip::tcp::acceptor (GetService (), m_LocalEndpoint)); - // update the local end point in case port has been set zero and got updated now - m_LocalEndpoint = m_Acceptor->local_endpoint(); - m_Acceptor->listen (); - Accept (); - } - - void TCPIPAcceptor::Stop () - { - if (m_Acceptor) - { - m_Acceptor->close(); - m_Acceptor.reset (nullptr); - } - m_Timer.cancel (); - ClearHandlers(); - } - - void TCPIPAcceptor::Accept () - { - auto newSocket = std::make_shared (GetService ()); - m_Acceptor->async_accept (*newSocket, std::bind (&TCPIPAcceptor::HandleAccept, this, - std::placeholders::_1, newSocket)); - } - - void TCPIPAcceptor::HandleAccept (const boost::system::error_code& ecode, std::shared_ptr socket) - { - if (!ecode) - { - LogPrint(eLogDebug, "I2PService: ", GetName(), " accepted"); - auto handler = CreateHandler(socket); - if (handler) - { - AddHandler(handler); - handler->Handle(); - } - else - socket->close(); - Accept(); - } - else - { - if (ecode != boost::asio::error::operation_aborted) - LogPrint (eLogError, "I2PService: ", GetName(), " closing socket on accept because: ", ecode.message ()); - } - } } } diff --git a/libi2pd_client/I2PService.h b/libi2pd_client/I2PService.h index b8973f9d..d35c954d 100644 --- a/libi2pd_client/I2PService.h +++ b/libi2pd_client/I2PService.h @@ -210,42 +210,81 @@ namespace client return std::make_shared >(owner, upstream, downstream); } - /* TODO: support IPv6 too */ - //This is a service that listens for connections on the IP network and interacts with I2P - class TCPIPAcceptor: public I2PService + //This is a service that listens for connections on the IP network or local socket and interacts with I2P + template + class ServiceAcceptor: public I2PService + { + public: + + ServiceAcceptor (const typename Protocol::endpoint& localEndpoint, std::shared_ptr localDestination = nullptr) : + I2PService(localDestination), m_LocalEndpoint (localEndpoint) {} + + virtual ~ServiceAcceptor () { Stop(); } + void Start () override + { + m_Acceptor.reset (new typename Protocol::acceptor (GetService (), m_LocalEndpoint)); + // update the local end point in case port has been set zero and got updated now + m_LocalEndpoint = m_Acceptor->local_endpoint(); + m_Acceptor->listen (); + Accept (); + } + void Stop () override + { + if (m_Acceptor) + { + m_Acceptor->close(); + m_Acceptor.reset (nullptr); + } + ClearHandlers(); + } + const typename Protocol::endpoint& GetLocalEndpoint () const { return m_LocalEndpoint; }; + + const char* GetName() override { return "Generic TCP/IP accepting daemon"; } + + protected: + + virtual std::shared_ptr CreateHandler(std::shared_ptr socket) = 0; + + private: + + void Accept() + { + auto newSocket = std::make_shared (GetService ()); + m_Acceptor->async_accept (*newSocket, + [newSocket, this](const boost::system::error_code& ecode) + { + if (ecode == boost::asio::error::operation_aborted) return; + if (!ecode) + { + LogPrint(eLogDebug, "ServiceAcceptor: ", GetName(), " accepted"); + auto handler = CreateHandler(newSocket); + if (handler) + { + AddHandler(handler); + handler->Handle(); + } + else + newSocket->close(); + Accept(); + } + else + LogPrint (eLogError, "ServiceAcceptor: ", GetName(), " closing socket on accept because: ", ecode.message ()); + }); + } + + private: + + typename Protocol::endpoint m_LocalEndpoint; + std::unique_ptr m_Acceptor; + }; + + class TCPIPAcceptor: public ServiceAcceptor { public: TCPIPAcceptor (const std::string& address, uint16_t port, std::shared_ptr localDestination = nullptr) : - I2PService(localDestination), - m_LocalEndpoint (boost::asio::ip::address::from_string(address), port), - m_Timer (GetService ()) {} - TCPIPAcceptor (const std::string& address, uint16_t port, i2p::data::SigningKeyType kt) : - I2PService(kt), - m_LocalEndpoint (boost::asio::ip::address::from_string(address), port), - m_Timer (GetService ()) {} - virtual ~TCPIPAcceptor () { TCPIPAcceptor::Stop(); } - //If you override this make sure you call it from the children - void Start (); - //If you override this make sure you call it from the children - void Stop (); - - const boost::asio::ip::tcp::endpoint& GetLocalEndpoint () const { return m_LocalEndpoint; }; - - virtual const char* GetName() { return "Generic TCP/IP accepting daemon"; } - - protected: - - virtual std::shared_ptr CreateHandler(std::shared_ptr socket) = 0; - - private: - - void Accept(); - void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr socket); - boost::asio::ip::tcp::endpoint m_LocalEndpoint; - std::unique_ptr m_Acceptor; - boost::asio::deadline_timer m_Timer; - }; + ServiceAcceptor (boost::asio::ip::tcp::endpoint (boost::asio::ip::address::from_string(address), port), localDestination) {} + }; } } From 577ed56af023c792dccee3bed9fe731b59e137bd Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 20 Feb 2024 18:51:37 -0500 Subject: [PATCH 0338/1171] store HTTP and SOCKS proxy as pointer to I2PService --- libi2pd_client/ClientContext.cpp | 1 + libi2pd_client/ClientContext.h | 11 ++++------- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index c27ce625..62295842 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -16,6 +16,7 @@ #include "Identity.h" #include "util.h" #include "ClientContext.h" +#include "HTTPProxy.h" #include "SOCKS.h" #include "MatchedDestination.h" diff --git a/libi2pd_client/ClientContext.h b/libi2pd_client/ClientContext.h index 4e969a6b..adec607a 100644 --- a/libi2pd_client/ClientContext.h +++ b/libi2pd_client/ClientContext.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -15,8 +15,6 @@ #include #include "Destination.h" #include "I2PService.h" -#include "HTTPProxy.h" -#include "SOCKS.h" #include "I2PTunnel.h" #include "UDPTunnel.h" #include "SAM.h" @@ -141,8 +139,7 @@ namespace client AddressBook m_AddressBook; - i2p::proxy::HTTPProxy * m_HttpProxy; - i2p::proxy::SOCKSProxy * m_SocksProxy; + I2PService * m_HttpProxy, * m_SocksProxy; std::map > m_ClientTunnels; // local endpoint -> tunnel std::map, std::shared_ptr > m_ServerTunnels; // -> tunnel @@ -167,8 +164,8 @@ namespace client const decltype(m_ServerTunnels)& GetServerTunnels () const { return m_ServerTunnels; }; const decltype(m_ClientForwards)& GetClientForwards () const { return m_ClientForwards; } const decltype(m_ServerForwards)& GetServerForwards () const { return m_ServerForwards; } - const i2p::proxy::HTTPProxy * GetHttpProxy () const { return m_HttpProxy; } - const i2p::proxy::SOCKSProxy * GetSocksProxy () const { return m_SocksProxy; } + const I2PService * GetHttpProxy () const { return m_HttpProxy; } + const I2PService * GetSocksProxy () const { return m_SocksProxy; } }; extern ClientContext context; From 36a060d50f66230251fe737b4c497eed961c1e67 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 21 Feb 2024 12:37:33 -0500 Subject: [PATCH 0339/1171] Consider 'M' routers as low bandwidth --- libi2pd/RouterContext.cpp | 6 +++--- libi2pd/RouterInfo.cpp | 5 ++--- libi2pd/RouterInfo.h | 8 ++++---- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 013f4dc5..864d2c61 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -602,9 +602,9 @@ namespace i2p { case i2p::data::CAPS_FLAG_LOW_BANDWIDTH1 : limit = 12; type = low; break; case i2p::data::CAPS_FLAG_LOW_BANDWIDTH2 : limit = i2p::data::LOW_BANDWIDTH_LIMIT; type = low; break; // 48 - case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH1 : limit = 64; type = high; break; - case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH2 : limit = 128; type = high; break; - case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH3 : limit = i2p::data::HIGH_BANDWIDTH_LIMIT; type = high; break; // 256 + case i2p::data::CAPS_FLAG_LOW_BANDWIDTH3 : limit = 64; type = low; break; + case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH1 : limit = 128; type = high; break; + case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH2 : limit = i2p::data::HIGH_BANDWIDTH_LIMIT; type = high; break; // 256 case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH1 : limit = i2p::data::EXTRA_BANDWIDTH_LIMIT; type = extra; break; // 2048 case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH2 : limit = 1000000; type = unlim; break; // 1Gbyte/s default: diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index a034691a..a9c43b2e 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -516,7 +516,6 @@ namespace data break; case CAPS_FLAG_HIGH_BANDWIDTH1: case CAPS_FLAG_HIGH_BANDWIDTH2: - case CAPS_FLAG_HIGH_BANDWIDTH3: m_Caps |= Caps::eHighBandwidth; break; case CAPS_FLAG_EXTRA_BANDWIDTH1: @@ -1178,7 +1177,7 @@ namespace data CAPS_FLAG_EXTRA_BANDWIDTH2 : // 'X' CAPS_FLAG_EXTRA_BANDWIDTH1; // 'P' else - caps += CAPS_FLAG_HIGH_BANDWIDTH3; // 'O' + caps += CAPS_FLAG_HIGH_BANDWIDTH2; // 'O' caps += CAPS_FLAG_FLOODFILL; // floodfill } else @@ -1186,7 +1185,7 @@ namespace data if (c & eExtraBandwidth) caps += (c & eHighBandwidth) ? CAPS_FLAG_EXTRA_BANDWIDTH2 /* 'X' */ : CAPS_FLAG_EXTRA_BANDWIDTH1; /*'P' */ else - caps += (c & eHighBandwidth) ? CAPS_FLAG_HIGH_BANDWIDTH3 /* 'O' */: CAPS_FLAG_LOW_BANDWIDTH2 /* 'L' */; // bandwidth + caps += (c & eHighBandwidth) ? CAPS_FLAG_HIGH_BANDWIDTH2 /* 'O' */: CAPS_FLAG_LOW_BANDWIDTH2 /* 'L' */; // bandwidth } if (c & eHidden) caps += CAPS_FLAG_HIDDEN; // hidden if (c & eReachable) caps += CAPS_FLAG_REACHABLE; // reachable diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index a95119ed..9e074b9a 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -39,9 +39,9 @@ namespace data /* bandwidth flags */ const char CAPS_FLAG_LOW_BANDWIDTH1 = 'K'; /* < 12 KBps */ const char CAPS_FLAG_LOW_BANDWIDTH2 = 'L'; /* 12-48 KBps */ - const char CAPS_FLAG_HIGH_BANDWIDTH1 = 'M'; /* 48-64 KBps */ - const char CAPS_FLAG_HIGH_BANDWIDTH2 = 'N'; /* 64-128 KBps */ - const char CAPS_FLAG_HIGH_BANDWIDTH3 = 'O'; /* 128-256 KBps */ + const char CAPS_FLAG_LOW_BANDWIDTH3 = 'M'; /* 48-64 KBps */ + const char CAPS_FLAG_HIGH_BANDWIDTH1 = 'N'; /* 64-128 KBps */ + const char CAPS_FLAG_HIGH_BANDWIDTH2 = 'O'; /* 128-256 KBps */ const char CAPS_FLAG_EXTRA_BANDWIDTH1 = 'P'; /* 256-2048 KBps */ const char CAPS_FLAG_EXTRA_BANDWIDTH2 = 'X'; /* > 2048 KBps */ // bandwidth limits in kBps From 5d7c6fb0b3e89d672a631392f6b15f19156dee2c Mon Sep 17 00:00:00 2001 From: r4sas Date: Wed, 21 Feb 2024 22:31:20 +0300 Subject: [PATCH 0340/1171] [gha] msvc: copy openssl libraries to fix build Signed-off-by: r4sas --- .github/workflows/build-windows-msvc.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-windows-msvc.yml b/.github/workflows/build-windows-msvc.yml index 36a70d5a..ef0bc52c 100644 --- a/.github/workflows/build-windows-msvc.yml +++ b/.github/workflows/build-windows-msvc.yml @@ -45,6 +45,7 @@ jobs: run: | powershell -Command "(Invoke-WebRequest -UserAgent "Wget" -Uri https://slproweb.com/download/Win64OpenSSL-3_2_1.exe -OutFile Win64OpenSSL-3_2_1.exe)" ./Win64OpenSSL-3_2_1.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- + xcopy "c:\Program Files\OpenSSL-Win64\lib\VC\x64\MTd\*" "c:\Program Files\OpenSSL-Win64\lib\" - name: Configure working-directory: build From d25206abcefff1c914ee16adad8229197f14ca3b Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 21 Feb 2024 19:46:29 -0500 Subject: [PATCH 0341/1171] encrypted tunnel test messages --- libi2pd/Destination.cpp | 5 ++-- libi2pd/ECIESX25519AEADRatchetSession.cpp | 8 +++++- libi2pd/ECIESX25519AEADRatchetSession.h | 2 +- libi2pd/RouterContext.cpp | 7 +++++ libi2pd/TunnelPool.cpp | 33 ++++++++++++++++------- libi2pd/TunnelPool.h | 1 + 6 files changed, 43 insertions(+), 13 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index ef0d5db3..64e5d085 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -367,8 +367,9 @@ namespace client HandleDataMessage (payload, len); break; case eI2NPDeliveryStatus: - // we assume tunnel tests non-encrypted - HandleDeliveryStatusMessage (bufbe32toh (payload + DELIVERY_STATUS_MSGID_OFFSET)); + // try tunnel test first + if (!m_Pool || !m_Pool->ProcessDeliveryStatus (bufbe32toh (payload + DELIVERY_STATUS_MSGID_OFFSET), bufbe64toh (payload + DELIVERY_STATUS_TIMESTAMP_OFFSET))) + HandleDeliveryStatusMessage (bufbe32toh (payload + DELIVERY_STATUS_MSGID_OFFSET)); break; case eI2NPDatabaseStore: HandleDatabaseStoreMessage (payload, len); diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 3513b7ac..b4730d0e 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -1154,7 +1154,7 @@ namespace garlic return len; } - std::shared_ptr WrapECIESX25519Message (std::shared_ptr msg, const uint8_t * key, uint64_t tag) + std::shared_ptr WrapECIESX25519Message (std::shared_ptr msg, const uint8_t * key, uint64_t tag) { auto m = NewI2NPMessage ((msg ? msg->GetPayloadLength () : 0) + 128); m->Align (12); // in order to get buf aligned to 16 (12 + 4) @@ -1174,6 +1174,12 @@ namespace garlic htobe32buf (m->GetPayload (), offset); m->len += offset + 4; m->FillI2NPMessageHeader (eI2NPGarlic); + if (msg->onDrop) + { + // move onDrop to the wrapping I2NP messages + m->onDrop = msg->onDrop; + msg->onDrop = nullptr; + } return m; } diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index 030e2c45..e6deb2bc 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -247,7 +247,7 @@ namespace garlic i2p::crypto::NoiseSymmetricState m_CurrentNoiseState; }; - std::shared_ptr WrapECIESX25519Message (std::shared_ptr msg, const uint8_t * key, uint64_t tag); + std::shared_ptr WrapECIESX25519Message (std::shared_ptr msg, const uint8_t * key, uint64_t tag); std::shared_ptr WrapECIESX25519MessageForRouter (std::shared_ptr msg, const uint8_t * routerPublicKey); } } diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 864d2c61..2c1dc979 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -1152,6 +1152,13 @@ namespace i2p bool RouterContext::HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len, uint32_t msgID) { + if (typeID == eI2NPDeliveryStatus) + { + // try tunnel test + auto pool = GetTunnelPool (); + if (pool && pool->ProcessDeliveryStatus (bufbe32toh (payload + DELIVERY_STATUS_MSGID_OFFSET), bufbe64toh (payload + DELIVERY_STATUS_TIMESTAMP_OFFSET))) + return true; + } auto msg = CreateI2NPMessage (typeID, payload, len, msgID); if (!msg) return false; i2p::HandleI2NPMessage (msg); diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index c342d546..898a05bc 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -13,6 +13,7 @@ #include "NetDb.hpp" #include "Timestamp.h" #include "Garlic.h" +#include "ECIESX25519AEADRatchetSession.h" #include "Transports.h" #include "Log.h" #include "Tunnel.h" @@ -383,6 +384,7 @@ namespace tunnel newTests.push_back(std::make_pair (*it1, *it2)); ++it1; ++it2; } + bool encrypt = m_LocalDestination ? m_LocalDestination->SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) : false; for (auto& it: newTests) { uint32_t msgID; @@ -407,6 +409,14 @@ namespace tunnel s->m_OutboundTunnels.erase (outbound); } }; + if (encrypt) + { + // encrypt + uint8_t key[32]; RAND_bytes (key, 32); + uint64_t tag; RAND_bytes ((uint8_t *)&tag, 8); + m_LocalDestination->SubmitECIESx25519Key (key, tag); + msg = i2p::garlic::WrapECIESX25519Message (msg, key, tag); + } outbound->SendTunnelDataMsgTo (it.second->GetNextIdentHash (), it.second->GetNextTunnelID (), msg); } } @@ -436,6 +446,17 @@ namespace tunnel buf += 4; uint64_t timestamp = bufbe64toh (buf); + if (!ProcessDeliveryStatus (msgID, timestamp)) + { + if (m_LocalDestination) + m_LocalDestination->ProcessDeliveryStatusMessage (msg); + else + LogPrint (eLogWarning, "Tunnels: Local destination doesn't exist, dropped"); + } + } + + bool TunnelPool::ProcessDeliveryStatus (uint32_t msgID, uint64_t timestamp) + { decltype(m_Tests)::mapped_type test; bool found = false; { @@ -477,15 +498,9 @@ namespace tunnel test.second->AddLatencySample(latency); } } - else - { - if (m_LocalDestination) - m_LocalDestination->ProcessDeliveryStatusMessage (msg); - else - LogPrint (eLogWarning, "Tunnels: Local destination doesn't exist, dropped"); - } - } - + return found; + } + bool TunnelPool::IsExploratory () const { return i2p::tunnel::tunnels.GetExploratoryPool () == shared_from_this (); diff --git a/libi2pd/TunnelPool.h b/libi2pd/TunnelPool.h index d9f5966d..3e845c0e 100644 --- a/libi2pd/TunnelPool.h +++ b/libi2pd/TunnelPool.h @@ -85,6 +85,7 @@ namespace tunnel void ManageTunnels (uint64_t ts); void ProcessGarlicMessage (std::shared_ptr msg); void ProcessDeliveryStatus (std::shared_ptr msg); + bool ProcessDeliveryStatus (uint32_t msgID, uint64_t timestamp); bool IsExploratory () const; bool IsActive () const { return m_IsActive; }; From 7d73c304b5b77493079b9aa2c5f9e927c89e2907 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 22 Feb 2024 14:22:11 -0500 Subject: [PATCH 0342/1171] Extend transit tunnels limit to 4 bytes. Bump default value to 10K --- daemon/Daemon.cpp | 2 +- daemon/HTTPServer.cpp | 2 +- daemon/HTTPServer.h | 4 ++-- libi2pd/Config.cpp | 2 +- libi2pd/Tunnel.cpp | 2 +- libi2pd/Tunnel.h | 6 +++--- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/daemon/Daemon.cpp b/daemon/Daemon.cpp index 17d17f72..090792bf 100644 --- a/daemon/Daemon.cpp +++ b/daemon/Daemon.cpp @@ -179,7 +179,7 @@ namespace util bool transit; i2p::config::GetOption("notransit", transit); i2p::context.SetAcceptsTunnels (!transit); - uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels); + uint32_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels); if (isFloodfill && i2p::config::IsDefault ("limits.transittunnels")) transitTunnels *= 2; // double default number of transit tunnels for floodfill i2p::tunnel::tunnels.SetMaxNumTransitTunnels (transitTunnels); diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 862d6e4a..494a4e8e 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -772,7 +772,7 @@ namespace http { s << " info \r\n"; s << " debug
\r\n
\r\n"; - uint16_t maxTunnels = i2p::tunnel::tunnels.GetMaxNumTransitTunnels (); + uint32_t maxTunnels = i2p::tunnel::tunnels.GetMaxNumTransitTunnels (); s << "" << tr("Transit tunnels limit") << "
\r\n"; s << "
\r\n"; s << " \r\n"; diff --git a/daemon/HTTPServer.h b/daemon/HTTPServer.h index f41d925d..f751c5a8 100644 --- a/daemon/HTTPServer.h +++ b/daemon/HTTPServer.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2023, The PurpleI2P Project +* Copyright (c) 2013-2024, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -25,7 +25,7 @@ namespace http const size_t HTTP_CONNECTION_BUFFER_SIZE = 8192; const int TOKEN_EXPIRATION_TIMEOUT = 30; // in seconds const int COMMAND_REDIRECT_TIMEOUT = 5; // in seconds - const int TRANSIT_TUNNELS_LIMIT = 65535; + const int TRANSIT_TUNNELS_LIMIT = 1000000; class HTTPConnection: public std::enable_shared_from_this { diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index b2ad7a17..a6885178 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -77,7 +77,7 @@ namespace config { limits.add_options() ("limits.coresize", value()->default_value(0), "Maximum size of corefile in Kb (0 - use system limit)") ("limits.openfiles", value()->default_value(0), "Maximum number of open files (0 - use system default)") - ("limits.transittunnels", value()->default_value(5000), "Maximum active transit tunnels (default:5000)") + ("limits.transittunnels", value()->default_value(10000), "Maximum active transit tunnels (default:10000)") ("limits.zombies", value()->default_value(0), "Minimum percentage of successfully created tunnels under which tunnel cleanup is paused (default [%]: 0.00)") ("limits.ntcpsoft", value()->default_value(0), "Ignored") ("limits.ntcphard", value()->default_value(0), "Ignored") diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 3e10ef1b..246f68e4 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -986,7 +986,7 @@ namespace tunnel return m_OutboundTunnels.size(); } - void Tunnels::SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels) + void Tunnels::SetMaxNumTransitTunnels (uint32_t maxNumTransitTunnels) { if (maxNumTransitTunnels > 0 && m_MaxNumTransitTunnels != maxNumTransitTunnels) { diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index cc5b9461..4903c75b 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -238,8 +238,8 @@ namespace tunnel std::shared_ptr NewI2NPTunnelMessage (bool endpoint); - void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels); - uint16_t GetMaxNumTransitTunnels () const { return m_MaxNumTransitTunnels; }; + void SetMaxNumTransitTunnels (uint32_t maxNumTransitTunnels); + uint32_t GetMaxNumTransitTunnels () const { return m_MaxNumTransitTunnels; }; int GetCongestionLevel() const { return CONGESTION_LEVEL_FULL * m_TransitTunnels.size() / m_MaxNumTransitTunnels; } private: @@ -300,7 +300,7 @@ namespace tunnel i2p::util::Queue > m_Queue; i2p::util::MemoryPoolMt > m_I2NPTunnelEndpointMessagesMemoryPool; i2p::util::MemoryPoolMt > m_I2NPTunnelMessagesMemoryPool; - uint16_t m_MaxNumTransitTunnels; + uint32_t m_MaxNumTransitTunnels; // count of tunnels for total TCSR algorithm int m_TotalNumSuccesiveTunnelCreations, m_TotalNumFailedTunnelCreations; double m_TunnelCreationSuccessRate; From 5415598f60878cd4879f3ce265f5d791da9b7fe8 Mon Sep 17 00:00:00 2001 From: Vort Date: Thu, 22 Feb 2024 21:50:05 +0200 Subject: [PATCH 0343/1171] add zero check to congestion level calculations --- libi2pd/Tunnel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index 4903c75b..4d9ea830 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -240,7 +240,7 @@ namespace tunnel void SetMaxNumTransitTunnels (uint32_t maxNumTransitTunnels); uint32_t GetMaxNumTransitTunnels () const { return m_MaxNumTransitTunnels; }; - int GetCongestionLevel() const { return CONGESTION_LEVEL_FULL * m_TransitTunnels.size() / m_MaxNumTransitTunnels; } + int GetCongestionLevel() const { return m_MaxNumTransitTunnels ? CONGESTION_LEVEL_FULL * m_TransitTunnels.size() / m_MaxNumTransitTunnels : CONGESTION_LEVEL_FULL; } private: From fd4513ebb232b42c6246b1d226be0a05ef863b72 Mon Sep 17 00:00:00 2001 From: Vort Date: Thu, 22 Feb 2024 23:07:07 +0200 Subject: [PATCH 0344/1171] show bandwidth caps for hops --- daemon/HTTPServer.cpp | 25 +++++++++++++++++++++---- libi2pd/RouterInfo.cpp | 7 +++++++ libi2pd/RouterInfo.h | 2 ++ 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 494a4e8e..7a6656dc 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -417,6 +417,15 @@ namespace http { } } + static void ShowHop(std::stringstream& s, const i2p::data::IdentityEx& ident) + { + auto identHash = ident.GetIdentHash(); + auto router = i2p::data::netdb.FindRouter(identHash); + s << i2p::data::GetIdentHashAbbreviation(identHash); + if (router) + s << " " << router->GetBandwidthCap() << ""; + } + static void ShowLeaseSetDestination (std::stringstream& s, std::shared_ptr dest, uint32_t token) { s << "Base32:
\r\n\r\n
\r\n
\r\n" @@ -1434,7 +1432,6 @@ namespace http { "\r\n" "\r\n
\r\n"; delete[] signature; - delete[] sig; } else s << "" << tr("ERROR") << ": " << tr("Domain can't end with .b32.i2p") << "\r\n
\r\n
\r\n"; diff --git a/libi2pd/Base.cpp b/libi2pd/Base.cpp index bce303a2..bc9da4fb 100644 --- a/libi2pd/Base.cpp +++ b/libi2pd/Base.cpp @@ -58,15 +58,13 @@ namespace data /* * Reverse Substitution Table (built in run time) */ - static char iT64[256]; static int isFirstTime = 1; /* * Padding */ - - static char P64 = '='; + static constexpr char P64 = '='; /* * @@ -76,80 +74,6 @@ namespace data * Converts binary encoded data to BASE64 format. * */ - - size_t ByteStreamToBase64 ( // Number of bytes in the encoded buffer - const uint8_t * InBuffer, // Input buffer, binary data - size_t InCount, // Number of bytes in the input buffer - char * OutBuffer, // output buffer - size_t len // length of output buffer - ) - { - unsigned char * ps; - unsigned char * pd; - unsigned char acc_1; - unsigned char acc_2; - int i; - int n; - int m; - size_t outCount; - - ps = (unsigned char *)InBuffer; - n = InCount / 3; - m = InCount % 3; - if (!m) - outCount = 4 * n; - else - outCount = 4 * (n + 1); - - if (outCount > len) return 0; - - pd = (unsigned char *)OutBuffer; - for ( i = 0; i < n; i++ ) - { - acc_1 = *ps++; - acc_2 = (acc_1 << 4) & 0x30; - acc_1 >>= 2; // base64 digit #1 - *pd++ = T64[acc_1]; - acc_1 = *ps++; - acc_2 |= acc_1 >> 4; // base64 digit #2 - *pd++ = T64[acc_2]; - acc_1 &= 0x0f; - acc_1 <<= 2; - acc_2 = *ps++; - acc_1 |= acc_2 >> 6; // base64 digit #3 - *pd++ = T64[acc_1]; - acc_2 &= 0x3f; // base64 digit #4 - *pd++ = T64[acc_2]; - } - if ( m == 1 ) - { - acc_1 = *ps++; - acc_2 = (acc_1 << 4) & 0x3f; // base64 digit #2 - acc_1 >>= 2; // base64 digit #1 - *pd++ = T64[acc_1]; - *pd++ = T64[acc_2]; - *pd++ = P64; - *pd++ = P64; - - } - else if ( m == 2 ) - { - acc_1 = *ps++; - acc_2 = (acc_1 << 4) & 0x3f; - acc_1 >>= 2; // base64 digit #1 - *pd++ = T64[acc_1]; - acc_1 = *ps++; - acc_2 |= acc_1 >> 4; // base64 digit #2 - *pd++ = T64[acc_2]; - acc_1 &= 0x0f; - acc_1 <<= 2; // base64 digit #3 - *pd++ = T64[acc_1]; - *pd++ = P64; - } - - return outCount; - } - std::string ByteStreamToBase64 (// base64 encoded string const uint8_t * InBuffer, // Input buffer, binary data size_t InCount // Number of bytes in the input buffer diff --git a/libi2pd/Base.h b/libi2pd/Base.h index daf0f7ed..945dc8b3 100644 --- a/libi2pd/Base.h +++ b/libi2pd/Base.h @@ -18,7 +18,6 @@ namespace i2p { namespace data { - size_t ByteStreamToBase64 (const uint8_t * InBuffer, size_t InCount, char * OutBuffer, size_t len); // called from SAM TODO: rewrite std::string ByteStreamToBase64 (const uint8_t * InBuffer, size_t InCount); size_t Base64ToByteStream (std::string_view base64Str, uint8_t * OutBuffer, size_t len); From 609cd401bb80129d00add10c2808b8b932033eb7 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 17 Mar 2025 20:08:39 -0400 Subject: [PATCH 0987/1171] don't calculate key's base64 if not used --- libi2pd/NetDb.cpp | 5 +++-- libi2pd/NetDbRequests.cpp | 5 ++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 2bfaa8d8..e53738e5 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -951,12 +951,13 @@ namespace data LogPrint (eLogError, "NetDb: DatabaseLookup for zero ident. Ignored"); return; } - auto key = i2p::data::ByteStreamToBase64 (buf, 32); + std::string key; + if (CheckLogLevel (eLogInfo)) + key = i2p::data::ByteStreamToBase64 (buf, 32); IdentHash replyIdent(buf + 32); uint8_t flag = buf[64]; - LogPrint (eLogDebug, "NetDb: DatabaseLookup for ", key, " received flags=", (int)flag); uint8_t lookupType = flag & DATABASE_LOOKUP_TYPE_FLAGS_MASK; const uint8_t * excluded = buf + 65; diff --git a/libi2pd/NetDbRequests.cpp b/libi2pd/NetDbRequests.cpp index 0648d6bf..94633e10 100644 --- a/libi2pd/NetDbRequests.cpp +++ b/libi2pd/NetDbRequests.cpp @@ -360,9 +360,12 @@ namespace data void NetDbRequests::HandleDatabaseSearchReplyMsg (std::shared_ptr msg) { const uint8_t * buf = msg->GetPayload (); - auto key = i2p::data::ByteStreamToBase64 (buf, 32); + std::string key; size_t num = buf[32]; // num + if (CheckLogLevel (eLogInfo)) + key = i2p::data::ByteStreamToBase64 (buf, 32); LogPrint (eLogDebug, "NetDbReq: DatabaseSearchReply for ", key, " num=", num); + IdentHash ident (buf); bool isExploratory = false; auto dest = FindRequest (ident); From bd2b96627c7328ee23ed43a3d6c83c9f0b30d878 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 18 Mar 2025 19:23:13 -0400 Subject: [PATCH 0988/1171] calculate crypto key length from key type --- libi2pd/CryptoKey.cpp | 17 +++++++++++------ libi2pd/CryptoKey.h | 28 ++++++++++++++++++++++++++-- libi2pd/Destination.cpp | 34 +++++++++++++++++++++------------- libi2pd/Destination.h | 13 +++++++++---- libi2pd/Identity.cpp | 4 ++-- libi2pd/Identity.h | 6 +++++- libi2pd/LeaseSet.cpp | 3 ++- libi2pd/RouterContext.cpp | 1 + libi2pd/RouterInfo.cpp | 1 + libi2pd_client/I2CP.h | 1 + 10 files changed, 79 insertions(+), 29 deletions(-) diff --git a/libi2pd/CryptoKey.cpp b/libi2pd/CryptoKey.cpp index ad986129..7ea0fc2c 100644 --- a/libi2pd/CryptoKey.cpp +++ b/libi2pd/CryptoKey.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2021, The PurpleI2P Project +* Copyright (c) 2013-2025, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -174,12 +174,17 @@ namespace crypto return m_StaticKeys.Agree (epub, sharedSecret); } - void CreateECIESX25519AEADRatchetRandomKeys (uint8_t * priv, uint8_t * pub) + bool CreateECIESX25519AEADRatchetRandomKeys (uint8_t * priv, uint8_t * pub, i2p::data::CryptoKeyType type) { - X25519Keys k; - k.GenerateKeys (); - k.GetPrivateKey (priv); - memcpy (pub, k.GetPublicKey (), 32); + if (type == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) + { + X25519Keys k; + k.GenerateKeys (); + k.GetPrivateKey (priv); + memcpy (pub, k.GetPublicKey (), 32); + return true; + } + return false; } } } diff --git a/libi2pd/CryptoKey.h b/libi2pd/CryptoKey.h index a7d86d09..5fe72307 100644 --- a/libi2pd/CryptoKey.h +++ b/libi2pd/CryptoKey.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2021, The PurpleI2P Project +* Copyright (c) 2013-2025, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -11,6 +11,7 @@ #include #include "Crypto.h" +#include "Identity.h" namespace i2p { @@ -157,7 +158,30 @@ namespace crypto X25519Keys m_StaticKeys; }; - void CreateECIESX25519AEADRatchetRandomKeys (uint8_t * priv, uint8_t * pub); + bool CreateECIESX25519AEADRatchetRandomKeys (uint8_t * priv, uint8_t * pub, + i2p::data::CryptoKeyType type = i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); + + constexpr size_t GetCryptoPrivateKeyLen (i2p::data::CryptoKeyType type) + { + switch (type) + { + case i2p::data::CRYPTO_KEY_TYPE_ELGAMAL: return 256; + case i2p::data::CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC: return 32; + case i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD: return 32; + }; + return 0; + } + + constexpr size_t GetCryptoPublicKeyLen (i2p::data::CryptoKeyType type) + { + switch (type) + { + case i2p::data::CRYPTO_KEY_TYPE_ELGAMAL: return 256; + case i2p::data::CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC: return 32; + case i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD: return 32; + }; + return 0; + } } } diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index be079ee3..8ba29ca5 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1416,21 +1416,29 @@ namespace client std::string path = i2p::fs::DataDirPath("destinations", ident + "." + std::to_string (keys->keyType) + ".dat"); std::ifstream f(path, std::ifstream::binary); - if (f) { - f.read ((char *)keys->pub, 256); - f.read ((char *)keys->priv, 256); + if (f) + { + char pub[256], priv[256]; + f.read (pub, 256); + memcpy (keys->pub.data(), pub, keys->pub.size()); + f.read (priv, 256); + memcpy (keys->priv.data (), priv, keys->priv.size ()); return; } LogPrint (eLogInfo, "Destination: Creating new temporary keys of type for address ", ident, ".b32.i2p"); - memset (keys->priv, 0, 256); - memset (keys->pub, 0, 256); + memset (keys->priv.data (), 0, keys->priv.size ()); + memset (keys->pub.data (), 0, keys->pub.size ()); keys->GenerateKeys (); // TODO:: persist crypto key type std::ofstream f1 (path, std::ofstream::binary | std::ofstream::out); - if (f1) { - f1.write ((char *)keys->pub, 256); - f1.write ((char *)keys->priv, 256); + if (f1) + { + char pub[256], priv[256]; + memset (pub, 0, 256); memcpy (pub, keys->pub.data (), keys->pub.size ()); + f1.write (pub, 256); + memset (priv, 0, 256); memcpy (priv, keys->priv.data (), keys->priv.size ()); + f1.write (priv, 256); return; } LogPrint(eLogCritical, "Destinations: Can't save keys to ", path); @@ -1443,7 +1451,7 @@ namespace client { if (m_StandardEncryptionKey) { - leaseSet = std::make_shared (GetIdentity (), m_StandardEncryptionKey->pub, tunnels); + leaseSet = std::make_shared (GetIdentity (), m_StandardEncryptionKey->pub.data (), tunnels); // sign Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ()); } @@ -1455,9 +1463,9 @@ namespace client // standard LS2 (type 3) first i2p::data::LocalLeaseSet2::KeySections keySections; if (m_ECIESx25519EncryptionKey) - keySections.push_back ({m_ECIESx25519EncryptionKey->keyType, 32, m_ECIESx25519EncryptionKey->pub} ); + keySections.push_back ({m_ECIESx25519EncryptionKey->keyType, (uint16_t)m_ECIESx25519EncryptionKey->pub.size (), m_ECIESx25519EncryptionKey->pub.data ()} ); if (m_StandardEncryptionKey) - keySections.push_back ({m_StandardEncryptionKey->keyType, (uint16_t)m_StandardEncryptionKey->decryptor->GetPublicKeyLen (), m_StandardEncryptionKey->pub} ); + keySections.push_back ({m_StandardEncryptionKey->keyType, (uint16_t)m_StandardEncryptionKey->decryptor->GetPublicKeyLen (), m_StandardEncryptionKey->pub.data ()} ); auto publishedTimestamp = i2p::util::GetSecondsSinceEpoch (); if (publishedTimestamp <= m_LastPublishedTimestamp) @@ -1501,8 +1509,8 @@ namespace client const uint8_t * ClientDestination::GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const { if (keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) - return m_ECIESx25519EncryptionKey ? m_ECIESx25519EncryptionKey->pub : nullptr; - return m_StandardEncryptionKey ? m_StandardEncryptionKey->pub : nullptr; + return m_ECIESx25519EncryptionKey ? m_ECIESx25519EncryptionKey->pub.data () : nullptr; + return m_StandardEncryptionKey ? m_StandardEncryptionKey->pub.data () : nullptr; } void ClientDestination::ReadAuthKey (const std::string& group, const std::map * params) diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 4278f1fd..7684c0f6 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -22,6 +22,7 @@ #include "Identity.h" #include "TunnelPool.h" #include "Crypto.h" +#include "CryptoKey.h" #include "LeaseSet.h" #include "Garlic.h" #include "NetDb.hpp" @@ -231,13 +232,17 @@ namespace client { struct EncryptionKey { - uint8_t pub[256], priv[256]; + std::vector pub, priv; i2p::data::CryptoKeyType keyType; std::shared_ptr decryptor; - EncryptionKey (i2p::data::CryptoKeyType t):keyType(t) { memset (pub, 0, 256); memset (priv, 0, 256); }; - void GenerateKeys () { i2p::data::PrivateKeys::GenerateCryptoKeyPair (keyType, priv, pub); }; - void CreateDecryptor () { decryptor = i2p::data::PrivateKeys::CreateDecryptor (keyType, priv); }; + EncryptionKey (i2p::data::CryptoKeyType t): keyType(t) + { + pub.resize (i2p::crypto::GetCryptoPublicKeyLen (keyType)); + priv.resize (i2p::crypto::GetCryptoPrivateKeyLen (keyType)); + } + void GenerateKeys () { i2p::data::PrivateKeys::GenerateCryptoKeyPair (keyType, priv.data (), pub.data ()); }; + void CreateDecryptor () { decryptor = i2p::data::PrivateKeys::CreateDecryptor (keyType, priv.data ()); }; }; public: diff --git a/libi2pd/Identity.cpp b/libi2pd/Identity.cpp index e98e5fbc..b5f86f11 100644 --- a/libi2pd/Identity.cpp +++ b/libi2pd/Identity.cpp @@ -10,6 +10,7 @@ #include "I2PEndian.h" #include "Log.h" #include "Timestamp.h" +#include "CryptoKey.h" #include "Identity.h" namespace i2p @@ -658,8 +659,7 @@ namespace data size_t PrivateKeys::GetPrivateKeyLen () const { - // private key length always 256, but type 4 - return (m_Public->GetCryptoKeyType () == CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) ? 32 : 256; + return i2p::crypto::GetCryptoPrivateKeyLen (m_Public->GetCryptoKeyType ()); } uint8_t * PrivateKeys::GetPadding() diff --git a/libi2pd/Identity.h b/libi2pd/Identity.h index e08ac802..1891c7a2 100644 --- a/libi2pd/Identity.h +++ b/libi2pd/Identity.h @@ -17,10 +17,14 @@ #include #include "Base.h" #include "Signature.h" -#include "CryptoKey.h" namespace i2p { +namespace crypto +{ + class CryptoKeyEncryptor; + class CryptoKeyDecryptor; +} namespace data { typedef Tag<32> IdentHash; diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index ee1964fc..3068b35d 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2024, The PurpleI2P Project +* Copyright (c) 2013-2025, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -14,6 +14,7 @@ #include "Timestamp.h" #include "NetDb.hpp" #include "Tunnel.h" +#include "CryptoKey.h" #include "LeaseSet.h" namespace i2p diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 6819a185..af90a46a 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -22,6 +22,7 @@ #include "ECIESX25519AEADRatchetSession.h" #include "Transports.h" #include "Tunnel.h" +#include "CryptoKey.h" #include "RouterContext.h" namespace i2p diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 41f71e14..4af32f57 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -25,6 +25,7 @@ #include "Transports.h" #include "NetDb.hpp" #include "RouterContext.h" +#include "CryptoKey.h" #include "RouterInfo.h" namespace i2p diff --git a/libi2pd_client/I2CP.h b/libi2pd_client/I2CP.h index d3949eaa..597a4878 100644 --- a/libi2pd_client/I2CP.h +++ b/libi2pd_client/I2CP.h @@ -21,6 +21,7 @@ #include "util.h" #include "Destination.h" #include "Streaming.h" +#include "CryptoKey.h" namespace i2p { From 46f530bfcd6b32ecb6557870ec5922a230503903 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 18 Mar 2025 21:15:37 -0400 Subject: [PATCH 0989/1171] persist temporary keys of actual size --- libi2pd/Destination.cpp | 49 +++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 8ba29ca5..bb77b804 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1415,33 +1415,50 @@ namespace client std::string ident = GetIdentHash().ToBase32(); std::string path = i2p::fs::DataDirPath("destinations", ident + "." + std::to_string (keys->keyType) + ".dat"); std::ifstream f(path, std::ifstream::binary); - if (f) { - char pub[256], priv[256]; - f.read (pub, 256); - memcpy (keys->pub.data(), pub, keys->pub.size()); - f.read (priv, 256); - memcpy (keys->priv.data (), priv, keys->priv.size ()); - return; + size_t len = 0; + if (keys->keyType == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL) + len = 512; + else if (keys->keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) + { + f.seekg (0, std::ios::end); + len = f.tellg(); + f.seekg (0, std::ios::beg); + } + + if (len == 512) + { + char pub[256], priv[256]; + f.read (pub, 256); + memcpy (keys->pub.data(), pub, keys->pub.size()); + f.read (priv, 256); + memcpy (keys->priv.data (), priv, keys->priv.size ()); + } + else + { + f.read ((char *)keys->pub.data(), keys->pub.size()); + f.read ((char *)keys->priv.data(), keys->priv.size()); + } + if (f) + return; + else + LogPrint(eLogWarning, "Destination: Can't read keys from ", path); } - LogPrint (eLogInfo, "Destination: Creating new temporary keys of type for address ", ident, ".b32.i2p"); + LogPrint (eLogInfo, "Destination: Creating new temporary keys of type ", keys->keyType, " for address ", ident, ".b32.i2p"); memset (keys->priv.data (), 0, keys->priv.size ()); memset (keys->pub.data (), 0, keys->pub.size ()); keys->GenerateKeys (); - // TODO:: persist crypto key type + std::ofstream f1 (path, std::ofstream::binary | std::ofstream::out); if (f1) { - char pub[256], priv[256]; - memset (pub, 0, 256); memcpy (pub, keys->pub.data (), keys->pub.size ()); - f1.write (pub, 256); - memset (priv, 0, 256); memcpy (priv, keys->priv.data (), keys->priv.size ()); - f1.write (priv, 256); - return; + f1.write ((char *)keys->pub.data (), keys->pub.size ()); + f1.write ((char *)keys->priv.data (), keys->priv.size ()); } - LogPrint(eLogCritical, "Destinations: Can't save keys to ", path); + if (!f1) + LogPrint(eLogError, "Destination: Can't save keys to ", path); } void ClientDestination::CreateNewLeaseSet (const std::vector >& tunnels) From 9ce515ff793271363b3a33fcd333154eb75455cd Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 19 Mar 2025 08:40:10 -0400 Subject: [PATCH 0990/1171] MLKEM512_X25519 crypto key added --- libi2pd/CryptoKey.cpp | 15 +++++---------- libi2pd/CryptoKey.h | 5 +++-- libi2pd/Destination.cpp | 8 ++++---- libi2pd/Identity.h | 1 + 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/libi2pd/CryptoKey.cpp b/libi2pd/CryptoKey.cpp index 7ea0fc2c..bac5d740 100644 --- a/libi2pd/CryptoKey.cpp +++ b/libi2pd/CryptoKey.cpp @@ -174,17 +174,12 @@ namespace crypto return m_StaticKeys.Agree (epub, sharedSecret); } - bool CreateECIESX25519AEADRatchetRandomKeys (uint8_t * priv, uint8_t * pub, i2p::data::CryptoKeyType type) + void CreateECIESX25519AEADRatchetRandomKeys (uint8_t * priv, uint8_t * pub) { - if (type == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) - { - X25519Keys k; - k.GenerateKeys (); - k.GetPrivateKey (priv); - memcpy (pub, k.GetPublicKey (), 32); - return true; - } - return false; + X25519Keys k; + k.GenerateKeys (); + k.GetPrivateKey (priv); + memcpy (pub, k.GetPublicKey (), 32); } } } diff --git a/libi2pd/CryptoKey.h b/libi2pd/CryptoKey.h index 5fe72307..14ef4fa8 100644 --- a/libi2pd/CryptoKey.h +++ b/libi2pd/CryptoKey.h @@ -158,8 +158,7 @@ namespace crypto X25519Keys m_StaticKeys; }; - bool CreateECIESX25519AEADRatchetRandomKeys (uint8_t * priv, uint8_t * pub, - i2p::data::CryptoKeyType type = i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); + void CreateECIESX25519AEADRatchetRandomKeys (uint8_t * priv, uint8_t * pub); // including hybrid constexpr size_t GetCryptoPrivateKeyLen (i2p::data::CryptoKeyType type) { @@ -168,6 +167,7 @@ namespace crypto case i2p::data::CRYPTO_KEY_TYPE_ELGAMAL: return 256; case i2p::data::CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC: return 32; case i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD: return 32; + case i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD: return 32; }; return 0; } @@ -179,6 +179,7 @@ namespace crypto case i2p::data::CRYPTO_KEY_TYPE_ELGAMAL: return 256; case i2p::data::CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC: return 32; case i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD: return 32; + case i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD: return 32; }; return 0; } diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index bb77b804..4621e147 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1520,14 +1520,14 @@ namespace client bool ClientDestination::SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const { - return keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD ? (bool)m_ECIESx25519EncryptionKey : (bool)m_StandardEncryptionKey; + return keyType == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL ? (bool)m_StandardEncryptionKey : (bool)m_ECIESx25519EncryptionKey; } const uint8_t * ClientDestination::GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const { - if (keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) - return m_ECIESx25519EncryptionKey ? m_ECIESx25519EncryptionKey->pub.data () : nullptr; - return m_StandardEncryptionKey ? m_StandardEncryptionKey->pub.data () : nullptr; + if (keyType == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL) + return m_StandardEncryptionKey ? m_StandardEncryptionKey->pub.data () : nullptr; + return m_ECIESx25519EncryptionKey ? m_ECIESx25519EncryptionKey->pub.data () : nullptr; } void ClientDestination::ReadAuthKey (const std::string& group, const std::map * params) diff --git a/libi2pd/Identity.h b/libi2pd/Identity.h index 1891c7a2..576ede0d 100644 --- a/libi2pd/Identity.h +++ b/libi2pd/Identity.h @@ -70,6 +70,7 @@ namespace data const uint16_t CRYPTO_KEY_TYPE_ELGAMAL = 0; const uint16_t CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC = 1; const uint16_t CRYPTO_KEY_TYPE_ECIES_X25519_AEAD = 4; + const uint16_t CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD = 5; const uint16_t SIGNING_KEY_TYPE_DSA_SHA1 = 0; const uint16_t SIGNING_KEY_TYPE_ECDSA_SHA256_P256 = 1; From b2fd30d042588349f8587e38f9eeb6e5d309162e Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 19 Mar 2025 15:22:09 -0400 Subject: [PATCH 0991/1171] map of encryption keys --- libi2pd/Destination.cpp | 60 ++++++++++++++++++++++++----------------- libi2pd/Destination.h | 5 ++-- 2 files changed, 37 insertions(+), 28 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 4621e147..414ef61c 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1046,20 +1046,15 @@ namespace client for (auto& it: encryptionKeyTypes) { - auto encryptionKey = new EncryptionKey (it); + auto encryptionKey = std::make_shared (it); if (IsPublic ()) PersistTemporaryKeys (encryptionKey); else encryptionKey->GenerateKeys (); encryptionKey->CreateDecryptor (); - if (it == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) - { - m_ECIESx25519EncryptionKey.reset (encryptionKey); - if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET) - SetLeaseSetType (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2); // Rathets must use LeaseSet2 - } - else - m_StandardEncryptionKey.reset (encryptionKey); + if (it > i2p::data::CRYPTO_KEY_TYPE_ELGAMAL && GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET) + SetLeaseSetType (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2); // Only DSA can use LeaseSet1 + m_EncryptionKeys.emplace (it, encryptionKey); } if (IsPublic ()) @@ -1409,7 +1404,7 @@ namespace client return ret; } - void ClientDestination::PersistTemporaryKeys (EncryptionKey * keys) + void ClientDestination::PersistTemporaryKeys (std::shared_ptr keys) { if (!keys) return; std::string ident = GetIdentHash().ToBase32(); @@ -1466,9 +1461,10 @@ namespace client std::shared_ptr leaseSet; if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET) { - if (m_StandardEncryptionKey) + auto it = m_EncryptionKeys.find (i2p::data::CRYPTO_KEY_TYPE_ELGAMAL); + if (it != m_EncryptionKeys.end ()) { - leaseSet = std::make_shared (GetIdentity (), m_StandardEncryptionKey->pub.data (), tunnels); + leaseSet = std::make_shared (GetIdentity (), it->second->pub.data (), tunnels); // sign Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ()); } @@ -1479,10 +1475,8 @@ namespace client { // standard LS2 (type 3) first i2p::data::LocalLeaseSet2::KeySections keySections; - if (m_ECIESx25519EncryptionKey) - keySections.push_back ({m_ECIESx25519EncryptionKey->keyType, (uint16_t)m_ECIESx25519EncryptionKey->pub.size (), m_ECIESx25519EncryptionKey->pub.data ()} ); - if (m_StandardEncryptionKey) - keySections.push_back ({m_StandardEncryptionKey->keyType, (uint16_t)m_StandardEncryptionKey->decryptor->GetPublicKeyLen (), m_StandardEncryptionKey->pub.data ()} ); + for (const auto& it: m_EncryptionKeys) + keySections.push_back ({it.first, (uint16_t)it.second->pub.size (), it.second->pub.data ()} ); auto publishedTimestamp = i2p::util::GetSecondsSinceEpoch (); if (publishedTimestamp <= m_LastPublishedTimestamp) @@ -1508,11 +1502,22 @@ namespace client bool ClientDestination::Decrypt (const uint8_t * encrypted, uint8_t * data, i2p::data::CryptoKeyType preferredCrypto) const { - if (preferredCrypto == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) - if (m_ECIESx25519EncryptionKey && m_ECIESx25519EncryptionKey->decryptor) - return m_ECIESx25519EncryptionKey->decryptor->Decrypt (encrypted, data); - if (m_StandardEncryptionKey && m_StandardEncryptionKey->decryptor) - return m_StandardEncryptionKey->decryptor->Decrypt (encrypted, data); + std::shared_ptr encryptionKey; + if (!m_EncryptionKeys.empty ()) + { + if (m_EncryptionKeys.rbegin ()->first == preferredCrypto) + encryptionKey = m_EncryptionKeys.rbegin ()->second; + else + { + auto it = m_EncryptionKeys.find (preferredCrypto); + if (it != m_EncryptionKeys.end ()) + encryptionKey = it->second; + } + if (!encryptionKey) + encryptionKey = m_EncryptionKeys.rbegin ()->second; + } + if (encryptionKey) + return encryptionKey->decryptor->Decrypt (encrypted, data); else LogPrint (eLogError, "Destinations: Decryptor is not set"); return false; @@ -1520,14 +1525,19 @@ namespace client bool ClientDestination::SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const { - return keyType == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL ? (bool)m_StandardEncryptionKey : (bool)m_ECIESx25519EncryptionKey; +#if __cplusplus >= 202002L // C++20 + return m_EncryptionKeys.contains (keyType); +#else + return m_EncryptionKeys.count (keyType) > 0; +#endif } const uint8_t * ClientDestination::GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const { - if (keyType == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL) - return m_StandardEncryptionKey ? m_StandardEncryptionKey->pub.data () : nullptr; - return m_ECIESx25519EncryptionKey ? m_ECIESx25519EncryptionKey->pub.data () : nullptr; + auto it = m_EncryptionKeys.find (keyType); + if (it != m_EncryptionKeys.end ()) + return it->second->pub.data (); + return nullptr; } void ClientDestination::ReadAuthKey (const std::string& group, const std::map * params) diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 7684c0f6..df87256d 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -306,7 +306,7 @@ namespace client std::shared_ptr GetSharedFromThis () { return std::static_pointer_cast(shared_from_this ()); } - void PersistTemporaryKeys (EncryptionKey * keys); + void PersistTemporaryKeys (std::shared_ptr keys); void ReadAuthKey (const std::string& group, const std::map * params); template @@ -315,8 +315,7 @@ namespace client private: i2p::data::PrivateKeys m_Keys; - std::unique_ptr m_StandardEncryptionKey; - std::unique_ptr m_ECIESx25519EncryptionKey; + std::map > m_EncryptionKeys; // last is most preferable int m_StreamingAckDelay,m_StreamingOutboundSpeed, m_StreamingInboundSpeed, m_StreamingMaxConcurrentStreams; bool m_IsStreamingAnswerPings; From 9684c86a6939667a96fdb7abcdd4cfd31df74930 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 19 Mar 2025 20:49:52 -0400 Subject: [PATCH 0992/1171] select key with max key type if no preferred. Changed default preferred type to 4 --- libi2pd/LeaseSet.cpp | 18 +++++++++++------- libi2pd/LeaseSet.h | 6 +++--- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index 3068b35d..e4edcb31 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -400,6 +400,7 @@ namespace data offset += propertiesLen; // skip for now. TODO: implement properties // key sections CryptoKeyType preferredKeyType = m_EncryptionType; + m_EncryptionType = 0; bool preferredKeyFound = false; if (offset + 1 > len) return 0; int numKeySections = buf[offset]; offset++; @@ -411,14 +412,17 @@ namespace data if (offset + encryptionKeyLen > len) return 0; if (IsStoreLeases () && !preferredKeyFound) // create encryptor with leases only { - // we pick first valid key if preferred not found - auto encryptor = i2p::data::IdentityEx::CreateEncryptor (keyType, buf + offset); - if (encryptor && (!m_Encryptor || keyType == preferredKeyType)) + // we pick max key type if preferred not found + if (keyType == preferredKeyType || !m_Encryptor || keyType > m_EncryptionType) { - m_Encryptor = encryptor; // TODO: atomic - m_EncryptionType = keyType; - if (keyType == preferredKeyType) preferredKeyFound = true; - } + auto encryptor = i2p::data::IdentityEx::CreateEncryptor (keyType, buf + offset); + if (encryptor) + { + m_Encryptor = encryptor; // TODO: atomic + m_EncryptionType = keyType; + if (keyType == preferredKeyType) preferredKeyFound = true; + } + } } offset += encryptionKeyLen; } diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index a365ae77..1a89229a 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2024, The PurpleI2P Project +* Copyright (c) 2013-2025, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -150,8 +150,8 @@ namespace data public: LeaseSet2 (uint8_t storeType): LeaseSet (true), m_StoreType (storeType) {}; // for update - LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases = true, CryptoKeyType preferredCrypto = CRYPTO_KEY_TYPE_ELGAMAL); - LeaseSet2 (const uint8_t * buf, size_t len, std::shared_ptr key, const uint8_t * secret = nullptr, CryptoKeyType preferredCrypto = CRYPTO_KEY_TYPE_ELGAMAL); // store type 5, called from local netdb only + LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases = true, CryptoKeyType preferredCrypto = CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); + LeaseSet2 (const uint8_t * buf, size_t len, std::shared_ptr key, const uint8_t * secret = nullptr, CryptoKeyType preferredCrypto = CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); // store type 5, called from local netdb only uint8_t GetStoreType () const { return m_StoreType; }; uint32_t GetPublishedTimestamp () const { return m_PublishedTimestamp; }; bool IsPublic () const { return m_IsPublic; }; From 9769ab0a465a6a1dca8a73995d3f169f1a85019c Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 19 Mar 2025 21:56:59 -0400 Subject: [PATCH 0993/1171] changed ML-DSA-44 code --- libi2pd/Identity.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Identity.h b/libi2pd/Identity.h index 576ede0d..ee736441 100644 --- a/libi2pd/Identity.h +++ b/libi2pd/Identity.h @@ -84,7 +84,7 @@ namespace data const uint16_t SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256 = 9; const uint16_t SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512 = 10; // approved by FSB const uint16_t SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519 = 11; // for LeaseSet2 only - const uint16_t SIGNING_KEY_TYPE_MLDSA44 = 15; + const uint16_t SIGNING_KEY_TYPE_MLDSA44 = 12; typedef uint16_t SigningKeyType; typedef uint16_t CryptoKeyType; From 935c055a35d92dcd045e9d2fd29e2913f0458c3e Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 19 Mar 2025 22:00:08 -0400 Subject: [PATCH 0994/1171] encryptor/decryptor/keygen for ECIES_MLKEM512_X25519_AEAD --- libi2pd/Identity.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libi2pd/Identity.cpp b/libi2pd/Identity.cpp index b5f86f11..3b2f5b97 100644 --- a/libi2pd/Identity.cpp +++ b/libi2pd/Identity.cpp @@ -419,6 +419,7 @@ namespace data return std::make_shared(key); break; case CRYPTO_KEY_TYPE_ECIES_X25519_AEAD: + case CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD: return std::make_shared(key); break; case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC: @@ -685,6 +686,7 @@ namespace data return std::make_shared(key); break; case CRYPTO_KEY_TYPE_ECIES_X25519_AEAD: + case CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD: return std::make_shared(key); break; case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC: @@ -772,6 +774,7 @@ namespace data i2p::crypto::CreateECIESP256RandomKeys (priv, pub); break; case CRYPTO_KEY_TYPE_ECIES_X25519_AEAD: + case CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD: i2p::crypto::CreateECIESX25519AEADRatchetRandomKeys (priv, pub); break; default: From 9fdbb14075c57e6c9baa5e0df0869d011448c90e Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 20 Mar 2025 18:56:10 -0400 Subject: [PATCH 0995/1171] calculate preferred crypto based i2cp.leaseSetEncType --- libi2pd/Destination.cpp | 14 +++++--------- libi2pd/Destination.h | 21 ++++++++++++--------- libi2pd_client/I2CP.cpp | 8 +++++++- libi2pd_client/I2CP.h | 18 ++++++++++-------- 4 files changed, 34 insertions(+), 27 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 414ef61c..d7f311cf 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -994,17 +994,10 @@ namespace client } } - i2p::data::CryptoKeyType LeaseSetDestination::GetPreferredCryptoType () const - { - if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) - return i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD; - return i2p::data::CRYPTO_KEY_TYPE_ELGAMAL; - } - ClientDestination::ClientDestination (boost::asio::io_context& service, const i2p::data::PrivateKeys& keys, bool isPublic, const std::map * params): LeaseSetDestination (service, isPublic, params), - m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY), + m_Keys (keys), m_PreferredCryptoType (0), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY), m_StreamingOutboundSpeed (DEFAULT_MAX_OUTBOUND_SPEED), m_StreamingInboundSpeed (DEFAULT_MAX_INBOUND_SPEED), m_StreamingMaxConcurrentStreams (DEFAULT_MAX_CONCURRENT_STREAMS), @@ -1029,7 +1022,10 @@ namespace client { try { - encryptionKeyTypes.insert (std::stoi(it1)); + i2p::data::CryptoKeyType preferredCryptoType = std::stoi(it1); + if (!m_PreferredCryptoType && preferredCryptoType) + m_PreferredCryptoType = preferredCryptoType; // first non-zero in the list + encryptionKeyTypes.insert (preferredCryptoType); } catch (std::exception& ex) { diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index df87256d..d844c085 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -171,10 +171,11 @@ namespace client void SetLeaseSetType (int leaseSetType) { m_LeaseSetType = leaseSetType; }; int GetAuthType () const { return m_AuthType; }; virtual void CleanupDestination () {}; // additional clean up in derived classes + virtual i2p::data::CryptoKeyType GetPreferredCryptoType () const = 0; // I2CP virtual void HandleDataMessage (const uint8_t * buf, size_t len) = 0; virtual void CreateNewLeaseSet (const std::vector >& tunnels) = 0; - + private: void UpdateLeaseSet (); @@ -193,7 +194,6 @@ namespace client void HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest); void HandleCleanupTimer (const boost::system::error_code& ecode); void CleanupRemoteLeaseSets (); - i2p::data::CryptoKeyType GetPreferredCryptoType () const; private: @@ -289,18 +289,20 @@ namespace client i2p::datagram::DatagramDestination * CreateDatagramDestination (bool gzip = true); // implements LocalDestination - bool Decrypt (const uint8_t * encrypted, uint8_t * data, i2p::data::CryptoKeyType preferredCrypto) const; - std::shared_ptr GetIdentity () const { return m_Keys.GetPublic (); }; - bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const; - const uint8_t * GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const; + bool Decrypt (const uint8_t * encrypted, uint8_t * data, i2p::data::CryptoKeyType preferredCrypto) const override; + std::shared_ptr GetIdentity () const override { return m_Keys.GetPublic (); }; + bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const override; + const uint8_t * GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const override; protected: - void CleanupDestination (); + // LeaseSetDestination + void CleanupDestination () override; + i2p::data::CryptoKeyType GetPreferredCryptoType () const override { return m_PreferredCryptoType; } // I2CP void HandleDataMessage (const uint8_t * buf, size_t len); void CreateNewLeaseSet (const std::vector >& tunnels); - + private: std::shared_ptr GetSharedFromThis () { @@ -316,7 +318,8 @@ namespace client i2p::data::PrivateKeys m_Keys; std::map > m_EncryptionKeys; // last is most preferable - + i2p::data::CryptoKeyType m_PreferredCryptoType; + int m_StreamingAckDelay,m_StreamingOutboundSpeed, m_StreamingInboundSpeed, m_StreamingMaxConcurrentStreams; bool m_IsStreamingAnswerPings; std::shared_ptr m_StreamingDestination; // default diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index df93082b..09fcee71 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -79,7 +79,13 @@ namespace client return keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD ? (bool)m_ECIESx25519Decryptor : m_EncryptionKeyType == keyType; } - + i2p::data::CryptoKeyType I2CPDestination::GetPreferredCryptoType () const + { + if (m_ECIESx25519Decryptor) + return i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD; + return i2p::data::CRYPTO_KEY_TYPE_ELGAMAL; + } + void I2CPDestination::HandleDataMessage (const uint8_t * buf, size_t len) { uint32_t length = bufbe32toh (buf); diff --git a/libi2pd_client/I2CP.h b/libi2pd_client/I2CP.h index 597a4878..936f3c49 100644 --- a/libi2pd_client/I2CP.h +++ b/libi2pd_client/I2CP.h @@ -101,18 +101,20 @@ namespace client bool SendMsg (const uint8_t * payload, size_t len, std::shared_ptr remoteSession, uint32_t nonce); // implements LocalDestination - bool Decrypt (const uint8_t * encrypted, uint8_t * data, i2p::data::CryptoKeyType preferredCrypto) const; - bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const; - const uint8_t * GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const; // for 4 only - std::shared_ptr GetIdentity () const { return m_Identity; }; + bool Decrypt (const uint8_t * encrypted, uint8_t * data, i2p::data::CryptoKeyType preferredCrypto) const override; + bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const override; + const uint8_t * GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const override; // for 4 only + std::shared_ptr GetIdentity () const override { return m_Identity; }; protected: - void CleanupDestination (); + // LeaseSetDestination + void CleanupDestination () override; + i2p::data::CryptoKeyType GetPreferredCryptoType () const override; // I2CP - void HandleDataMessage (const uint8_t * buf, size_t len); - void CreateNewLeaseSet (const std::vector >& tunnels); - + void HandleDataMessage (const uint8_t * buf, size_t len) override; + void CreateNewLeaseSet (const std::vector >& tunnels) override; + private: std::shared_ptr GetSharedFromThis () From 7b98dd84d880a4ef8286d442f233fdab74c14ec2 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 21 Mar 2025 19:40:02 -0400 Subject: [PATCH 0996/1171] pass type with static key --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 4 +- libi2pd/ECIESX25519AEADRatchetSession.h | 9 +++-- libi2pd/Garlic.cpp | 48 ++++++++++++----------- 3 files changed, 34 insertions(+), 27 deletions(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index bdf5f7f7..7a799d29 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -167,7 +167,7 @@ namespace garlic } ECIESX25519AEADRatchetSession::ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSetNS): - GarlicRoutingSession (owner, true) + GarlicRoutingSession (owner, true), m_RemoteStaticKeyType (0) { if (!attachLeaseSetNS) SetLeaseSetUpdateStatus (eLeaseSetUpToDate); RAND_bytes (m_PaddingSizes, 32); m_NextPaddingSize = 0; @@ -291,7 +291,7 @@ namespace garlic if (isStatic) { // static key, fs is apk - memcpy (m_RemoteStaticKey, fs, 32); + SetRemoteStaticKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD, fs); // TODO: actual key type if (!GetOwner ()->Decrypt (fs, sharedSecret, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) // x25519(bsk, apk) { LogPrint (eLogWarning, "Garlic: Incorrect Alice static key"); diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index d17565a8..5614e6cb 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -168,14 +168,16 @@ namespace garlic std::shared_ptr WrapOneTimeMessage (std::shared_ptr msg); const uint8_t * GetRemoteStaticKey () const { return m_RemoteStaticKey; } - void SetRemoteStaticKey (const uint8_t * key) { memcpy (m_RemoteStaticKey, key, 32); } - + void SetRemoteStaticKey (i2p::data::CryptoKeyType keyType, const uint8_t * key) + { + m_RemoteStaticKeyType = keyType; + memcpy (m_RemoteStaticKey, key, 32); + } void Terminate () { m_IsTerminated = true; } void SetDestination (const i2p::data::IdentHash& dest) { if (!m_Destination) m_Destination.reset (new i2p::data::IdentHash (dest)); } - bool CheckExpired (uint64_t ts); // true is expired bool CanBeRestarted (uint64_t ts) const { return ts > m_SessionCreatedTimestamp + ECIESX25519_RESTART_TIMEOUT; } bool IsInactive (uint64_t ts) const { return ts > m_LastActivityTimestamp + ECIESX25519_INACTIVITY_TIMEOUT && CanBeRestarted (ts); } @@ -219,6 +221,7 @@ namespace garlic private: + i2p::data::CryptoKeyType m_RemoteStaticKeyType; uint8_t m_RemoteStaticKey[32]; uint8_t m_Aepk[32]; // Alice's ephemeral keys, for incoming only uint8_t m_NSREncodedKey[32], m_NSRH[32], m_NSRKey[32]; // new session reply, for incoming only diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 89737db0..0098bdcd 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2024, The PurpleI2P Project +* Copyright (c) 2013-2025, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -747,31 +747,35 @@ namespace garlic std::shared_ptr destination, bool attachLeaseSet, bool requestNewIfNotFound) { - if (destination->GetEncryptionType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD && - SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) + if (destination->GetEncryptionType () >= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) { - ECIESX25519AEADRatchetSessionPtr session; - uint8_t staticKey[32]; - destination->Encrypt (nullptr, staticKey); // we are supposed to get static key - auto it = m_ECIESx25519Sessions.find (staticKey); - if (it != m_ECIESx25519Sessions.end ()) - { - session = it->second; - if (session->IsInactive (i2p::util::GetSecondsSinceEpoch ())) + if (SupportsEncryptionType (destination->GetEncryptionType ())) + { + ECIESX25519AEADRatchetSessionPtr session; + uint8_t staticKey[32]; + destination->Encrypt (nullptr, staticKey); // we are supposed to get static key + auto it = m_ECIESx25519Sessions.find (staticKey); + if (it != m_ECIESx25519Sessions.end ()) { - LogPrint (eLogDebug, "Garlic: Session restarted"); - requestNewIfNotFound = true; // it's not a new session - session = nullptr; + session = it->second; + if (session->IsInactive (i2p::util::GetSecondsSinceEpoch ())) + { + LogPrint (eLogDebug, "Garlic: Session restarted"); + requestNewIfNotFound = true; // it's not a new session + session = nullptr; + } } + if (!session && requestNewIfNotFound) + { + session = std::make_shared (this, true); + session->SetRemoteStaticKey (destination->GetEncryptionType (), staticKey); + } + if (session && destination->IsDestination ()) + session->SetDestination (destination->GetIdentHash ()); // NS or NSR + return session; } - if (!session && requestNewIfNotFound) - { - session = std::make_shared (this, true); - session->SetRemoteStaticKey (staticKey); - } - if (session && destination->IsDestination ()) - session->SetDestination (destination->GetIdentHash ()); // NS or NSR - return session; + else + LogPrint (eLogError, "Garlic: Non-supported encryption type ", destination->GetEncryptionType ()); } else { From af5d2a415c26fffb7c5158cbea9fa716d5e2960e Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 22 Mar 2025 12:01:47 -0400 Subject: [PATCH 0997/1171] c++20 --- Makefile.haiku | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.haiku b/Makefile.haiku index bc3094f6..5dce7d7f 100644 --- a/Makefile.haiku +++ b/Makefile.haiku @@ -1,8 +1,8 @@ CXX = g++ -CXXFLAGS := -Wall -std=c++17 +CXXFLAGS := -Wall -std=c++20 INCFLAGS = -I/system/develop/headers DEFINES = -D_DEFAULT_SOURCE -D_GNU_SOURCE -LDLIBS = -lbe -lbsd -lnetwork -lz -lssl -lcrypto -lboost_system -lboost_program_options -lpthread +LDLIBS = -lbe -lbsd -lnetwork -lz -lssl -lcrypto -lboost_program_options -lpthread ifeq ($(USE_UPNP),yes) DEFINES += -DUSE_UPNP From 029e279b487af61cb9577d40baa46642060c76f2 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 22 Mar 2025 12:30:51 -0400 Subject: [PATCH 0998/1171] fixed typo --- libi2pd_client/AddressBook.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd_client/AddressBook.cpp b/libi2pd_client/AddressBook.cpp index c0f440f9..8333e87d 100644 --- a/libi2pd_client/AddressBook.cpp +++ b/libi2pd_client/AddressBook.cpp @@ -584,7 +584,7 @@ namespace client } #if __cplusplus >= 202002L // C++20 - if (name.ends_with (".i2p")) + if (!name.ends_with (".i2p")) #else if (name.find(".i2p") == name.npos) #endif From 41197264c626f908c3afcea0b0d162e6349aac2a Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 22 Mar 2025 15:42:22 -0400 Subject: [PATCH 0999/1171] fixed warning --- libi2pd/Destination.h | 8 ++++---- libi2pd_client/I2CP.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index d844c085..802d7780 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -251,8 +251,8 @@ namespace client bool isPublic, const std::map * params = nullptr); ~ClientDestination (); - void Start (); - void Stop (); + void Start () override; + void Stop () override; const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; }; void Sign (const uint8_t * buf, int len, uint8_t * signature) const { m_Keys.Sign (buf, len, signature); }; @@ -300,8 +300,8 @@ namespace client void CleanupDestination () override; i2p::data::CryptoKeyType GetPreferredCryptoType () const override { return m_PreferredCryptoType; } // I2CP - void HandleDataMessage (const uint8_t * buf, size_t len); - void CreateNewLeaseSet (const std::vector >& tunnels); + void HandleDataMessage (const uint8_t * buf, size_t len) override; + void CreateNewLeaseSet (const std::vector >& tunnels) override; private: diff --git a/libi2pd_client/I2CP.h b/libi2pd_client/I2CP.h index 936f3c49..3a9a7e7f 100644 --- a/libi2pd_client/I2CP.h +++ b/libi2pd_client/I2CP.h @@ -90,7 +90,7 @@ namespace client const std::map& params); ~I2CPDestination () {}; - void Stop (); + void Stop () override; void SetEncryptionPrivateKey (const uint8_t * key); void SetEncryptionType (i2p::data::CryptoKeyType keyType) { m_EncryptionKeyType = keyType; }; From a193186935a4098200ecfd19da1678b21bbc57dd Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 22 Mar 2025 22:25:06 -0400 Subject: [PATCH 1000/1171] MLKEM512 keygen added --- libi2pd/Crypto.cpp | 73 +++++++++++++++++++++++++++++++++++++--------- libi2pd/Crypto.h | 20 +++++++++++++ 2 files changed, 79 insertions(+), 14 deletions(-) diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index 095f25d6..cd3b0fbc 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -29,7 +29,7 @@ namespace i2p { namespace crypto { - const uint8_t elgp_[256]= + constexpr uint8_t elgp_[256]= { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, @@ -49,9 +49,9 @@ namespace crypto 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - const int elgg_ = 2; + constexpr int elgg_ = 2; - const uint8_t dsap_[128]= + constexpr uint8_t dsap_[128]= { 0x9c, 0x05, 0xb2, 0xaa, 0x96, 0x0d, 0x9b, 0x97, 0xb8, 0x93, 0x19, 0x63, 0xc9, 0xcc, 0x9e, 0x8c, 0x30, 0x26, 0xe9, 0xb8, 0xed, 0x92, 0xfa, 0xd0, 0xa6, 0x9c, 0xc8, 0x86, 0xd5, 0xbf, 0x80, 0x15, @@ -63,13 +63,13 @@ namespace crypto 0x28, 0x5d, 0x4c, 0xf2, 0x95, 0x38, 0xd9, 0xe3, 0xb6, 0x05, 0x1f, 0x5b, 0x22, 0xcc, 0x1c, 0x93 }; - const uint8_t dsaq_[20]= + constexpr uint8_t dsaq_[20]= { 0xa5, 0xdf, 0xc2, 0x8f, 0xef, 0x4c, 0xa1, 0xe2, 0x86, 0x74, 0x4c, 0xd8, 0xee, 0xd9, 0xd2, 0x9d, 0x68, 0x40, 0x46, 0xb7 }; - const uint8_t dsag_[128]= + constexpr uint8_t dsag_[128]= { 0x0c, 0x1f, 0x4d, 0x27, 0xd4, 0x00, 0x93, 0xb4, 0x29, 0xe9, 0x62, 0xd7, 0x22, 0x38, 0x24, 0xe0, 0xbb, 0xc4, 0x7e, 0x7c, 0x83, 0x2a, 0x39, 0x23, 0x6f, 0xc6, 0x83, 0xaf, 0x84, 0x88, 0x95, 0x81, @@ -81,7 +81,7 @@ namespace crypto 0xb3, 0xdb, 0xb1, 0x4a, 0x90, 0x5e, 0x7b, 0x2b, 0x3e, 0x93, 0xbe, 0x47, 0x08, 0xcb, 0xcc, 0x82 }; - const int rsae_ = 65537; + constexpr int rsae_ = 65537; struct CryptoConstants { @@ -824,8 +824,8 @@ namespace crypto void InitNoiseNState (NoiseSymmetricState& state, const uint8_t * pub) { - static const char protocolName[] = "Noise_N_25519_ChaChaPoly_SHA256"; // 31 chars - static const uint8_t hh[32] = + static constexpr char protocolName[] = "Noise_N_25519_ChaChaPoly_SHA256"; // 31 chars + static constexpr uint8_t hh[32] = { 0x69, 0x4d, 0x52, 0x44, 0x5a, 0x27, 0xd9, 0xad, 0xfa, 0xd2, 0x9c, 0x76, 0x32, 0x39, 0x5d, 0xc1, 0xe4, 0x35, 0x4c, 0x69, 0xb4, 0xf9, 0x2e, 0xac, 0x8a, 0x1e, 0xe4, 0x6a, 0x9e, 0xd2, 0x15, 0x54 @@ -835,12 +835,12 @@ namespace crypto void InitNoiseXKState (NoiseSymmetricState& state, const uint8_t * pub) { - static const uint8_t protocolNameHash[32] = + static constexpr uint8_t protocolNameHash[32] = { 0x72, 0xe8, 0x42, 0xc5, 0x45, 0xe1, 0x80, 0x80, 0xd3, 0x9c, 0x44, 0x93, 0xbb, 0x91, 0xd7, 0xed, 0xf2, 0x28, 0x98, 0x17, 0x71, 0x21, 0x8c, 0x1f, 0x62, 0x4e, 0x20, 0x6f, 0x28, 0xd3, 0x2f, 0x71 }; // SHA256 ("Noise_XKaesobfse+hs2+hs3_25519_ChaChaPoly_SHA256") - static const uint8_t hh[32] = + static constexpr uint8_t hh[32] = { 0x49, 0xff, 0x48, 0x3f, 0xc4, 0x04, 0xb9, 0xb2, 0x6b, 0x11, 0x94, 0x36, 0x72, 0xff, 0x05, 0xb5, 0x61, 0x27, 0x03, 0x31, 0xba, 0x89, 0xb8, 0xfc, 0x33, 0x15, 0x93, 0x87, 0x57, 0xdd, 0x3d, 0x1e @@ -850,12 +850,12 @@ namespace crypto void InitNoiseXKState1 (NoiseSymmetricState& state, const uint8_t * pub) { - static const uint8_t protocolNameHash[32] = + static constexpr uint8_t protocolNameHash[32] = { 0xb1, 0x37, 0x22, 0x81, 0x74, 0x23, 0xa8, 0xfd, 0xf4, 0x2d, 0xf2, 0xe6, 0x0e, 0xd1, 0xed, 0xf4, 0x1b, 0x93, 0x07, 0x1d, 0xb1, 0xec, 0x24, 0xa3, 0x67, 0xf7, 0x84, 0xec, 0x27, 0x0d, 0x81, 0x32 }; // SHA256 ("Noise_XKchaobfse+hs1+hs2+hs3_25519_ChaChaPoly_SHA256") - static const uint8_t hh[32] = + static constexpr uint8_t hh[32] = { 0xdc, 0x85, 0xe6, 0xaf, 0x7b, 0x02, 0x65, 0x0c, 0xf1, 0xf9, 0x0d, 0x71, 0xfb, 0xc6, 0xd4, 0x53, 0xa7, 0xcf, 0x6d, 0xbf, 0xbd, 0x52, 0x5e, 0xa5, 0xb5, 0x79, 0x1c, 0x47, 0xb3, 0x5e, 0xbc, 0x33 @@ -865,12 +865,12 @@ namespace crypto void InitNoiseIKState (NoiseSymmetricState& state, const uint8_t * pub) { - static const uint8_t protocolNameHash[32] = + static constexpr uint8_t protocolNameHash[32] = { 0x4c, 0xaf, 0x11, 0xef, 0x2c, 0x8e, 0x36, 0x56, 0x4c, 0x53, 0xe8, 0x88, 0x85, 0x06, 0x4d, 0xba, 0xac, 0xbe, 0x00, 0x54, 0xad, 0x17, 0x8f, 0x80, 0x79, 0xa6, 0x46, 0x82, 0x7e, 0x6e, 0xe4, 0x0c }; // SHA256("Noise_IKelg2+hs2_25519_ChaChaPoly_SHA256"), 40 bytes - static const uint8_t hh[32] = + static constexpr uint8_t hh[32] = { 0x9c, 0xcf, 0x85, 0x2c, 0xc9, 0x3b, 0xb9, 0x50, 0x44, 0x41, 0xe9, 0x50, 0xe0, 0x1d, 0x52, 0x32, 0x2e, 0x0d, 0x47, 0xad, 0xd1, 0xe9, 0xa5, 0x55, 0xf7, 0x55, 0xb5, 0x69, 0xae, 0x18, 0x3b, 0x5c @@ -878,6 +878,21 @@ namespace crypto InitNoiseState (state, protocolNameHash, hh, pub); } + void InitNoiseIKStateMLKEM512 (NoiseSymmetricState& state, const uint8_t * pub) + { + static constexpr uint8_t protocolNameHash[32] = + { + 0xb0, 0x8f, 0xb1, 0x73, 0x92, 0x66, 0xc9, 0x90, 0x45, 0x7f, 0xdd, 0xc6, 0x4e, 0x55, 0x40, 0xd8, + 0x0a, 0x37, 0x99, 0x06, 0x92, 0x2a, 0x78, 0xc4, 0xb1, 0xef, 0x86, 0x06, 0xd0, 0x15, 0x9f, 0x4d + }; // SHA256("Noise_IKhfselg2_25519+MLKEM512_ChaChaPoly_SHA256") + static constexpr uint8_t hh[32] = + { + 0x95, 0x8d, 0xf6, 0x6c, 0x95, 0xce, 0xa9, 0xf7, 0x42, 0xfc, 0xfa, 0x62, 0x71, 0x36, 0x1e, 0xa7, + 0xdc, 0x7a, 0xc0, 0x75, 0x01, 0xcf, 0xf9, 0xfc, 0x9f, 0xdb, 0x4c, 0x68, 0x3a, 0x53, 0x49, 0xeb + }; // SHA256 (protocolNameHash) + InitNoiseState (state, protocolNameHash, hh, pub); + } + // init and terminate /* std::vector > m_OpenSSLMutexes; @@ -926,5 +941,35 @@ namespace crypto /* CRYPTO_set_locking_callback (nullptr); m_OpenSSLMutexes.clear ();*/ } + +#if OPENSSL_PQ +#include + + MLKEM512Keys::MLKEM512Keys (): + m_Pkey (nullptr) + { + } + + MLKEM512Keys::~MLKEM512Keys () + { + if (m_Pkey) EVP_PKEY_free (m_Pkey); + } + + void MLKEM512Keys::GenerateKeys () + { + if (m_Pkey) + { + EVP_PKEY_free (m_Pkey); + m_Pkey = nullptr; + } + m_Pkey = EVP_PKEY_Q_keygen(NULL, NULL, "ML-KEM-512"); + } + + void MLKEM512Keys::GetPublicKey (uint8_t * pub) const + { + size_t len = MLKEM512_KEY_LENGTH; + EVP_PKEY_get_octet_string_param (m_Pkey, OSSL_PKEY_PARAM_PUB_KEY, pub, MLKEM512_KEY_LENGTH, &len); + } +#endif } } diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index b2fa0292..6b7b0e30 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -261,10 +261,30 @@ namespace crypto void InitNoiseXKState (NoiseSymmetricState& state, const uint8_t * pub); // Noise_XK (NTCP2) void InitNoiseXKState1 (NoiseSymmetricState& state, const uint8_t * pub); // Noise_XK (SSU2) void InitNoiseIKState (NoiseSymmetricState& state, const uint8_t * pub); // Noise_IK (ratchets) + void InitNoiseIKStateMLKEM512 (NoiseSymmetricState& state, const uint8_t * pub); // Noise_IK (ratchets) PQ ML-KEM512 // init and terminate void InitCrypto (bool precomputation); void TerminateCrypto (); + +#if OPENSSL_PQ +// Post Quantum + constexpr size_t MLKEM512_KEY_LENGTH = 800; + class MLKEM512Keys + { + public: + + MLKEM512Keys (); + ~MLKEM512Keys (); + + void GenerateKeys (); + void GetPublicKey (uint8_t * pub) const; + + private: + + EVP_PKEY * m_Pkey; + }; +#endif } } From 75d5c6036e9b9df63443b04ce93606a1f34106fb Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 23 Mar 2025 18:53:32 -0400 Subject: [PATCH 1001/1171] use EVP interface for DSA sign/verify with OpenSSL 3 --- libi2pd/Crypto.cpp | 39 +++++++++- libi2pd/Crypto.h | 4 ++ libi2pd/Signature.cpp | 164 +++++++++++++++++++++++++++++++++++++++++- libi2pd/Signature.h | 88 +++++++---------------- 4 files changed, 227 insertions(+), 68 deletions(-) diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index cd3b0fbc..414314cf 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -19,6 +19,10 @@ #if OPENSSL_HKDF #include #endif +#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 +#include +#include +#endif #include "CPU.h" #include "Crypto.h" #include "Ed25519.h" @@ -146,6 +150,37 @@ namespace crypto #define dsap GetCryptoConstants ().dsap #define dsaq GetCryptoConstants ().dsaq #define dsag GetCryptoConstants ().dsag +#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 + EVP_PKEY * CreateDSA (BIGNUM * pubKey, BIGNUM * privKey) + { + EVP_PKEY * pkey = nullptr; + int selection = EVP_PKEY_KEY_PARAMETERS; + auto bld = OSSL_PARAM_BLD_new(); + OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_P, dsap); + OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_Q, dsaq); + OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_G, dsag); + if (pubKey) + { + OSSL_PARAM_BLD_push_BN (bld, OSSL_PKEY_PARAM_PUB_KEY, pubKey); + selection = EVP_PKEY_PUBLIC_KEY; + } + if (privKey) + { + OSSL_PARAM_BLD_push_BN (bld, OSSL_PKEY_PARAM_PRIV_KEY, privKey); + selection = EVP_PKEY_KEYPAIR; + } + auto params = OSSL_PARAM_BLD_to_param(bld); + + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name (NULL, "DSA", NULL); + EVP_PKEY_fromdata_init(ctx); + EVP_PKEY_fromdata(ctx, &pkey, selection, params); + + EVP_PKEY_CTX_free(ctx); + OSSL_PARAM_free(params); + OSSL_PARAM_BLD_free(bld); + return pkey; + } +#else DSA * CreateDSA () { DSA * dsa = DSA_new (); @@ -153,7 +188,8 @@ namespace crypto DSA_set0_key (dsa, NULL, NULL); return dsa; } - +#endif + // DH/ElGamal #if !IS_X86_64 @@ -943,7 +979,6 @@ namespace crypto } #if OPENSSL_PQ -#include MLKEM512Keys::MLKEM512Keys (): m_Pkey (nullptr) diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index 6b7b0e30..b6ab3fa4 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -45,7 +45,11 @@ namespace crypto bool bn2buf (const BIGNUM * bn, uint8_t * buf, size_t len); // DSA +#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 + EVP_PKEY * CreateDSA (BIGNUM * pubKey = nullptr, BIGNUM * privKey = nullptr); +#else DSA * CreateDSA (); +#endif // RSA const BIGNUM * GetRSAE (); diff --git a/libi2pd/Signature.cpp b/libi2pd/Signature.cpp index f684f10f..3e4b451b 100644 --- a/libi2pd/Signature.cpp +++ b/libi2pd/Signature.cpp @@ -7,6 +7,10 @@ */ #include +#include +#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 +#include +#endif #include "Log.h" #include "Signature.h" @@ -14,6 +18,163 @@ namespace i2p { namespace crypto { +#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 + DSAVerifier::DSAVerifier (): + m_PublicKey (nullptr) + { + } + + DSAVerifier::~DSAVerifier () + { + if (m_PublicKey) + EVP_PKEY_free (m_PublicKey); + } + + void DSAVerifier::SetPublicKey (const uint8_t * signingKey) + { + if (m_PublicKey) + EVP_PKEY_free (m_PublicKey); + BIGNUM * pub = BN_bin2bn (signingKey, DSA_PUBLIC_KEY_LENGTH, NULL); + m_PublicKey = CreateDSA (pub); + BN_free (pub); + } + + bool DSAVerifier::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const + { + // calculate SHA1 digest + uint8_t digest[20], sign[48]; + SHA1 (buf, len, digest); + // signature + DSA_SIG * sig = DSA_SIG_new(); + DSA_SIG_set0 (sig, BN_bin2bn (signature, DSA_SIGNATURE_LENGTH/2, NULL), BN_bin2bn (signature + DSA_SIGNATURE_LENGTH/2, DSA_SIGNATURE_LENGTH/2, NULL)); + // to DER format + uint8_t * s = sign; + auto l = i2d_DSA_SIG (sig, &s); + DSA_SIG_free(sig); + // verify + auto ctx = EVP_PKEY_CTX_new (m_PublicKey, NULL); + EVP_PKEY_verify_init(ctx); + EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha1()); + bool ret = EVP_PKEY_verify(ctx, sign, l, digest, 20); + EVP_PKEY_CTX_free(ctx); + return ret; + } + + DSASigner::DSASigner (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey) + { + BIGNUM * priv = BN_bin2bn (signingPrivateKey, DSA_PRIVATE_KEY_LENGTH, NULL); + m_PrivateKey = CreateDSA (nullptr, priv); + BN_free (priv); + } + + DSASigner::~DSASigner () + { + if (m_PrivateKey) + EVP_PKEY_free (m_PrivateKey); + } + + void DSASigner::Sign (const uint8_t * buf, int len, uint8_t * signature) const + { + uint8_t digest[20], sign[48]; + SHA1 (buf, len, digest); + auto ctx = EVP_PKEY_CTX_new (m_PrivateKey, NULL); + EVP_PKEY_sign_init(ctx); + EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha1()); + size_t l = 48; + EVP_PKEY_sign(ctx, sign, &l, digest, 20); + const uint8_t * s1 = sign; + DSA_SIG * sig = d2i_DSA_SIG (NULL, &s1, l); + const BIGNUM * r, * s; + DSA_SIG_get0 (sig, &r, &s); + bn2buf (r, signature, DSA_SIGNATURE_LENGTH/2); + bn2buf (s, signature + DSA_SIGNATURE_LENGTH/2, DSA_SIGNATURE_LENGTH/2); + DSA_SIG_free(sig); + EVP_PKEY_CTX_free(ctx); + } + + void CreateDSARandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey) + { + EVP_PKEY * paramskey = CreateDSA(); + EVP_PKEY_CTX * ctx = EVP_PKEY_CTX_new_from_pkey(NULL, paramskey, NULL); + EVP_PKEY_keygen_init(ctx); + EVP_PKEY * pkey = nullptr; + EVP_PKEY_keygen(ctx, &pkey); + BIGNUM * pub = NULL, * priv = NULL; + EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PUB_KEY, &pub); + bn2buf (pub, signingPublicKey, DSA_PUBLIC_KEY_LENGTH); + EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY, &priv); + bn2buf (priv, signingPrivateKey, DSA_PRIVATE_KEY_LENGTH); + BN_free (pub); BN_free (priv); + EVP_PKEY_free (pkey); + EVP_PKEY_free (paramskey); + EVP_PKEY_CTX_free (ctx); + } +#else + + DSAVerifier::DSAVerifier () + { + m_PublicKey = CreateDSA (); + } + + DSAVerifier::~DSAVerifier () + { + DSA_free (m_PublicKey); + } + + void DSAVerifier::SetPublicKey (const uint8_t * signingKey) + { + DSA_set0_key (m_PublicKey, BN_bin2bn (signingKey, DSA_PUBLIC_KEY_LENGTH, NULL), NULL); + } + + bool DSAVerifier::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const + { + // calculate SHA1 digest + uint8_t digest[20]; + SHA1 (buf, len, digest); + // signature + DSA_SIG * sig = DSA_SIG_new(); + DSA_SIG_set0 (sig, BN_bin2bn (signature, DSA_SIGNATURE_LENGTH/2, NULL), BN_bin2bn (signature + DSA_SIGNATURE_LENGTH/2, DSA_SIGNATURE_LENGTH/2, NULL)); + // DSA verification + int ret = DSA_do_verify (digest, 20, sig, m_PublicKey); + DSA_SIG_free(sig); + return ret; + } + + DSASigner::DSASigner (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey) + { + m_PrivateKey = CreateDSA (); + DSA_set0_key (m_PrivateKey, BN_bin2bn (signingPublicKey, DSA_PUBLIC_KEY_LENGTH, NULL), BN_bin2bn (signingPrivateKey, DSA_PRIVATE_KEY_LENGTH, NULL)); + } + + DSASigner::~DSASigner () + { + DSA_free (m_PrivateKey); + } + + void DSASigner::Sign (const uint8_t * buf, int len, uint8_t * signature) const + { + uint8_t digest[20]; + SHA1 (buf, len, digest); + DSA_SIG * sig = DSA_do_sign (digest, 20, m_PrivateKey); + const BIGNUM * r, * s; + DSA_SIG_get0 (sig, &r, &s); + bn2buf (r, signature, DSA_SIGNATURE_LENGTH/2); + bn2buf (s, signature + DSA_SIGNATURE_LENGTH/2, DSA_SIGNATURE_LENGTH/2); + DSA_SIG_free(sig); + } + + void CreateDSARandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey) + { + DSA * dsa = CreateDSA (); + DSA_generate_key (dsa); + const BIGNUM * pub_key, * priv_key; + DSA_get0_key(dsa, &pub_key, &priv_key); + bn2buf (priv_key, signingPrivateKey, DSA_PRIVATE_KEY_LENGTH); + bn2buf (pub_key, signingPublicKey, DSA_PUBLIC_KEY_LENGTH); + DSA_free (dsa); + } +#endif + #if OPENSSL_EDDSA EDDSA25519Verifier::EDDSA25519Verifier (): m_Pkey (nullptr) @@ -202,8 +363,7 @@ namespace crypto #endif #if OPENSSL_PQ -#include - + MLDSA44Verifier::MLDSA44Verifier (): m_Pkey (nullptr) { diff --git a/libi2pd/Signature.h b/libi2pd/Signature.h index c77e10dd..20c7e11b 100644 --- a/libi2pd/Signature.h +++ b/libi2pd/Signature.h @@ -43,94 +43,55 @@ namespace crypto virtual void Sign (const uint8_t * buf, int len, uint8_t * signature) const = 0; }; + // DSA const size_t DSA_PUBLIC_KEY_LENGTH = 128; const size_t DSA_SIGNATURE_LENGTH = 40; const size_t DSA_PRIVATE_KEY_LENGTH = DSA_SIGNATURE_LENGTH/2; class DSAVerifier: public Verifier { public: + + DSAVerifier (); + ~DSAVerifier (); - DSAVerifier () - { - m_PublicKey = CreateDSA (); - } - - void SetPublicKey (const uint8_t * signingKey) - { - DSA_set0_key (m_PublicKey, BN_bin2bn (signingKey, DSA_PUBLIC_KEY_LENGTH, NULL), NULL); - } - - ~DSAVerifier () - { - DSA_free (m_PublicKey); - } - - bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const - { - // calculate SHA1 digest - uint8_t digest[20]; - SHA1 (buf, len, digest); - // signature - DSA_SIG * sig = DSA_SIG_new(); - DSA_SIG_set0 (sig, BN_bin2bn (signature, DSA_SIGNATURE_LENGTH/2, NULL), BN_bin2bn (signature + DSA_SIGNATURE_LENGTH/2, DSA_SIGNATURE_LENGTH/2, NULL)); - // DSA verification - int ret = DSA_do_verify (digest, 20, sig, m_PublicKey); - DSA_SIG_free(sig); - return ret; - } - - size_t GetPublicKeyLen () const { return DSA_PUBLIC_KEY_LENGTH; }; - size_t GetSignatureLen () const { return DSA_SIGNATURE_LENGTH; }; - + // implements Verifier + void SetPublicKey (const uint8_t * signingKey) override; + bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const override; + size_t GetPublicKeyLen () const override { return DSA_PUBLIC_KEY_LENGTH; }; + size_t GetSignatureLen () const override { return DSA_SIGNATURE_LENGTH; }; + private: +#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 + EVP_PKEY * m_PublicKey; +#else DSA * m_PublicKey; +#endif }; class DSASigner: public Signer { public: - DSASigner (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey) + DSASigner (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey); // openssl 1.1 always requires DSA public key even for signing - { - m_PrivateKey = CreateDSA (); - DSA_set0_key (m_PrivateKey, BN_bin2bn (signingPublicKey, DSA_PUBLIC_KEY_LENGTH, NULL), BN_bin2bn (signingPrivateKey, DSA_PRIVATE_KEY_LENGTH, NULL)); - } + ~DSASigner (); - ~DSASigner () - { - DSA_free (m_PrivateKey); - } - - void Sign (const uint8_t * buf, int len, uint8_t * signature) const - { - uint8_t digest[20]; - SHA1 (buf, len, digest); - DSA_SIG * sig = DSA_do_sign (digest, 20, m_PrivateKey); - const BIGNUM * r, * s; - DSA_SIG_get0 (sig, &r, &s); - bn2buf (r, signature, DSA_SIGNATURE_LENGTH/2); - bn2buf (s, signature + DSA_SIGNATURE_LENGTH/2, DSA_SIGNATURE_LENGTH/2); - DSA_SIG_free(sig); - } + // implements Signer + void Sign (const uint8_t * buf, int len, uint8_t * signature) const override; private: +#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 + EVP_PKEY * m_PrivateKey; +#else DSA * m_PrivateKey; +#endif }; - inline void CreateDSARandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey) - { - DSA * dsa = CreateDSA (); - DSA_generate_key (dsa); - const BIGNUM * pub_key, * priv_key; - DSA_get0_key(dsa, &pub_key, &priv_key); - bn2buf (priv_key, signingPrivateKey, DSA_PRIVATE_KEY_LENGTH); - bn2buf (pub_key, signingPublicKey, DSA_PUBLIC_KEY_LENGTH); - DSA_free (dsa); - } + void CreateDSARandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey); + // ECDSA struct SHA256Hash { static void CalculateHash (const uint8_t * buf, size_t len, uint8_t * digest) @@ -161,7 +122,6 @@ namespace crypto enum { hashLen = 64 }; }; - // EcDSA template class ECDSAVerifier: public Verifier { From 22d854a6be8d34cd63401c32f7afc1f6a7606913 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 24 Mar 2025 15:45:06 -0400 Subject: [PATCH 1002/1171] ML-KEM-512 encaps/decaps --- libi2pd/Crypto.cpp | 66 +++++++++++++++++++++++++++++++++++++++++----- libi2pd/Crypto.h | 4 +++ 2 files changed, 63 insertions(+), 7 deletions(-) diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index 414314cf..9bdfe43f 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -992,19 +992,71 @@ namespace crypto void MLKEM512Keys::GenerateKeys () { - if (m_Pkey) - { - EVP_PKEY_free (m_Pkey); - m_Pkey = nullptr; - } + if (m_Pkey) EVP_PKEY_free (m_Pkey); m_Pkey = EVP_PKEY_Q_keygen(NULL, NULL, "ML-KEM-512"); } void MLKEM512Keys::GetPublicKey (uint8_t * pub) const { - size_t len = MLKEM512_KEY_LENGTH; - EVP_PKEY_get_octet_string_param (m_Pkey, OSSL_PKEY_PARAM_PUB_KEY, pub, MLKEM512_KEY_LENGTH, &len); + if (m_Pkey) + { + size_t len = MLKEM512_KEY_LENGTH; + EVP_PKEY_get_octet_string_param (m_Pkey, OSSL_PKEY_PARAM_PUB_KEY, pub, MLKEM512_KEY_LENGTH, &len); + } } + + void MLKEM512Keys::SetPublicKey (const uint8_t * pub) + { + if (m_Pkey) + { + EVP_PKEY_free (m_Pkey); + m_Pkey = nullptr; + } + OSSL_PARAM params[] = + { + OSSL_PARAM_octet_string (OSSL_PKEY_PARAM_PUB_KEY, (uint8_t *)pub, MLKEM512_KEY_LENGTH), + OSSL_PARAM_END + }; + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name (NULL, "ML-KEM-512", NULL); + if (ctx) + { + EVP_PKEY_fromdata_init (ctx); + EVP_PKEY_fromdata (ctx, &m_Pkey, OSSL_KEYMGMT_SELECT_PUBLIC_KEY, params); + EVP_PKEY_CTX_free (ctx); + } + else + LogPrint (eLogError, "MLKEM512 can't create PKEY context"); + } + + void MLKEM512Keys::Encaps (uint8_t * ciphertext, uint8_t * shared) + { + if (!m_Pkey) return; + auto ctx = EVP_PKEY_CTX_new_from_pkey (NULL, m_Pkey, NULL); + if (ctx) + { + EVP_PKEY_encapsulate_init (ctx, NULL); + size_t len = MLKEM512_CIPHER_TEXT_LENGTH, sharedLen = 32; + EVP_PKEY_encapsulate (ctx, ciphertext, &len, shared, &sharedLen); + EVP_PKEY_CTX_free (ctx); + } + else + LogPrint (eLogError, "MLKEM512 can't create PKEY context"); + } + + void MLKEM512Keys::Decaps (const uint8_t * ciphertext, uint8_t * shared) + { + if (!m_Pkey) return; + auto ctx = EVP_PKEY_CTX_new_from_pkey (NULL, m_Pkey, NULL); + if (ctx) + { + EVP_PKEY_decapsulate_init (ctx, NULL); + size_t sharedLen = 32; + EVP_PKEY_decapsulate (ctx, shared, &sharedLen, ciphertext, MLKEM512_CIPHER_TEXT_LENGTH); + EVP_PKEY_CTX_free (ctx); + } + else + LogPrint (eLogError, "MLKEM512 can't create PKEY context"); + } #endif } } diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index b6ab3fa4..dcdc27d3 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -274,6 +274,7 @@ namespace crypto #if OPENSSL_PQ // Post Quantum constexpr size_t MLKEM512_KEY_LENGTH = 800; + constexpr size_t MLKEM512_CIPHER_TEXT_LENGTH = 768; class MLKEM512Keys { public: @@ -283,6 +284,9 @@ namespace crypto void GenerateKeys (); void GetPublicKey (uint8_t * pub) const; + void SetPublicKey (const uint8_t * pub); + void Encaps (uint8_t * ciphertext, uint8_t * shared); + void Decaps (const uint8_t * ciphertext, uint8_t * shared); private: From d3cfbbd6b0484c6b0c2c225de00f9bfbea384d29 Mon Sep 17 00:00:00 2001 From: AsciiMoth Date: Tue, 25 Mar 2025 09:35:00 +0400 Subject: [PATCH 1003/1171] Update dates range in licence --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 93280084..f59491f5 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2013-2023, The PurpleI2P Project +Copyright (c) 2013-2025, The PurpleI2P Project All rights reserved. From ecf19278e86d75e4834ad0af61a0c534f7332703 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 25 Mar 2025 18:55:28 -0400 Subject: [PATCH 1004/1171] skip post-quantum keys if not supported --- libi2pd/Destination.cpp | 13 +++++++++---- libi2pd/LeaseSet.cpp | 21 +++++++++++++-------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index d7f311cf..e20249c5 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1022,10 +1022,15 @@ namespace client { try { - i2p::data::CryptoKeyType preferredCryptoType = std::stoi(it1); - if (!m_PreferredCryptoType && preferredCryptoType) - m_PreferredCryptoType = preferredCryptoType; // first non-zero in the list - encryptionKeyTypes.insert (preferredCryptoType); + i2p::data::CryptoKeyType cryptoType = std::stoi(it1); +#if !OPENSSL_PQ + if (cryptoType <= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) // skip PQ keys if not supported +#endif + { + if (!m_PreferredCryptoType && cryptoType) + m_PreferredCryptoType = cryptoType; // first non-zero in the list + encryptionKeyTypes.insert (cryptoType); + } } catch (std::exception& ex) { diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index e4edcb31..db8c1aad 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -413,15 +413,20 @@ namespace data if (IsStoreLeases () && !preferredKeyFound) // create encryptor with leases only { // we pick max key type if preferred not found - if (keyType == preferredKeyType || !m_Encryptor || keyType > m_EncryptionType) - { - auto encryptor = i2p::data::IdentityEx::CreateEncryptor (keyType, buf + offset); - if (encryptor) +#if !OPENSSL_PQ + if (keyType <= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) // skip PQ keys if not supported +#endif + { + if (keyType == preferredKeyType || !m_Encryptor || keyType > m_EncryptionType) { - m_Encryptor = encryptor; // TODO: atomic - m_EncryptionType = keyType; - if (keyType == preferredKeyType) preferredKeyFound = true; - } + auto encryptor = i2p::data::IdentityEx::CreateEncryptor (keyType, buf + offset); + if (encryptor) + { + m_Encryptor = encryptor; // TODO: atomic + m_EncryptionType = keyType; + if (keyType == preferredKeyType) preferredKeyFound = true; + } + } } } offset += encryptionKeyLen; From 81ba19e1ae060347add0179f9594e0c3b9383473 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 25 Mar 2025 21:31:16 -0400 Subject: [PATCH 1005/1171] use find_directory to detect data dir in Haiku --- libi2pd/FS.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/libi2pd/FS.cpp b/libi2pd/FS.cpp index a623a4eb..3f5fc6b9 100644 --- a/libi2pd/FS.cpp +++ b/libi2pd/FS.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2024, The PurpleI2P Project +* Copyright (c) 2013-2025, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -15,6 +15,10 @@ #include #endif +#if defined(__HAIKU__) +#include +#endif + #ifdef _WIN32 #include #include @@ -169,12 +173,11 @@ namespace fs { dataDir += "/Library/Application Support/" + appName; return; #elif defined(__HAIKU__) - char *home = getenv("HOME"); - if (home != NULL && strlen(home) > 0) { - dataDir = std::string(home) + "/config/settings/" + appName; - } else { + char home[PATH_MAX]; // /boot/home/config/settings + if (find_directory(B_USER_SETTINGS_DIRECTORY, -1, false, home, PATH_MAX) == B_OK) + dataDir = std::string(home) + "/" + appName; + else dataDir = "/tmp/" + appName; - } return; #else /* other unix */ #if defined(ANDROID) From 871fc14ba64bdeeab7a51914b5a9d266832afd27 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 27 Mar 2025 16:24:02 -0400 Subject: [PATCH 1006/1171] ML-KEM section for NS and NSR outgoing sessions --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 54 ++++++++++++++++++++++- libi2pd/ECIESX25519AEADRatchetSession.h | 3 ++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 7a799d29..865fc973 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -492,7 +492,16 @@ namespace garlic offset += 32; // KDF1 - i2p::crypto::InitNoiseIKState (GetNoiseState (), m_RemoteStaticKey); // bpk +#if OPENSSL_PQ + if (m_RemoteStaticKeyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD) + { + i2p::crypto::InitNoiseIKStateMLKEM512 (GetNoiseState (), m_RemoteStaticKey); // bpk + m_PQKeys = std::make_unique(); + m_PQKeys->GenerateKeys (); + } + else +#endif + i2p::crypto::InitNoiseIKState (GetNoiseState (), m_RemoteStaticKey); // bpk MixHash (m_EphemeralKeys->GetPublicKey (), 32); // h = SHA256(h || aepk) uint8_t sharedSecret[32]; if (!m_EphemeralKeys->Agree (m_RemoteStaticKey, sharedSecret)) // x25519(aesk, bpk) @@ -501,9 +510,29 @@ namespace garlic return false; } MixKey (sharedSecret); + uint64_t n = 0; // seqn +#if OPENSSL_PQ + if (m_RemoteStaticKeyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD) + { + uint8_t encapsKey[i2p::crypto::MLKEM512_KEY_LENGTH]; + m_PQKeys->GetPublicKey (encapsKey); + // encrypt encapsKey + uint8_t nonce[12]; + CreateNonce (n, nonce); + if (!i2p::crypto::AEADChaCha20Poly1305 (encapsKey, i2p::crypto::MLKEM512_KEY_LENGTH, + m_H, 32, m_CK + 32, nonce, out + offset, i2p::crypto::MLKEM512_KEY_LENGTH + 16, true)) // encrypt + { + LogPrint (eLogWarning, "Garlic: ML-KEM encap_key section AEAD encryption failed "); + return false; + } + MixHash (out + offset, i2p::crypto::MLKEM512_KEY_LENGTH + 16); // h = SHA256(h || ciphertext) + offset += i2p::crypto::MLKEM512_KEY_LENGTH + 16; + n++; + } +#endif // encrypt flags/static key section uint8_t nonce[12]; - CreateNonce (0, nonce); + CreateNonce (n, nonce); const uint8_t * fs; if (isStatic) fs = GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); @@ -675,6 +704,24 @@ namespace garlic uint8_t nonce[12]; CreateNonce (0, nonce); +#if OPENSSL_PQ + if (m_RemoteStaticKeyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD) + { + // decrypt kem_ciphertext section + uint8_t kemCiphertext[i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH]; + if (!i2p::crypto::AEADChaCha20Poly1305 (buf, i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH, + m_H, 32, m_CK + 32, nonce, kemCiphertext, i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH, false)) // decrypt, DECRYPT(k, n, ZEROLEN, ad) verification only + { + LogPrint (eLogWarning, "Garlic: Reply ML-KEM ciphertext section AEAD decryption failed"); + return false; + } + MixHash (buf, i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH + 16); + buf += i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH + 16; + // decaps + m_PQKeys->Decaps (kemCiphertext, sharedSecret); + MixKey (sharedSecret); + } +#endif // calculate hash for zero length if (!i2p::crypto::AEADChaCha20Poly1305 (buf, 0, m_H, 32, m_CK + 32, nonce, sharedSecret/* can be anything */, 0, false)) // decrypt, DECRYPT(k, n, ZEROLEN, ad) verification only { @@ -711,6 +758,9 @@ namespace garlic { m_State = eSessionStateEstablished; //m_EphemeralKeys = nullptr; // TODO: delete after a while +#if OPENSSL_PQ + // m_PQKeys = nullptr; // TODO: delete after a while +#endif m_SessionCreatedTimestamp = i2p::util::GetSecondsSinceEpoch (); GetOwner ()->AddECIESx25519Session (m_RemoteStaticKey, shared_from_this ()); } diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index 5614e6cb..cd32cb98 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -226,6 +226,9 @@ namespace garlic uint8_t m_Aepk[32]; // Alice's ephemeral keys, for incoming only uint8_t m_NSREncodedKey[32], m_NSRH[32], m_NSRKey[32]; // new session reply, for incoming only std::shared_ptr m_EphemeralKeys; +#if OPENSSL_PQ + std::unique_ptr m_PQKeys; +#endif SessionState m_State = eSessionStateNew; uint64_t m_SessionCreatedTimestamp = 0, m_LastActivityTimestamp = 0, // incoming (in seconds) m_LastSentTimestamp = 0; // in milliseconds From 7404ce7fd2e69b8e3e70d90b594a04e44053836c Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 28 Mar 2025 19:34:36 -0400 Subject: [PATCH 1007/1171] update session's remote enpoint after receiving path response --- libi2pd/SSU2Session.cpp | 24 +++++++++++++++--------- libi2pd/SSU2Session.h | 4 ++-- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index e0a9a48f..dd170714 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1498,11 +1498,11 @@ namespace transport ResendHandshakePacket (); // assume we receive return; } - if (from != m_RemoteEndpoint && !i2p::transport::transports.IsInReservedRange (from.address ())) + if (from != m_RemoteEndpoint && !i2p::transport::transports.IsInReservedRange (from.address ()) && + (!m_PathChallenge || from != m_PathChallenge->second)) // path challenge was not sent to this endpoint yet { LogPrint (eLogInfo, "SSU2: Remote endpoint update ", m_RemoteEndpoint, "->", from); - m_RemoteEndpoint = from; - SendPathChallenge (); + SendPathChallenge (from); } if (len < 32) { @@ -1660,10 +1660,13 @@ namespace transport LogPrint (eLogDebug, "SSU2: Path response"); if (m_PathChallenge) { - i2p::data::IdentHash hash; + i2p::data::Tag<32> hash; SHA256 (buf + offset, size, hash); - if (hash == *m_PathChallenge) + if (hash == m_PathChallenge->first) + { + m_RemoteEndpoint = m_PathChallenge->second; m_PathChallenge.reset (nullptr); + } } break; } @@ -3070,7 +3073,7 @@ namespace transport SendData (payload, payloadSize); } - void SSU2Session::SendPathChallenge () + void SSU2Session::SendPathChallenge (const boost::asio::ip::udp::endpoint& to) { uint8_t payload[SSU2_MAX_PACKET_SIZE]; payload[0] = eSSU2BlkPathChallenge; @@ -3078,15 +3081,18 @@ namespace transport htobe16buf (payload + 1, len); if (len > 0) { + m_PathChallenge = std::make_unique, boost::asio::ip::udp::endpoint> >(); RAND_bytes (payload + 3, len); - i2p::data::IdentHash * hash = new i2p::data::IdentHash (); - SHA256 (payload + 3, len, *hash); - m_PathChallenge.reset (hash); + SHA256 (payload + 3, len, m_PathChallenge->first); + m_PathChallenge->second = to; } len += 3; if (len < m_MaxPayloadSize) len += CreatePaddingBlock (payload + len, m_MaxPayloadSize - len, len < 8 ? 8 : 0); + auto existing = m_RemoteEndpoint; + m_RemoteEndpoint = to; // send path challenge to new endpoint SendData (payload, len); + m_RemoteEndpoint = existing; // restore endpoint back until path response received } void SSU2Session::CleanUp (uint64_t ts) diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index ee295acb..6d2bf103 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -327,7 +327,7 @@ namespace transport void SendQuickAck (); void SendTermination (); void SendPathResponse (const uint8_t * data, size_t len); - void SendPathChallenge (); + void SendPathChallenge (const boost::asio::ip::udp::endpoint& to); void HandleDateTime (const uint8_t * buf, size_t len); void HandleRouterInfo (const uint8_t * buf, size_t len); @@ -394,7 +394,7 @@ namespace transport boost::asio::deadline_timer m_ConnectTimer; SSU2TerminationReason m_TerminationReason; size_t m_MaxPayloadSize; - std::unique_ptr m_PathChallenge; + std::unique_ptr, boost::asio::ip::udp::endpoint> > m_PathChallenge; std::unordered_map m_ReceivedI2NPMsgIDs; // msgID -> timestamp in seconds uint64_t m_LastResendTime, m_LastResendAttemptTime; // in milliseconds int m_NumRanges; From c2f68d70216466af48d805ad2fc3416ca9ea01da Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 29 Mar 2025 21:34:16 -0400 Subject: [PATCH 1008/1171] send datetime and address blocks with path challenge --- libi2pd/SSU2Session.cpp | 42 +++++++++++++++++++++++++++-------------- libi2pd/SSU2Session.h | 2 +- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index dd170714..a4a9fa03 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -2562,17 +2562,19 @@ namespace transport return nullptr; } - void SSU2Session::AdjustMaxPayloadSize () + void SSU2Session::AdjustMaxPayloadSize (size_t maxMtu) { auto addr = FindLocalAddress (); if (addr && addr->ssu) { int mtu = addr->ssu->mtu; if (!mtu && addr->IsV4 ()) mtu = SSU2_MAX_PACKET_SIZE; + if (mtu > (int)maxMtu) mtu = maxMtu; if (m_Address && m_Address->ssu && (!mtu || m_Address->ssu->mtu < mtu)) mtu = m_Address->ssu->mtu; if (mtu) { + if (mtu > (int)SSU2_MAX_PACKET_SIZE) mtu = SSU2_MAX_PACKET_SIZE; if (mtu < (int)SSU2_MIN_PACKET_SIZE) mtu = SSU2_MIN_PACKET_SIZE; m_MaxPayloadSize = mtu - (addr->IsV6 () ? IPV6_HEADER_SIZE: IPV4_HEADER_SIZE) - UDP_HEADER_SIZE - 32; LogPrint (eLogDebug, "SSU2: Session MTU=", mtu, ", max payload size=", m_MaxPayloadSize); @@ -3075,23 +3077,35 @@ namespace transport void SSU2Session::SendPathChallenge (const boost::asio::ip::udp::endpoint& to) { + AdjustMaxPayloadSize (SSU2_MIN_PACKET_SIZE); // reduce to minimum + m_WindowSize = SSU2_MIN_WINDOW_SIZE; // reduce window to minimum + uint8_t payload[SSU2_MAX_PACKET_SIZE]; - payload[0] = eSSU2BlkPathChallenge; - size_t len = m_Server.GetRng ()() % (m_MaxPayloadSize - 3); - htobe16buf (payload + 1, len); - if (len > 0) - { - m_PathChallenge = std::make_unique, boost::asio::ip::udp::endpoint> >(); - RAND_bytes (payload + 3, len); - SHA256 (payload + 3, len, m_PathChallenge->first); + size_t payloadSize = 0; + // datetime block + payload[0] = eSSU2BlkDateTime; + htobe16buf (payload + 1, 4); + htobe32buf (payload + 3, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); + payloadSize += 7; + // address block with new address + payloadSize += CreateAddressBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, to); + // path challenge block + payload[payloadSize] = eSSU2BlkPathChallenge; + size_t len = m_Server.GetRng ()() % (m_MaxPayloadSize - payloadSize - 3 - 8) + 8; // 8 bytes min + htobe16buf (payload + payloadSize + 1, len); + payloadSize += 3; + m_PathChallenge = std::make_unique, boost::asio::ip::udp::endpoint> >(); + RAND_bytes (payload + payloadSize, len); + SHA256 (payload + payloadSize, len, m_PathChallenge->first); m_PathChallenge->second = to; - } - len += 3; - if (len < m_MaxPayloadSize) - len += CreatePaddingBlock (payload + len, m_MaxPayloadSize - len, len < 8 ? 8 : 0); + payloadSize += len; + // padding block + if (payloadSize < m_MaxPayloadSize) + payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); + // send to new endpoint auto existing = m_RemoteEndpoint; m_RemoteEndpoint = to; // send path challenge to new endpoint - SendData (payload, len); + SendData (payload, payloadSize); m_RemoteEndpoint = existing; // restore endpoint back until path response received } diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index 6d2bf103..7edc01a5 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -336,7 +336,7 @@ namespace transport virtual void HandleAddress (const uint8_t * buf, size_t len); size_t CreateEndpoint (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& ep); std::shared_ptr FindLocalAddress () const; - void AdjustMaxPayloadSize (); + void AdjustMaxPayloadSize (size_t maxMtu = SSU2_MAX_PACKET_SIZE); bool GetTestingState () const; void SetTestingState(bool testing) const; std::shared_ptr ExtractRouterInfo (const uint8_t * buf, size_t size); From 567183647e8dab9bde51b4a29ebb2432bf77d43e Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 30 Mar 2025 12:37:40 -0400 Subject: [PATCH 1009/1171] non-copyable RouterInfo --- libi2pd/RouterInfo.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 387906ad..cb3ae499 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -210,8 +210,8 @@ namespace data typedef boost::shared_ptr AddressesPtr; #endif RouterInfo (const std::string& fullPath); - RouterInfo (const RouterInfo& ) = default; - RouterInfo& operator=(const RouterInfo& ) = default; + RouterInfo (const RouterInfo& ) = delete; + RouterInfo& operator=(const RouterInfo& ) = delete; RouterInfo (std::shared_ptr&& buf, size_t len); RouterInfo (const uint8_t * buf, size_t len); virtual ~RouterInfo (); From 00920a049d764db6d21459ad5b28f4bfc7866d85 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 30 Mar 2025 13:28:45 -0400 Subject: [PATCH 1010/1171] use g++-x86 for 32-bits platform --- Makefile.haiku | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile.haiku b/Makefile.haiku index 5dce7d7f..eb56a207 100644 --- a/Makefile.haiku +++ b/Makefile.haiku @@ -1,4 +1,8 @@ +ifeq ($(shell $(CXX) -dumpmachine | cut -c 1-4), i586) +CXX = g++-x86 +else CXX = g++ +endif CXXFLAGS := -Wall -std=c++20 INCFLAGS = -I/system/develop/headers DEFINES = -D_DEFAULT_SOURCE -D_GNU_SOURCE From ad3b999732ce9d70492d1980295eca300eb3ba65 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 31 Mar 2025 10:29:16 -0400 Subject: [PATCH 1011/1171] send path challenge of 8 bytes. add Ack block --- libi2pd/SSU2Session.cpp | 21 ++++++++++----------- libi2pd/SSU2Session.h | 2 +- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index a4a9fa03..94a27877 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1660,9 +1660,7 @@ namespace transport LogPrint (eLogDebug, "SSU2: Path response"); if (m_PathChallenge) { - i2p::data::Tag<32> hash; - SHA256 (buf + offset, size, hash); - if (hash == m_PathChallenge->first) + if (buf64toh (buf + offset) == m_PathChallenge->first) { m_RemoteEndpoint = m_PathChallenge->second; m_PathChallenge.reset (nullptr); @@ -3091,14 +3089,15 @@ namespace transport payloadSize += CreateAddressBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, to); // path challenge block payload[payloadSize] = eSSU2BlkPathChallenge; - size_t len = m_Server.GetRng ()() % (m_MaxPayloadSize - payloadSize - 3 - 8) + 8; // 8 bytes min - htobe16buf (payload + payloadSize + 1, len); - payloadSize += 3; - m_PathChallenge = std::make_unique, boost::asio::ip::udp::endpoint> >(); - RAND_bytes (payload + payloadSize, len); - SHA256 (payload + payloadSize, len, m_PathChallenge->first); - m_PathChallenge->second = to; - payloadSize += len; + uint64_t challenge; + RAND_bytes ((uint8_t *)&challenge, 8); + htobe16buf (payload + payloadSize + 1, 8); // always 8 bytes + htobuf64 (payload + payloadSize + 3, challenge); + payloadSize += 11; + m_PathChallenge = std::make_unique >(challenge, to); + // ack block + if (payloadSize < m_MaxPayloadSize) + payloadSize += CreateAckBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); // padding block if (payloadSize < m_MaxPayloadSize) payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index 7edc01a5..ee26255f 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -394,7 +394,7 @@ namespace transport boost::asio::deadline_timer m_ConnectTimer; SSU2TerminationReason m_TerminationReason; size_t m_MaxPayloadSize; - std::unique_ptr, boost::asio::ip::udp::endpoint> > m_PathChallenge; + std::unique_ptr > m_PathChallenge; std::unordered_map m_ReceivedI2NPMsgIDs; // msgID -> timestamp in seconds uint64_t m_LastResendTime, m_LastResendAttemptTime; // in milliseconds int m_NumRanges; From 2280338900695c84e192beb6f4dac5718e02f4aa Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 31 Mar 2025 15:50:16 -0400 Subject: [PATCH 1012/1171] datetime, address, ack blocks in path response packet --- libi2pd/SSU2Session.cpp | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 94a27877..cb10f848 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -3058,18 +3058,31 @@ namespace transport void SSU2Session::SendPathResponse (const uint8_t * data, size_t len) { - if (len > m_MaxPayloadSize - 3) + uint8_t payload[SSU2_MAX_PACKET_SIZE]; + size_t payloadSize = 0; + // datetime block + payload[0] = eSSU2BlkDateTime; + htobe16buf (payload + 1, 4); + htobe32buf (payload + 3, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); + payloadSize += 7; + // address block + payloadSize += CreateAddressBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, m_RemoteEndpoint); + // path response + if (payloadSize + len > m_MaxPayloadSize) { LogPrint (eLogWarning, "SSU2: Incorrect data size for path response ", len); return; - } - uint8_t payload[SSU2_MAX_PACKET_SIZE]; - payload[0] = eSSU2BlkPathResponse; - htobe16buf (payload + 1, len); - memcpy (payload + 3, data, len); - size_t payloadSize = len + 3; + } + payload[payloadSize] = eSSU2BlkPathResponse; + htobe16buf (payload + payloadSize + 1, len); + memcpy (payload + payloadSize + 3, data, len); + payloadSize += len + 3; + // ack block if (payloadSize < m_MaxPayloadSize) - payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, payloadSize < 8 ? 8 : 0); + payloadSize += CreateAckBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); + // padding + if (payloadSize < m_MaxPayloadSize) + payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize); SendData (payload, payloadSize); } From 78d97179b8a994ae2509517840ccc70069f41584 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 1 Apr 2025 20:46:41 -0400 Subject: [PATCH 1013/1171] handle ML-KEM section for new session and create for new session reply --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 86 +++++++++++++++++++---- 1 file changed, 74 insertions(+), 12 deletions(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 865fc973..82be0ebd 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -257,27 +257,66 @@ namespace garlic if (!GetOwner ()) return false; // we are Bob // KDF1 - i2p::crypto::InitNoiseIKState (GetNoiseState (), GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)); // bpk - + if (!i2p::crypto::GetElligator ()->Decode (buf, m_Aepk)) { LogPrint (eLogError, "Garlic: Can't decode elligator"); return false; } buf += 32; len -= 32; - MixHash (m_Aepk, 32); // h = SHA256(h || aepk) + uint64_t n = 0; uint8_t sharedSecret[32]; - if (!GetOwner ()->Decrypt (m_Aepk, sharedSecret, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) // x25519(bsk, aepk) + bool decrypted = false; +#if OPENSSL_PQ + if (GetOwner ()->SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD)) { - LogPrint (eLogWarning, "Garlic: Incorrect Alice ephemeral key"); - return false; - } - MixKey (sharedSecret); + i2p::crypto::InitNoiseIKStateMLKEM512 (GetNoiseState (), GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD)); // bpk + MixHash (m_Aepk, 32); // h = SHA256(h || aepk) + + if (GetOwner ()->Decrypt (m_Aepk, sharedSecret, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) // x25519(bsk, aepk) + { + MixKey (sharedSecret); + + uint8_t nonce[12], encapsKey[i2p::crypto::MLKEM512_KEY_LENGTH]; + CreateNonce (n, nonce); + if (i2p::crypto::AEADChaCha20Poly1305 (buf, i2p::crypto::MLKEM512_KEY_LENGTH, + m_H, 32, m_CK + 32, nonce, encapsKey, i2p::crypto::MLKEM512_KEY_LENGTH , false)) // decrypt + { + decrypted = true; // encaps section has right hash + MixHash (buf, i2p::crypto::MLKEM512_KEY_LENGTH); + n++; + + m_PQKeys = std::make_unique(); + m_PQKeys->SetPublicKey (encapsKey); + } + } + } +#endif + if (!decrypted) + { + if (GetOwner ()->SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) + { + i2p::crypto::InitNoiseIKState (GetNoiseState (), GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)); // bpk + MixHash (m_Aepk, 32); // h = SHA256(h || aepk) + + if (!GetOwner ()->Decrypt (m_Aepk, sharedSecret, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) // x25519(bsk, aepk) + { + LogPrint (eLogWarning, "Garlic: Incorrect Alice ephemeral key"); + return false; + } + MixKey (sharedSecret); + } + else + { + LogPrint (eLogWarning, "Garlic: No supported encryption type"); + return false; + } + } // decrypt flags/static uint8_t nonce[12], fs[32]; - CreateNonce (0, nonce); + CreateNonce (n, nonce); if (!i2p::crypto::AEADChaCha20Poly1305 (buf, 32, m_H, 32, m_CK + 32, nonce, fs, 32, false)) // decrypt { LogPrint (eLogWarning, "Garlic: Flags/static section AEAD verification failed "); @@ -291,8 +330,13 @@ namespace garlic if (isStatic) { // static key, fs is apk - SetRemoteStaticKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD, fs); // TODO: actual key type - if (!GetOwner ()->Decrypt (fs, sharedSecret, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) // x25519(bsk, apk) +#if OPENSSL_PQ + if (m_PQKeys) + SetRemoteStaticKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD, fs); + else +#endif + SetRemoteStaticKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD, fs); + if (!GetOwner ()->Decrypt (fs, sharedSecret, m_RemoteStaticKeyType)) // x25519(bsk, apk) { LogPrint (eLogWarning, "Garlic: Incorrect Alice static key"); return false; @@ -596,7 +640,7 @@ namespace garlic } memcpy (m_NSREncodedKey, out + offset, 32); // for possible next NSR memcpy (m_NSRH, m_H, 32); - offset += 32; + offset += 32; // KDF for Reply Key Section MixHash ((const uint8_t *)&tag, 8); // h = SHA256(h || tag) MixHash (m_EphemeralKeys->GetPublicKey (), 32); // h = SHA256(h || bepk) @@ -613,8 +657,26 @@ namespace garlic return false; } MixKey (sharedSecret); + uint8_t nonce[12]; CreateNonce (0, nonce); +#if OPENSSL_PQ + if (m_PQKeys) + { + uint8_t kemCiphertext[i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH]; + m_PQKeys->Encaps (kemCiphertext, sharedSecret); + + if (!i2p::crypto::AEADChaCha20Poly1305 (kemCiphertext, i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH, + m_H, 32, m_CK + 32, nonce, out + offset, i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH + 16, true)) // encrypt + { + LogPrint (eLogWarning, "Garlic: NSR ML-KEM ciphertext section AEAD encryption failed"); + return false; + } + MixHash (out + offset, i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH + 16); + MixKey (sharedSecret); + offset += i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH + 16; + } +#endif // calculate hash for zero length if (!i2p::crypto::AEADChaCha20Poly1305 (nonce /* can be anything */, 0, m_H, 32, m_CK + 32, nonce, out + offset, 16, true)) // encrypt, ciphertext = ENCRYPT(k, n, ZEROLEN, ad) { From 3be4c7217f29bf837e0591cb1435f856e3f7a0d1 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 3 Apr 2025 18:42:34 -0400 Subject: [PATCH 1014/1171] move buffer when insert to buffer queue. clean entire queue in one call --- libi2pd/Streaming.cpp | 58 ++++++++++++++++++++++++++--------------- libi2pd/Streaming.h | 4 +-- libi2pd_client/I2CP.cpp | 4 +-- 3 files changed, 41 insertions(+), 25 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 0ed6067c..d21cfa62 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2024, The PurpleI2P Project +* Copyright (c) 2013-2025, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -19,39 +19,55 @@ namespace i2p { namespace stream { - void SendBufferQueue::Add (std::shared_ptr buf) + void SendBufferQueue::Add (std::shared_ptr&& buf) { if (buf) { - m_Buffers.push_back (buf); m_Size += buf->len; + m_Buffers.push_back (std::move (buf)); } } size_t SendBufferQueue::Get (uint8_t * buf, size_t len) { + if (!m_Size) return 0; size_t offset = 0; - while (!m_Buffers.empty () && offset < len) + if (len >= m_Size) { - auto nextBuffer = m_Buffers.front (); - auto rem = nextBuffer->GetRemainingSize (); - if (offset + rem <= len) + for (auto& it: m_Buffers) { - // whole buffer - memcpy (buf + offset, nextBuffer->GetRemaningBuffer (), rem); + auto rem = it->GetRemainingSize (); + memcpy (buf + offset, it->GetRemaningBuffer (), rem); offset += rem; - m_Buffers.pop_front (); // delete it } - else + m_Buffers.clear (); + m_Size = 0; + return offset; + } + else + { + while (!m_Buffers.empty () && offset < len) { - // partially - rem = len - offset; - memcpy (buf + offset, nextBuffer->GetRemaningBuffer (), rem); - nextBuffer->offset += rem; - offset = len; // break + auto nextBuffer = m_Buffers.front (); + auto rem = nextBuffer->GetRemainingSize (); + if (offset + rem <= len) + { + // whole buffer + memcpy (buf + offset, nextBuffer->GetRemaningBuffer (), rem); + offset += rem; + m_Buffers.pop_front (); // delete it + } + else + { + // partially + rem = len - offset; + memcpy (buf + offset, nextBuffer->GetRemaningBuffer (), rem); + nextBuffer->offset += rem; + offset = len; // break + } } - } - m_Size -= offset; + m_Size -= offset; + } return offset; } @@ -59,7 +75,7 @@ namespace stream { if (!m_Buffers.empty ()) { - for (auto it: m_Buffers) + for (auto& it: m_Buffers) it->Cancel (); m_Buffers.clear (); m_Size = 0; @@ -717,10 +733,10 @@ namespace stream else if (handler) handler(boost::system::error_code ()); auto s = shared_from_this (); - boost::asio::post (m_Service, [s, buffer]() + boost::asio::post (m_Service, [s, buffer = std::move(buffer)]() mutable { if (buffer) - s->m_SendBuffer.Add (buffer); + s->m_SendBuffer.Add (std::move(buffer)); s->SendBuffer (); }); } diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index d75cb6eb..8280477b 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2024, The PurpleI2P Project +* Copyright (c) 2013-2025, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -150,7 +150,7 @@ namespace stream SendBufferQueue (): m_Size (0) {}; ~SendBufferQueue () { CleanUp (); }; - void Add (std::shared_ptr buf); + void Add (std::shared_ptr&& buf); size_t Get (uint8_t * buf, size_t len); size_t GetSize () const { return m_Size; }; bool IsEmpty () const { return m_Buffers.empty (); }; diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index 09fcee71..11278e7a 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -533,7 +533,7 @@ namespace client if (sendBuf) { if (m_SendQueue.GetSize () < I2CP_MAX_SEND_QUEUE_SIZE) - m_SendQueue.Add (sendBuf); + m_SendQueue.Add (std::move(sendBuf)); else { LogPrint (eLogWarning, "I2CP: Send queue size exceeds ", I2CP_MAX_SEND_QUEUE_SIZE); @@ -1079,7 +1079,7 @@ namespace client if (sendBuf) { if (m_SendQueue.GetSize () < I2CP_MAX_SEND_QUEUE_SIZE) - m_SendQueue.Add (sendBuf); + m_SendQueue.Add (std::move(sendBuf)); else { LogPrint (eLogWarning, "I2CP: Send queue size exceeds ", I2CP_MAX_SEND_QUEUE_SIZE); From 8ca74a3e1d9ccd8b835d565fdb6383f0fd4b7840 Mon Sep 17 00:00:00 2001 From: Alexey Chernov Date: Fri, 4 Apr 2025 22:35:56 +0300 Subject: [PATCH 1015/1171] [systemd] Wait for network-online target when starting service (#2169) --- contrib/i2pd.service | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contrib/i2pd.service b/contrib/i2pd.service index 381ae483..1ab46979 100644 --- a/contrib/i2pd.service +++ b/contrib/i2pd.service @@ -1,7 +1,8 @@ [Unit] Description=I2P Router written in C++ Documentation=man:i2pd(1) https://i2pd.readthedocs.io/en/latest/ -After=network.target +Wants=network.target +After=network.target network-online.target [Service] User=i2pd From bce0ccf161124b752d434bd58b0c3cc7bdc1818a Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 4 Apr 2025 19:52:32 -0400 Subject: [PATCH 1016/1171] all ratchets types are eligible for ECIESx25519 --- libi2pd/Destination.cpp | 6 ++++++ libi2pd/Destination.h | 2 ++ libi2pd/Garlic.cpp | 4 ++-- libi2pd/Garlic.h | 2 ++ libi2pd_client/I2CP.h | 2 ++ 5 files changed, 14 insertions(+), 2 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index e20249c5..a3f6a8c9 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1533,6 +1533,12 @@ namespace client #endif } + bool ClientDestination::SupportsRatchets () const + { + if (m_EncryptionKeys.empty ()) return false; + return m_EncryptionKeys.rbegin ()->first >= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD; + } + const uint8_t * ClientDestination::GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const { auto it = m_EncryptionKeys.find (keyType); diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 802d7780..a76a1be4 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -296,6 +296,8 @@ namespace client protected: + // GarlicDestionation + bool SupportsRatchets () const override; // LeaseSetDestination void CleanupDestination () override; i2p::data::CryptoKeyType GetPreferredCryptoType () const override { return m_PreferredCryptoType; } diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 0098bdcd..5a3e4cae 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -498,7 +498,7 @@ namespace garlic buf += 4; // length bool found = false; - if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) + if (SupportsRatchets ()) // try ECIESx25519 tag found = HandleECIESx25519TagMessage (buf, length); if (!found) @@ -535,7 +535,7 @@ namespace garlic decryption->Decrypt(buf + 514, length - 514, iv, buf + 514); HandleAESBlock (buf + 514, length - 514, decryption, msg->from); } - else if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) + else if (SupportsRatchets ()) { // otherwise ECIESx25519 auto ts = i2p::util::GetMillisecondsSinceEpoch (); diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index 6283d740..0eef4871 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -279,6 +279,8 @@ namespace garlic void SaveTags (); void LoadTags (); + virtual bool SupportsRatchets () const { return GetIdentity ()->GetCryptoKeyType () >= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD; } + private: void HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr decryption, diff --git a/libi2pd_client/I2CP.h b/libi2pd_client/I2CP.h index 3a9a7e7f..84243e6f 100644 --- a/libi2pd_client/I2CP.h +++ b/libi2pd_client/I2CP.h @@ -108,6 +108,8 @@ namespace client protected: + // GarlicDestination + bool SupportsRatchets () const override { return (bool)m_ECIESx25519Decryptor; } // LeaseSetDestination void CleanupDestination () override; i2p::data::CryptoKeyType GetPreferredCryptoType () const override; From 2f2ecc32d2ce31530f98a450e869174b8d13d6cf Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 5 Apr 2025 18:12:38 -0400 Subject: [PATCH 1017/1171] correct key type and message size for ML-KEM-512 --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 31 +++++++++++++++++------ 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 82be0ebd..5e7faefe 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -274,22 +274,24 @@ namespace garlic i2p::crypto::InitNoiseIKStateMLKEM512 (GetNoiseState (), GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD)); // bpk MixHash (m_Aepk, 32); // h = SHA256(h || aepk) - if (GetOwner ()->Decrypt (m_Aepk, sharedSecret, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) // x25519(bsk, aepk) + if (GetOwner ()->Decrypt (m_Aepk, sharedSecret, i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD)) // x25519(bsk, aepk) { MixKey (sharedSecret); uint8_t nonce[12], encapsKey[i2p::crypto::MLKEM512_KEY_LENGTH]; CreateNonce (n, nonce); if (i2p::crypto::AEADChaCha20Poly1305 (buf, i2p::crypto::MLKEM512_KEY_LENGTH, - m_H, 32, m_CK + 32, nonce, encapsKey, i2p::crypto::MLKEM512_KEY_LENGTH , false)) // decrypt + m_H, 32, m_CK + 32, nonce, encapsKey, i2p::crypto::MLKEM512_KEY_LENGTH, false)) // decrypt { decrypted = true; // encaps section has right hash - MixHash (buf, i2p::crypto::MLKEM512_KEY_LENGTH); + MixHash (buf, i2p::crypto::MLKEM512_KEY_LENGTH + 16); + buf += i2p::crypto::MLKEM512_KEY_LENGTH + 16; + len -= i2p::crypto::MLKEM512_KEY_LENGTH + 16; n++; m_PQKeys = std::make_unique(); m_PQKeys->SetPublicKey (encapsKey); - } + } } } #endif @@ -579,7 +581,7 @@ namespace garlic CreateNonce (n, nonce); const uint8_t * fs; if (isStatic) - fs = GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); + fs = GetOwner ()->GetEncryptionPublicKey (m_RemoteStaticKeyType); else { memset (out + offset, 0, 32); // all zeros flags section @@ -596,7 +598,7 @@ namespace garlic // KDF2 if (isStatic) { - GetOwner ()->Decrypt (m_RemoteStaticKey, sharedSecret, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); // x25519 (ask, bpk) + GetOwner ()->Decrypt (m_RemoteStaticKey, sharedSecret, m_RemoteStaticKeyType); // x25519 (ask, bpk) MixKey (sharedSecret); } else @@ -665,7 +667,7 @@ namespace garlic { uint8_t kemCiphertext[i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH]; m_PQKeys->Encaps (kemCiphertext, sharedSecret); - + if (!i2p::crypto::AEADChaCha20Poly1305 (kemCiphertext, i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH, m_H, 32, m_CK + 32, nonce, out + offset, i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH + 16, true)) // encrypt { @@ -761,7 +763,7 @@ namespace garlic return false; } MixKey (sharedSecret); - GetOwner ()->Decrypt (bepk, sharedSecret, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); // x25519 (ask, bepk) + GetOwner ()->Decrypt (bepk, sharedSecret, m_RemoteStaticKeyType); // x25519 (ask, bepk) MixKey (sharedSecret); uint8_t nonce[12]; @@ -779,6 +781,7 @@ namespace garlic } MixHash (buf, i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH + 16); buf += i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH + 16; + len -= i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH + 16; // decaps m_PQKeys->Decaps (kemCiphertext, sharedSecret); MixKey (sharedSecret); @@ -945,7 +948,11 @@ namespace garlic if (!payload) return nullptr; size_t len = CreatePayload (msg, m_State != eSessionStateEstablished, payload); if (!len) return nullptr; +#if OPENSSL_PQ + auto m = NewI2NPMessage (len + (m_State == eSessionStateEstablished ? 28 : i2p::crypto::MLKEM512_KEY_LENGTH + 116)); +#else auto m = NewI2NPMessage (len + 100); // 96 + 4 +#endif m->Align (12); // in order to get buf aligned to 16 (12 + 4) uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length @@ -960,11 +967,19 @@ namespace garlic if (!NewOutgoingSessionMessage (payload, len, buf, m->maxLen)) return nullptr; len += 96; +#if OPENSSL_PQ + if (m_RemoteStaticKeyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD) + len += i2p::crypto::MLKEM512_KEY_LENGTH + 16; +#endif break; case eSessionStateNewSessionReceived: if (!NewSessionReplyMessage (payload, len, buf, m->maxLen)) return nullptr; len += 72; +#if OPENSSL_PQ + if (m_RemoteStaticKeyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD) + len += i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH + 16; +#endif break; case eSessionStateNewSessionReplySent: if (!NextNewSessionReplyMessage (payload, len, buf, m->maxLen)) From 3afe6455b285329198805a47e8f79d407f402415 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 6 Apr 2025 15:34:01 -0400 Subject: [PATCH 1018/1171] reset nonce to 0 before payload encrypt/decrypt for ML-KEM-512 --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 5e7faefe..37481d96 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -334,7 +334,10 @@ namespace garlic // static key, fs is apk #if OPENSSL_PQ if (m_PQKeys) + { SetRemoteStaticKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD, fs); + CreateNonce (0, nonce); // reset nonce + } else #endif SetRemoteStaticKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD, fs); @@ -600,6 +603,10 @@ namespace garlic { GetOwner ()->Decrypt (m_RemoteStaticKey, sharedSecret, m_RemoteStaticKeyType); // x25519 (ask, bpk) MixKey (sharedSecret); +#if OPENSSL_PQ + if (m_RemoteStaticKeyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD) + CreateNonce (0, nonce); // reset nonce +#endif } else CreateNonce (1, nonce); From 6b38085f277b6625c5d1ee470e603db2e475f961 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 7 Apr 2025 18:47:53 -0400 Subject: [PATCH 1019/1171] Noise state Encrypt/Decrypt operations --- libi2pd/Crypto.cpp | 59 +++++++++++++++++------ libi2pd/Crypto.h | 6 +++ libi2pd/ECIESX25519AEADRatchetSession.cpp | 53 ++++++++------------ 3 files changed, 72 insertions(+), 46 deletions(-) diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index 9bdfe43f..e8210a27 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -821,6 +821,18 @@ namespace crypto // Noise + void NoiseSymmetricState::Init (const uint8_t * ck, const uint8_t * hh, const uint8_t * pub) + { + // pub is Bob's public static key, hh = SHA256(h) + memcpy (m_CK, ck, 32); + SHA256_CTX ctx; + SHA256_Init (&ctx); + SHA256_Update (&ctx, hh, 32); + SHA256_Update (&ctx, pub, 32); + SHA256_Final (m_H, &ctx); // h = MixHash(pub) = SHA256(hh || pub) + m_N = 0; + } + void NoiseSymmetricState::MixHash (const uint8_t * buf, size_t len) { SHA256_CTX ctx; @@ -844,20 +856,39 @@ namespace crypto { HKDF (m_CK, sharedSecret, 32, "", m_CK); // new ck is m_CK[0:31], key is m_CK[32:63] + m_N = 0; } - static void InitNoiseState (NoiseSymmetricState& state, const uint8_t * ck, - const uint8_t * hh, const uint8_t * pub) + bool NoiseSymmetricState::Encrypt (const uint8_t * in, uint8_t * out, size_t len) { - // pub is Bob's public static key, hh = SHA256(h) - memcpy (state.m_CK, ck, 32); - SHA256_CTX ctx; - SHA256_Init (&ctx); - SHA256_Update (&ctx, hh, 32); - SHA256_Update (&ctx, pub, 32); - SHA256_Final (state.m_H, &ctx); // h = MixHash(pub) = SHA256(hh || pub) + uint8_t nonce[12]; + if (m_N) + { + memset (nonce, 0, 4); + htole64buf (nonce + 4, m_N); + } + else + memset (nonce, 0, 12); + auto ret = AEADChaCha20Poly1305 (in, len, m_H, 32, m_CK + 32, nonce, out, len + 16, true); + if (ret) m_N++; + return ret; } + bool NoiseSymmetricState::Decrypt (const uint8_t * in, uint8_t * out, size_t len) + { + uint8_t nonce[12]; + if (m_N) + { + memset (nonce, 0, 4); + htole64buf (nonce + 4, m_N); + } + else + memset (nonce, 0, 12); + auto ret = AEADChaCha20Poly1305 (in, len, m_H, 32, m_CK + 32, nonce, out, len, false); + if (ret) m_N++; + return ret; + } + void InitNoiseNState (NoiseSymmetricState& state, const uint8_t * pub) { static constexpr char protocolName[] = "Noise_N_25519_ChaChaPoly_SHA256"; // 31 chars @@ -866,7 +897,7 @@ namespace crypto 0x69, 0x4d, 0x52, 0x44, 0x5a, 0x27, 0xd9, 0xad, 0xfa, 0xd2, 0x9c, 0x76, 0x32, 0x39, 0x5d, 0xc1, 0xe4, 0x35, 0x4c, 0x69, 0xb4, 0xf9, 0x2e, 0xac, 0x8a, 0x1e, 0xe4, 0x6a, 0x9e, 0xd2, 0x15, 0x54 }; // hh = SHA256(protocol_name || 0) - InitNoiseState (state, (const uint8_t *)protocolName, hh, pub); // ck = protocol_name || 0 + state.Init ((const uint8_t *)protocolName, hh, pub); // ck = protocol_name || 0 } void InitNoiseXKState (NoiseSymmetricState& state, const uint8_t * pub) @@ -881,7 +912,7 @@ namespace crypto 0x49, 0xff, 0x48, 0x3f, 0xc4, 0x04, 0xb9, 0xb2, 0x6b, 0x11, 0x94, 0x36, 0x72, 0xff, 0x05, 0xb5, 0x61, 0x27, 0x03, 0x31, 0xba, 0x89, 0xb8, 0xfc, 0x33, 0x15, 0x93, 0x87, 0x57, 0xdd, 0x3d, 0x1e }; // SHA256 (protocolNameHash) - InitNoiseState (state, protocolNameHash, hh, pub); + state.Init (protocolNameHash, hh, pub); } void InitNoiseXKState1 (NoiseSymmetricState& state, const uint8_t * pub) @@ -896,7 +927,7 @@ namespace crypto 0xdc, 0x85, 0xe6, 0xaf, 0x7b, 0x02, 0x65, 0x0c, 0xf1, 0xf9, 0x0d, 0x71, 0xfb, 0xc6, 0xd4, 0x53, 0xa7, 0xcf, 0x6d, 0xbf, 0xbd, 0x52, 0x5e, 0xa5, 0xb5, 0x79, 0x1c, 0x47, 0xb3, 0x5e, 0xbc, 0x33 }; // SHA256 (protocolNameHash) - InitNoiseState (state, protocolNameHash, hh, pub); + state.Init (protocolNameHash, hh, pub); } void InitNoiseIKState (NoiseSymmetricState& state, const uint8_t * pub) @@ -911,7 +942,7 @@ namespace crypto 0x9c, 0xcf, 0x85, 0x2c, 0xc9, 0x3b, 0xb9, 0x50, 0x44, 0x41, 0xe9, 0x50, 0xe0, 0x1d, 0x52, 0x32, 0x2e, 0x0d, 0x47, 0xad, 0xd1, 0xe9, 0xa5, 0x55, 0xf7, 0x55, 0xb5, 0x69, 0xae, 0x18, 0x3b, 0x5c }; // SHA256 (protocolNameHash) - InitNoiseState (state, protocolNameHash, hh, pub); + state.Init (protocolNameHash, hh, pub); } void InitNoiseIKStateMLKEM512 (NoiseSymmetricState& state, const uint8_t * pub) @@ -926,7 +957,7 @@ namespace crypto 0x95, 0x8d, 0xf6, 0x6c, 0x95, 0xce, 0xa9, 0xf7, 0x42, 0xfc, 0xfa, 0x62, 0x71, 0x36, 0x1e, 0xa7, 0xdc, 0x7a, 0xc0, 0x75, 0x01, 0xcf, 0xf9, 0xfc, 0x9f, 0xdb, 0x4c, 0x68, 0x3a, 0x53, 0x49, 0xeb }; // SHA256 (protocolNameHash) - InitNoiseState (state, protocolNameHash, hh, pub); + state.Init (protocolNameHash, hh, pub); } // init and terminate diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index dcdc27d3..aa6466be 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -255,10 +255,16 @@ namespace crypto struct NoiseSymmetricState { uint8_t m_H[32] /*h*/, m_CK[64] /*[ck, k]*/; + uint64_t m_N; + void Init (const uint8_t * ck, const uint8_t * hh, const uint8_t * pub); + void MixHash (const uint8_t * buf, size_t len); void MixHash (const std::vector >& bufs); void MixKey (const uint8_t * sharedSecret); + + bool Encrypt (const uint8_t * in, uint8_t * out, size_t len); // out length = len + 16 + bool Decrypt (const uint8_t * in, uint8_t * out, size_t len); // len without 16 bytes tag }; void InitNoiseNState (NoiseSymmetricState& state, const uint8_t * pub); // Noise_N (tunnels, router) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 37481d96..467a3752 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -559,29 +559,22 @@ namespace garlic return false; } MixKey (sharedSecret); - uint64_t n = 0; // seqn #if OPENSSL_PQ if (m_RemoteStaticKeyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD) { uint8_t encapsKey[i2p::crypto::MLKEM512_KEY_LENGTH]; m_PQKeys->GetPublicKey (encapsKey); // encrypt encapsKey - uint8_t nonce[12]; - CreateNonce (n, nonce); - if (!i2p::crypto::AEADChaCha20Poly1305 (encapsKey, i2p::crypto::MLKEM512_KEY_LENGTH, - m_H, 32, m_CK + 32, nonce, out + offset, i2p::crypto::MLKEM512_KEY_LENGTH + 16, true)) // encrypt + if (!Encrypt (encapsKey, out + offset, i2p::crypto::MLKEM512_KEY_LENGTH)) { LogPrint (eLogWarning, "Garlic: ML-KEM encap_key section AEAD encryption failed "); return false; } MixHash (out + offset, i2p::crypto::MLKEM512_KEY_LENGTH + 16); // h = SHA256(h || ciphertext) offset += i2p::crypto::MLKEM512_KEY_LENGTH + 16; - n++; } #endif // encrypt flags/static key section - uint8_t nonce[12]; - CreateNonce (n, nonce); const uint8_t * fs; if (isStatic) fs = GetOwner ()->GetEncryptionPublicKey (m_RemoteStaticKeyType); @@ -590,7 +583,7 @@ namespace garlic memset (out + offset, 0, 32); // all zeros flags section fs = out + offset; } - if (!i2p::crypto::AEADChaCha20Poly1305 (fs, 32, m_H, 32, m_CK + 32, nonce, out + offset, 48, true)) // encrypt + if (!Encrypt (fs, out + offset, 32)) { LogPrint (eLogWarning, "Garlic: Flags/static section AEAD encryption failed "); return false; @@ -602,16 +595,10 @@ namespace garlic if (isStatic) { GetOwner ()->Decrypt (m_RemoteStaticKey, sharedSecret, m_RemoteStaticKeyType); // x25519 (ask, bpk) - MixKey (sharedSecret); -#if OPENSSL_PQ - if (m_RemoteStaticKeyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD) - CreateNonce (0, nonce); // reset nonce -#endif + MixKey (sharedSecret); } - else - CreateNonce (1, nonce); // encrypt payload - if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_CK + 32, nonce, out + offset, len + 16, true)) // encrypt + if (!Encrypt (payload, out + offset, len)) { LogPrint (eLogWarning, "Garlic: Payload section AEAD encryption failed"); return false; @@ -667,16 +654,13 @@ namespace garlic } MixKey (sharedSecret); - uint8_t nonce[12]; - CreateNonce (0, nonce); #if OPENSSL_PQ if (m_PQKeys) { uint8_t kemCiphertext[i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH]; m_PQKeys->Encaps (kemCiphertext, sharedSecret); - if (!i2p::crypto::AEADChaCha20Poly1305 (kemCiphertext, i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH, - m_H, 32, m_CK + 32, nonce, out + offset, i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH + 16, true)) // encrypt + if (!Encrypt (kemCiphertext, out + offset, i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH)) { LogPrint (eLogWarning, "Garlic: NSR ML-KEM ciphertext section AEAD encryption failed"); return false; @@ -687,7 +671,7 @@ namespace garlic } #endif // calculate hash for zero length - if (!i2p::crypto::AEADChaCha20Poly1305 (nonce /* can be anything */, 0, m_H, 32, m_CK + 32, nonce, out + offset, 16, true)) // encrypt, ciphertext = ENCRYPT(k, n, ZEROLEN, ad) + if (!Encrypt (sharedSecret /* can be anything */, out + offset, 0)) // encrypt, ciphertext = ENCRYPT(k, n, ZEROLEN, ad) { LogPrint (eLogWarning, "Garlic: Reply key section AEAD encryption failed"); return false; @@ -708,6 +692,7 @@ namespace garlic GetOwner ()->GetNumRatchetInboundTags () : ECIESX25519_MIN_NUM_GENERATED_TAGS); i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", m_NSRKey, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32) // encrypt payload + uint8_t nonce[12]; memset (nonce, 0, 12); // seqn = 0 if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_NSRKey, nonce, out + offset, len + 16, true)) // encrypt { LogPrint (eLogWarning, "Garlic: NSR payload section AEAD encryption failed"); @@ -729,16 +714,22 @@ namespace garlic memcpy (m_H, m_NSRH, 32); MixHash ((const uint8_t *)&tag, 8); // h = SHA256(h || tag) MixHash (m_EphemeralKeys->GetPublicKey (), 32); // h = SHA256(h || bepk) - uint8_t nonce[12]; - CreateNonce (0, nonce); - if (!i2p::crypto::AEADChaCha20Poly1305 (nonce /* can be anything */, 0, m_H, 32, m_CK + 32, nonce, out + 40, 16, true)) // encrypt, ciphertext = ENCRYPT(k, n, ZEROLEN, ad) + m_N = 0; + size_t offset = 40; +#if OPENSSL_PQ + if (m_PQKeys) + // TODO: encrypted ML-KEM section + offset += i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH + 16; +#endif + if (!Encrypt (m_NSRH /* can be anything */, out + offset, 0)) // encrypt, ciphertext = ENCRYPT(k, n, ZEROLEN, ad) { LogPrint (eLogWarning, "Garlic: Reply key section AEAD encryption failed"); return false; } - MixHash (out + 40, 16); // h = SHA256(h || ciphertext) + MixHash (out + offset, 16); // h = SHA256(h || ciphertext) // encrypt payload - if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_NSRKey, nonce, out + 56, len + 16, true)) // encrypt + uint8_t nonce[12]; memset (nonce, 0, 12); + if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_NSRKey, nonce, out + offset + 16, len + 16, true)) // encrypt { LogPrint (eLogWarning, "Garlic: Next NSR payload section AEAD encryption failed"); return false; @@ -773,15 +764,12 @@ namespace garlic GetOwner ()->Decrypt (bepk, sharedSecret, m_RemoteStaticKeyType); // x25519 (ask, bepk) MixKey (sharedSecret); - uint8_t nonce[12]; - CreateNonce (0, nonce); #if OPENSSL_PQ if (m_RemoteStaticKeyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD) { // decrypt kem_ciphertext section uint8_t kemCiphertext[i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH]; - if (!i2p::crypto::AEADChaCha20Poly1305 (buf, i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH, - m_H, 32, m_CK + 32, nonce, kemCiphertext, i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH, false)) // decrypt, DECRYPT(k, n, ZEROLEN, ad) verification only + if (!Decrypt (buf, kemCiphertext, i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH)) { LogPrint (eLogWarning, "Garlic: Reply ML-KEM ciphertext section AEAD decryption failed"); return false; @@ -795,7 +783,7 @@ namespace garlic } #endif // calculate hash for zero length - if (!i2p::crypto::AEADChaCha20Poly1305 (buf, 0, m_H, 32, m_CK + 32, nonce, sharedSecret/* can be anything */, 0, false)) // decrypt, DECRYPT(k, n, ZEROLEN, ad) verification only + if (!Decrypt (buf, sharedSecret/* can be anything */, 0)) // decrypt, DECRYPT(k, n, ZEROLEN, ad) verification only { LogPrint (eLogWarning, "Garlic: Reply key section AEAD decryption failed"); return false; @@ -820,6 +808,7 @@ namespace garlic } i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", keydata, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32) // decrypt payload + uint8_t nonce[12]; memset (nonce, 0, 12); // seqn = 0 if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_H, 32, keydata, nonce, buf, len - 16, false)) // decrypt { LogPrint (eLogWarning, "Garlic: Payload section AEAD decryption failed"); From 711f5bcc6210bf2806ae477739d771303dcd6e65 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 7 Apr 2025 20:33:19 -0400 Subject: [PATCH 1020/1171] store ML-KEM section for possible next NSR --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 21 +++++++++++++++++++-- libi2pd/ECIESX25519AEADRatchetSession.h | 2 ++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 467a3752..cfcbf5bb 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -665,6 +665,8 @@ namespace garlic LogPrint (eLogWarning, "Garlic: NSR ML-KEM ciphertext section AEAD encryption failed"); return false; } + m_NSREncodedPQKey = std::make_unique >(); + memcpy (m_NSREncodedPQKey->data (), out + offset, i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH + 16); MixHash (out + offset, i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH + 16); MixKey (sharedSecret); offset += i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH + 16; @@ -718,8 +720,19 @@ namespace garlic size_t offset = 40; #if OPENSSL_PQ if (m_PQKeys) - // TODO: encrypted ML-KEM section - offset += i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH + 16; + { + if (m_NSREncodedPQKey) + { + memcpy (out + offset, m_NSREncodedPQKey->data (), i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH + 16); + MixHash (out + offset, i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH + 16); + offset += i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH + 16; + } + else + { + LogPrint (eLogWarning, "Garlic: No stored ML-KEM keys"); + return false; + } + } #endif if (!Encrypt (m_NSRH /* can be anything */, out + offset, 0)) // encrypt, ciphertext = ENCRYPT(k, n, ZEROLEN, ad) { @@ -914,6 +927,10 @@ namespace garlic m_State = eSessionStateEstablished; m_NSRSendTagset = nullptr; m_EphemeralKeys = nullptr; +#if OPENSSL_PQ + m_PQKeys = nullptr; + m_NSREncodedPQKey = nullptr; +#endif [[fallthrough]]; case eSessionStateEstablished: if (m_SendReverseKey && receiveTagset->GetTagSetID () == m_NextReceiveRatchet->GetReceiveTagSetID ()) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index cd32cb98..b988263a 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include "Identity.h" @@ -228,6 +229,7 @@ namespace garlic std::shared_ptr m_EphemeralKeys; #if OPENSSL_PQ std::unique_ptr m_PQKeys; + std::unique_ptr > m_NSREncodedPQKey; #endif SessionState m_State = eSessionStateNew; uint64_t m_SessionCreatedTimestamp = 0, m_LastActivityTimestamp = 0, // incoming (in seconds) From f6abbe59086ed2ca8b32fe63e6f120c4c0258d86 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 8 Apr 2025 14:39:46 -0400 Subject: [PATCH 1021/1171] Use noise state Encrypt/Decrypt operations --- libi2pd/NTCP2.cpp | 81 ++++++++++++++++++++++++++--------------------- libi2pd/NTCP2.h | 9 +++--- 2 files changed, 49 insertions(+), 41 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 870fcc19..b3a51488 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -145,10 +145,12 @@ namespace transport // 2 bytes reserved htobe32buf (options + 8, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); // tsA, rounded to seconds // 4 bytes reserved - // sign and encrypt options, use m_H as AD - uint8_t nonce[12]; - memset (nonce, 0, 12); // set nonce to zero - i2p::crypto::AEADChaCha20Poly1305 (options, 16, GetH (), 32, GetK (), nonce, m_SessionRequestBuffer + 32, 32, true); // encrypt + // encrypt options + if (!Encrypt (options, m_SessionRequestBuffer + 32, 16)) + { + LogPrint (eLogWarning, "NTCP2: SessionRequest failed to encrypt options"); + return false; + } return true; } @@ -167,14 +169,16 @@ namespace transport memset (options, 0, 16); htobe16buf (options + 2, paddingLen); // padLen htobe32buf (options + 8, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); // tsB, rounded to seconds - // sign and encrypt options, use m_H as AD - uint8_t nonce[12]; - memset (nonce, 0, 12); // set nonce to zero - i2p::crypto::AEADChaCha20Poly1305 (options, 16, GetH (), 32, GetK (), nonce, m_SessionCreatedBuffer + 32, 32, true); // encrypt + // encrypt options + if (!Encrypt (options, m_SessionCreatedBuffer + 32, 16)) + { + LogPrint (eLogWarning, "NTCP2: SessionCreated failed to encrypt options"); + return false; + } return true; } - void NTCP2Establisher::CreateSessionConfirmedMessagePart1 (const uint8_t * nonce) + bool NTCP2Establisher::CreateSessionConfirmedMessagePart1 () { // update AD MixHash (m_SessionCreatedBuffer + 32, 32); // encrypted payload @@ -182,19 +186,28 @@ namespace transport if (paddingLength > 0) MixHash (m_SessionCreatedBuffer + 64, paddingLength); - // part1 48 bytes - i2p::crypto::AEADChaCha20Poly1305 (i2p::context.GetNTCP2StaticPublicKey (), 32, GetH (), 32, GetK (), nonce, m_SessionConfirmedBuffer, 48, true); // encrypt + // part1 48 bytes, n = 1 + if (!Encrypt (i2p::context.GetNTCP2StaticPublicKey (), m_SessionConfirmedBuffer, 32)) + { + LogPrint (eLogWarning, "NTCP2: SessionConfirmed failed to encrypt part1"); + return false; + } + return true; } - bool NTCP2Establisher::CreateSessionConfirmedMessagePart2 (const uint8_t * nonce) + bool NTCP2Establisher::CreateSessionConfirmedMessagePart2 () { // part 2 // update AD again MixHash (m_SessionConfirmedBuffer, 48); // encrypt m3p2, it must be filled in SessionRequest - if (!KDF3Alice ()) return false; + if (!KDF3Alice ()) return false; // MixKey, n = 0 uint8_t * m3p2 = m_SessionConfirmedBuffer + 48; - i2p::crypto::AEADChaCha20Poly1305 (m3p2, m3p2Len - 16, GetH (), 32, GetK (), nonce, m3p2, m3p2Len, true); // encrypt + if (!Encrypt (m3p2, m3p2, m3p2Len - 16)) + { + LogPrint (eLogWarning, "NTCP2: SessionConfirmed failed to encrypt part2"); + return false; + } // update h again MixHash (m3p2, m3p2Len); //h = SHA256(h || ciphertext) return true; @@ -214,10 +227,9 @@ namespace transport LogPrint (eLogWarning, "NTCP2: SessionRequest KDF failed"); return false; } - // verify MAC and decrypt options block (32 bytes), use m_H as AD - uint8_t nonce[12], options[16]; - memset (nonce, 0, 12); // set nonce to zero - if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionRequestBuffer + 32, 16, GetH (), 32, GetK (), nonce, options, 16, false)) // decrypt + // verify MAC and decrypt options block (32 bytes) + uint8_t options[16]; + if (Decrypt (m_SessionRequestBuffer + 32, options, 16)) { // options if (options[0] && options[0] != i2p::context.GetNetID ()) @@ -274,9 +286,7 @@ namespace transport } // decrypt and verify MAC uint8_t payload[16]; - uint8_t nonce[12]; - memset (nonce, 0, 12); // set nonce to zero - if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionCreatedBuffer + 32, 16, GetH (), 32, GetK (), nonce, payload, 16, false)) // decrypt + if (Decrypt (m_SessionCreatedBuffer + 32, payload, 16)) { // options paddingLen = bufbe16toh(payload + 2); @@ -297,7 +307,7 @@ namespace transport return true; } - bool NTCP2Establisher::ProcessSessionConfirmedMessagePart1 (const uint8_t * nonce) + bool NTCP2Establisher::ProcessSessionConfirmedMessagePart1 () { // update AD MixHash (m_SessionCreatedBuffer + 32, 32); // encrypted payload @@ -305,7 +315,8 @@ namespace transport if (paddingLength > 0) MixHash (m_SessionCreatedBuffer + 64, paddingLength); - if (!i2p::crypto::AEADChaCha20Poly1305 (m_SessionConfirmedBuffer, 32, GetH (), 32, GetK (), nonce, m_RemoteStaticKey, 32, false)) // decrypt S + // decrypt S, n = 1 + if (!Decrypt (m_SessionConfirmedBuffer, m_RemoteStaticKey, 32)) { LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part1 AEAD verification failed "); return false; @@ -313,17 +324,17 @@ namespace transport return true; } - bool NTCP2Establisher::ProcessSessionConfirmedMessagePart2 (const uint8_t * nonce, uint8_t * m3p2Buf) + bool NTCP2Establisher::ProcessSessionConfirmedMessagePart2 (uint8_t * m3p2Buf) { // update AD again MixHash (m_SessionConfirmedBuffer, 48); - if (!KDF3Bob ()) + if (!KDF3Bob ()) // MixKey, n = 0 { LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part2 KDF failed"); return false; } - if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionConfirmedBuffer + 48, m3p2Len - 16, GetH (), 32, GetK (), nonce, m3p2Buf, m3p2Len - 16, false)) // decrypt + if (Decrypt (m_SessionConfirmedBuffer + 48, m3p2Buf, m3p2Len - 16)) // calculate new h again for KDF data MixHash (m_SessionConfirmedBuffer + 48, m3p2Len); // h = SHA256(h || ciphertext) else @@ -657,11 +668,12 @@ namespace transport void NTCP2Session::SendSessionConfirmed () { - uint8_t nonce[12]; - CreateNonce (1, nonce); // set nonce to 1 - m_Establisher->CreateSessionConfirmedMessagePart1 (nonce); - memset (nonce, 0, 12); // set nonce back to 0 - if (!m_Establisher->CreateSessionConfirmedMessagePart2 (nonce)) + if (!m_Establisher->CreateSessionConfirmedMessagePart1 ()) + { + boost::asio::post (m_Server.GetService (), std::bind (&NTCP2Session::Terminate, shared_from_this ())); + return; + } + if (!m_Establisher->CreateSessionConfirmedMessagePart2 ()) { LogPrint (eLogWarning, "NTCP2: Send SessionConfirmed Part2 KDF failed"); boost::asio::post (m_Server.GetService (), std::bind (&NTCP2Session::Terminate, shared_from_this ())); @@ -740,14 +752,11 @@ namespace transport // run on establisher thread LogPrint (eLogDebug, "NTCP2: SessionConfirmed received"); // part 1 - uint8_t nonce[12]; - CreateNonce (1, nonce); - if (m_Establisher->ProcessSessionConfirmedMessagePart1 (nonce)) + if (m_Establisher->ProcessSessionConfirmedMessagePart1 ()) { // part 2 auto buf = std::make_shared > (m_Establisher->m3p2Len - 16); // -MAC - memset (nonce, 0, 12); // set nonce to 0 again - if (m_Establisher->ProcessSessionConfirmedMessagePart2 (nonce, buf->data ())) // TODO:handle in establisher thread + if (m_Establisher->ProcessSessionConfirmedMessagePart2 (buf->data ())) // TODO:handle in establisher thread { // payload // RI block must be first diff --git a/libi2pd/NTCP2.h b/libi2pd/NTCP2.h index 47354f32..5ad5b955 100644 --- a/libi2pd/NTCP2.h +++ b/libi2pd/NTCP2.h @@ -91,7 +91,6 @@ namespace transport const uint8_t * GetRemotePub () const { return m_RemoteEphemeralPublicKey; }; // Y for Alice and X for Bob uint8_t * GetRemotePub () { return m_RemoteEphemeralPublicKey; }; // to set - const uint8_t * GetK () const { return m_CK + 32; }; const uint8_t * GetCK () const { return m_CK; }; const uint8_t * GetH () const { return m_H; }; @@ -108,13 +107,13 @@ namespace transport bool CreateSessionRequestMessage (std::mt19937& rng); bool CreateSessionCreatedMessage (std::mt19937& rng); - void CreateSessionConfirmedMessagePart1 (const uint8_t * nonce); - bool CreateSessionConfirmedMessagePart2 (const uint8_t * nonce); + bool CreateSessionConfirmedMessagePart1 (); + bool CreateSessionConfirmedMessagePart2 (); bool ProcessSessionRequestMessage (uint16_t& paddingLen, bool& clockSkew); bool ProcessSessionCreatedMessage (uint16_t& paddingLen); - bool ProcessSessionConfirmedMessagePart1 (const uint8_t * nonce); - bool ProcessSessionConfirmedMessagePart2 (const uint8_t * nonce, uint8_t * m3p2Buf); + bool ProcessSessionConfirmedMessagePart1 (); + bool ProcessSessionConfirmedMessagePart2 (uint8_t * m3p2Buf); std::shared_ptr m_EphemeralKeys; uint8_t m_RemoteEphemeralPublicKey[32]; // x25519 From 9ab1a67f0be9d33dc0984fa284fbab792137bd54 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 13 Apr 2025 18:18:44 -0400 Subject: [PATCH 1022/1171] common ML-KEM names and key lengths --- libi2pd/Crypto.cpp | 30 ++++++------- libi2pd/Crypto.h | 30 ++++++++++--- libi2pd/CryptoKey.h | 17 +++++++ libi2pd/ECIESX25519AEADRatchetSession.cpp | 55 ++++++++++++----------- libi2pd/ECIESX25519AEADRatchetSession.h | 2 +- 5 files changed, 88 insertions(+), 46 deletions(-) diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index e8210a27..cf8303d1 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -1011,32 +1011,32 @@ namespace crypto #if OPENSSL_PQ - MLKEM512Keys::MLKEM512Keys (): - m_Pkey (nullptr) + MLKEMKeys::MLKEMKeys (std::string_view name, size_t keyLen, size_t ctLen): + m_Name (name), m_KeyLen (keyLen), m_CTLen (ctLen),m_Pkey (nullptr) { } - MLKEM512Keys::~MLKEM512Keys () + MLKEMKeys::~MLKEMKeys () { if (m_Pkey) EVP_PKEY_free (m_Pkey); } - void MLKEM512Keys::GenerateKeys () + void MLKEMKeys::GenerateKeys () { if (m_Pkey) EVP_PKEY_free (m_Pkey); - m_Pkey = EVP_PKEY_Q_keygen(NULL, NULL, "ML-KEM-512"); + m_Pkey = EVP_PKEY_Q_keygen(NULL, NULL, m_Name.c_str ()); } - void MLKEM512Keys::GetPublicKey (uint8_t * pub) const + void MLKEMKeys::GetPublicKey (uint8_t * pub) const { if (m_Pkey) { - size_t len = MLKEM512_KEY_LENGTH; - EVP_PKEY_get_octet_string_param (m_Pkey, OSSL_PKEY_PARAM_PUB_KEY, pub, MLKEM512_KEY_LENGTH, &len); + size_t len = m_KeyLen; + EVP_PKEY_get_octet_string_param (m_Pkey, OSSL_PKEY_PARAM_PUB_KEY, pub, m_KeyLen, &len); } } - void MLKEM512Keys::SetPublicKey (const uint8_t * pub) + void MLKEMKeys::SetPublicKey (const uint8_t * pub) { if (m_Pkey) { @@ -1045,10 +1045,10 @@ namespace crypto } OSSL_PARAM params[] = { - OSSL_PARAM_octet_string (OSSL_PKEY_PARAM_PUB_KEY, (uint8_t *)pub, MLKEM512_KEY_LENGTH), + OSSL_PARAM_octet_string (OSSL_PKEY_PARAM_PUB_KEY, (uint8_t *)pub, m_KeyLen), OSSL_PARAM_END }; - EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name (NULL, "ML-KEM-512", NULL); + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name (NULL, m_Name.c_str (), NULL); if (ctx) { EVP_PKEY_fromdata_init (ctx); @@ -1059,14 +1059,14 @@ namespace crypto LogPrint (eLogError, "MLKEM512 can't create PKEY context"); } - void MLKEM512Keys::Encaps (uint8_t * ciphertext, uint8_t * shared) + void MLKEMKeys::Encaps (uint8_t * ciphertext, uint8_t * shared) { if (!m_Pkey) return; auto ctx = EVP_PKEY_CTX_new_from_pkey (NULL, m_Pkey, NULL); if (ctx) { EVP_PKEY_encapsulate_init (ctx, NULL); - size_t len = MLKEM512_CIPHER_TEXT_LENGTH, sharedLen = 32; + size_t len = m_CTLen, sharedLen = 32; EVP_PKEY_encapsulate (ctx, ciphertext, &len, shared, &sharedLen); EVP_PKEY_CTX_free (ctx); } @@ -1074,7 +1074,7 @@ namespace crypto LogPrint (eLogError, "MLKEM512 can't create PKEY context"); } - void MLKEM512Keys::Decaps (const uint8_t * ciphertext, uint8_t * shared) + void MLKEMKeys::Decaps (const uint8_t * ciphertext, uint8_t * shared) { if (!m_Pkey) return; auto ctx = EVP_PKEY_CTX_new_from_pkey (NULL, m_Pkey, NULL); @@ -1082,7 +1082,7 @@ namespace crypto { EVP_PKEY_decapsulate_init (ctx, NULL); size_t sharedLen = 32; - EVP_PKEY_decapsulate (ctx, shared, &sharedLen, ciphertext, MLKEM512_CIPHER_TEXT_LENGTH); + EVP_PKEY_decapsulate (ctx, shared, &sharedLen, ciphertext, m_CTLen); EVP_PKEY_CTX_free (ctx); } else diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index aa6466be..9b47f806 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -11,7 +11,10 @@ #include #include +#include #include +#include +#include #include #include #include @@ -279,14 +282,13 @@ namespace crypto #if OPENSSL_PQ // Post Quantum - constexpr size_t MLKEM512_KEY_LENGTH = 800; - constexpr size_t MLKEM512_CIPHER_TEXT_LENGTH = 768; - class MLKEM512Keys + + class MLKEMKeys { public: - MLKEM512Keys (); - ~MLKEM512Keys (); + MLKEMKeys (std::string_view name, size_t keyLen, size_t ctLen); + ~MLKEMKeys (); void GenerateKeys (); void GetPublicKey (uint8_t * pub) const; @@ -296,8 +298,26 @@ namespace crypto private: + const std::string m_Name; + const size_t m_KeyLen, m_CTLen; EVP_PKEY * m_Pkey; }; + + constexpr size_t MLKEM512_KEY_LENGTH = 800; + constexpr size_t MLKEM512_CIPHER_TEXT_LENGTH = 768; + + constexpr std::array, 1> MLKEMS = + { + std::make_tuple ("ML-KEM-512", MLKEM512_KEY_LENGTH, MLKEM512_CIPHER_TEXT_LENGTH) + }; + + class MLKEM512Keys: public MLKEMKeys + { + public: + + MLKEM512Keys (): MLKEMKeys (std::get<0>(MLKEMS[0]), std::get<1>(MLKEMS[0]), std::get<2>(MLKEMS[0])) {} + }; + #endif } } diff --git a/libi2pd/CryptoKey.h b/libi2pd/CryptoKey.h index 14ef4fa8..1e0ea3f2 100644 --- a/libi2pd/CryptoKey.h +++ b/libi2pd/CryptoKey.h @@ -183,6 +183,23 @@ namespace crypto }; return 0; } + +#if OPENSSL_PQ + constexpr size_t GetMLKEMPublicKeyLen (i2p::data::CryptoKeyType type) + { + if (type <= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD || + type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD > (int)MLKEMS.size ()) return 0; + return std::get<1>(MLKEMS[type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD - 1]); + } + + constexpr size_t GetMLKEMCipherTextLen (i2p::data::CryptoKeyType type) + { + if (type <= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD || + type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD > (int)MLKEMS.size ()) return 0; + return std::get<2>(MLKEMS[type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD - 1]); + } + +#endif } } diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index cfcbf5bb..de95ce00 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -11,6 +11,7 @@ #include "Log.h" #include "util.h" #include "Crypto.h" +#include "CryptoKey.h" #include "Elligator.h" #include "Tag.h" #include "I2PEndian.h" @@ -560,18 +561,19 @@ namespace garlic } MixKey (sharedSecret); #if OPENSSL_PQ - if (m_RemoteStaticKeyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD) + if (m_RemoteStaticKeyType >= i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD) { - uint8_t encapsKey[i2p::crypto::MLKEM512_KEY_LENGTH]; - m_PQKeys->GetPublicKey (encapsKey); + auto keyLen = i2p::crypto::GetMLKEMPublicKeyLen (m_RemoteStaticKeyType); + std::vector encapsKey(keyLen); + m_PQKeys->GetPublicKey (encapsKey.data ()); // encrypt encapsKey - if (!Encrypt (encapsKey, out + offset, i2p::crypto::MLKEM512_KEY_LENGTH)) + if (!Encrypt (encapsKey.data (), out + offset, keyLen)) { LogPrint (eLogWarning, "Garlic: ML-KEM encap_key section AEAD encryption failed "); return false; } - MixHash (out + offset, i2p::crypto::MLKEM512_KEY_LENGTH + 16); // h = SHA256(h || ciphertext) - offset += i2p::crypto::MLKEM512_KEY_LENGTH + 16; + MixHash (out + offset, keyLen + 16); // h = SHA256(h || ciphertext) + offset += keyLen + 16; } #endif // encrypt flags/static key section @@ -657,19 +659,20 @@ namespace garlic #if OPENSSL_PQ if (m_PQKeys) { - uint8_t kemCiphertext[i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH]; - m_PQKeys->Encaps (kemCiphertext, sharedSecret); + size_t cipherTextLen = i2p::crypto::GetMLKEMCipherTextLen (m_RemoteStaticKeyType); + std::vector kemCiphertext(cipherTextLen); + m_PQKeys->Encaps (kemCiphertext.data (), sharedSecret); - if (!Encrypt (kemCiphertext, out + offset, i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH)) + if (!Encrypt (kemCiphertext.data (), out + offset, cipherTextLen)) { LogPrint (eLogWarning, "Garlic: NSR ML-KEM ciphertext section AEAD encryption failed"); return false; } - m_NSREncodedPQKey = std::make_unique >(); - memcpy (m_NSREncodedPQKey->data (), out + offset, i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH + 16); - MixHash (out + offset, i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH + 16); + m_NSREncodedPQKey = std::make_unique > (cipherTextLen + 16); + memcpy (m_NSREncodedPQKey->data (), out + offset, cipherTextLen + 16); + MixHash (out + offset, cipherTextLen + 16); MixKey (sharedSecret); - offset += i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH + 16; + offset += cipherTextLen + 16; } #endif // calculate hash for zero length @@ -723,9 +726,10 @@ namespace garlic { if (m_NSREncodedPQKey) { - memcpy (out + offset, m_NSREncodedPQKey->data (), i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH + 16); - MixHash (out + offset, i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH + 16); - offset += i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH + 16; + size_t cipherTextLen = i2p::crypto::GetMLKEMCipherTextLen (m_RemoteStaticKeyType); + memcpy (out + offset, m_NSREncodedPQKey->data (), cipherTextLen + 16); + MixHash (out + offset, cipherTextLen + 16); + offset += cipherTextLen + 16; } else { @@ -778,20 +782,21 @@ namespace garlic MixKey (sharedSecret); #if OPENSSL_PQ - if (m_RemoteStaticKeyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD) + if (m_RemoteStaticKeyType >= i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD) { // decrypt kem_ciphertext section - uint8_t kemCiphertext[i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH]; - if (!Decrypt (buf, kemCiphertext, i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH)) + size_t cipherTextLen = i2p::crypto::GetMLKEMCipherTextLen (m_RemoteStaticKeyType); + std::vector kemCiphertext(cipherTextLen); + if (!Decrypt (buf, kemCiphertext.data (), cipherTextLen)) { LogPrint (eLogWarning, "Garlic: Reply ML-KEM ciphertext section AEAD decryption failed"); return false; } - MixHash (buf, i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH + 16); - buf += i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH + 16; - len -= i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH + 16; + MixHash (buf, cipherTextLen + 16); + buf += cipherTextLen + 16; + len -= cipherTextLen + 16; // decaps - m_PQKeys->Decaps (kemCiphertext, sharedSecret); + m_PQKeys->Decaps (kemCiphertext.data (), sharedSecret); MixKey (sharedSecret); } #endif @@ -981,8 +986,8 @@ namespace garlic return nullptr; len += 96; #if OPENSSL_PQ - if (m_RemoteStaticKeyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD) - len += i2p::crypto::MLKEM512_KEY_LENGTH + 16; + if (m_RemoteStaticKeyType >= i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD) + len += i2p::crypto::GetMLKEMPublicKeyLen (m_RemoteStaticKeyType) + 16; #endif break; case eSessionStateNewSessionReceived: diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index b988263a..2077219f 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -229,7 +229,7 @@ namespace garlic std::shared_ptr m_EphemeralKeys; #if OPENSSL_PQ std::unique_ptr m_PQKeys; - std::unique_ptr > m_NSREncodedPQKey; + std::unique_ptr > m_NSREncodedPQKey; #endif SessionState m_State = eSessionStateNew; uint64_t m_SessionCreatedTimestamp = 0, m_LastActivityTimestamp = 0, // incoming (in seconds) From a83cd99f58f7ecd75e335a88cc94aea13381e6a6 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 14 Apr 2025 13:29:53 -0400 Subject: [PATCH 1023/1171] all ML-KEM crypto types --- libi2pd/Crypto.h | 28 ++++++++++++++++++++++++---- libi2pd/Identity.h | 2 ++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index 9b47f806..10f65b32 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -305,10 +305,16 @@ namespace crypto constexpr size_t MLKEM512_KEY_LENGTH = 800; constexpr size_t MLKEM512_CIPHER_TEXT_LENGTH = 768; - - constexpr std::array, 1> MLKEMS = + constexpr size_t MLKEM768_KEY_LENGTH = 1184; + constexpr size_t MLKEM768_CIPHER_TEXT_LENGTH = 1088; + constexpr size_t MLKEM1024_KEY_LENGTH = 1568; + constexpr size_t MLKEM1024_CIPHER_TEXT_LENGTH = 1568; + + constexpr std::array, 3> MLKEMS = { - std::make_tuple ("ML-KEM-512", MLKEM512_KEY_LENGTH, MLKEM512_CIPHER_TEXT_LENGTH) + std::make_tuple ("ML-KEM-512", MLKEM512_KEY_LENGTH, MLKEM512_CIPHER_TEXT_LENGTH), + std::make_tuple ("ML-KEM-768", MLKEM768_KEY_LENGTH, MLKEM768_CIPHER_TEXT_LENGTH), + std::make_tuple ("ML-KEM-1024", MLKEM1024_KEY_LENGTH, MLKEM1024_CIPHER_TEXT_LENGTH) }; class MLKEM512Keys: public MLKEMKeys @@ -317,7 +323,21 @@ namespace crypto MLKEM512Keys (): MLKEMKeys (std::get<0>(MLKEMS[0]), std::get<1>(MLKEMS[0]), std::get<2>(MLKEMS[0])) {} }; - + + class MLKEM768Keys: public MLKEMKeys + { + public: + + MLKEM768Keys (): MLKEMKeys (std::get<0>(MLKEMS[1]), std::get<1>(MLKEMS[1]), std::get<2>(MLKEMS[1])) {} + }; + + class MLKEM1024Keys: public MLKEMKeys + { + public: + + MLKEM1024Keys (): MLKEMKeys (std::get<0>(MLKEMS[2]), std::get<1>(MLKEMS[2]), std::get<2>(MLKEMS[2])) {} + }; + #endif } } diff --git a/libi2pd/Identity.h b/libi2pd/Identity.h index ee736441..173559e9 100644 --- a/libi2pd/Identity.h +++ b/libi2pd/Identity.h @@ -71,6 +71,8 @@ namespace data const uint16_t CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC = 1; const uint16_t CRYPTO_KEY_TYPE_ECIES_X25519_AEAD = 4; const uint16_t CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD = 5; + const uint16_t CRYPTO_KEY_TYPE_ECIES_MLKEM768_X25519_AEAD = 6; + const uint16_t CRYPTO_KEY_TYPE_ECIES_MLKEM1024_X25519_AEAD = 7; const uint16_t SIGNING_KEY_TYPE_DSA_SHA1 = 0; const uint16_t SIGNING_KEY_TYPE_ECDSA_SHA256_P256 = 1; From 459be02d18d8e9b2c7a838a956d5d437a3f1f80a Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 14 Apr 2025 13:31:37 -0400 Subject: [PATCH 1024/1171] correct sequence of MixKey for ML-KEM NSR --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index de95ce00..d5b7150d 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -649,13 +649,6 @@ namespace garlic return false; } MixKey (sharedSecret); - if (!m_EphemeralKeys->Agree (m_RemoteStaticKey, sharedSecret)) // sharedSecret = x25519(besk, apk) - { - LogPrint (eLogWarning, "Garlic: Incorrect Alice static key"); - return false; - } - MixKey (sharedSecret); - #if OPENSSL_PQ if (m_PQKeys) { @@ -675,6 +668,12 @@ namespace garlic offset += cipherTextLen + 16; } #endif + if (!m_EphemeralKeys->Agree (m_RemoteStaticKey, sharedSecret)) // sharedSecret = x25519(besk, apk) + { + LogPrint (eLogWarning, "Garlic: Incorrect Alice static key"); + return false; + } + MixKey (sharedSecret); // calculate hash for zero length if (!Encrypt (sharedSecret /* can be anything */, out + offset, 0)) // encrypt, ciphertext = ENCRYPT(k, n, ZEROLEN, ad) { @@ -778,9 +777,6 @@ namespace garlic return false; } MixKey (sharedSecret); - GetOwner ()->Decrypt (bepk, sharedSecret, m_RemoteStaticKeyType); // x25519 (ask, bepk) - MixKey (sharedSecret); - #if OPENSSL_PQ if (m_RemoteStaticKeyType >= i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD) { @@ -799,7 +795,10 @@ namespace garlic m_PQKeys->Decaps (kemCiphertext.data (), sharedSecret); MixKey (sharedSecret); } -#endif +#endif + GetOwner ()->Decrypt (bepk, sharedSecret, m_RemoteStaticKeyType); // x25519 (ask, bepk) + MixKey (sharedSecret); + // calculate hash for zero length if (!Decrypt (buf, sharedSecret/* can be anything */, 0)) // decrypt, DECRYPT(k, n, ZEROLEN, ad) verification only { From 4c5d0116f8891c272b0d150a74dfc779c5efb333 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 14 Apr 2025 18:21:07 -0400 Subject: [PATCH 1025/1171] moved ML-KEM code to PostQuntum.h/.cpp --- libi2pd/Crypto.cpp | 81 ----------------- libi2pd/Crypto.h | 63 -------------- libi2pd/CryptoKey.h | 17 ---- libi2pd/ECIESX25519AEADRatchetSession.cpp | 2 +- libi2pd/ECIESX25519AEADRatchetSession.h | 3 +- libi2pd/PostQuantum.cpp | 101 ++++++++++++++++++++++ libi2pd/PostQuantum.h | 97 +++++++++++++++++++++ 7 files changed, 201 insertions(+), 163 deletions(-) create mode 100644 libi2pd/PostQuantum.cpp create mode 100644 libi2pd/PostQuantum.h diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index cf8303d1..be2863f4 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -1008,86 +1008,5 @@ namespace crypto /* CRYPTO_set_locking_callback (nullptr); m_OpenSSLMutexes.clear ();*/ } - -#if OPENSSL_PQ - - MLKEMKeys::MLKEMKeys (std::string_view name, size_t keyLen, size_t ctLen): - m_Name (name), m_KeyLen (keyLen), m_CTLen (ctLen),m_Pkey (nullptr) - { - } - - MLKEMKeys::~MLKEMKeys () - { - if (m_Pkey) EVP_PKEY_free (m_Pkey); - } - - void MLKEMKeys::GenerateKeys () - { - if (m_Pkey) EVP_PKEY_free (m_Pkey); - m_Pkey = EVP_PKEY_Q_keygen(NULL, NULL, m_Name.c_str ()); - } - - void MLKEMKeys::GetPublicKey (uint8_t * pub) const - { - if (m_Pkey) - { - size_t len = m_KeyLen; - EVP_PKEY_get_octet_string_param (m_Pkey, OSSL_PKEY_PARAM_PUB_KEY, pub, m_KeyLen, &len); - } - } - - void MLKEMKeys::SetPublicKey (const uint8_t * pub) - { - if (m_Pkey) - { - EVP_PKEY_free (m_Pkey); - m_Pkey = nullptr; - } - OSSL_PARAM params[] = - { - OSSL_PARAM_octet_string (OSSL_PKEY_PARAM_PUB_KEY, (uint8_t *)pub, m_KeyLen), - OSSL_PARAM_END - }; - EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name (NULL, m_Name.c_str (), NULL); - if (ctx) - { - EVP_PKEY_fromdata_init (ctx); - EVP_PKEY_fromdata (ctx, &m_Pkey, OSSL_KEYMGMT_SELECT_PUBLIC_KEY, params); - EVP_PKEY_CTX_free (ctx); - } - else - LogPrint (eLogError, "MLKEM512 can't create PKEY context"); - } - - void MLKEMKeys::Encaps (uint8_t * ciphertext, uint8_t * shared) - { - if (!m_Pkey) return; - auto ctx = EVP_PKEY_CTX_new_from_pkey (NULL, m_Pkey, NULL); - if (ctx) - { - EVP_PKEY_encapsulate_init (ctx, NULL); - size_t len = m_CTLen, sharedLen = 32; - EVP_PKEY_encapsulate (ctx, ciphertext, &len, shared, &sharedLen); - EVP_PKEY_CTX_free (ctx); - } - else - LogPrint (eLogError, "MLKEM512 can't create PKEY context"); - } - - void MLKEMKeys::Decaps (const uint8_t * ciphertext, uint8_t * shared) - { - if (!m_Pkey) return; - auto ctx = EVP_PKEY_CTX_new_from_pkey (NULL, m_Pkey, NULL); - if (ctx) - { - EVP_PKEY_decapsulate_init (ctx, NULL); - size_t sharedLen = 32; - EVP_PKEY_decapsulate (ctx, shared, &sharedLen, ciphertext, m_CTLen); - EVP_PKEY_CTX_free (ctx); - } - else - LogPrint (eLogError, "MLKEM512 can't create PKEY context"); - } -#endif } } diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index 10f65b32..6abbd9b2 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -11,10 +11,7 @@ #include #include -#include #include -#include -#include #include #include #include @@ -279,66 +276,6 @@ namespace crypto // init and terminate void InitCrypto (bool precomputation); void TerminateCrypto (); - -#if OPENSSL_PQ -// Post Quantum - - class MLKEMKeys - { - public: - - MLKEMKeys (std::string_view name, size_t keyLen, size_t ctLen); - ~MLKEMKeys (); - - void GenerateKeys (); - void GetPublicKey (uint8_t * pub) const; - void SetPublicKey (const uint8_t * pub); - void Encaps (uint8_t * ciphertext, uint8_t * shared); - void Decaps (const uint8_t * ciphertext, uint8_t * shared); - - private: - - const std::string m_Name; - const size_t m_KeyLen, m_CTLen; - EVP_PKEY * m_Pkey; - }; - - constexpr size_t MLKEM512_KEY_LENGTH = 800; - constexpr size_t MLKEM512_CIPHER_TEXT_LENGTH = 768; - constexpr size_t MLKEM768_KEY_LENGTH = 1184; - constexpr size_t MLKEM768_CIPHER_TEXT_LENGTH = 1088; - constexpr size_t MLKEM1024_KEY_LENGTH = 1568; - constexpr size_t MLKEM1024_CIPHER_TEXT_LENGTH = 1568; - - constexpr std::array, 3> MLKEMS = - { - std::make_tuple ("ML-KEM-512", MLKEM512_KEY_LENGTH, MLKEM512_CIPHER_TEXT_LENGTH), - std::make_tuple ("ML-KEM-768", MLKEM768_KEY_LENGTH, MLKEM768_CIPHER_TEXT_LENGTH), - std::make_tuple ("ML-KEM-1024", MLKEM1024_KEY_LENGTH, MLKEM1024_CIPHER_TEXT_LENGTH) - }; - - class MLKEM512Keys: public MLKEMKeys - { - public: - - MLKEM512Keys (): MLKEMKeys (std::get<0>(MLKEMS[0]), std::get<1>(MLKEMS[0]), std::get<2>(MLKEMS[0])) {} - }; - - class MLKEM768Keys: public MLKEMKeys - { - public: - - MLKEM768Keys (): MLKEMKeys (std::get<0>(MLKEMS[1]), std::get<1>(MLKEMS[1]), std::get<2>(MLKEMS[1])) {} - }; - - class MLKEM1024Keys: public MLKEMKeys - { - public: - - MLKEM1024Keys (): MLKEMKeys (std::get<0>(MLKEMS[2]), std::get<1>(MLKEMS[2]), std::get<2>(MLKEMS[2])) {} - }; - -#endif } } diff --git a/libi2pd/CryptoKey.h b/libi2pd/CryptoKey.h index 1e0ea3f2..14ef4fa8 100644 --- a/libi2pd/CryptoKey.h +++ b/libi2pd/CryptoKey.h @@ -183,23 +183,6 @@ namespace crypto }; return 0; } - -#if OPENSSL_PQ - constexpr size_t GetMLKEMPublicKeyLen (i2p::data::CryptoKeyType type) - { - if (type <= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD || - type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD > (int)MLKEMS.size ()) return 0; - return std::get<1>(MLKEMS[type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD - 1]); - } - - constexpr size_t GetMLKEMCipherTextLen (i2p::data::CryptoKeyType type) - { - if (type <= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD || - type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD > (int)MLKEMS.size ()) return 0; - return std::get<2>(MLKEMS[type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD - 1]); - } - -#endif } } diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index d5b7150d..5d563d97 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -11,7 +11,7 @@ #include "Log.h" #include "util.h" #include "Crypto.h" -#include "CryptoKey.h" +#include "PostQuantum.h" #include "Elligator.h" #include "Tag.h" #include "I2PEndian.h" diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index 2077219f..b7704534 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -19,6 +19,7 @@ #include #include "Identity.h" #include "Crypto.h" +#include "PostQuantum.h" #include "Garlic.h" #include "Tag.h" @@ -228,7 +229,7 @@ namespace garlic uint8_t m_NSREncodedKey[32], m_NSRH[32], m_NSRKey[32]; // new session reply, for incoming only std::shared_ptr m_EphemeralKeys; #if OPENSSL_PQ - std::unique_ptr m_PQKeys; + std::unique_ptr m_PQKeys; std::unique_ptr > m_NSREncodedPQKey; #endif SessionState m_State = eSessionStateNew; diff --git a/libi2pd/PostQuantum.cpp b/libi2pd/PostQuantum.cpp new file mode 100644 index 00000000..abe207d2 --- /dev/null +++ b/libi2pd/PostQuantum.cpp @@ -0,0 +1,101 @@ +/* +* Copyright (c) 2025, The PurpleI2P Project +* +* This file is part of Purple i2pd project and licensed under BSD3 +* +* See full license text in LICENSE file at top of project tree +*/ + +#include "Log.h" +#include "PostQuantum.h" + +#if OPENSSL_PQ + +#include +#include + +namespace i2p +{ +namespace crypto +{ + MLKEMKeys::MLKEMKeys (std::string_view name, size_t keyLen, size_t ctLen): + m_Name (name), m_KeyLen (keyLen), m_CTLen (ctLen),m_Pkey (nullptr) + { + } + + MLKEMKeys::~MLKEMKeys () + { + if (m_Pkey) EVP_PKEY_free (m_Pkey); + } + + void MLKEMKeys::GenerateKeys () + { + if (m_Pkey) EVP_PKEY_free (m_Pkey); + m_Pkey = EVP_PKEY_Q_keygen(NULL, NULL, m_Name.c_str ()); + } + + void MLKEMKeys::GetPublicKey (uint8_t * pub) const + { + if (m_Pkey) + { + size_t len = m_KeyLen; + EVP_PKEY_get_octet_string_param (m_Pkey, OSSL_PKEY_PARAM_PUB_KEY, pub, m_KeyLen, &len); + } + } + + void MLKEMKeys::SetPublicKey (const uint8_t * pub) + { + if (m_Pkey) + { + EVP_PKEY_free (m_Pkey); + m_Pkey = nullptr; + } + OSSL_PARAM params[] = + { + OSSL_PARAM_octet_string (OSSL_PKEY_PARAM_PUB_KEY, (uint8_t *)pub, m_KeyLen), + OSSL_PARAM_END + }; + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name (NULL, m_Name.c_str (), NULL); + if (ctx) + { + EVP_PKEY_fromdata_init (ctx); + EVP_PKEY_fromdata (ctx, &m_Pkey, OSSL_KEYMGMT_SELECT_PUBLIC_KEY, params); + EVP_PKEY_CTX_free (ctx); + } + else + LogPrint (eLogError, "MLKEM512 can't create PKEY context"); + } + + void MLKEMKeys::Encaps (uint8_t * ciphertext, uint8_t * shared) + { + if (!m_Pkey) return; + auto ctx = EVP_PKEY_CTX_new_from_pkey (NULL, m_Pkey, NULL); + if (ctx) + { + EVP_PKEY_encapsulate_init (ctx, NULL); + size_t len = m_CTLen, sharedLen = 32; + EVP_PKEY_encapsulate (ctx, ciphertext, &len, shared, &sharedLen); + EVP_PKEY_CTX_free (ctx); + } + else + LogPrint (eLogError, "MLKEM512 can't create PKEY context"); + } + + void MLKEMKeys::Decaps (const uint8_t * ciphertext, uint8_t * shared) + { + if (!m_Pkey) return; + auto ctx = EVP_PKEY_CTX_new_from_pkey (NULL, m_Pkey, NULL); + if (ctx) + { + EVP_PKEY_decapsulate_init (ctx, NULL); + size_t sharedLen = 32; + EVP_PKEY_decapsulate (ctx, shared, &sharedLen, ciphertext, m_CTLen); + EVP_PKEY_CTX_free (ctx); + } + else + LogPrint (eLogError, "MLKEM512 can't create PKEY context"); + } +} +} + +#endif \ No newline at end of file diff --git a/libi2pd/PostQuantum.h b/libi2pd/PostQuantum.h new file mode 100644 index 00000000..6081f653 --- /dev/null +++ b/libi2pd/PostQuantum.h @@ -0,0 +1,97 @@ +/* +* Copyright (c) 2025, The PurpleI2P Project +* +* This file is part of Purple i2pd project and licensed under BSD3 +* +* See full license text in LICENSE file at top of project tree +*/ + +#ifndef POST_QUANTUM_H__ +#define POST_QUANTUM_H__ + +#include +#include +#include +#include "Crypto.h" +#include "Identity.h" + +#if OPENSSL_PQ + +namespace i2p +{ +namespace crypto +{ + class MLKEMKeys + { + public: + + MLKEMKeys (std::string_view name, size_t keyLen, size_t ctLen); + ~MLKEMKeys (); + + void GenerateKeys (); + void GetPublicKey (uint8_t * pub) const; + void SetPublicKey (const uint8_t * pub); + void Encaps (uint8_t * ciphertext, uint8_t * shared); + void Decaps (const uint8_t * ciphertext, uint8_t * shared); + + private: + + const std::string m_Name; + const size_t m_KeyLen, m_CTLen; + EVP_PKEY * m_Pkey; + }; + + constexpr size_t MLKEM512_KEY_LENGTH = 800; + constexpr size_t MLKEM512_CIPHER_TEXT_LENGTH = 768; + constexpr size_t MLKEM768_KEY_LENGTH = 1184; + constexpr size_t MLKEM768_CIPHER_TEXT_LENGTH = 1088; + constexpr size_t MLKEM1024_KEY_LENGTH = 1568; + constexpr size_t MLKEM1024_CIPHER_TEXT_LENGTH = 1568; + + constexpr std::array, 3> MLKEMS = + { + std::make_tuple ("ML-KEM-512", MLKEM512_KEY_LENGTH, MLKEM512_CIPHER_TEXT_LENGTH), + std::make_tuple ("ML-KEM-768", MLKEM768_KEY_LENGTH, MLKEM768_CIPHER_TEXT_LENGTH), + std::make_tuple ("ML-KEM-1024", MLKEM1024_KEY_LENGTH, MLKEM1024_CIPHER_TEXT_LENGTH) + }; + + class MLKEM512Keys: public MLKEMKeys + { + public: + + MLKEM512Keys (): MLKEMKeys (std::get<0>(MLKEMS[0]), std::get<1>(MLKEMS[0]), std::get<2>(MLKEMS[0])) {} + }; + + class MLKEM768Keys: public MLKEMKeys + { + public: + + MLKEM768Keys (): MLKEMKeys (std::get<0>(MLKEMS[1]), std::get<1>(MLKEMS[1]), std::get<2>(MLKEMS[1])) {} + }; + + class MLKEM1024Keys: public MLKEMKeys + { + public: + + MLKEM1024Keys (): MLKEMKeys (std::get<0>(MLKEMS[2]), std::get<1>(MLKEMS[2]), std::get<2>(MLKEMS[2])) {} + }; + + constexpr size_t GetMLKEMPublicKeyLen (i2p::data::CryptoKeyType type) + { + if (type <= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD || + type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD > (int)MLKEMS.size ()) return 0; + return std::get<1>(MLKEMS[type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD - 1]); + } + + constexpr size_t GetMLKEMCipherTextLen (i2p::data::CryptoKeyType type) + { + if (type <= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD || + type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD > (int)MLKEMS.size ()) return 0; + return std::get<2>(MLKEMS[type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD - 1]); + } +} +} + +#endif + +#endif From 828cd9d07b4f90e39a16bec4adb36bcdb78bd48c Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 14 Apr 2025 19:38:43 -0400 Subject: [PATCH 1026/1171] common MLKEMKeys for all types --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 4 +- libi2pd/PostQuantum.cpp | 12 +++- libi2pd/PostQuantum.h | 87 ++++++++++------------- 3 files changed, 50 insertions(+), 53 deletions(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 5d563d97..fbea786f 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -290,7 +290,7 @@ namespace garlic len -= i2p::crypto::MLKEM512_KEY_LENGTH + 16; n++; - m_PQKeys = std::make_unique(); + m_PQKeys = i2p::crypto::CreateMLKEMKeys (i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD); m_PQKeys->SetPublicKey (encapsKey); } } @@ -546,7 +546,7 @@ namespace garlic if (m_RemoteStaticKeyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD) { i2p::crypto::InitNoiseIKStateMLKEM512 (GetNoiseState (), m_RemoteStaticKey); // bpk - m_PQKeys = std::make_unique(); + m_PQKeys = i2p::crypto::CreateMLKEMKeys (m_RemoteStaticKeyType); m_PQKeys->GenerateKeys (); } else diff --git a/libi2pd/PostQuantum.cpp b/libi2pd/PostQuantum.cpp index abe207d2..16823c19 100644 --- a/libi2pd/PostQuantum.cpp +++ b/libi2pd/PostQuantum.cpp @@ -18,8 +18,9 @@ namespace i2p { namespace crypto { - MLKEMKeys::MLKEMKeys (std::string_view name, size_t keyLen, size_t ctLen): - m_Name (name), m_KeyLen (keyLen), m_CTLen (ctLen),m_Pkey (nullptr) + MLKEMKeys::MLKEMKeys (MLKEMTypes type): + m_Name (std::get<0>(MLKEMS[type])), m_KeyLen (std::get<1>(MLKEMS[type])), + m_CTLen (std::get<2>(MLKEMS[type])), m_Pkey (nullptr) { } @@ -95,6 +96,13 @@ namespace crypto else LogPrint (eLogError, "MLKEM512 can't create PKEY context"); } + + std::unique_ptr CreateMLKEMKeys (i2p::data::CryptoKeyType type) + { + if (type <= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD || + type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD > (int)MLKEMS.size ()) return nullptr; + return std::make_unique((MLKEMTypes)(type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD - 1)); + } } } diff --git a/libi2pd/PostQuantum.h b/libi2pd/PostQuantum.h index 6081f653..6bf2f238 100644 --- a/libi2pd/PostQuantum.h +++ b/libi2pd/PostQuantum.h @@ -9,6 +9,7 @@ #ifndef POST_QUANTUM_H__ #define POST_QUANTUM_H__ +#include #include #include #include @@ -21,11 +22,46 @@ namespace i2p { namespace crypto { + enum MLKEMTypes + { + eMLKEM512 = 0, + eMLKEM768, + eMLKEM1024 + }; + + constexpr size_t MLKEM512_KEY_LENGTH = 800; + constexpr size_t MLKEM512_CIPHER_TEXT_LENGTH = 768; + constexpr size_t MLKEM768_KEY_LENGTH = 1184; + constexpr size_t MLKEM768_CIPHER_TEXT_LENGTH = 1088; + constexpr size_t MLKEM1024_KEY_LENGTH = 1568; + constexpr size_t MLKEM1024_CIPHER_TEXT_LENGTH = 1568; + + constexpr std::array, 3> MLKEMS = + { + std::make_tuple ("ML-KEM-512", MLKEM512_KEY_LENGTH, MLKEM512_CIPHER_TEXT_LENGTH), + std::make_tuple ("ML-KEM-768", MLKEM768_KEY_LENGTH, MLKEM768_CIPHER_TEXT_LENGTH), + std::make_tuple ("ML-KEM-1024", MLKEM1024_KEY_LENGTH, MLKEM1024_CIPHER_TEXT_LENGTH) + }; + + constexpr size_t GetMLKEMPublicKeyLen (i2p::data::CryptoKeyType type) + { + if (type <= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD || + type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD > (int)MLKEMS.size ()) return 0; + return std::get<1>(MLKEMS[type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD - 1]); + } + + constexpr size_t GetMLKEMCipherTextLen (i2p::data::CryptoKeyType type) + { + if (type <= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD || + type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD > (int)MLKEMS.size ()) return 0; + return std::get<2>(MLKEMS[type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD - 1]); + } + class MLKEMKeys { public: - MLKEMKeys (std::string_view name, size_t keyLen, size_t ctLen); + MLKEMKeys (MLKEMTypes type); ~MLKEMKeys (); void GenerateKeys (); @@ -41,54 +77,7 @@ namespace crypto EVP_PKEY * m_Pkey; }; - constexpr size_t MLKEM512_KEY_LENGTH = 800; - constexpr size_t MLKEM512_CIPHER_TEXT_LENGTH = 768; - constexpr size_t MLKEM768_KEY_LENGTH = 1184; - constexpr size_t MLKEM768_CIPHER_TEXT_LENGTH = 1088; - constexpr size_t MLKEM1024_KEY_LENGTH = 1568; - constexpr size_t MLKEM1024_CIPHER_TEXT_LENGTH = 1568; - - constexpr std::array, 3> MLKEMS = - { - std::make_tuple ("ML-KEM-512", MLKEM512_KEY_LENGTH, MLKEM512_CIPHER_TEXT_LENGTH), - std::make_tuple ("ML-KEM-768", MLKEM768_KEY_LENGTH, MLKEM768_CIPHER_TEXT_LENGTH), - std::make_tuple ("ML-KEM-1024", MLKEM1024_KEY_LENGTH, MLKEM1024_CIPHER_TEXT_LENGTH) - }; - - class MLKEM512Keys: public MLKEMKeys - { - public: - - MLKEM512Keys (): MLKEMKeys (std::get<0>(MLKEMS[0]), std::get<1>(MLKEMS[0]), std::get<2>(MLKEMS[0])) {} - }; - - class MLKEM768Keys: public MLKEMKeys - { - public: - - MLKEM768Keys (): MLKEMKeys (std::get<0>(MLKEMS[1]), std::get<1>(MLKEMS[1]), std::get<2>(MLKEMS[1])) {} - }; - - class MLKEM1024Keys: public MLKEMKeys - { - public: - - MLKEM1024Keys (): MLKEMKeys (std::get<0>(MLKEMS[2]), std::get<1>(MLKEMS[2]), std::get<2>(MLKEMS[2])) {} - }; - - constexpr size_t GetMLKEMPublicKeyLen (i2p::data::CryptoKeyType type) - { - if (type <= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD || - type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD > (int)MLKEMS.size ()) return 0; - return std::get<1>(MLKEMS[type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD - 1]); - } - - constexpr size_t GetMLKEMCipherTextLen (i2p::data::CryptoKeyType type) - { - if (type <= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD || - type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD > (int)MLKEMS.size ()) return 0; - return std::get<2>(MLKEMS[type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD - 1]); - } + std::unique_ptr CreateMLKEMKeys (i2p::data::CryptoKeyType type); } } From 1a04b5958557be826a86058cfd7b8dcc12aee82c Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 14 Apr 2025 21:45:53 -0400 Subject: [PATCH 1027/1171] common InitNoiseIKState for all ML-KEM crypto --- libi2pd/Crypto.cpp | 15 -------------- libi2pd/Crypto.h | 3 +-- libi2pd/ECIESX25519AEADRatchetSession.cpp | 14 ++++++------- libi2pd/PostQuantum.cpp | 25 +++++++++++++++++++++++ libi2pd/PostQuantum.h | 2 ++ 5 files changed, 35 insertions(+), 24 deletions(-) diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index be2863f4..c41b4c10 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -944,21 +944,6 @@ namespace crypto }; // SHA256 (protocolNameHash) state.Init (protocolNameHash, hh, pub); } - - void InitNoiseIKStateMLKEM512 (NoiseSymmetricState& state, const uint8_t * pub) - { - static constexpr uint8_t protocolNameHash[32] = - { - 0xb0, 0x8f, 0xb1, 0x73, 0x92, 0x66, 0xc9, 0x90, 0x45, 0x7f, 0xdd, 0xc6, 0x4e, 0x55, 0x40, 0xd8, - 0x0a, 0x37, 0x99, 0x06, 0x92, 0x2a, 0x78, 0xc4, 0xb1, 0xef, 0x86, 0x06, 0xd0, 0x15, 0x9f, 0x4d - }; // SHA256("Noise_IKhfselg2_25519+MLKEM512_ChaChaPoly_SHA256") - static constexpr uint8_t hh[32] = - { - 0x95, 0x8d, 0xf6, 0x6c, 0x95, 0xce, 0xa9, 0xf7, 0x42, 0xfc, 0xfa, 0x62, 0x71, 0x36, 0x1e, 0xa7, - 0xdc, 0x7a, 0xc0, 0x75, 0x01, 0xcf, 0xf9, 0xfc, 0x9f, 0xdb, 0x4c, 0x68, 0x3a, 0x53, 0x49, 0xeb - }; // SHA256 (protocolNameHash) - state.Init (protocolNameHash, hh, pub); - } // init and terminate diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index 6abbd9b2..125a217c 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -271,8 +271,7 @@ namespace crypto void InitNoiseXKState (NoiseSymmetricState& state, const uint8_t * pub); // Noise_XK (NTCP2) void InitNoiseXKState1 (NoiseSymmetricState& state, const uint8_t * pub); // Noise_XK (SSU2) void InitNoiseIKState (NoiseSymmetricState& state, const uint8_t * pub); // Noise_IK (ratchets) - void InitNoiseIKStateMLKEM512 (NoiseSymmetricState& state, const uint8_t * pub); // Noise_IK (ratchets) PQ ML-KEM512 - + // init and terminate void InitCrypto (bool precomputation); void TerminateCrypto (); diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index fbea786f..d38abd13 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -272,7 +272,8 @@ namespace garlic #if OPENSSL_PQ if (GetOwner ()->SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD)) { - i2p::crypto::InitNoiseIKStateMLKEM512 (GetNoiseState (), GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD)); // bpk + i2p::crypto::InitNoiseIKStateMLKEM (GetNoiseState (), i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD, + GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD)); // bpk MixHash (m_Aepk, 32); // h = SHA256(h || aepk) if (GetOwner ()->Decrypt (m_Aepk, sharedSecret, i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD)) // x25519(bsk, aepk) @@ -281,8 +282,7 @@ namespace garlic uint8_t nonce[12], encapsKey[i2p::crypto::MLKEM512_KEY_LENGTH]; CreateNonce (n, nonce); - if (i2p::crypto::AEADChaCha20Poly1305 (buf, i2p::crypto::MLKEM512_KEY_LENGTH, - m_H, 32, m_CK + 32, nonce, encapsKey, i2p::crypto::MLKEM512_KEY_LENGTH, false)) // decrypt + if (Decrypt (buf, encapsKey, i2p::crypto::MLKEM512_KEY_LENGTH)) { decrypted = true; // encaps section has right hash MixHash (buf, i2p::crypto::MLKEM512_KEY_LENGTH + 16); @@ -320,7 +320,7 @@ namespace garlic // decrypt flags/static uint8_t nonce[12], fs[32]; CreateNonce (n, nonce); - if (!i2p::crypto::AEADChaCha20Poly1305 (buf, 32, m_H, 32, m_CK + 32, nonce, fs, 32, false)) // decrypt + if (!Decrypt (buf, fs, 32)) { LogPrint (eLogWarning, "Garlic: Flags/static section AEAD verification failed "); return false; @@ -354,7 +354,7 @@ namespace garlic // decrypt payload std::vector payload (len - 16); // we must save original ciphertext - if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_H, 32, m_CK + 32, nonce, payload.data (), len - 16, false)) // decrypt + if (!Decrypt (buf, payload.data (), len - 16)) { LogPrint (eLogWarning, "Garlic: Payload section AEAD verification failed"); return false; @@ -543,9 +543,9 @@ namespace garlic // KDF1 #if OPENSSL_PQ - if (m_RemoteStaticKeyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD) + if (m_RemoteStaticKeyType >= i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD) { - i2p::crypto::InitNoiseIKStateMLKEM512 (GetNoiseState (), m_RemoteStaticKey); // bpk + i2p::crypto::InitNoiseIKStateMLKEM (GetNoiseState (), m_RemoteStaticKeyType, m_RemoteStaticKey); // bpk m_PQKeys = i2p::crypto::CreateMLKEMKeys (m_RemoteStaticKeyType); m_PQKeys->GenerateKeys (); } diff --git a/libi2pd/PostQuantum.cpp b/libi2pd/PostQuantum.cpp index 16823c19..0a55ca4d 100644 --- a/libi2pd/PostQuantum.cpp +++ b/libi2pd/PostQuantum.cpp @@ -103,6 +103,31 @@ namespace crypto type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD > (int)MLKEMS.size ()) return nullptr; return std::make_unique((MLKEMTypes)(type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD - 1)); } + + static constexpr std::array, std::array >, 1> NoiseIKInitMLKEMKeys = + { + std::make_pair + ( + std::array + { + 0xb0, 0x8f, 0xb1, 0x73, 0x92, 0x66, 0xc9, 0x90, 0x45, 0x7f, 0xdd, 0xc6, 0x4e, 0x55, 0x40, 0xd8, + 0x0a, 0x37, 0x99, 0x06, 0x92, 0x2a, 0x78, 0xc4, 0xb1, 0xef, 0x86, 0x06, 0xd0, 0x15, 0x9f, 0x4d + }, // SHA256("Noise_IKhfselg2_25519+MLKEM512_ChaChaPoly_SHA256") + std::array + { + 0x95, 0x8d, 0xf6, 0x6c, 0x95, 0xce, 0xa9, 0xf7, 0x42, 0xfc, 0xfa, 0x62, 0x71, 0x36, 0x1e, 0xa7, + 0xdc, 0x7a, 0xc0, 0x75, 0x01, 0xcf, 0xf9, 0xfc, 0x9f, 0xdb, 0x4c, 0x68, 0x3a, 0x53, 0x49, 0xeb + } // SHA256 (first) + ) + }; + + void InitNoiseIKStateMLKEM (NoiseSymmetricState& state, i2p::data::CryptoKeyType type, const uint8_t * pub) + { + if (type <= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD || + type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD > (int)NoiseIKInitMLKEMKeys.size ()) return; + auto ind = type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD - 1; + state.Init (NoiseIKInitMLKEMKeys[ind].first.data(), NoiseIKInitMLKEMKeys[ind].second.data(), pub); + } } } diff --git a/libi2pd/PostQuantum.h b/libi2pd/PostQuantum.h index 6bf2f238..f426d661 100644 --- a/libi2pd/PostQuantum.h +++ b/libi2pd/PostQuantum.h @@ -78,6 +78,8 @@ namespace crypto }; std::unique_ptr CreateMLKEMKeys (i2p::data::CryptoKeyType type); + + void InitNoiseIKStateMLKEM (NoiseSymmetricState& state, i2p::data::CryptoKeyType type, const uint8_t * pub); // Noise_IK (ratchets) PQ ML-KEM5 } } From 9c46ff244991d7f80d01a17875a41d018d04927e Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 15 Apr 2025 13:26:19 -0400 Subject: [PATCH 1028/1171] Initial Noise states and encryptors/decryptors for ML-KEM-768 and ML-KEM-1024 --- libi2pd/CryptoKey.h | 12 ++++++++++-- libi2pd/Identity.cpp | 12 +++++++++--- libi2pd/PostQuantum.cpp | 36 +++++++++++++++++++++++++++++++----- 3 files changed, 50 insertions(+), 10 deletions(-) diff --git a/libi2pd/CryptoKey.h b/libi2pd/CryptoKey.h index 14ef4fa8..657a6a91 100644 --- a/libi2pd/CryptoKey.h +++ b/libi2pd/CryptoKey.h @@ -167,7 +167,11 @@ namespace crypto case i2p::data::CRYPTO_KEY_TYPE_ELGAMAL: return 256; case i2p::data::CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC: return 32; case i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD: return 32; - case i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD: return 32; + // ML-KEM hybrid + case i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD: + case i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM768_X25519_AEAD: + case i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM1024_X25519_AEAD: + return 32; }; return 0; } @@ -179,7 +183,11 @@ namespace crypto case i2p::data::CRYPTO_KEY_TYPE_ELGAMAL: return 256; case i2p::data::CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC: return 32; case i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD: return 32; - case i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD: return 32; + // ML-KEM hybrid + case i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD: + case i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM768_X25519_AEAD: + case i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM1024_X25519_AEAD: + return 32; }; return 0; } diff --git a/libi2pd/Identity.cpp b/libi2pd/Identity.cpp index 3b2f5b97..798d9505 100644 --- a/libi2pd/Identity.cpp +++ b/libi2pd/Identity.cpp @@ -419,7 +419,9 @@ namespace data return std::make_shared(key); break; case CRYPTO_KEY_TYPE_ECIES_X25519_AEAD: - case CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD: + case CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD: + case CRYPTO_KEY_TYPE_ECIES_MLKEM768_X25519_AEAD: + case CRYPTO_KEY_TYPE_ECIES_MLKEM1024_X25519_AEAD: return std::make_shared(key); break; case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC: @@ -686,7 +688,9 @@ namespace data return std::make_shared(key); break; case CRYPTO_KEY_TYPE_ECIES_X25519_AEAD: - case CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD: + case CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD: + case CRYPTO_KEY_TYPE_ECIES_MLKEM768_X25519_AEAD: + case CRYPTO_KEY_TYPE_ECIES_MLKEM1024_X25519_AEAD: return std::make_shared(key); break; case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC: @@ -774,7 +778,9 @@ namespace data i2p::crypto::CreateECIESP256RandomKeys (priv, pub); break; case CRYPTO_KEY_TYPE_ECIES_X25519_AEAD: - case CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD: + case CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD: + case CRYPTO_KEY_TYPE_ECIES_MLKEM768_X25519_AEAD: + case CRYPTO_KEY_TYPE_ECIES_MLKEM1024_X25519_AEAD: i2p::crypto::CreateECIESX25519AEADRatchetRandomKeys (priv, pub); break; default: diff --git a/libi2pd/PostQuantum.cpp b/libi2pd/PostQuantum.cpp index 0a55ca4d..fa268828 100644 --- a/libi2pd/PostQuantum.cpp +++ b/libi2pd/PostQuantum.cpp @@ -64,7 +64,7 @@ namespace crypto EVP_PKEY_CTX_free (ctx); } else - LogPrint (eLogError, "MLKEM512 can't create PKEY context"); + LogPrint (eLogError, "MLKEM can't create PKEY context"); } void MLKEMKeys::Encaps (uint8_t * ciphertext, uint8_t * shared) @@ -79,7 +79,7 @@ namespace crypto EVP_PKEY_CTX_free (ctx); } else - LogPrint (eLogError, "MLKEM512 can't create PKEY context"); + LogPrint (eLogError, "MLKEM can't create PKEY context"); } void MLKEMKeys::Decaps (const uint8_t * ciphertext, uint8_t * shared) @@ -94,7 +94,7 @@ namespace crypto EVP_PKEY_CTX_free (ctx); } else - LogPrint (eLogError, "MLKEM512 can't create PKEY context"); + LogPrint (eLogError, "MLKEM can't create PKEY context"); } std::unique_ptr CreateMLKEMKeys (i2p::data::CryptoKeyType type) @@ -104,7 +104,7 @@ namespace crypto return std::make_unique((MLKEMTypes)(type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD - 1)); } - static constexpr std::array, std::array >, 1> NoiseIKInitMLKEMKeys = + static constexpr std::array, std::array >, 3> NoiseIKInitMLKEMKeys = { std::make_pair ( @@ -118,7 +118,33 @@ namespace crypto 0x95, 0x8d, 0xf6, 0x6c, 0x95, 0xce, 0xa9, 0xf7, 0x42, 0xfc, 0xfa, 0x62, 0x71, 0x36, 0x1e, 0xa7, 0xdc, 0x7a, 0xc0, 0x75, 0x01, 0xcf, 0xf9, 0xfc, 0x9f, 0xdb, 0x4c, 0x68, 0x3a, 0x53, 0x49, 0xeb } // SHA256 (first) - ) + ), + std::make_pair + ( + std::array + { + 0x36, 0x03, 0x90, 0x2d, 0xf9, 0xa2, 0x2a, 0x5e, 0xc9, 0x3d, 0xdb, 0x8f, 0xa8, 0x1b, 0xdb, 0x4b, + 0xae, 0x9d, 0x93, 0x9c, 0xdf, 0xaf, 0xde, 0x55, 0x49, 0x13, 0xfe, 0x98, 0xf8, 0x4a, 0xd4, 0xbd + }, // SHA256("Noise_IKhfselg2_25519+MLKEM768_ChaChaPoly_SHA256") + std::array + { + 0x15, 0x44, 0x89, 0xbf, 0x30, 0xf0, 0xc9, 0x77, 0x66, 0x10, 0xcb, 0xb1, 0x57, 0x3f, 0xab, 0x68, + 0x79, 0x57, 0x39, 0x57, 0x0a, 0xe7, 0xc0, 0x31, 0x8a, 0xa2, 0x96, 0xef, 0xbf, 0xa9, 0x6a, 0xbb + } // SHA256 (first) + ), + std::make_pair + ( + std::array + { + 0x86, 0xa5, 0x36, 0x44, 0xc6, 0x12, 0xd5, 0x71, 0xa1, 0x2d, 0xd8, 0xb6, 0x0a, 0x00, 0x9f, 0x2c, + 0x1a, 0xa8, 0x7d, 0x22, 0xa4, 0xff, 0x2b, 0xcd, 0x61, 0x34, 0x97, 0x6d, 0xa1, 0x49, 0xeb, 0x4a + }, // SHA256("Noise_IKhfselg2_25519+MLKEM1024_ChaChaPoly_SHA256") + std::array + { + 0x42, 0x0d, 0xc2, 0x1c, 0x7b, 0x18, 0x61, 0xb7, 0x4a, 0x04, 0x3d, 0xae, 0x0f, 0xdc, 0xf2, 0x71, + 0xb9, 0xba, 0x19, 0xbb, 0xbd, 0x5f, 0xd4, 0x9c, 0x3f, 0x4b, 0x01, 0xed, 0x6d, 0x13, 0x1d, 0xa2 + } // SHA256 (first) + ) }; void InitNoiseIKStateMLKEM (NoiseSymmetricState& state, i2p::data::CryptoKeyType type, const uint8_t * pub) From f6c93f734569e778ab1873ce47de4498dea28611 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 16 Apr 2025 15:40:09 -0400 Subject: [PATCH 1029/1171] common LocalEncryptionKey to pass to loacl LeaseSet --- libi2pd/CryptoKey.cpp | 16 ++++++++++++++++ libi2pd/CryptoKey.h | 11 +++++++++++ libi2pd/Destination.cpp | 10 +++++----- libi2pd/Destination.h | 19 ++----------------- libi2pd/LeaseSet.cpp | 10 +++++----- libi2pd/LeaseSet.h | 11 ++++------- 6 files changed, 43 insertions(+), 34 deletions(-) diff --git a/libi2pd/CryptoKey.cpp b/libi2pd/CryptoKey.cpp index bac5d740..e37d4039 100644 --- a/libi2pd/CryptoKey.cpp +++ b/libi2pd/CryptoKey.cpp @@ -181,5 +181,21 @@ namespace crypto k.GetPrivateKey (priv); memcpy (pub, k.GetPublicKey (), 32); } + + LocalEncryptionKey::LocalEncryptionKey (i2p::data::CryptoKeyType t): keyType(t) + { + pub.resize (GetCryptoPublicKeyLen (keyType)); + priv.resize (GetCryptoPrivateKeyLen (keyType)); + } + + void LocalEncryptionKey::GenerateKeys () + { + i2p::data::PrivateKeys::GenerateCryptoKeyPair (keyType, priv.data (), pub.data ()); + } + + void LocalEncryptionKey::CreateDecryptor () + { + decryptor = i2p::data::PrivateKeys::CreateDecryptor (keyType, priv.data ()); + } } } diff --git a/libi2pd/CryptoKey.h b/libi2pd/CryptoKey.h index 657a6a91..b6c37ddf 100644 --- a/libi2pd/CryptoKey.h +++ b/libi2pd/CryptoKey.h @@ -191,6 +191,17 @@ namespace crypto }; return 0; } + + struct LocalEncryptionKey + { + std::vector pub, priv; + i2p::data::CryptoKeyType keyType; + std::shared_ptr decryptor; + + LocalEncryptionKey (i2p::data::CryptoKeyType t); + void GenerateKeys (); + void CreateDecryptor (); + }; } } diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index a3f6a8c9..b23d31ed 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1047,7 +1047,7 @@ namespace client for (auto& it: encryptionKeyTypes) { - auto encryptionKey = std::make_shared (it); + auto encryptionKey = std::make_shared (it); if (IsPublic ()) PersistTemporaryKeys (encryptionKey); else @@ -1405,7 +1405,7 @@ namespace client return ret; } - void ClientDestination::PersistTemporaryKeys (std::shared_ptr keys) + void ClientDestination::PersistTemporaryKeys (std::shared_ptr keys) { if (!keys) return; std::string ident = GetIdentHash().ToBase32(); @@ -1475,9 +1475,9 @@ namespace client else { // standard LS2 (type 3) first - i2p::data::LocalLeaseSet2::KeySections keySections; + i2p::data::LocalLeaseSet2::EncryptionKeys keySections; for (const auto& it: m_EncryptionKeys) - keySections.push_back ({it.first, (uint16_t)it.second->pub.size (), it.second->pub.data ()} ); + keySections.push_back (it.second); auto publishedTimestamp = i2p::util::GetSecondsSinceEpoch (); if (publishedTimestamp <= m_LastPublishedTimestamp) @@ -1503,7 +1503,7 @@ namespace client bool ClientDestination::Decrypt (const uint8_t * encrypted, uint8_t * data, i2p::data::CryptoKeyType preferredCrypto) const { - std::shared_ptr encryptionKey; + std::shared_ptr encryptionKey; if (!m_EncryptionKeys.empty ()) { if (m_EncryptionKeys.rbegin ()->first == preferredCrypto) diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index a76a1be4..33e8bf08 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -230,21 +230,6 @@ namespace client class ClientDestination: public LeaseSetDestination { - struct EncryptionKey - { - std::vector pub, priv; - i2p::data::CryptoKeyType keyType; - std::shared_ptr decryptor; - - EncryptionKey (i2p::data::CryptoKeyType t): keyType(t) - { - pub.resize (i2p::crypto::GetCryptoPublicKeyLen (keyType)); - priv.resize (i2p::crypto::GetCryptoPrivateKeyLen (keyType)); - } - void GenerateKeys () { i2p::data::PrivateKeys::GenerateCryptoKeyPair (keyType, priv.data (), pub.data ()); }; - void CreateDecryptor () { decryptor = i2p::data::PrivateKeys::CreateDecryptor (keyType, priv.data ()); }; - }; - public: ClientDestination (boost::asio::io_context& service, const i2p::data::PrivateKeys& keys, @@ -310,7 +295,7 @@ namespace client std::shared_ptr GetSharedFromThis () { return std::static_pointer_cast(shared_from_this ()); } - void PersistTemporaryKeys (std::shared_ptr keys); + void PersistTemporaryKeys (std::shared_ptr keys); void ReadAuthKey (const std::string& group, const std::map * params); template @@ -319,7 +304,7 @@ namespace client private: i2p::data::PrivateKeys m_Keys; - std::map > m_EncryptionKeys; // last is most preferable + std::map > m_EncryptionKeys; // last is most preferable i2p::data::CryptoKeyType m_PreferredCryptoType; int m_StreamingAckDelay,m_StreamingOutboundSpeed, m_StreamingInboundSpeed, m_StreamingMaxConcurrentStreams; diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index db8c1aad..fc0e722d 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -848,7 +848,7 @@ namespace data } LocalLeaseSet2::LocalLeaseSet2 (uint8_t storeType, const i2p::data::PrivateKeys& keys, - const KeySections& encryptionKeys, const std::vector >& tunnels, + const EncryptionKeys& encryptionKeys, const std::vector >& tunnels, bool isPublic, uint64_t publishedTimestamp, bool isPublishedEncrypted): LocalLeaseSet (keys.GetPublic (), nullptr, 0) { @@ -858,7 +858,7 @@ namespace data if (num > MAX_NUM_LEASES) num = MAX_NUM_LEASES; size_t keySectionsLen = 0; for (const auto& it: encryptionKeys) - keySectionsLen += 2/*key type*/ + 2/*key len*/ + it.keyLen/*key*/; + keySectionsLen += 2/*key type*/ + 2/*key len*/ + it->pub.size()/*key*/; m_BufferLen = identity->GetFullLen () + 4/*published*/ + 2/*expires*/ + 2/*flag*/ + 2/*properties len*/ + 1/*num keys*/ + keySectionsLen + 1/*num leases*/ + num*LEASE2_SIZE + keys.GetSignatureLen (); uint16_t flags = 0; @@ -893,9 +893,9 @@ namespace data m_Buffer[offset] = encryptionKeys.size (); offset++; // 1 key for (const auto& it: encryptionKeys) { - htobe16buf (m_Buffer + offset, it.keyType); offset += 2; // key type - htobe16buf (m_Buffer + offset, it.keyLen); offset += 2; // key len - memcpy (m_Buffer + offset, it.encryptionPublicKey, it.keyLen); offset += it.keyLen; // key + htobe16buf (m_Buffer + offset, it->keyType); offset += 2; // key type + htobe16buf (m_Buffer + offset, it->pub.size()); offset += 2; // key len + memcpy (m_Buffer + offset, it->pub.data(), it->pub.size()); offset += it->pub.size(); // key } // leases uint32_t expirationTime = 0; // in seconds diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index 1a89229a..3594083c 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -12,12 +12,14 @@ #include #include #include +#include #include #include #include "Identity.h" #include "Timestamp.h" #include "I2PEndian.h" #include "Blinding.h" +#include "CryptoKey.h" namespace i2p { @@ -247,15 +249,10 @@ namespace data { public: - struct KeySection - { - uint16_t keyType, keyLen; - const uint8_t * encryptionPublicKey; - }; - typedef std::vector KeySections; + typedef std::list > EncryptionKeys; LocalLeaseSet2 (uint8_t storeType, const i2p::data::PrivateKeys& keys, - const KeySections& encryptionKeys, + const EncryptionKeys& encryptionKeys, const std::vector >& tunnels, bool isPublic, uint64_t publishedTimestamp, bool isPublishedEncrypted = false); From e69b56c4e37bfc5df155b54c912660363a6649b1 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 16 Apr 2025 16:44:01 -0400 Subject: [PATCH 1030/1171] publish preferred key first --- libi2pd/Destination.cpp | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index b23d31ed..3d910e54 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1475,10 +1475,27 @@ namespace client else { // standard LS2 (type 3) first + if (m_EncryptionKeys.empty ()) + { + LogPrint (eLogError, "Destinations: No encryption keys"); + return; + } + i2p::data::LocalLeaseSet2::EncryptionKeys keySections; - for (const auto& it: m_EncryptionKeys) - keySections.push_back (it.second); - + std::shared_ptr preferredSection; + if (m_EncryptionKeys.size () == 1) + preferredSection = m_EncryptionKeys.begin ()->second; // only key + else + { + for (const auto& it: m_EncryptionKeys) + if (it.first == m_PreferredCryptoType) + preferredSection = it.second; + else + keySections.push_back (it.second); + } + if (preferredSection) + keySections.push_front (preferredSection); // make preferred first + auto publishedTimestamp = i2p::util::GetSecondsSinceEpoch (); if (publishedTimestamp <= m_LastPublishedTimestamp) { From 1c162f9fd5b0507feb12f2d9cf0f8cada522597b Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 16 Apr 2025 21:59:10 -0400 Subject: [PATCH 1031/1171] get preferred crypto key type from ratchets session --- libi2pd/Destination.cpp | 18 ++++++++++++------ libi2pd/Destination.h | 5 +++-- libi2pd/ECIESX25519AEADRatchetSession.cpp | 4 ++-- libi2pd/ECIESX25519AEADRatchetSession.h | 1 + libi2pd/Garlic.cpp | 5 +++-- libi2pd/Garlic.h | 5 +++-- 6 files changed, 24 insertions(+), 14 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 3d910e54..f89fc0f0 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -13,6 +13,7 @@ #include #include #include "Crypto.h" +#include "ECIESX25519AEADRatchetSession.h" #include "Log.h" #include "FS.h" #include "Timestamp.h" @@ -377,10 +378,12 @@ namespace client { I2NPMessageType typeID = (I2NPMessageType)(buf[I2NP_HEADER_TYPEID_OFFSET]); uint32_t msgID = bufbe32toh (buf + I2NP_HEADER_MSGID_OFFSET); - LeaseSetDestination::HandleCloveI2NPMessage (typeID, buf + I2NP_HEADER_SIZE, GetI2NPMessageLength(buf, len) - I2NP_HEADER_SIZE, msgID); + LeaseSetDestination::HandleCloveI2NPMessage (typeID, buf + I2NP_HEADER_SIZE, + GetI2NPMessageLength(buf, len) - I2NP_HEADER_SIZE, msgID, nullptr); } - bool LeaseSetDestination::HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len, uint32_t msgID) + bool LeaseSetDestination::HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, + size_t len, uint32_t msgID, i2p::garlic::ECIESX25519AEADRatchetSession * from) { switch (typeID) { @@ -395,7 +398,7 @@ namespace client m_Pool->ProcessTunnelTest (bufbe32toh (payload + TUNNEL_TEST_MSGID_OFFSET), bufbe64toh (payload + TUNNEL_TEST_TIMESTAMP_OFFSET)); break; case eI2NPDatabaseStore: - HandleDatabaseStoreMessage (payload, len); + HandleDatabaseStoreMessage (payload, len, from); break; case eI2NPDatabaseSearchReply: HandleDatabaseSearchReplyMessage (payload, len); @@ -410,7 +413,8 @@ namespace client return true; } - void LeaseSetDestination::HandleDatabaseStoreMessage (const uint8_t * buf, size_t len) + void LeaseSetDestination::HandleDatabaseStoreMessage (const uint8_t * buf, size_t len, + i2p::garlic::ECIESX25519AEADRatchetSession * from) { if (len < DATABASE_STORE_HEADER_SIZE) { @@ -465,7 +469,8 @@ namespace client if (buf[DATABASE_STORE_TYPE_OFFSET] == i2p::data::NETDB_STORE_TYPE_LEASESET) leaseSet = std::make_shared (buf + offset, len - offset); // LeaseSet else - leaseSet = std::make_shared (buf[DATABASE_STORE_TYPE_OFFSET], buf + offset, len - offset, true, GetPreferredCryptoType () ); // LeaseSet2 + leaseSet = std::make_shared (buf[DATABASE_STORE_TYPE_OFFSET], + buf + offset, len - offset, true, from ? from->GetRemoteStaticKeyType () : GetPreferredCryptoType () ); // LeaseSet2 if (leaseSet->IsValid () && leaseSet->GetIdentHash () == key && !leaseSet->IsExpired ()) { if (leaseSet->GetIdentHash () != GetIdentHash ()) @@ -494,7 +499,8 @@ namespace client if (request->requestedBlindedKey) { auto ls2 = std::make_shared (buf + offset, len - offset, - request->requestedBlindedKey, m_LeaseSetPrivKey ? ((const uint8_t *)*m_LeaseSetPrivKey) : nullptr , GetPreferredCryptoType ()); + request->requestedBlindedKey, m_LeaseSetPrivKey ? ((const uint8_t *)*m_LeaseSetPrivKey) : nullptr, + from ? from->GetRemoteStaticKeyType () : GetPreferredCryptoType ()); if (ls2->IsValid () && !ls2->IsExpired ()) { leaseSet = ls2; diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 33e8bf08..abb63af2 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -164,7 +164,8 @@ namespace client // implements GarlicDestination void HandleI2NPMessage (const uint8_t * buf, size_t len) override; - bool HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len, uint32_t msgID) override; + bool HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, + size_t len, uint32_t msgID, i2p::garlic::ECIESX25519AEADRatchetSession * from) override; void SetLeaseSet (std::shared_ptr newLeaseSet); int GetLeaseSetType () const { return m_LeaseSetType; }; @@ -184,7 +185,7 @@ namespace client void HandlePublishConfirmationTimer (const boost::system::error_code& ecode); void HandlePublishVerificationTimer (const boost::system::error_code& ecode); void HandlePublishDelayTimer (const boost::system::error_code& ecode); - void HandleDatabaseStoreMessage (const uint8_t * buf, size_t len); + void HandleDatabaseStoreMessage (const uint8_t * buf, size_t len, i2p::garlic::ECIESX25519AEADRatchetSession * from); void HandleDatabaseSearchReplyMessage (const uint8_t * buf, size_t len); void HandleDeliveryStatusMessage (uint32_t msgID); diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index d38abd13..266caeaa 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -163,7 +163,7 @@ namespace garlic return false; } if (m_Destination) - m_Destination->HandleECIESx25519GarlicClove (buf + offset, size); + m_Destination->HandleECIESx25519GarlicClove (buf + offset, size, nullptr); return true; } @@ -390,7 +390,7 @@ namespace garlic { case eECIESx25519BlkGalicClove: if (GetOwner ()) - GetOwner ()->HandleECIESx25519GarlicClove (buf + offset, size); + GetOwner ()->HandleECIESx25519GarlicClove (buf + offset, size, this); break; case eECIESx25519BlkNextKey: LogPrint (eLogDebug, "Garlic: Next key"); diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index b7704534..1b810cd0 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -170,6 +170,7 @@ namespace garlic std::shared_ptr WrapOneTimeMessage (std::shared_ptr msg); const uint8_t * GetRemoteStaticKey () const { return m_RemoteStaticKey; } + i2p::data::CryptoKeyType GetRemoteStaticKeyType () const { return m_RemoteStaticKeyType; } void SetRemoteStaticKey (i2p::data::CryptoKeyType keyType, const uint8_t * key) { m_RemoteStaticKeyType = keyType; diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 5a3e4cae..3675b0b0 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -1003,7 +1003,8 @@ namespace garlic i2p::fs::Remove (it); } - void GarlicDestination::HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len) + void GarlicDestination::HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len, + ECIESX25519AEADRatchetSession * from) { const uint8_t * buf1 = buf; uint8_t flag = buf[0]; buf++; // flag @@ -1023,7 +1024,7 @@ namespace garlic buf += 4; // expiration ptrdiff_t offset = buf - buf1; if (offset <= (int)len) - HandleCloveI2NPMessage (typeID, buf, len - offset, msgID); + HandleCloveI2NPMessage (typeID, buf, len - offset, msgID, from); else LogPrint (eLogError, "Garlic: Clove is too long"); break; diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index 0eef4871..dc6b9bba 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -257,7 +257,7 @@ namespace garlic uint64_t AddECIESx25519SessionNextTag (ReceiveRatchetTagSetPtr tagset); void AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session); void RemoveECIESx25519Session (const uint8_t * staticKey); - void HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len); + void HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len, ECIESX25519AEADRatchetSession * from); uint8_t * GetPayloadBuffer (); virtual void ProcessGarlicMessage (std::shared_ptr msg); @@ -272,7 +272,8 @@ namespace garlic void AddECIESx25519Key (const uint8_t * key, const uint8_t * tag); // one tag bool HandleECIESx25519TagMessage (uint8_t * buf, size_t len); // return true if found virtual void HandleI2NPMessage (const uint8_t * buf, size_t len) = 0; // called from clove only - virtual bool HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len, uint32_t msgID) = 0; + virtual bool HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, + size_t len, uint32_t msgID, ECIESX25519AEADRatchetSession * from) = 0; void HandleGarlicMessage (std::shared_ptr msg); void HandleDeliveryStatusMessage (uint32_t msgID); From 67fe6faf2d3f1bf54a10129dde60ae0eab33e726 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 16 Apr 2025 22:08:16 -0400 Subject: [PATCH 1032/1171] get preferred crypto key type from ratchets session --- libi2pd/RouterContext.cpp | 3 ++- libi2pd/RouterContext.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index af90a46a..33fb5487 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -1194,7 +1194,8 @@ namespace i2p i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len))); } - bool RouterContext::HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len, uint32_t msgID) + bool RouterContext::HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, + size_t len, uint32_t msgID, i2p::garlic::ECIESX25519AEADRatchetSession * from) { if (typeID == eI2NPTunnelTest) { diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index c3336336..754c49da 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -204,7 +204,8 @@ namespace garlic // implements GarlicDestination void HandleI2NPMessage (const uint8_t * buf, size_t len) override; - bool HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len, uint32_t msgID) override; + bool HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, + size_t len, uint32_t msgID, i2p::garlic::ECIESX25519AEADRatchetSession * from) override; private: From bbfe81cb795da01d8011e94ea814f0349cd7c601 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 17 Apr 2025 22:15:17 -0400 Subject: [PATCH 1033/1171] handle any incoming post quantum crypto type --- libi2pd/Destination.cpp | 9 ++-- libi2pd/Destination.h | 2 +- libi2pd/ECIESX25519AEADRatchetSession.cpp | 56 ++++++++++------------- libi2pd/Garlic.cpp | 5 +- libi2pd/Garlic.h | 7 ++- libi2pd_client/I2CP.h | 5 +- 6 files changed, 41 insertions(+), 43 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index f89fc0f0..b88865b6 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1556,11 +1556,12 @@ namespace client #endif } - bool ClientDestination::SupportsRatchets () const + i2p::data::CryptoKeyType ClientDestination::GetRatchetsHighestCryptoType () const { - if (m_EncryptionKeys.empty ()) return false; - return m_EncryptionKeys.rbegin ()->first >= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD; - } + if (m_EncryptionKeys.empty ()) return 0; + auto cryptoType = m_EncryptionKeys.rbegin ()->first; + return cryptoType >= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD ? cryptoType : 0; + } const uint8_t * ClientDestination::GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const { diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index abb63af2..35557859 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -283,7 +283,7 @@ namespace client protected: // GarlicDestionation - bool SupportsRatchets () const override; + i2p::data::CryptoKeyType GetRatchetsHighestCryptoType () const override; // LeaseSetDestination void CleanupDestination () override; i2p::data::CryptoKeyType GetPreferredCryptoType () const override { return m_PreferredCryptoType; } diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 266caeaa..7436e775 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -266,40 +266,40 @@ namespace garlic } buf += 32; len -= 32; - uint64_t n = 0; uint8_t sharedSecret[32]; bool decrypted = false; + auto cryptoType = GetOwner ()->GetRatchetsHighestCryptoType (); #if OPENSSL_PQ - if (GetOwner ()->SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD)) + if (cryptoType > i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) // we support post quantum { - i2p::crypto::InitNoiseIKStateMLKEM (GetNoiseState (), i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD, - GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD)); // bpk + i2p::crypto::InitNoiseIKStateMLKEM (GetNoiseState (), cryptoType, GetOwner ()->GetEncryptionPublicKey (cryptoType)); // bpk MixHash (m_Aepk, 32); // h = SHA256(h || aepk) - if (GetOwner ()->Decrypt (m_Aepk, sharedSecret, i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD)) // x25519(bsk, aepk) + if (GetOwner ()->Decrypt (m_Aepk, sharedSecret, cryptoType)) // x25519(bsk, aepk) { MixKey (sharedSecret); - - uint8_t nonce[12], encapsKey[i2p::crypto::MLKEM512_KEY_LENGTH]; - CreateNonce (n, nonce); - if (Decrypt (buf, encapsKey, i2p::crypto::MLKEM512_KEY_LENGTH)) + + auto keyLen = i2p::crypto::GetMLKEMPublicKeyLen (cryptoType); + std::vector encapsKey(keyLen); + if (Decrypt (buf, encapsKey.data (), keyLen)) { decrypted = true; // encaps section has right hash - MixHash (buf, i2p::crypto::MLKEM512_KEY_LENGTH + 16); - buf += i2p::crypto::MLKEM512_KEY_LENGTH + 16; - len -= i2p::crypto::MLKEM512_KEY_LENGTH + 16; - n++; + MixHash (buf, keyLen + 16); + buf += keyLen + 16; + len -= keyLen + 16; - m_PQKeys = i2p::crypto::CreateMLKEMKeys (i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD); - m_PQKeys->SetPublicKey (encapsKey); + m_PQKeys = i2p::crypto::CreateMLKEMKeys (cryptoType); + m_PQKeys->SetPublicKey (encapsKey.data ()); } } } #endif if (!decrypted) { - if (GetOwner ()->SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) + if (cryptoType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD || + GetOwner ()->SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) { + cryptoType = i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD; i2p::crypto::InitNoiseIKState (GetNoiseState (), GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)); // bpk MixHash (m_Aepk, 32); // h = SHA256(h || aepk) @@ -318,8 +318,7 @@ namespace garlic } // decrypt flags/static - uint8_t nonce[12], fs[32]; - CreateNonce (n, nonce); + uint8_t fs[32]; if (!Decrypt (buf, fs, 32)) { LogPrint (eLogWarning, "Garlic: Flags/static section AEAD verification failed "); @@ -332,16 +331,8 @@ namespace garlic bool isStatic = !i2p::data::Tag<32> (fs).IsZero (); if (isStatic) { - // static key, fs is apk -#if OPENSSL_PQ - if (m_PQKeys) - { - SetRemoteStaticKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD, fs); - CreateNonce (0, nonce); // reset nonce - } - else -#endif - SetRemoteStaticKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD, fs); + // static key, fs is apk + SetRemoteStaticKey (cryptoType, fs); if (!GetOwner ()->Decrypt (fs, sharedSecret, m_RemoteStaticKeyType)) // x25519(bsk, apk) { LogPrint (eLogWarning, "Garlic: Incorrect Alice static key"); @@ -349,8 +340,6 @@ namespace garlic } MixKey (sharedSecret); } - else // all zeros flags - CreateNonce (1, nonce); // decrypt payload std::vector payload (len - 16); // we must save original ciphertext @@ -966,7 +955,8 @@ namespace garlic size_t len = CreatePayload (msg, m_State != eSessionStateEstablished, payload); if (!len) return nullptr; #if OPENSSL_PQ - auto m = NewI2NPMessage (len + (m_State == eSessionStateEstablished ? 28 : i2p::crypto::MLKEM512_KEY_LENGTH + 116)); + auto m = NewI2NPMessage (len + (m_State == eSessionStateEstablished ? 28 : + i2p::crypto::GetMLKEMPublicKeyLen (m_RemoteStaticKeyType) + 116)); #else auto m = NewI2NPMessage (len + 100); // 96 + 4 #endif @@ -994,8 +984,8 @@ namespace garlic return nullptr; len += 72; #if OPENSSL_PQ - if (m_RemoteStaticKeyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD) - len += i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH + 16; + if (m_RemoteStaticKeyType >= i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD) + len += i2p::crypto::GetMLKEMPublicKeyLen (m_RemoteStaticKeyType) + 16; #endif break; case eSessionStateNewSessionReplySent: diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 3675b0b0..8c8602e8 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -498,7 +498,8 @@ namespace garlic buf += 4; // length bool found = false; - if (SupportsRatchets ()) + bool supportsRatchets = SupportsRatchets (); + if (supportsRatchets) // try ECIESx25519 tag found = HandleECIESx25519TagMessage (buf, length); if (!found) @@ -535,7 +536,7 @@ namespace garlic decryption->Decrypt(buf + 514, length - 514, iv, buf + 514); HandleAESBlock (buf + 514, length - 514, decryption, msg->from); } - else if (SupportsRatchets ()) + else if (supportsRatchets) { // otherwise ECIESx25519 auto ts = i2p::util::GetMillisecondsSinceEpoch (); diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index dc6b9bba..25106c45 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -266,6 +266,10 @@ namespace garlic virtual std::shared_ptr GetLeaseSet () = 0; // TODO virtual std::shared_ptr GetTunnelPool () const = 0; + virtual i2p::data::CryptoKeyType GetRatchetsHighestCryptoType () const + { + return GetIdentity ()->GetCryptoKeyType () >= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD ? GetIdentity ()->GetCryptoKeyType () : 0; + } protected: @@ -279,11 +283,10 @@ namespace garlic void SaveTags (); void LoadTags (); - - virtual bool SupportsRatchets () const { return GetIdentity ()->GetCryptoKeyType () >= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD; } private: + bool SupportsRatchets () const { return GetRatchetsHighestCryptoType () > 0; } void HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr decryption, std::shared_ptr from); void HandleGarlicPayload (uint8_t * buf, size_t len, std::shared_ptr from); diff --git a/libi2pd_client/I2CP.h b/libi2pd_client/I2CP.h index 84243e6f..37c14dbb 100644 --- a/libi2pd_client/I2CP.h +++ b/libi2pd_client/I2CP.h @@ -109,7 +109,10 @@ namespace client protected: // GarlicDestination - bool SupportsRatchets () const override { return (bool)m_ECIESx25519Decryptor; } + i2p::data::CryptoKeyType GetRatchetsHighestCryptoType () const override + { + return m_ECIESx25519Decryptor ? i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD : 0; + } // LeaseSetDestination void CleanupDestination () override; i2p::data::CryptoKeyType GetPreferredCryptoType () const override; From 58818514e783d76654dab4d5a6aa171912a03fab Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 17 Apr 2025 22:34:39 -0400 Subject: [PATCH 1034/1171] correct NSR size --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 7436e775..87c99d51 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -985,13 +985,17 @@ namespace garlic len += 72; #if OPENSSL_PQ if (m_RemoteStaticKeyType >= i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD) - len += i2p::crypto::GetMLKEMPublicKeyLen (m_RemoteStaticKeyType) + 16; + len += i2p::crypto::GetMLKEMCipherTextLen (m_RemoteStaticKeyType) + 16; #endif break; case eSessionStateNewSessionReplySent: if (!NextNewSessionReplyMessage (payload, len, buf, m->maxLen)) return nullptr; len += 72; +#if OPENSSL_PQ + if (m_RemoteStaticKeyType >= i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD) + len += i2p::crypto::GetMLKEMCipherTextLen (m_RemoteStaticKeyType) + 16; +#endif break; case eSessionStateOneTime: if (!NewOutgoingSessionMessage (payload, len, buf, m->maxLen, false)) From 9b967059ada5c1acfd49d75466bd99c58085135d Mon Sep 17 00:00:00 2001 From: R4SAS Date: Fri, 18 Apr 2025 21:52:44 +0300 Subject: [PATCH 1035/1171] [gha] Update docker containers build --- .github/workflows/docker.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 34923f31..c6d55664 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -108,7 +108,7 @@ jobs: uses: Noelware/docker-manifest-action@master with: inputs: purplei2p/i2pd:latest - images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7 + tags: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7 push: true - name: Create and push latest manifest image to GHCR @@ -116,7 +116,7 @@ jobs: uses: Noelware/docker-manifest-action@master with: inputs: ghcr.io/purplei2p/i2pd:latest - images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7 + tags: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7 push: true - name: Store release version to env @@ -128,7 +128,7 @@ jobs: uses: Noelware/docker-manifest-action@master with: inputs: purplei2p/i2pd:latest,purplei2p/i2pd:latest-release,purplei2p/i2pd:release-${{ env.RELEASE_VERSION }} - images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7 + tags: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7 push: true - name: Create and push release manifest to GHCR @@ -136,5 +136,5 @@ jobs: uses: Noelware/docker-manifest-action@master with: inputs: ghcr.io/purplei2p/i2pd:latest,ghcr.io/purplei2p/i2pd:latest-release,ghcr.io/purplei2p/i2pd:release-${{ env.RELEASE_VERSION }} - images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7 + tags: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7 push: true From 2afdd5b723ca55151aad7a71ffc817bacaf8381b Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 19 Apr 2025 12:33:09 -0400 Subject: [PATCH 1036/1171] cleanup NSR keys --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 25 +++++++++++++++++++---- libi2pd/ECIESX25519AEADRatchetSession.h | 7 ++++--- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 87c99d51..08af4be3 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -95,6 +95,17 @@ namespace garlic m_ItermediateSymmKeys.erase (index); } + ReceiveRatchetTagSet::ReceiveRatchetTagSet (std::shared_ptr session, bool isNS): + m_Session (session), m_IsNS (isNS) + { + } + + ReceiveRatchetTagSet::~ReceiveRatchetTagSet () + { + if (m_IsNS && m_Session) + m_Session->CleanupReceiveNSRKeys (); + } + void ReceiveRatchetTagSet::Expire () { if (!m_ExpirationTimestamp) @@ -252,6 +263,14 @@ namespace garlic } return false; } + + void ECIESX25519AEADRatchetSession::CleanupReceiveNSRKeys () + { + m_EphemeralKeys = nullptr; +#if OPENSSL_PQ + m_PQKeys = nullptr; +#endif + } bool ECIESX25519AEADRatchetSession::HandleNewIncomingSession (const uint8_t * buf, size_t len) { @@ -824,10 +843,8 @@ namespace garlic if (m_State == eSessionStateNewSessionSent) { m_State = eSessionStateEstablished; - //m_EphemeralKeys = nullptr; // TODO: delete after a while -#if OPENSSL_PQ - // m_PQKeys = nullptr; // TODO: delete after a while -#endif + // don't delete m_EpehemralKey and m_PQKeys because delayd NSR's migth come + // done in CleanupReceiveNSRKeys called from NSR tagset destructor m_SessionCreatedTimestamp = i2p::util::GetSecondsSinceEpoch (); GetOwner ()->AddECIESx25519Session (m_RemoteStaticKey, shared_from_this ()); } diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index 1b810cd0..fd9cc45d 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -81,8 +81,8 @@ namespace garlic { public: - ReceiveRatchetTagSet (std::shared_ptr session, bool isNS = false): - m_Session (session), m_IsNS (isNS) {}; + ReceiveRatchetTagSet (std::shared_ptr session, bool isNS = false); + ~ReceiveRatchetTagSet () override; bool IsNS () const { return m_IsNS; }; std::shared_ptr GetSession () { return m_Session; }; @@ -184,7 +184,8 @@ namespace garlic bool CheckExpired (uint64_t ts); // true is expired bool CanBeRestarted (uint64_t ts) const { return ts > m_SessionCreatedTimestamp + ECIESX25519_RESTART_TIMEOUT; } bool IsInactive (uint64_t ts) const { return ts > m_LastActivityTimestamp + ECIESX25519_INACTIVITY_TIMEOUT && CanBeRestarted (ts); } - + void CleanupReceiveNSRKeys (); // called from ReceiveRatchetTagSet at Alice's side + bool IsRatchets () const override { return true; }; bool IsReadyToSend () const override { return m_State != eSessionStateNewSessionSent; }; bool IsTerminated () const override { return m_IsTerminated; } From 9bd2b8df761c36c59361d0946d6b190e78dee57b Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 20 Apr 2025 18:53:21 -0400 Subject: [PATCH 1037/1171] create and handle ML-DSA identities and signatures --- libi2pd/Identity.cpp | 109 +++++++++++++++++++++++++++++++------------ libi2pd/Identity.h | 10 ++-- libi2pd/LeaseSet.h | 2 +- 3 files changed, 88 insertions(+), 33 deletions(-) diff --git a/libi2pd/Identity.cpp b/libi2pd/Identity.cpp index 798d9505..de84b53b 100644 --- a/libi2pd/Identity.cpp +++ b/libi2pd/Identity.cpp @@ -127,6 +127,7 @@ namespace data excessLen = i2p::crypto::MLDSA44_PUBLIC_KEY_LENGTH - 384; excessBuf = new uint8_t[excessLen]; memcpy (excessBuf, signingKey + 384, excessLen); + cryptoType = 0xFF; // crypto key is not used break; } #endif @@ -142,12 +143,15 @@ namespace data htobe16buf (m_ExtendedBuffer + 2, cryptoType); if (excessLen && excessBuf) { - if (excessLen > MAX_EXTENDED_BUFFER_SIZE - 4) + if (m_ExtendedLen > MAX_EXTENDED_BUFFER_SIZE) { - LogPrint (eLogError, "Identity: Unexpected excessive signing key len ", excessLen); - excessLen = MAX_EXTENDED_BUFFER_SIZE - 4; + auto newBuf = new uint8_t[m_ExtendedLen]; + memcpy (newBuf, m_ExtendedBuffer, 4); + memcpy (newBuf + 4, excessBuf, excessLen); + m_ExtendedBufferPtr = newBuf; } - memcpy (m_ExtendedBuffer + 4, excessBuf, excessLen); + else + memcpy (m_ExtendedBuffer + 4, excessBuf, excessLen); delete[] excessBuf; } // calculate ident hash @@ -195,6 +199,8 @@ namespace data IdentityEx::~IdentityEx () { + if (m_ExtendedLen > MAX_EXTENDED_BUFFER_SIZE) + delete[] m_ExtendedBufferPtr; } IdentityEx& IdentityEx::operator=(const IdentityEx& other) @@ -202,11 +208,29 @@ namespace data memcpy (&m_StandardIdentity, &other.m_StandardIdentity, DEFAULT_IDENTITY_SIZE); m_IdentHash = other.m_IdentHash; + size_t oldLen = m_ExtendedLen; m_ExtendedLen = other.m_ExtendedLen; if (m_ExtendedLen > 0) { - if (m_ExtendedLen > MAX_EXTENDED_BUFFER_SIZE) m_ExtendedLen = MAX_EXTENDED_BUFFER_SIZE; - memcpy (m_ExtendedBuffer, other.m_ExtendedBuffer, m_ExtendedLen); + if (m_ExtendedLen > MAX_EXTENDED_BUFFER_SIZE) + { + if (oldLen > MAX_EXTENDED_BUFFER_SIZE) + { + if (m_ExtendedLen > oldLen) + { + delete[] m_ExtendedBufferPtr; + m_ExtendedBufferPtr = new uint8_t[m_ExtendedLen]; + } + } + else + m_ExtendedBufferPtr = new uint8_t[m_ExtendedLen]; + memcpy (m_ExtendedBufferPtr, other.m_ExtendedBufferPtr, m_ExtendedLen); + } + else + { + if (oldLen > MAX_EXTENDED_BUFFER_SIZE) delete[] m_ExtendedBufferPtr; + memcpy (m_ExtendedBuffer, other.m_ExtendedBuffer, m_ExtendedLen); + } } m_Verifier = nullptr; CreateVerifier (); @@ -235,13 +259,28 @@ namespace data } memcpy (&m_StandardIdentity, buf, DEFAULT_IDENTITY_SIZE); + size_t oldLen = m_ExtendedLen; m_ExtendedLen = bufbe16toh (m_StandardIdentity.certificate + 1); if (m_ExtendedLen) { if (m_ExtendedLen + DEFAULT_IDENTITY_SIZE <= len) { - if (m_ExtendedLen > MAX_EXTENDED_BUFFER_SIZE) m_ExtendedLen = MAX_EXTENDED_BUFFER_SIZE; - memcpy (m_ExtendedBuffer, buf + DEFAULT_IDENTITY_SIZE, m_ExtendedLen); + if (m_ExtendedLen > MAX_EXTENDED_BUFFER_SIZE) + { + if (oldLen > MAX_EXTENDED_BUFFER_SIZE) + { + if (m_ExtendedLen > oldLen) + { + delete[] m_ExtendedBufferPtr; + m_ExtendedBufferPtr = new uint8_t[m_ExtendedLen]; + } + } + else + m_ExtendedBufferPtr = new uint8_t[m_ExtendedLen]; + memcpy (m_ExtendedBufferPtr, buf + DEFAULT_IDENTITY_SIZE, m_ExtendedLen); + } + else + memcpy (m_ExtendedBuffer, buf + DEFAULT_IDENTITY_SIZE, m_ExtendedLen); } else { @@ -266,7 +305,12 @@ namespace data if (fullLen > len) return 0; // buffer is too small and may overflow somewhere else memcpy (buf, &m_StandardIdentity, DEFAULT_IDENTITY_SIZE); if (m_ExtendedLen > 0) - memcpy (buf + DEFAULT_IDENTITY_SIZE, m_ExtendedBuffer, m_ExtendedLen); + { + if (m_ExtendedLen > MAX_EXTENDED_BUFFER_SIZE) + memcpy (buf + DEFAULT_IDENTITY_SIZE, m_ExtendedBufferPtr, m_ExtendedLen); + else + memcpy (buf + DEFAULT_IDENTITY_SIZE, m_ExtendedBuffer, m_ExtendedLen); + } return fullLen; } @@ -295,7 +339,7 @@ namespace data const uint8_t * IdentityEx::GetSigningPublicKeyBuffer () const { auto keyLen = GetSigningPublicKeyLen (); - if (keyLen > 128) return nullptr; // P521 + if (keyLen > 128) return nullptr; // P521 or PQ return m_StandardIdentity.signingKey + 128 - keyLen; } @@ -322,7 +366,7 @@ namespace data SigningKeyType IdentityEx::GetSigningKeyType () const { if (m_StandardIdentity.certificate[0] == CERTIFICATE_TYPE_KEY && m_ExtendedLen >= 2) - return bufbe16toh (m_ExtendedBuffer); // signing key + return bufbe16toh (m_ExtendedLen <= MAX_EXTENDED_BUFFER_SIZE ? m_ExtendedBuffer : m_ExtendedBufferPtr); // signing key return SIGNING_KEY_TYPE_DSA_SHA1; } @@ -335,7 +379,7 @@ namespace data CryptoKeyType IdentityEx::GetCryptoKeyType () const { if (m_StandardIdentity.certificate[0] == CERTIFICATE_TYPE_KEY && m_ExtendedLen >= 4) - return bufbe16toh (m_ExtendedBuffer + 2); // crypto key + return bufbe16toh (m_ExtendedLen <= MAX_EXTENDED_BUFFER_SIZE ? m_ExtendedBuffer + 2 : m_ExtendedBufferPtr + 2); // crypto key return CRYPTO_KEY_TYPE_ELGAMAL; } @@ -359,7 +403,7 @@ namespace data return new i2p::crypto::GOSTR3410_512_Verifier (i2p::crypto::eGOSTR3410TC26A512); case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519: return new i2p::crypto::RedDSA25519Verifier (); -#if OPENSSL_PQ +#if OPENSSL_PQ case SIGNING_KEY_TYPE_MLDSA44: return new i2p::crypto::MLDSA44Verifier (); #endif @@ -391,7 +435,7 @@ namespace data uint8_t * signingKey = new uint8_t[keyLen]; memcpy (signingKey, m_StandardIdentity.signingKey, 384); size_t excessLen = keyLen - 384; - memcpy (signingKey + 384, m_ExtendedBuffer + 4, excessLen); // right after signing and crypto key types + memcpy (signingKey + 384, m_ExtendedBufferPtr + 4, excessLen); // right after signing and crypto key types verifier->SetPublicKey (signingKey); delete[] signingKey; } @@ -451,7 +495,9 @@ namespace data { m_Public = std::make_shared(Identity (keys)); memcpy (m_PrivateKey, keys.privateKey, 256); // 256 - memcpy (m_SigningPrivateKey, keys.signingPrivateKey, m_Public->GetSigningPrivateKeyLen ()); + size_t keyLen = m_Public->GetSigningPrivateKeyLen (); + if (keyLen > 128) m_SigningPrivateKey.resize (keyLen); + memcpy (m_SigningPrivateKey.data (), keys.signingPrivateKey, keyLen); m_OfflineSignature.resize (0); m_TransientSignatureLen = 0; m_TransientSigningPrivateKeyLen = 0; @@ -467,7 +513,7 @@ namespace data m_OfflineSignature = other.m_OfflineSignature; m_TransientSignatureLen = other.m_TransientSignatureLen; m_TransientSigningPrivateKeyLen = other.m_TransientSigningPrivateKeyLen; - memcpy (m_SigningPrivateKey, other.m_SigningPrivateKey, m_TransientSigningPrivateKeyLen > 0 ? m_TransientSigningPrivateKeyLen : m_Public->GetSigningPrivateKeyLen ()); + m_SigningPrivateKey = other.m_SigningPrivateKey; m_Signer = nullptr; CreateSigner (); return *this; @@ -490,8 +536,9 @@ namespace data memcpy (m_PrivateKey, buf + ret, cryptoKeyLen); ret += cryptoKeyLen; size_t signingPrivateKeySize = m_Public->GetSigningPrivateKeyLen (); - if(signingPrivateKeySize + ret > len || signingPrivateKeySize > 128) return 0; // overflow - memcpy (m_SigningPrivateKey, buf + ret, signingPrivateKeySize); + if (signingPrivateKeySize + ret > len) return 0; // overflow + m_SigningPrivateKey.resize (signingPrivateKeySize); + memcpy (m_SigningPrivateKey.data (), buf + ret, signingPrivateKeySize); ret += signingPrivateKeySize; m_Signer = nullptr; // check if signing private key is all zeros @@ -532,8 +579,9 @@ namespace data memcpy (m_OfflineSignature.data (), offlineInfo, offlineInfoLen); // override signing private key m_TransientSigningPrivateKeyLen = transientVerifier->GetPrivateKeyLen (); - if (m_TransientSigningPrivateKeyLen + ret > len || m_TransientSigningPrivateKeyLen > 128) return 0; - memcpy (m_SigningPrivateKey, buf + ret, m_TransientSigningPrivateKeyLen); + if (m_TransientSigningPrivateKeyLen + ret > len) return 0; + if (m_TransientSigningPrivateKeyLen > 128) m_SigningPrivateKey.resize (m_TransientSigningPrivateKeyLen); + memcpy (m_SigningPrivateKey.data (), buf + ret, m_TransientSigningPrivateKeyLen); ret += m_TransientSigningPrivateKeyLen; CreateSigner (keyType); } @@ -553,7 +601,7 @@ namespace data if (IsOfflineSignature ()) memset (buf + ret, 0, signingPrivateKeySize); else - memcpy (buf + ret, m_SigningPrivateKey, signingPrivateKeySize); + memcpy (buf + ret, m_SigningPrivateKey.data (), signingPrivateKeySize); ret += signingPrivateKeySize; if (IsOfflineSignature ()) { @@ -564,7 +612,7 @@ namespace data ret += offlineSignatureLen; // transient private key if (ret + m_TransientSigningPrivateKeyLen > len) return 0; - memcpy (buf + ret, m_SigningPrivateKey, m_TransientSigningPrivateKeyLen); + memcpy (buf + ret, m_SigningPrivateKey.data (), m_TransientSigningPrivateKeyLen); ret += m_TransientSigningPrivateKeyLen; } return ret; @@ -603,13 +651,13 @@ namespace data { if (m_Signer) return; if (keyType == SIGNING_KEY_TYPE_DSA_SHA1) - m_Signer.reset (new i2p::crypto::DSASigner (m_SigningPrivateKey, m_Public->GetStandardIdentity ().signingKey)); + m_Signer.reset (new i2p::crypto::DSASigner (m_SigningPrivateKey.data (), m_Public->GetStandardIdentity ().signingKey)); else if (keyType == SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519 && !IsOfflineSignature ()) - m_Signer.reset (new i2p::crypto::EDDSA25519Signer (m_SigningPrivateKey, m_Public->GetStandardIdentity ().signingKey + (sizeof(Identity::signingKey) - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH))); // TODO: remove public key check + m_Signer.reset (new i2p::crypto::EDDSA25519Signer (m_SigningPrivateKey.data (), m_Public->GetStandardIdentity ().signingKey + (sizeof(Identity::signingKey) - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH))); // TODO: remove public key check else { // public key is not required - auto signer = CreateSigner (keyType, m_SigningPrivateKey); + auto signer = CreateSigner (keyType, m_SigningPrivateKey.data ()); if (signer) m_Signer.reset (signer); } } @@ -708,8 +756,10 @@ namespace data { PrivateKeys keys; // signature - uint8_t signingPublicKey[512]; // signing public key is 512 bytes max - GenerateSigningKeyPair (type, keys.m_SigningPrivateKey, signingPublicKey); + std::unique_ptr verifier (IdentityEx::CreateVerifier (type)); + std::vector signingPublicKey(verifier->GetPublicKeyLen ()); + keys.m_SigningPrivateKey.resize (verifier->GetPrivateKeyLen ()); + GenerateSigningKeyPair (type, keys.m_SigningPrivateKey.data (), signingPublicKey.data ()); // encryption uint8_t publicKey[256]; if (isDestination) @@ -717,7 +767,7 @@ namespace data else GenerateCryptoKeyPair (cryptoType, keys.m_PrivateKey, publicKey); // identity - keys.m_Public = std::make_shared (isDestination ? nullptr : publicKey, signingPublicKey, type, cryptoType); + keys.m_Public = std::make_shared (isDestination ? nullptr : publicKey, signingPublicKey.data (), type, cryptoType); keys.CreateSigner (); return keys; @@ -798,9 +848,10 @@ namespace data keys.m_TransientSigningPrivateKeyLen = verifier->GetPrivateKeyLen (); keys.m_TransientSignatureLen = verifier->GetSignatureLen (); keys.m_OfflineSignature.resize (pubKeyLen + m_Public->GetSignatureLen () + 6); + keys.m_SigningPrivateKey.resize (verifier->GetPrivateKeyLen ()); htobe32buf (keys.m_OfflineSignature.data (), expires); // expires htobe16buf (keys.m_OfflineSignature.data () + 4, type); // type - GenerateSigningKeyPair (type, keys.m_SigningPrivateKey, keys.m_OfflineSignature.data () + 6); // public key + GenerateSigningKeyPair (type, keys.m_SigningPrivateKey.data (), keys.m_OfflineSignature.data () + 6); // public key Sign (keys.m_OfflineSignature.data (), pubKeyLen + 6, keys.m_OfflineSignature.data () + 6 + pubKeyLen); // signature // recreate signer keys.m_Signer = nullptr; diff --git a/libi2pd/Identity.h b/libi2pd/Identity.h index 173559e9..c95ce000 100644 --- a/libi2pd/Identity.h +++ b/libi2pd/Identity.h @@ -142,7 +142,11 @@ namespace data IdentHash m_IdentHash; std::unique_ptr m_Verifier; size_t m_ExtendedLen; - uint8_t m_ExtendedBuffer[MAX_EXTENDED_BUFFER_SIZE]; // TODO: support PQ keys + union + { + uint8_t m_ExtendedBuffer[MAX_EXTENDED_BUFFER_SIZE]; + uint8_t * m_ExtendedBufferPtr; + }; }; size_t GetIdentityBufferLen (const uint8_t * buf, size_t len); // return actual identity length in buffer @@ -160,7 +164,7 @@ namespace data std::shared_ptr GetPublic () const { return m_Public; }; const uint8_t * GetPrivateKey () const { return m_PrivateKey; }; - const uint8_t * GetSigningPrivateKey () const { return m_SigningPrivateKey; }; + const uint8_t * GetSigningPrivateKey () const { return m_SigningPrivateKey.data (); }; size_t GetSignatureLen () const; // might not match identity bool IsOfflineSignature () const { return m_TransientSignatureLen > 0; }; uint8_t * GetPadding(); @@ -196,7 +200,7 @@ namespace data std::shared_ptr m_Public; uint8_t m_PrivateKey[256]; - uint8_t m_SigningPrivateKey[128]; // assume private key doesn't exceed 128 bytes + std::vector m_SigningPrivateKey; mutable std::unique_ptr m_Signer; std::vector m_OfflineSignature; // non zero length, if applicable size_t m_TransientSignatureLen = 0; diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index 3594083c..c24c8696 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -60,7 +60,7 @@ namespace data typedef std::function LeaseInspectFunc; - const size_t MAX_LS_BUFFER_SIZE = 3072; + const size_t MAX_LS_BUFFER_SIZE = 4096; const size_t LEASE_SIZE = 44; // 32 + 4 + 8 const size_t LEASE2_SIZE = 40; // 32 + 4 + 4 const uint8_t MAX_NUM_LEASES = 16; From 724d8bde4edf58a2f9a6fc0b32aa6a5839b5ba6d Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 21 Apr 2025 21:25:51 -0400 Subject: [PATCH 1038/1171] handle incoming packets with ML-DSA signature --- libi2pd/Identity.cpp | 2 +- libi2pd/LeaseSet.h | 5 ++++- libi2pd/Streaming.cpp | 49 +++++++++++++++++++++++++++---------------- libi2pd/Streaming.h | 4 ++++ 4 files changed, 40 insertions(+), 20 deletions(-) diff --git a/libi2pd/Identity.cpp b/libi2pd/Identity.cpp index de84b53b..865beeb8 100644 --- a/libi2pd/Identity.cpp +++ b/libi2pd/Identity.cpp @@ -433,7 +433,7 @@ namespace data { // for post-quantum uint8_t * signingKey = new uint8_t[keyLen]; - memcpy (signingKey, m_StandardIdentity.signingKey, 384); + memcpy (signingKey, m_StandardIdentity, 384); size_t excessLen = keyLen - 384; memcpy (signingKey + 384, m_ExtendedBufferPtr + 4, excessLen); // right after signing and crypto key types verifier->SetPublicKey (signingKey); diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index c24c8696..f5197eb5 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -59,8 +59,11 @@ namespace data }; typedef std::function LeaseInspectFunc; - +#if OPENSSL_PQ + const size_t MAX_LS_BUFFER_SIZE = 8192; +#else const size_t MAX_LS_BUFFER_SIZE = 4096; +#endif const size_t LEASE_SIZE = 44; // 32 + 4 + 8 const size_t LEASE2_SIZE = 40; // 32 + 4 + 4 const uint8_t MAX_NUM_LEASES = 16; diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index d21cfa62..99da5fd2 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -450,29 +450,42 @@ namespace stream if (flags & PACKET_FLAG_SIGNATURE_INCLUDED) { - uint8_t signature[256]; + bool verified = false; auto signatureLen = m_TransientVerifier ? m_TransientVerifier->GetSignatureLen () : m_RemoteIdentity->GetSignatureLen (); - if(signatureLen <= sizeof(signature)) - { - memcpy (signature, optionData, signatureLen); - memset (const_cast(optionData), 0, signatureLen); - bool verified = m_TransientVerifier ? - m_TransientVerifier->Verify (packet->GetBuffer (), packet->GetLength (), signature) : - m_RemoteIdentity->Verify (packet->GetBuffer (), packet->GetLength (), signature); - if (!verified) - { - LogPrint (eLogError, "Streaming: Signature verification failed, sSID=", m_SendStreamID, ", rSID=", m_RecvStreamID); - Close (); - flags |= PACKET_FLAG_CLOSE; - } - memcpy (const_cast(optionData), signature, signatureLen); - optionData += signatureLen; - } - else + if (signatureLen > packet->GetLength ()) { LogPrint (eLogError, "Streaming: Signature too big, ", signatureLen, " bytes"); return false; + } + if(signatureLen <= 256) + { + // standard + uint8_t signature[256]; + memcpy (signature, optionData, signatureLen); + memset (const_cast(optionData), 0, signatureLen); + verified = m_TransientVerifier ? + m_TransientVerifier->Verify (packet->GetBuffer (), packet->GetLength (), signature) : + m_RemoteIdentity->Verify (packet->GetBuffer (), packet->GetLength (), signature); + if (verified) + memcpy (const_cast(optionData), signature, signatureLen); } + else + { + // post quantum + std::vector signature(signatureLen); + memcpy (signature.data (), optionData, signatureLen); + memset (const_cast(optionData), 0, signatureLen); + verified = m_TransientVerifier ? + m_TransientVerifier->Verify (packet->GetBuffer (), packet->GetLength (), signature.data ()) : + m_RemoteIdentity->Verify (packet->GetBuffer (), packet->GetLength (), signature.data ()); + } + if (verified) + optionData += signatureLen; + else + { + LogPrint (eLogError, "Streaming: Signature verification failed, sSID=", m_SendStreamID, ", rSID=", m_RecvStreamID); + return false; + } } if (immediateAckRequested) SendQuickAck (); diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 8280477b..8a5c355c 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -51,7 +51,11 @@ namespace stream const size_t STREAMING_MTU = 1730; const size_t STREAMING_MTU_RATCHETS = 1812; +#if OPENSSL_PQ + const size_t MAX_PACKET_SIZE = 8192; +#else const size_t MAX_PACKET_SIZE = 4096; +#endif const size_t COMPRESSION_THRESHOLD_SIZE = 66; const int MAX_NUM_RESEND_ATTEMPTS = 10; const int INITIAL_WINDOW_SIZE = 10; From a5fa4ddb4cb5f0362ab7d763bf20f462e7a7b68b Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 22 Apr 2025 21:21:51 -0400 Subject: [PATCH 1039/1171] compare LeaseSet's static keys with ratchets session it was received from --- libi2pd/Destination.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index b88865b6..91cc8380 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -469,9 +469,21 @@ namespace client if (buf[DATABASE_STORE_TYPE_OFFSET] == i2p::data::NETDB_STORE_TYPE_LEASESET) leaseSet = std::make_shared (buf + offset, len - offset); // LeaseSet else + { leaseSet = std::make_shared (buf[DATABASE_STORE_TYPE_OFFSET], buf + offset, len - offset, true, from ? from->GetRemoteStaticKeyType () : GetPreferredCryptoType () ); // LeaseSet2 - if (leaseSet->IsValid () && leaseSet->GetIdentHash () == key && !leaseSet->IsExpired ()) + if (from) + { + uint8_t pub[32]; + leaseSet->Encrypt (nullptr, pub); + if (memcmp (from->GetRemoteStaticKey (), pub, 32)) + { + LogPrint (eLogError, "Destination: Remote LeaseSet static key mismatch"); + leaseSet = nullptr; + } + } + } + if (leaseSet && leaseSet->IsValid () && leaseSet->GetIdentHash () == key && !leaseSet->IsExpired ()) { if (leaseSet->GetIdentHash () != GetIdentHash ()) { From 9d44a32e4cf63f2b34f66e428b2911c6a8e3f036 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 24 Apr 2025 16:37:50 -0400 Subject: [PATCH 1040/1171] fixed #2183. Give more time to close streams after session disconnect if needed --- libi2pd/Streaming.h | 1 + libi2pd_client/SAM.cpp | 50 +++++++++++++++++++++++++++++------------- libi2pd_client/SAM.h | 6 ++++- 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 8a5c355c..570fdd1d 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -326,6 +326,7 @@ namespace stream void SendPing (std::shared_ptr remote); void DeleteStream (std::shared_ptr stream); bool DeleteStream (uint32_t recvStreamID); + size_t GetNumStreams () const { return m_Streams.size (); }; void SetAcceptor (const Acceptor& acceptor); void ResetAcceptor (); bool IsAcceptorSet () const { return m_Acceptor != nullptr; }; diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 3114bb5a..2c0f8d92 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -43,23 +43,21 @@ namespace client m_Stream->AsyncClose (); m_Stream = nullptr; } - auto Session = m_Owner.FindSession(m_ID); switch (m_SocketType) { case eSAMSocketTypeSession: m_Owner.CloseSession (m_ID); break; case eSAMSocketTypeStream: - { - break; - } + break; case eSAMSocketTypeAcceptor: case eSAMSocketTypeForward: { - if (Session) + auto session = m_Owner.FindSession(m_ID); + if (session) { - if (m_IsAccepting && Session->GetLocalDestination ()) - Session->GetLocalDestination ()->StopAcceptingStreams (); + if (m_IsAccepting && session->GetLocalDestination ()) + session->GetLocalDestination ()->StopAcceptingStreams (); } break; } @@ -1479,17 +1477,39 @@ namespace client session->StopLocalDestination (); session->Close (); if (m_IsSingleThread) - { - auto timer = std::make_shared(GetService ()); - timer->expires_from_now (boost::posix_time::seconds(5)); // postpone destination clean for 5 seconds - timer->async_wait ([timer, session](const boost::system::error_code& ecode) - { - // session's destructor is called here - }); - } + ScheduleSessionCleanupTimer (session); // let all session's streams close } } + void SAMBridge::ScheduleSessionCleanupTimer (std::shared_ptr session) + { + auto timer = std::make_shared(GetService ()); + timer->expires_from_now (boost::posix_time::seconds(5)); // postpone destination clean for 5 seconds + timer->async_wait (std::bind (&SAMBridge::HandleSessionCleanupTimer, this, std::placeholders::_1, session, timer)); + } + + void SAMBridge::HandleSessionCleanupTimer (const boost::system::error_code& ecode, + std::shared_ptr session, std::shared_ptr timer) + { + if (ecode != boost::asio::error::operation_aborted && session) + { + auto dest = session->GetLocalDestination (); + if (dest) + { + auto streamingDest = dest->GetStreamingDestination (); + auto numStreams = streamingDest->GetNumStreams (); + if (numStreams > 0) + { + LogPrint (eLogInfo, "SAM: Session ", session->Name, " still has ", numStreams, " streams"); + ScheduleSessionCleanupTimer (session); + } + else + LogPrint (eLogDebug, "SAM: Session ", session->Name, " terminated"); + } + } + // session's destructor is called here unless rescheduled + } + std::shared_ptr SAMBridge::FindSession (const std::string& id) const { std::unique_lock l(m_SessionsMutex); diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index 10ef4957..1886324a 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2024, The PurpleI2P Project +* Copyright (c) 2013-2025, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -271,6 +271,10 @@ namespace client void ReceiveDatagram (); void HandleReceivedDatagram (const boost::system::error_code& ecode, std::size_t bytes_transferred); + void ScheduleSessionCleanupTimer (std::shared_ptr session); + void HandleSessionCleanupTimer (const boost::system::error_code& ecode, + std::shared_ptr session, std::shared_ptr timer); + private: bool m_IsSingleThread; From 929ff6e3587332f24deeb89f566f8ae58ac79916 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 26 Apr 2025 08:39:11 -0400 Subject: [PATCH 1041/1171] encrypted LeaseSet never comes through a session --- libi2pd/Destination.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 91cc8380..fd23e228 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -512,7 +512,7 @@ namespace client { auto ls2 = std::make_shared (buf + offset, len - offset, request->requestedBlindedKey, m_LeaseSetPrivKey ? ((const uint8_t *)*m_LeaseSetPrivKey) : nullptr, - from ? from->GetRemoteStaticKeyType () : GetPreferredCryptoType ()); + GetPreferredCryptoType ()); if (ls2->IsValid () && !ls2->IsExpired ()) { leaseSet = ls2; From f164b420b19d2a1497611f717ff307d891dacd38 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 26 Apr 2025 08:43:32 -0400 Subject: [PATCH 1042/1171] cubicchaos.net reseed added --- .../reseed/unixeno_at_cubicchaos.net.crt | 34 +++++++++++++++++++ libi2pd/Config.cpp | 3 +- 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 contrib/certificates/reseed/unixeno_at_cubicchaos.net.crt diff --git a/contrib/certificates/reseed/unixeno_at_cubicchaos.net.crt b/contrib/certificates/reseed/unixeno_at_cubicchaos.net.crt new file mode 100644 index 00000000..c94d319e --- /dev/null +++ b/contrib/certificates/reseed/unixeno_at_cubicchaos.net.crt @@ -0,0 +1,34 @@ +-----BEGIN CERTIFICATE----- +MIIF2TCCA8GgAwIBAgIQVpTNnJZlUTDqmZiHRU4wCjANBgkqhkiG9w0BAQsFADB2 +MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYDVQQK +ExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEfMB0GA1UEAwwW +dW5peGVub0BjdWJpY2NoYW9zLm5ldDAeFw0yNTAzMDQxODU5NDZaFw0zNTAzMDQx +ODU5NDZaMHYxCzAJBgNVBAYTAlhYMQswCQYDVQQHEwJYWDELMAkGA1UECRMCWFgx +HjAcBgNVBAoTFUkyUCBBbm9ueW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMR8w +HQYDVQQDDBZ1bml4ZW5vQGN1YmljY2hhb3MubmV0MIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEAr/JoAzLDtHXoAc7QcP4IxO+xNTeiYs78Wlg/Sl/sa6qz +gJoGaKH/X++z4Xe9lBSZalXCamnO4QMTgsWOIeoMy6XVbGzNTXPl8JUcblTIXwkP +pv848b1nxLfgLHzPRz1mJMpMikBugJ3Iz1sQzDVlUdye2fgbGChWliz9P4ClEODv +A/4+7i6uvJgEZ7A+jx3vBCXhiJppE3wTuz5D9BQqG8NuEwwjwBTBByoCC4oxOe0h +Qu1k7kEr+n4qpSEg/1eJ/RYSm+I8BftK1RUfykTwxlfmyEmKsfLBQWczE8Ca9nUB +5V34UH2bRy1cvavJYcNW3EPsGNf4naRs+Gy8XIFrb315GgWC1Z6+tzk+QFli9YeF +0DgtYEZciqu/407o8ZEURTnPjB7GhLDDp1LAQ7CQRhzaraXjHj0hyO+6rFpFdD0D +mXhvI/Eph3QIldsgnQc7nPhU2csN8Vi6bNDgm0HZ8cdmIBpI2Uxn/acZX/9G40oj +czrhsCBEecu/BluLJsfaWCYg90rvONP8Fc4edHAMonzYZR4r0q4hbv7AM8GmDRDN +J9/DZFi+Qs9NAe06jJC3jSsj7IdIs8TMhw8FX3xWOlXwjmVETAgY/dta/MpLJ6tJ +i+E+TH/Ndntj/D6WUwdQq+LyCR6gqHUWR6rl6EDQz+08DWb7j/72JSLb/DaXrDUC +AwEAAaNjMGEwDgYDVR0PAQH/BAQDAgKEMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggr +BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB8GA1UdDgQYBBZ1bml4ZW5vQGN1Ymlj +Y2hhb3MubmV0MA0GCSqGSIb3DQEBCwUAA4ICAQBBVoPeuOkmJDUdzIrzmxTmjMyz +gpfrZnjirTQKWhbv53sAWNeJ3kZ9l9m+0YpqEtFDrZPL5LTBXcSci5gGuxPkp+i/ +f/axsdcFMKbI9B/M53fyXLLJY0EM4mdhNAWtph1kTowFPhhReefCdqxYIy9uk2pL +gfb6NYJf+w9//fKYFZXb9SsiRchfv81+lbN+PIprnCpV3cTZWmpLRi2hN86pMW20 +3rh7rqJ4dPnA/NoyM+JstL10IU/4StqInweEvoo4W44+cC0zYGvfkkrKL4LB8w5S +6DKebtk7NQDtzuw2QnA9Ms4bmqWQpbL6/7uGaauS0+nmF+2gkqi9hcv0W5ZoBb/D +IVRauySnCtp9PbYM7pIJP9a1U6naLj7L1VixqsJGfPQ8V9TCOOi5bDc3RTetI/DX +bXHhAqHYzboakptylCp+Ao5h2hu0+w4rqnG63HwsHDJWcETbdVFQfzlzUmbx53yV +GnBsUxDgMOiHTZdKLkEnH4Q/XI76uc0ntTRlK9ktKWZPSISUlHrFnFl6I5UdeBMy +6vpB9sJO5L5RPRi4945K5Xdennywdi508mNXtMMmNCqrk1SMYbwaY6ZtIvXEGam9 +uHQTiTEX9LED/VXzFGqzdyDbG43HgS0PksgzedelHWfVAEnc06U3JX2lqUyihYHa +N4jAXWQ7s5p4GYaf4Q== +-----END CERTIFICATE----- diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 3da74da0..bd9329a1 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -243,7 +243,8 @@ namespace config { "https://www2.mk16.de/," "https://i2p.ghativega.in/," "https://i2p.novg.net/," - "https://reseed.stormycloud.org/" + "https://reseed.stormycloud.org/," + "https://cubicchaos.net:8443/" ), "Reseed URLs, separated by comma") ("reseed.yggurls", value()->default_value( "http://[324:71e:281a:9ed3::ace]:7070/," From fdbf4366ebaf9857edcb1a932193259a57749097 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 28 Apr 2025 20:41:36 -0400 Subject: [PATCH 1043/1171] remove reseed.memcpy.io --- .../reseed/hottuna_at_mail.i2p.crt | 33 ------------------- libi2pd/Config.cpp | 1 - 2 files changed, 34 deletions(-) delete mode 100644 contrib/certificates/reseed/hottuna_at_mail.i2p.crt diff --git a/contrib/certificates/reseed/hottuna_at_mail.i2p.crt b/contrib/certificates/reseed/hottuna_at_mail.i2p.crt deleted file mode 100644 index d0ff7c33..00000000 --- a/contrib/certificates/reseed/hottuna_at_mail.i2p.crt +++ /dev/null @@ -1,33 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFxzCCA6+gAwIBAgIQZfqn0yiJL3dGgCjeOeWS6DANBgkqhkiG9w0BAQsFADBw -MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYDVQQK -ExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEZMBcGA1UEAwwQ -aG90dHVuYUBtYWlsLmkycDAeFw0xNjExMDkwMzE1MzJaFw0yNjExMDkwMzE1MzJa -MHAxCzAJBgNVBAYTAlhYMQswCQYDVQQHEwJYWDELMAkGA1UECRMCWFgxHjAcBgNV -BAoTFUkyUCBBbm9ueW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMRkwFwYDVQQD -DBBob3R0dW5hQG1haWwuaTJwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC -AgEA21Bfgcc9VVH4l2u1YvYlTw2OPUyQb16X2IOW0PzdsUO5W78Loueu974BkiKi -84lQZanLr0OwEopdfutGc6gegSLmwaWx5YCG5uwpLOPkDiObfX+nptH6As/B1cn+ -mzejYdVKRnWd7EtHW0iseSsILBK1YbGw4AGpXJ8k18DJSzUt2+spOkpBW6XqectN -8y2JDSTns8yiNxietVeRN/clolDXT9ZwWHkd+QMHTKhgl3Uz1knOffU0L9l4ij4E -oFgPfQo8NL63kLM24hF1hM/At7XvE4iOlObFwPXE+H5EGZpT5+A7Oezepvd/VMzM -tCJ49hM0OlR393tKFONye5GCYeSDJGdPEB6+rBptpRrlch63tG9ktpCRrg2wQWgC -e3aOE1xVRrmwiTZ+jpfsOCbZrrSA/C4Bmp6AfGchyHuDGGkRU/FJwa1YLJe0dkWG -ITLWeh4zeVuAS5mctdv9NQ5wflSGz9S8HjsPBS5+CDOFHh4cexXRG3ITfk6aLhuY -KTMlkIO4SHKmnwAvy1sFlsqj6PbfVjpHPLg625fdNxBpe57TLxtIdBB3C7ccQSRW -+UG6Cmbcmh80PbsSR132NLMlzLhbaOjxeCWWJRo6cLuHBptAFMNwqsXt8xVf9M0N -NdJoKUmblyvjnq0N8aMEqtQ1uGMTaCB39cutHQq+reD/uzsCAwEAAaNdMFswDgYD -VR0PAQH/BAQDAgKEMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNV -HRMBAf8EBTADAQH/MBkGA1UdDgQSBBBob3R0dW5hQG1haWwuaTJwMA0GCSqGSIb3 -DQEBCwUAA4ICAQCibFV8t4pajP176u3jx31x1kgqX6Nd+0YFARPZQjq99kUyoZer -GyHGsMWgM281RxiZkveHxR7Hm7pEd1nkhG3rm+d7GdJ2p2hujr9xUvl0zEqAAqtm -lkYI6uJ13WBjFc9/QuRIdeIeSUN+eazSXNg2nJhoV4pF9n2Q2xDc9dH4GWO93cMX -JPKVGujT3s0b7LWsEguZBPdaPW7wwZd902Cg/M5fE1hZQ8/SIAGUtylb/ZilVeTS -spxWP1gX3NT1SSvv0s6oL7eADCgtggWaMxEjZhi6WMnPUeeFY8X+6trkTlnF9+r/ -HiVvvzQKrPPtB3j1xfQCAF6gUKN4iY+2AOExv4rl/l+JJbPhpd/FuvD8AVkLMZ8X -uPe0Ew2xv30cc8JjGDzQvoSpBmVTra4f+xqH+w8UEmxnx97Ye2aUCtnPykACnFte -oT97K5052B1zq+4fu4xaHZnEzPYVK5POzOufNLPgciJsWrR5GDWtHd+ht/ZD37+b -+j1BXpeBWUBQgluFv+lNMVNPJxc2OMELR1EtEwXD7mTuuUEtF5Pi63IerQ5LzD3G -KBvXhMB0XhpE6WG6pBwAvkGf5zVv/CxClJH4BQbdZwj9HYddfEQlPl0z/XFR2M0+ -9/8nBfGSPYIt6KeHBCeyQWTdE9gqSzMwTMFsennXmaT8gyc7eKqKF6adqw== ------END CERTIFICATE----- diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index bd9329a1..939cd9ff 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -234,7 +234,6 @@ namespace config { "https://reseed2.i2p.net/," "https://reseed.diva.exchange/," "https://reseed-fr.i2pd.xyz/," - "https://reseed.memcpy.io/," "https://reseed.onion.im/," "https://i2pseed.creativecowpat.net:8443/," "https://reseed.i2pgit.org/," From b03ec650eff99b3b1dcd0960eaf6b7eba88dfef5 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 29 Apr 2025 12:56:35 -0400 Subject: [PATCH 1044/1171] keep receving new data from socket while previous is being sent to stream --- libi2pd_client/I2PTunnel.cpp | 22 +++++++++++++++------- libi2pd_client/I2PTunnel.h | 1 + 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index d6436c78..ae9849db 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -32,7 +32,8 @@ namespace client I2PTunnelConnection::I2PTunnelConnection (I2PService * owner, std::shared_ptr socket, std::shared_ptr leaseSet, uint16_t port): - I2PServiceHandler(owner), m_Socket (socket), m_RemoteEndpoint (socket->remote_endpoint ()) + I2PServiceHandler(owner), m_Socket (socket), m_RemoteEndpoint (socket->remote_endpoint ()), + m_IsReceiving (false) { m_Stream = GetOwner()->GetLocalDestination ()->CreateStream (leaseSet, port); } @@ -40,13 +41,13 @@ namespace client I2PTunnelConnection::I2PTunnelConnection (I2PService * owner, std::shared_ptr socket, std::shared_ptr stream): I2PServiceHandler(owner), m_Socket (socket), m_Stream (stream), - m_RemoteEndpoint (socket->remote_endpoint ()) + m_RemoteEndpoint (socket->remote_endpoint ()), m_IsReceiving (false) { } I2PTunnelConnection::I2PTunnelConnection (I2PService * owner, std::shared_ptr stream, const boost::asio::ip::tcp::endpoint& target,std::shared_ptr sslCtx): - I2PServiceHandler(owner), m_Stream (stream), m_RemoteEndpoint (target) + I2PServiceHandler(owner), m_Stream (stream), m_RemoteEndpoint (target), m_IsReceiving (false) { m_Socket = std::make_shared (owner->GetService ()); if (sslCtx) @@ -149,18 +150,23 @@ namespace client void I2PTunnelConnection::Receive () { + if (m_IsReceiving) return; // already receiving + size_t unsentSize = m_Stream ? m_Stream->GetSendBufferSize () : 0; + if (unsentSize >= I2P_TUNNEL_CONNECTION_BUFFER_SIZE) return; // buffer is full + m_IsReceiving = true; if (m_SSL) - m_SSL->async_read_some (boost::asio::buffer(m_Buffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE), + m_SSL->async_read_some (boost::asio::buffer(m_Buffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE - unsentSize), std::bind(&I2PTunnelConnection::HandleReceive, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); else - m_Socket->async_read_some (boost::asio::buffer(m_Buffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE), + m_Socket->async_read_some (boost::asio::buffer(m_Buffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE - unsentSize), std::bind(&I2PTunnelConnection::HandleReceive, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); } void I2PTunnelConnection::HandleReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred) { + m_IsReceiving = false; if (ecode) { if (ecode != boost::asio::error::operation_aborted) @@ -170,16 +176,18 @@ namespace client } } else + { WriteToStream (m_Buffer, bytes_transferred); + Receive (); // try to receive more while being sent to stream + } } void I2PTunnelConnection::WriteToStream (const uint8_t * buf, size_t len) { if (m_Stream) { - auto s = shared_from_this (); m_Stream->AsyncSend (buf, len, - [s](const boost::system::error_code& ecode) + [s = shared_from_this ()](const boost::system::error_code& ecode) { if (!ecode) s->Receive (); diff --git a/libi2pd_client/I2PTunnel.h b/libi2pd_client/I2PTunnel.h index 7d4c3400..be35cfec 100644 --- a/libi2pd_client/I2PTunnel.h +++ b/libi2pd_client/I2PTunnel.h @@ -82,6 +82,7 @@ namespace client std::shared_ptr > m_SSL; std::shared_ptr m_Stream; boost::asio::ip::tcp::endpoint m_RemoteEndpoint; + bool m_IsReceiving; }; class I2PClientTunnelConnectionHTTP: public I2PTunnelConnection From d9f64c6f51e341d913f2512e2e7f7d66c0527c55 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 1 May 2025 18:09:39 -0400 Subject: [PATCH 1045/1171] connection max stream buffer size --- libi2pd_client/I2PTunnel.cpp | 6 +++--- libi2pd_client/I2PTunnel.h | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index ae9849db..4d818e60 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -152,7 +152,7 @@ namespace client { if (m_IsReceiving) return; // already receiving size_t unsentSize = m_Stream ? m_Stream->GetSendBufferSize () : 0; - if (unsentSize >= I2P_TUNNEL_CONNECTION_BUFFER_SIZE) return; // buffer is full + if (unsentSize >= I2P_TUNNEL_CONNECTION_STREAM_MAX_SEND_BUFFER_SIZE) return; // buffer is full m_IsReceiving = true; if (m_SSL) m_SSL->async_read_some (boost::asio::buffer(m_Buffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE - unsentSize), @@ -216,7 +216,7 @@ namespace client if (m_Stream->GetStatus () == i2p::stream::eStreamStatusNew || m_Stream->GetStatus () == i2p::stream::eStreamStatusOpen) // regular { - m_Stream->AsyncReceive (boost::asio::buffer (m_StreamBuffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE), + m_Stream->AsyncReceive (boost::asio::buffer (m_StreamBuffer, I2P_TUNNEL_CONNECTION_STREAM_BUFFER_SIZE), std::bind (&I2PTunnelConnection::HandleStreamReceive, shared_from_this (), std::placeholders::_1, std::placeholders::_2), I2P_TUNNEL_CONNECTION_MAX_IDLE); @@ -224,7 +224,7 @@ namespace client else // closed by peer { // get remaining data - auto len = m_Stream->ReadSome (m_StreamBuffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE); + auto len = m_Stream->ReadSome (m_StreamBuffer, I2P_TUNNEL_CONNECTION_STREAM_BUFFER_SIZE); if (len > 0) // still some data Write (m_StreamBuffer, len); else // no more data diff --git a/libi2pd_client/I2PTunnel.h b/libi2pd_client/I2PTunnel.h index be35cfec..9abae09a 100644 --- a/libi2pd_client/I2PTunnel.h +++ b/libi2pd_client/I2PTunnel.h @@ -27,7 +27,9 @@ namespace i2p { namespace client { - const size_t I2P_TUNNEL_CONNECTION_BUFFER_SIZE = 16384; + constexpr size_t I2P_TUNNEL_CONNECTION_BUFFER_SIZE = 8192; + constexpr size_t I2P_TUNNEL_CONNECTION_STREAM_MAX_SEND_BUFFER_SIZE = 8*I2P_TUNNEL_CONNECTION_BUFFER_SIZE; + constexpr size_t I2P_TUNNEL_CONNECTION_STREAM_BUFFER_SIZE = 16384; const int I2P_TUNNEL_CONNECTION_MAX_IDLE = 3600; // in seconds const int I2P_TUNNEL_DESTINATION_REQUEST_TIMEOUT = 10; // in seconds // for HTTP tunnels @@ -77,7 +79,7 @@ namespace client private: - uint8_t m_Buffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE], m_StreamBuffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE]; + uint8_t m_Buffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE], m_StreamBuffer[I2P_TUNNEL_CONNECTION_STREAM_BUFFER_SIZE]; std::shared_ptr m_Socket; std::shared_ptr > m_SSL; std::shared_ptr m_Stream; From 855e111bd011b87d5126a2040d3a324798576043 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 2 May 2025 08:32:20 -0400 Subject: [PATCH 1046/1171] fixed private key size and publishing for crypto type 1 --- libi2pd/CryptoKey.h | 2 +- libi2pd/Destination.cpp | 17 ++--------------- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/libi2pd/CryptoKey.h b/libi2pd/CryptoKey.h index b6c37ddf..099bdd56 100644 --- a/libi2pd/CryptoKey.h +++ b/libi2pd/CryptoKey.h @@ -165,7 +165,7 @@ namespace crypto switch (type) { case i2p::data::CRYPTO_KEY_TYPE_ELGAMAL: return 256; - case i2p::data::CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC: return 32; + case i2p::data::CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC: return 256; // actual size is 32, but we use 256 for compatibility with old keys files case i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD: return 32; // ML-KEM hybrid case i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD: diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index fd23e228..b243ba0a 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -728,22 +728,9 @@ namespace client { if (m_PublishReplyToken) { + LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " milliseconds or failed. will try again"); m_PublishReplyToken = 0; - if (GetIdentity ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL) - { - LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " milliseconds or failed. will try again"); - Publish (); - } - else - { - LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " milliseconds from Java floodfill for crypto type ", (int)GetIdentity ()->GetCryptoKeyType ()); - // Java floodfill never sends confirmation back for unknown crypto type - // assume it successive and try to verify - m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT + PUBLISH_VERIFICATION_TIMEOUT_VARIANCE)); // always max - m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer, - shared_from_this (), std::placeholders::_1)); - - } + Publish (); } } } From 0cbada2196f44a3ed5972569568b58d3dfc205ce Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 2 May 2025 13:23:53 -0400 Subject: [PATCH 1047/1171] correct receive buffer size --- libi2pd_client/I2PTunnel.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index 4d818e60..c06a35a0 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -155,11 +155,11 @@ namespace client if (unsentSize >= I2P_TUNNEL_CONNECTION_STREAM_MAX_SEND_BUFFER_SIZE) return; // buffer is full m_IsReceiving = true; if (m_SSL) - m_SSL->async_read_some (boost::asio::buffer(m_Buffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE - unsentSize), + m_SSL->async_read_some (boost::asio::buffer(m_Buffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE), std::bind(&I2PTunnelConnection::HandleReceive, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); else - m_Socket->async_read_some (boost::asio::buffer(m_Buffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE - unsentSize), + m_Socket->async_read_some (boost::asio::buffer(m_Buffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE), std::bind(&I2PTunnelConnection::HandleReceive, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); } From 539cd5a656d937e3bab94744c74ed718f91af2ec Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 2 May 2025 13:36:59 -0400 Subject: [PATCH 1048/1171] max i2p stream buffer size --- libi2pd_client/SAM.cpp | 45 ++++++++++++++++++++++++------------------ libi2pd_client/SAM.h | 7 +++++-- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 2c0f8d92..7ec94dcb 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -27,7 +27,7 @@ namespace client m_Owner (owner), m_Socket(owner.GetService()), m_Timer (m_Owner.GetService ()), m_BufferOffset (0), m_SocketType (eSAMSocketTypeUnknown), m_IsSilent (false), - m_IsAccepting (false), m_Stream (nullptr) + m_IsAccepting (false), m_IsReceiving (false) { } @@ -944,13 +944,23 @@ namespace client void SAMSocket::Receive () { - m_Socket.async_read_some (boost::asio::buffer(m_Buffer + m_BufferOffset, SAM_SOCKET_BUFFER_SIZE - m_BufferOffset), - std::bind((m_SocketType == eSAMSocketTypeStream) ? &SAMSocket::HandleReceived : &SAMSocket::HandleMessage, - shared_from_this (), std::placeholders::_1, std::placeholders::_2)); + if (m_SocketType == eSAMSocketTypeStream) + { + if (m_IsReceiving) return; + size_t unsentSize = m_Stream ? m_Stream->GetSendBufferSize () : 0; + if (unsentSize >= SAM_STREAM_MAX_SEND_BUFFER_SIZE) return; // buffer is full + m_IsReceiving = true; + m_Socket.async_read_some (boost::asio::buffer(m_Buffer, SAM_SOCKET_BUFFER_SIZE), + std::bind(&SAMSocket::HandleReceived, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); + } + else + m_Socket.async_read_some (boost::asio::buffer(m_Buffer + m_BufferOffset, SAM_SOCKET_BUFFER_SIZE - m_BufferOffset), + std::bind(&SAMSocket::HandleMessage, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); } void SAMSocket::HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred) { + m_IsReceiving = false; if (ecode) { LogPrint (eLogError, "SAM: Read error: ", ecode.message ()); @@ -960,16 +970,13 @@ namespace client else { if (m_Stream) - { - bytes_transferred += m_BufferOffset; - m_BufferOffset = 0; + { m_Stream->AsyncSend ((uint8_t *)m_Buffer, bytes_transferred, std::bind(&SAMSocket::HandleStreamSend, shared_from_this(), std::placeholders::_1)); - } + Receive (); + } else - { Terminate("No Stream Remaining"); - } } } @@ -980,16 +987,16 @@ namespace client if (m_Stream->GetStatus () == i2p::stream::eStreamStatusNew || m_Stream->GetStatus () == i2p::stream::eStreamStatusOpen) // regular { - m_Stream->AsyncReceive (boost::asio::buffer (m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE), + m_Stream->AsyncReceive (boost::asio::buffer (m_StreamBuffer, SAM_STREAM_BUFFER_SIZE), std::bind (&SAMSocket::HandleI2PReceive, shared_from_this(), std::placeholders::_1, std::placeholders::_2), SAM_SOCKET_CONNECTION_MAX_IDLE); } else // closed by peer { - uint8_t * buff = new uint8_t[SAM_SOCKET_BUFFER_SIZE]; + uint8_t * buff = new uint8_t[SAM_STREAM_BUFFER_SIZE]; // get remaining data - auto len = m_Stream->ReadSome (buff, SAM_SOCKET_BUFFER_SIZE); + auto len = m_Stream->ReadSome (buff, SAM_STREAM_BUFFER_SIZE); if (len > 0) // still some data { WriteI2PDataImmediate(buff, len); @@ -1186,11 +1193,11 @@ namespace client else { #ifdef _MSC_VER - size_t l = sprintf_s ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_DATAGRAM_RECEIVED, base64.c_str (), (long unsigned int)len); + size_t l = sprintf_s ((char *)m_StreamBuffer, SAM_STREAM_BUFFER_SIZE, SAM_DATAGRAM_RECEIVED, base64.c_str (), (long unsigned int)len); #else - size_t l = snprintf ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_DATAGRAM_RECEIVED, base64.c_str (), (long unsigned int)len); + size_t l = snprintf ((char *)m_StreamBuffer, SAM_STREAM_BUFFER_SIZE, SAM_DATAGRAM_RECEIVED, base64.c_str (), (long unsigned int)len); #endif - if (len < SAM_SOCKET_BUFFER_SIZE - l) + if (len < SAM_STREAM_BUFFER_SIZE - l) { memcpy (m_StreamBuffer + l, buf, len); WriteI2PData(len + l); @@ -1214,11 +1221,11 @@ namespace client else { #ifdef _MSC_VER - size_t l = sprintf_s ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_RAW_RECEIVED, (long unsigned int)len); + size_t l = sprintf_s ((char *)m_StreamBuffer, SAM_STREAM_BUFFER_SIZE, SAM_RAW_RECEIVED, (long unsigned int)len); #else - size_t l = snprintf ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_RAW_RECEIVED, (long unsigned int)len); + size_t l = snprintf ((char *)m_StreamBuffer, SAM_STREAM_BUFFER_SIZE, SAM_RAW_RECEIVED, (long unsigned int)len); #endif - if (len < SAM_SOCKET_BUFFER_SIZE - l) + if (len < SAM_STREAM_BUFFER_SIZE - l) { memcpy (m_StreamBuffer + l, buf, len); WriteI2PData(len + l); diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index 1886324a..cd619678 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -29,6 +29,8 @@ namespace i2p namespace client { const size_t SAM_SOCKET_BUFFER_SIZE = 8192; + const size_t SAM_STREAM_BUFFER_SIZE = 16384; + const size_t SAM_STREAM_MAX_SEND_BUFFER_SIZE = 8*SAM_SOCKET_BUFFER_SIZE; const int SAM_SOCKET_CONNECTION_MAX_IDLE = 3600; // in seconds const int SAM_SESSION_READINESS_CHECK_INTERVAL = 3; // in seconds const size_t SAM_SESSION_MAX_ACCEPT_QUEUE_SIZE = 50; @@ -170,12 +172,13 @@ namespace client Socket_t m_Socket; boost::asio::deadline_timer m_Timer; char m_Buffer[SAM_SOCKET_BUFFER_SIZE + 1]; - size_t m_BufferOffset; - uint8_t m_StreamBuffer[SAM_SOCKET_BUFFER_SIZE]; + size_t m_BufferOffset; // for session only + uint8_t m_StreamBuffer[SAM_STREAM_BUFFER_SIZE]; SAMSocketType m_SocketType; std::string m_ID; // nickname bool m_IsSilent; bool m_IsAccepting; // for eSAMSocketTypeAcceptor only + bool m_IsReceiving; // for eSAMSocketTypeStream only std::shared_ptr m_Stream; }; From aece5bb16c3877fcafe29239ca15856f0057ce35 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 3 May 2025 08:47:49 -0400 Subject: [PATCH 1049/1171] don't exceed stream max send buffer size --- libi2pd_client/I2PTunnel.cpp | 12 +++++++++--- libi2pd_client/SAM.cpp | 10 ++++++++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index c06a35a0..82a6ed03 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -151,15 +151,21 @@ namespace client void I2PTunnelConnection::Receive () { if (m_IsReceiving) return; // already receiving + size_t bufSize = I2P_TUNNEL_CONNECTION_BUFFER_SIZE; size_t unsentSize = m_Stream ? m_Stream->GetSendBufferSize () : 0; - if (unsentSize >= I2P_TUNNEL_CONNECTION_STREAM_MAX_SEND_BUFFER_SIZE) return; // buffer is full + if (unsentSize) + { + if (unsentSize >= I2P_TUNNEL_CONNECTION_STREAM_MAX_SEND_BUFFER_SIZE) return; // buffer is full + if (unsentSize > I2P_TUNNEL_CONNECTION_STREAM_MAX_SEND_BUFFER_SIZE - I2P_TUNNEL_CONNECTION_BUFFER_SIZE) + bufSize = I2P_TUNNEL_CONNECTION_STREAM_MAX_SEND_BUFFER_SIZE - unsentSize; + } m_IsReceiving = true; if (m_SSL) - m_SSL->async_read_some (boost::asio::buffer(m_Buffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE), + m_SSL->async_read_some (boost::asio::buffer(m_Buffer, bufSize), std::bind(&I2PTunnelConnection::HandleReceive, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); else - m_Socket->async_read_some (boost::asio::buffer(m_Buffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE), + m_Socket->async_read_some (boost::asio::buffer(m_Buffer, bufSize), std::bind(&I2PTunnelConnection::HandleReceive, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); } diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 7ec94dcb..f0df414c 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -947,10 +947,16 @@ namespace client if (m_SocketType == eSAMSocketTypeStream) { if (m_IsReceiving) return; + size_t bufSize = SAM_SOCKET_BUFFER_SIZE; size_t unsentSize = m_Stream ? m_Stream->GetSendBufferSize () : 0; - if (unsentSize >= SAM_STREAM_MAX_SEND_BUFFER_SIZE) return; // buffer is full + if (unsentSize) + { + if (unsentSize >= SAM_STREAM_MAX_SEND_BUFFER_SIZE) return; // buffer is full + if (unsentSize > SAM_STREAM_MAX_SEND_BUFFER_SIZE - SAM_SOCKET_BUFFER_SIZE) + bufSize = SAM_STREAM_MAX_SEND_BUFFER_SIZE - unsentSize; + } m_IsReceiving = true; - m_Socket.async_read_some (boost::asio::buffer(m_Buffer, SAM_SOCKET_BUFFER_SIZE), + m_Socket.async_read_some (boost::asio::buffer(m_Buffer, bufSize), std::bind(&SAMSocket::HandleReceived, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); } else From 0d278d2ae58dea13ec7d82dee24184975c513bb8 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 3 May 2025 13:09:06 -0400 Subject: [PATCH 1050/1171] probing resistance --- libi2pd/NTCP2.cpp | 17 +++++++++++++++-- libi2pd/NTCP2.h | 3 ++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index b3a51488..bc18f5a6 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -528,6 +528,7 @@ namespace transport } else { + m_Establisher->CreateEphemeralKey (); boost::asio::post (m_Server.GetEstablisherService (), [s = shared_from_this (), bytes_transferred] () { @@ -566,7 +567,7 @@ namespace transport SendSessionCreated (); } else - boost::asio::post (m_Server.GetService (), std::bind (&NTCP2Session::Terminate, shared_from_this ())); + ReadSomethingAndTerminate (); // probing resistance } void NTCP2Session::HandleSessionRequestPaddingReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred) @@ -918,7 +919,6 @@ namespace transport { SetTerminationTimeout (NTCP2_ESTABLISH_TIMEOUT); SetLastActivityTimestamp (i2p::util::GetSecondsSinceEpoch ()); - m_Establisher->CreateEphemeralKey (); boost::asio::async_read (m_Socket, boost::asio::buffer(m_Establisher->m_SessionRequestBuffer, 64), boost::asio::transfer_all (), std::bind(&NTCP2Session::HandleSessionRequestReceived, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); @@ -1399,6 +1399,19 @@ namespace transport boost::asio::post (m_Server.GetService (), std::bind (&NTCP2Session::Terminate, shared_from_this ())); // let termination message go } + void NTCP2Session::ReadSomethingAndTerminate () + { + size_t len = m_Server.GetRng ()() % NTCP2_SESSION_REQUEST_MAX_SIZE; + if (len > 0 && m_Establisher) + boost::asio::async_read (m_Socket, boost::asio::buffer(m_Establisher->m_SessionRequestBuffer, len), boost::asio::transfer_all (), + [s = shared_from_this()](const boost::system::error_code& ecode, size_t bytes_transferred) + { + s->Terminate (); + }); + else + boost::asio::post (m_Server.GetService (), std::bind (&NTCP2Session::Terminate, shared_from_this ())); + } + void NTCP2Session::SendI2NPMessages (std::list >& msgs) { if (m_IsTerminated || msgs.empty ()) diff --git a/libi2pd/NTCP2.h b/libi2pd/NTCP2.h index 5ad5b955..b50d9087 100644 --- a/libi2pd/NTCP2.h +++ b/libi2pd/NTCP2.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2024, The PurpleI2P Project +* Copyright (c) 2013-2025, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -200,6 +200,7 @@ namespace transport void SendRouterInfo (); void SendTermination (NTCP2TerminationReason reason); void SendTerminationAndTerminate (NTCP2TerminationReason reason); + void ReadSomethingAndTerminate (); void PostI2NPMessages (); private: From 209eb174c6b0f0c181329f0da9874124cbde3b42 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 4 May 2025 18:59:21 -0400 Subject: [PATCH 1051/1171] fixed choked stream hanging --- libi2pd/Streaming.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 99da5fd2..25608cbc 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -642,7 +642,7 @@ namespace stream if (wasInitial) ScheduleResend (); } - if (m_IsClientChoked && ackThrough >= m_DropWindowDelaySequenceNumber) + if (m_IsClientChoked && (ackThrough >= m_DropWindowDelaySequenceNumber || m_SentPackets.empty ())) m_IsClientChoked = false; if (m_IsWinDropped && ackThrough > m_DropWindowDelaySequenceNumber) { From 246bc43dea07e72de90283acfcabbcf7d367c31f Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 7 May 2025 18:54:55 -0400 Subject: [PATCH 1052/1171] read more data from socket if available and stream buffer is not full --- libi2pd_client/I2PTunnel.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index 82a6ed03..fe83d47f 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -183,6 +183,29 @@ namespace client } else { + if (bytes_transferred < I2P_TUNNEL_CONNECTION_BUFFER_SIZE && !m_SSL) + { + boost::system::error_code ec; + size_t moreBytes = m_Socket->available(ec); + if (!ec && moreBytes && m_Stream) + { + // read more data from socket before sending to stream + if (bytes_transferred + moreBytes > I2P_TUNNEL_CONNECTION_BUFFER_SIZE) + moreBytes = I2P_TUNNEL_CONNECTION_BUFFER_SIZE - bytes_transferred; + if (m_Stream->GetSendBufferSize () < I2P_TUNNEL_CONNECTION_STREAM_MAX_SEND_BUFFER_SIZE) + { + size_t remaining = I2P_TUNNEL_CONNECTION_STREAM_MAX_SEND_BUFFER_SIZE - m_Stream->GetSendBufferSize (); + if (remaining < moreBytes) moreBytes = remaining; + } + else + moreBytes = 0; + } + if (moreBytes) + { + moreBytes = boost::asio::read (*m_Socket, boost::asio::buffer(m_Buffer + bytes_transferred, moreBytes), boost::asio::transfer_all (), ec); + if (!ec) bytes_transferred += moreBytes; + } + } WriteToStream (m_Buffer, bytes_transferred); Receive (); // try to receive more while being sent to stream } From aab82966190e59036be7839603800e49712d21ae Mon Sep 17 00:00:00 2001 From: r4sas Date: Sun, 18 May 2025 02:20:31 +0300 Subject: [PATCH 1053/1171] [i18n] add Hebrew and Hindi translations, add rtl support (testing) Signed-off-by: r4sas --- daemon/HTTPServer.cpp | 11 +- i18n/Afrikaans.cpp | 5 +- i18n/Armenian.cpp | 5 +- i18n/Chinese.cpp | 5 +- i18n/Czech.cpp | 5 +- i18n/English.cpp | 5 +- i18n/French.cpp | 7 +- i18n/German.cpp | 5 +- i18n/Hebrew.cpp | 202 +++++++++++++++++++++++++++++++++++++ i18n/Hindi.cpp | 226 ++++++++++++++++++++++++++++++++++++++++++ i18n/I18N.h | 11 +- i18n/I18N_langs.h | 6 +- i18n/Italian.cpp | 5 +- i18n/Polish.cpp | 5 +- i18n/Portuguese.cpp | 5 +- i18n/Russian.cpp | 5 +- i18n/Spanish.cpp | 5 +- i18n/Swedish.cpp | 5 +- i18n/Turkish.cpp | 5 +- i18n/Turkmen.cpp | 5 +- i18n/Ukrainian.cpp | 5 +- i18n/Uzbek.cpp | 5 +- 22 files changed, 518 insertions(+), 25 deletions(-) create mode 100644 i18n/Hebrew.cpp create mode 100644 i18n/Hindi.cpp diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index dca545fe..be1ec4ac 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -134,7 +134,7 @@ namespace http { { std::string state; std::string_view stateText; - switch (eState) + switch (eState) { case i2p::tunnel::eTunnelStateBuildReplyReceived : case i2p::tunnel::eTunnelStatePending : state = "building"; break; @@ -146,7 +146,7 @@ namespace http { default: state = "unknown"; break; } if (stateText.empty ()) stateText = tr(state); - + s << " " << stateText << ((explr) ? " (" + std::string(tr("exploratory")) + ")" : "") << ", "; // TODO: ShowTraffic(s, bytes); s << "\r\n"; @@ -172,9 +172,12 @@ namespace http { auto it = i2p::i18n::languages.find(currLang); std::string langCode = it->second.ShortCode; + // Right to Left language option + bool rtl = i2p::client::context.GetLanguage ()->GetRTL(); + s << "\r\n" - "\r\n" + "\r\n" " \r\n" /* TODO: Find something to parse html/template system. This is horrible. */ " \r\n" " \r\n" @@ -1479,7 +1482,7 @@ namespace http { reply.body = content; m_SendBuffer = reply.to_string(); - boost::asio::async_write (*m_Socket, boost::asio::buffer(m_SendBuffer), boost::asio::transfer_all (), + boost::asio::async_write (*m_Socket, boost::asio::buffer(m_SendBuffer), boost::asio::transfer_all (), std::bind (&HTTPConnection::Terminate, shared_from_this (), std::placeholders::_1)); } diff --git a/i18n/Afrikaans.cpp b/i18n/Afrikaans.cpp index b69c42ef..0afa086f 100644 --- a/i18n/Afrikaans.cpp +++ b/i18n/Afrikaans.cpp @@ -29,6 +29,9 @@ namespace afrikaans // language namespace return n != 1 ? 1 : 0; } + // Right to Left language? + static bool rtl = false; + static const LocaleStrings strings { {"failed", "Het misluk"}, @@ -73,7 +76,7 @@ namespace afrikaans // language namespace std::shared_ptr GetLocale() { - return std::make_shared(language, strings, plurals, [] (int n)->int { return plural(n); }); + return std::make_shared(language, rtl, strings, plurals, [] (int n)->int { return plural(n); }); } } // language diff --git a/i18n/Armenian.cpp b/i18n/Armenian.cpp index 67955d8a..af22d0d9 100644 --- a/i18n/Armenian.cpp +++ b/i18n/Armenian.cpp @@ -29,6 +29,9 @@ namespace armenian // language namespace return n != 1 ? 1 : 0; } + // Right to Left language? + static bool rtl = false; + static const LocaleStrings strings { {"%.2f KiB", "%.2f ԿիԲ"}, @@ -196,7 +199,7 @@ namespace armenian // language namespace std::shared_ptr GetLocale() { - return std::make_shared(language, strings, plurals, [] (int n)->int { return plural(n); }); + return std::make_shared(language, rtl, strings, plurals, [] (int n)->int { return plural(n); }); } } // language diff --git a/i18n/Chinese.cpp b/i18n/Chinese.cpp index e3b63ebd..f439bb67 100644 --- a/i18n/Chinese.cpp +++ b/i18n/Chinese.cpp @@ -29,6 +29,9 @@ namespace chinese // language namespace return 0; } + // Right to Left language? + static bool rtl = false; + static const LocaleStrings strings { {"%.2f KiB", "%.2f KiB"}, @@ -215,7 +218,7 @@ namespace chinese // language namespace std::shared_ptr GetLocale() { - return std::make_shared(language, strings, plurals, [] (int n)->int { return plural(n); }); + return std::make_shared(language, rtl, strings, plurals, [] (int n)->int { return plural(n); }); } } // language diff --git a/i18n/Czech.cpp b/i18n/Czech.cpp index 94803354..c9697f41 100644 --- a/i18n/Czech.cpp +++ b/i18n/Czech.cpp @@ -29,6 +29,9 @@ namespace czech // language namespace return (n == 1) ? 0 : (n >= 2 && n <= 4) ? 1 : 2; } + // Right to Left language? + static bool rtl = false; + static const LocaleStrings strings { {"%.2f KiB", "%.2f KiB"}, @@ -215,7 +218,7 @@ namespace czech // language namespace std::shared_ptr GetLocale() { - return std::make_shared(language, strings, plurals, [] (int n)->int { return plural(n); }); + return std::make_shared(language, rtl, strings, plurals, [] (int n)->int { return plural(n); }); } } // language diff --git a/i18n/English.cpp b/i18n/English.cpp index fb774527..eb7067e2 100644 --- a/i18n/English.cpp +++ b/i18n/English.cpp @@ -30,6 +30,9 @@ namespace english // language namespace return n != 1 ? 1 : 0; } + // Right to Left language? + static bool rtl = false; + static const LocaleStrings strings { {"", ""}, @@ -42,7 +45,7 @@ namespace english // language namespace std::shared_ptr GetLocale() { - return std::make_shared(language, strings, plurals, [] (int n)->int { return plural(n); }); + return std::make_shared(language, rtl, strings, plurals, [] (int n)->int { return plural(n); }); } } // language diff --git a/i18n/French.cpp b/i18n/French.cpp index 985296a3..2618772f 100644 --- a/i18n/French.cpp +++ b/i18n/French.cpp @@ -29,6 +29,9 @@ namespace french // language namespace return n != 1 ? 1 : 0; } + // Right to Left language? + static bool rtl = false; + static const LocaleStrings strings { {"%.2f KiB", "%.2f Kio"}, @@ -44,7 +47,7 @@ namespace french // language namespace {"i2pd webconsole", "Console web i2pd"}, {"Main page", "Page principale"}, {"Router commands", "Commandes du routeur"}, - {"Local Destinations", "Destinations locales"}, + {"Local Destinations", "Destinatioans localeAlger"}, {"LeaseSets", "Jeu de baux"}, {"Tunnels", "Tunnels"}, {"Transit Tunnels", "Tunnels transitoires"}, @@ -215,7 +218,7 @@ namespace french // language namespace std::shared_ptr GetLocale() { - return std::make_shared(language, strings, plurals, [] (int n)->int { return plural(n); }); + return std::make_shared(language, rtl, strings, plurals, [] (int n)->int { return plural(n); }); } } // language diff --git a/i18n/German.cpp b/i18n/German.cpp index 90ce82f4..b3b35e99 100644 --- a/i18n/German.cpp +++ b/i18n/German.cpp @@ -29,6 +29,9 @@ namespace german // language namespace return n != 1 ? 1 : 0; } + // Right to Left language? + static bool rtl = false; + static const LocaleStrings strings { {"%.2f KiB", "%.2f KiB"}, @@ -210,7 +213,7 @@ namespace german // language namespace std::shared_ptr GetLocale() { - return std::make_shared(language, strings, plurals, [] (int n)->int { return plural(n); }); + return std::make_shared(language, rtl, strings, plurals, [] (int n)->int { return plural(n); }); } } // language diff --git a/i18n/Hebrew.cpp b/i18n/Hebrew.cpp new file mode 100644 index 00000000..7e56395f --- /dev/null +++ b/i18n/Hebrew.cpp @@ -0,0 +1,202 @@ +/* +* Copyright (c) 2025, The PurpleI2P Project +* +* This file is part of Purple i2pd project and licensed under BSD3 +* +* See full license text in LICENSE file at top of project tree +*/ + +#include +#include +#include +#include +#include "I18N.h" + +// Hebrew localization file + +namespace i2p +{ +namespace i18n +{ +namespace hebrew // language namespace +{ + // language name in lowercase + static std::string language = "hebrew"; + + // See for language plural forms here: + // https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html + static int plural (int n) { + return n % 100 == 1 ? 0 : n % 100 == 2 ? 1 : n % 100 == 3 || n % 100 == 4 ? 2 : 3; + } + + // Right to Left language? + static bool rtl = true; + + static const LocaleStrings strings + { + {"%.2f KiB", "%.2f קי״ב"}, + {"%.2f MiB", "%.2f מי״ב"}, + {"%.2f GiB", "%.2f קי״ב"}, + {"Purple I2P Webconsole", "קונסולת Purple I2P"}, + {"i2pd webconsole", "קונסולת i2pd"}, + {"Main page", "עמוד ראשי"}, + {"Router commands", "פקודות נתב"}, + {"Local Destinations", "יעדים מקומיים"}, + {"Tunnels", "מנהרות"}, + {"Transit Tunnels", "מנהרות מעבר"}, + {"Transports", "מובילים"}, + {"I2P tunnels", "מנהרות I2P"}, + {"SAM sessions", "הפעלות SAM"}, + {"Unknown", "לא מוכר"}, + {"Proxy", "פרוקסי"}, + {"Mesh", "סיבוך"}, + {"Clock skew", "לכסון שעון"}, + {"Offline", "לא מקוון"}, + {"Symmetric NAT", "NAT סימטרי"}, + {"Full cone NAT", "NAT חסום לחלוטין"}, + {"No Descriptors", "אין מתארים"}, + {"Uptime", "זמן הפעלה"}, + {"Network status", "מצב רשת תקשורת"}, + {"Network status v6", "מצב רשת תקשורת v6"}, + {"Stopping in", "מפסיק בעוד"}, + {"Family", "משפחה"}, + {"Tunnel creation success rate", "שיעור הצלחה של יצירת מנהרות"}, + {"Total tunnel creation success rate", "שיעור הצלחה כולל של יצירת מנהרות"}, + {"Received", "נתקבל"}, + {"%.2f KiB/s", "%.2f קי״ב/ש"}, + {"Sent", "נשלח"}, + {"Transit", "מעבר"}, + {"Data path", "נתיב מידע"}, + {"Hidden content. Press on text to see.", "תוכן מוסתר. לחץ על הטקסט כדי לראותו."}, + {"Router Ident", "מזהה נתב"}, + {"Router Family", "משפחת נתב"}, + {"Version", "גרסא"}, + {"Our external address", "הכתובת החיצונית שלנו"}, + {"supported", "נתמך"}, + {"Routers", "נתבים"}, + {"Client Tunnels", "מנהרות לקוח"}, + {"Services", "שירותים"}, + {"Enabled", "מאופשר"}, + {"Disabled", "מנוטרל"}, + {"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.", "הערה מחרוזת תוצאה יכולה להיות מועילה רק לצורך רישום תחומים 2LD (example.i2p). לשם רישום תתי-תחום עליך להיוועץ עם i2pd-tools."}, + {"Address", "כתובת"}, + {"Type", "טיפוס"}, + {"Expire LeaseSet", "פקיעת LeaseSet"}, + {"Inbound tunnels", "מנהרות פנימיות"}, + {"%dms", "מילישניות %d"}, + {"Outbound tunnels", "מנהרות חיצוניות"}, + {"Tags", "תוויות"}, + {"Incoming", "נכנס"}, + {"Outgoing", "יוצא"}, + {"Destination", "יעד"}, + {"Amount", "כמות"}, + {"Incoming Tags", "תוויות נכנסות"}, + {"Tags sessions", "הפעלות תוויות"}, + {"Status", "מצב"}, + {"Local Destination", "יעד מקומי"}, + {"Streams", "זרמים"}, + {"Close stream", "סגור זרם"}, + {"Such destination is not found", "יעד כזה לא נמצא"}, + {"I2CP session not found", "הפעלת I2CP לא נמצאה"}, + {"I2CP is not enabled", "I2CP לא מאופשר"}, + {"Invalid", "לא תקין"}, + {"Store type", "טיפוס אחסון"}, + {"Expires", "פוקע"}, + {"Non Expired Leases", "חכירות בלתי פקיעות"}, + {"Gateway", "שער-דרך"}, + {"TunnelID", "מזהה מנהרה"}, + {"EndDate", "תאריך סיום"}, + {"floodfill mode is disabled", "מצב floodfill הינו מנוטרל"}, + {"Queue size", "גודל תור"}, + {"Run peer test", "הרץ בדיקת עמית"}, + {"Reload tunnels configuration", "טען מחדש תצורת מנהרות"}, + {"Decline transit tunnels", "דחה מנהרות מעבר"}, + {"Accept transit tunnels", "קבל מנהרות מעבר"}, + {"Cancel graceful shutdown", "בטל כיבוי עדין"}, + {"Start graceful shutdown", "התחל כיבוי עדין"}, + {"Force shutdown", "כפה כיבוי"}, + {"Reload external CSS styles", "טען מחדש סגנונות CSS חיצוניים"}, + {"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", "מנהרות שרת"}, + {"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 in %d seconds", "אתה תכוון מחדש בעוד %d שניות"}, + {"LeaseSet expiration time updated", "זמן פקיעה של LeaseSet עודכן"}, + {"LeaseSet is not found or already expired", "LeaseSet אינו נמצא או שהוא כבר פקע"}, + {"Transit tunnels count must not exceed %d", "אסור לספירת מנהרות מעבר לעלות על %d"}, + {"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"}, + {"Unknown command", "פקודה לא מוכרת"}, + {"Command accepted", "פקודה נתקבלה"}, + {"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", "באפשרותך לנסות למצוא את מארח זה דרך שירותי קפיצה להלן"}, + {"Invalid request", "בקשה לא תקינה"}, + {"Proxy unable to parse your request", "פרוקסי לא מסוגל לנתח את בקשתך"}, + {"Addresshelper is not supported", "סייען-כתובות אינו נתמך"}, + {"Host %s is already in router's addressbook. Be careful: source of this URL may be harmful! Click here to update record: Continue.", "מארח %s is כבר נמצא בפנקס כתובות של הנתב. זהירות: מקור URL זה עלול להזיק! לחץ כאן כדי לעדכן מרשם: המשך."}, + {"Addresshelper forced update rejected", "אילוץ עדכון של סייען-כתובות נדחה"}, + {"To add host %s in router's addressbook, click here: Continue.", "Tכדי להוסיף את מארח %s לפנקס כתובות של הנתב: המשך."}, + {"Addresshelper request", "בקשת סייען-כתובות"}, + {"Host %s added to router's addressbook from helper. Click here to proceed: Continue.", "מארח %s נתווסף לסייען-כתובות של הנתב דרך סייען. לחץ כאן כדי proceed: המשך."}, + {"Addresshelper adding", "הוספת סייען-כתובות"}, + {"Host %s is already in router's addressbook. Click here to update record: Continue.", "מארח %s כבר נמצא בספר כתובות של הנתב. לחץ כאן כדי לעדכן מרשם: המשך."}, + {"Addresshelper update", "עדכון סייען-כתובות"}, + {"Invalid request URI", "בקשת URI לא תקינה"}, + {"Can't detect destination host from request", "לא יכול לאתר יעד מארח מתוך בקשה"}, + {"Host %s is not inside I2P network, but outproxy is not enabled", "מארח %s לא נמצא בתוך רשת I2P, אולם outproxy אינו מאופשר"}, + {"Hostname is too long", "שם-מארח הינו ארוך מדי"}, + {"Cannot negotiate with SOCKS proxy", "לא מסוגל להסדיר פרוקסי SOCKS"}, + {"CONNECT error", "שגיאת חיבור"}, + {"Failed to connect", "נכשל להתחבר"}, + {"SOCKS proxy error", "שגיאת פרוקסי SOCKS"}, + {"No reply from SOCKS proxy", "אין מענה מתוך פרוקסי SOCKS"}, + {"Cannot connect", "לא מסוגל להתחבר"}, + {"Host is down", "מארח הינו מושבת"}, + {"Can't create connection to requested host, it may be down. Please try again later.", "לא יכול ליצור חיבור למארח מבוקש, המארח עשוי להיות מושבת. אנא נסה שוב מאוחר יותר."}, + {"", ""}, + }; + + static std::map> plurals + { + {"%d days", {"יום %d", "יומיים", "ימים %d", "ימים %d"}}, + {"%d hours", {"שעה %d", "שעתיים", "שעות %d", "שעות %d"}}, + {"%d minutes", {"דקה %d", "שתי דקות", "דקות %d", "דקות %d"}}, + {"%d seconds", {"שניה %d", "שתי שניות", "שניות %d", "שניות %d"}}, + {"", {"", "", ""}}, + }; + + std::shared_ptr GetLocale() + { + return std::make_shared(language, rtl, strings, plurals, [] (int n)->int { return plural(n); }); + } + +} // language +} // i18n +} // i2p diff --git a/i18n/Hindi.cpp b/i18n/Hindi.cpp new file mode 100644 index 00000000..7ce9b65b --- /dev/null +++ b/i18n/Hindi.cpp @@ -0,0 +1,226 @@ +/* +* Copyright (c) 2025, The PurpleI2P Project +* +* This file is part of Purple i2pd project and licensed under BSD3 +* +* See full license text in LICENSE file at top of project tree +*/ + +#include +#include +#include +#include +#include "I18N.h" + +// Hindi localization file + +namespace i2p +{ +namespace i18n +{ +namespace hindi // language namespace +{ + // language name in lowercase + static std::string language = "hindi"; + + // See for language plural forms here: + // https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html + static int plural (int n) { + return n != 1 ? 1 : 0; + } + + // Right to Left language? + static bool rtl = false; + + static const LocaleStrings strings + { + {"%.2f KiB", "%.2f कीबी"}, + {"%.2f MiB", "%.2f मीबी"}, + {"%.2f GiB", "%.2f जीबी"}, + {"building", "निर्माण"}, + {"failed", "विफल"}, + {"expiring", "समाप्त होना"}, + {"established", "स्थापित"}, + {"unknown", "अज्ञात"}, + {"exploratory", "अन्वेषणात्मक"}, + {"Purple I2P Webconsole", "पर्पल I2P वेब कंसोल"}, + {"i2pd webconsole", "i2pd वेब कंसोल"}, + {"Main page", "मुख्य पृष्ठ"}, + {"Router commands", "राउटर आदेश"}, + {"Local Destinations", "स्थानीय गंतव्य"}, + {"LeaseSets", "पट्ट समुच्चय"}, + {"Tunnels", "सुरंग"}, + {"Transit Tunnels", "संचरण सुरंगें"}, + {"Transports", "परिवहन"}, + {"I2P tunnels", "I2P सुरंगें"}, + {"SAM sessions", "SAM सत्र"}, + {"ERROR", "त्रुटि"}, + {"OK", "ठीक है"}, + {"Testing", "परीक्षण"}, + {"Firewalled", "फायरवॉल"}, + {"Unknown", "अज्ञात"}, + {"Proxy", "प्रॉक्सी"}, + {"Mesh", "जाली"}, + {"Clock skew", "घड़ी संकेत विचलन"}, + {"Offline", "ऑफलाइन"}, + {"Symmetric NAT", "सममितीय NAT"}, + {"Full cone NAT", "पूर्णकोण NAT"}, + {"No Descriptors", "कोई वर्णनकर्त्तृ नहीं हैं"}, + {"Uptime", "संचालन समय"}, + {"Network status", "संपर्क स्थिति"}, + {"Network status v6", "संपर्क स्थिति v6"}, + {"Stopping in", "में अवसान प्रारंभ हो रहा है"}, + {"Family", "परिवार"}, + {"Tunnel creation success rate", "सुरंग निर्माण सफलता दर"}, + {"Total tunnel creation success rate", "कुल सुरंग निर्माण सफलता दर"}, + {"Received", "प्राप्त हुआ"}, + {"%.2f KiB/s", "%.2f कीबी/से"}, + {"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", "क्लाइंट सुरंगें"}, + {"Services", "सेवाएँ"}, + {"Enabled", "सक्षम है"}, + {"Disabled", "निष्क्रिय है"}, + {"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.", "नोट: परिणाम स्ट्रिंग का उपयोग केवल 2LD डोमेनों (जैसे example.i2p) को रजिस्टर करने के लिए किया जा सकता है। सबडोमेन रजिस्टर करने के लिए कृपया i2pd-tools का उपयोग करें।"}, + {"Address", "पता"}, + {"Type", "प्रकार"}, + {"EncType", "कूट प्रकार"}, + {"Expire LeaseSet", "पट्ट समुच्चय का अवसान करें"}, + {"Inbound tunnels", "आगमनशील सुरंगें"}, + {"%dms", "%dms"}, + {"Outbound tunnels", "प्रस्थानशील सुरंगें"}, + {"Tags", "चिन्हित"}, + {"Incoming", "आगामी"}, + {"Outgoing", "निर्गामी"}, + {"Destination", "गंतव्य"}, + {"Amount", "मात्रा"}, + {"Incoming Tags", "आगामी चिन्हित"}, + {"Tags sessions", "चिन्हित सत्र OR सत्र को चिन्हित करें"}, + {"Status", "स्थिति"}, + {"Local Destination", "स्थानीय गंतव्य"}, + {"Streams", "धाराएँ"}, + {"Close stream", "प्रवाह समाप्त करें"}, + {"Such destination is not found", "ऐसा गंतव्य नहीं मिला"}, + {"I2CP session not found", "I2CP सत्र नहीं मिला"}, + {"I2CP is not enabled", "I2CP निष्क्रिय है"}, + {"Invalid", "अमान्य"}, + {"Store type", "भण्डारगार का प्रकार"}, + {"Expires", "अवसान होता है"}, + {"Non Expired Leases", "अनवसित पट्ट"}, + {"Gateway", "प्रवेशद्वार"}, + {"TunnelID", "सुरंग ID"}, + {"EndDate", "समाप्ति तिथि"}, + {"floodfill mode is disabled", "पूर्णक संवाहक विधि निष्क्रिय है"}, + {"Queue size", "क्यू आकार"}, + {"Run peer test", "सहकर्मी परीक्षण चलाएँ"}, + {"Reload tunnels configuration", "सुरंग विन्यास पुनः लोड करें"}, + {"Decline transit tunnels", "संचरण सुरंगों को अस्वीकार करें"}, + {"Accept transit tunnels", "संचरण सुरंगों को स्वीकार करें"}, + {"Cancel graceful shutdown", "सौम्य अवसान निरस्त करें"}, + {"Start graceful shutdown", "सौम्य समापन प्रारंभ करें"}, + {"Force shutdown", "बाध्य अवसान"}, + {"Reload external CSS styles", "बाह्य CSS शैलियों को पुनः लोड करें"}, + {"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", "प्रवाह ID शून्य नहीं हो सकता है"}, + {"Return to destination page", "गंतव्य पृष्ठ पर पुनः वापस जाएँ"}, + {"You will be redirected in %d seconds", "आपको %d सेकंड में पुनर्निर्देशित किया जाएगा"}, + {"LeaseSet expiration time updated", "पट्ट समुच्चय की अवसान समय को अद्यतित किया गया है"}, + {"LeaseSet is not found or already expired", "पट्ट समुच्चय प्राप्त नहीं हुआ या इसका पूर्वमेव अवसान हो चुका है"}, + {"Transit tunnels count must not exceed %d", "संचरण सुरंगों की संख्या %d से अधिक नहीं होनी चाहिए"}, + {"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 से होना आवश्यक है"}, + {"Unknown command", "अज्ञात आदेश"}, + {"Command accepted", "आदेश स्वीकार किया गया"}, + {"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", "आप नीचे दिए गए जंप सेवाओं में इस होस्ट को खोजने की कोशिश कर सकते हैं"}, + {"Invalid request", "अमान्य अनुरोध"}, + {"Proxy unable to parse your request", "प्रॉक्सी आपके अनुरोध को विश्लेषित करने में असमर्थ है"}, + {"Addresshelper is not supported", "Addresshelper समर्थित नहीं है"}, + {"Host %s is already in router's addressbook. Be careful: source of this URL may be harmful! Click here to update record: Continue.", "होस्ट %s पहले से ही राउटर की पता-पुस्तिका में उपस्थित हैसावधान रहें: इस URL का स्रोत हानिकारक हो सकता है! अभिलेख को अद्यतन करने हेतु यहाँ क्लिक करें: जारी रखें।"}, + {"Addresshelper forced update rejected", "Addresshelper का जबरन अद्यतन अस्वीकृत किया गया"}, + {"To add host %s in router's addressbook, click here: Continue.", "राउटर की पता-पुस्तिका में होस्ट %s को जोड़ने हेतु, कृपया यहाँ क्लिक करें: जारी रखें।"}, + {"Addresshelper request", "Addresshelper अनुरोध"}, + {"Host %s added to router's addressbook from helper. Click here to proceed: Continue.", "सहायक से होस्ट %s राउटर की पता-पुस्तिका में जोड़ दिया गया है। आगे बढ़ने हेतु यहाँ क्लिक करें: जारी रखें।"}, + {"Addresshelper adding", "Addresshelper जोड़ना"}, + {"Host %s is already in router's addressbook. Click here to update record: Continue.", "होस्ट %s पहले से ही राउटर की पता-पुस्तिका में उपस्थित है। अभिलेख को अद्यतन करने हेतु यहाँ क्लिक करें: जारी रखें।"}, + {"Addresshelper update", "Addresshelper अद्यतन करना"}, + {"Invalid request URI", "अमान्य अनुरोध URI"}, + {"Can't detect destination host from request", "अनुरोध से गंतव्य होस्ट का पता नहीं लगा सकते"}, + {"Outproxy failure", "आउटप्रॉक्सी विफलता"}, + {"Bad outproxy settings", "गलत आउटप्रॉक्सी सेटिंग्स"}, + {"Host %s is not inside I2P network, but outproxy is not enabled", "होस्ट %s I2P नेटवर्क के भीतर नहीं है, लेकिन आउटप्रॉक्सी सक्षम नहीं है"}, + {"Unknown outproxy URL", "अज्ञात आउटप्रॉक्सी URL"}, + {"Cannot resolve upstream proxy", "ऊर्ध्वधारा प्रॉक्सी का समाधान नहीं किया जा सका"}, + {"Hostname is too long", "होस्टनाम अत्यधिक लंबा है"}, + {"Cannot connect to upstream SOCKS proxy", "उर्ध्वधारा SOCKS प्रॉक्सी से संपर्क स्थापित नहीं हो पा रहा है"}, + {"Cannot negotiate with SOCKS proxy", "SOCKS प्रॉक्सी के साथ समन्वयन स्थापित नहीं किया जा सका"}, + {"CONNECT error", "संपर्क त्रुटि"}, + {"Failed to connect", "संपर्क स्थापित करने में विफल"}, + {"SOCKS proxy error", "SOCKS प्रॉक्सी त्रुटि"}, + {"Failed to send request to upstream", "ऊर्ध्ववाहिनी को अनुरोध प्रेषित करने में विफलता हुई"}, + {"No reply from SOCKS proxy", "SOCKS प्रॉक्सी से कोई प्रत्युत्तर प्राप्त नहीं हुआ"}, + {"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.", "अनुरोधित होस्ट से संपर्क स्थापित नहीं किया जा सका। संभवतः वह सक्रिय नहीं है। कृपया बाद में पुनः प्रयास करें।"}, + {"", ""}, + }; + + static std::map> plurals + { + {"%d days", {"%d दिन", "%d दिन"}}, + {"%d hours", {"%d घंटा", "%dघंटे"}}, + {"%d minutes", {"%d मिनट", "%d मिनट"}}, + {"%d seconds", {"%d सेकंड", "%d सेकंड"}}, + {"", {"", "", ""}}, + }; + + std::shared_ptr GetLocale() + { + return std::make_shared(language, rtl, strings, plurals, [] (int n)->int { return plural(n); }); + } + +} // language +} // i18n +} // i2p diff --git a/i18n/I18N.h b/i18n/I18N.h index 8ed77a6b..00398f78 100644 --- a/i18n/I18N.h +++ b/i18n/I18N.h @@ -19,16 +19,17 @@ namespace i2p { namespace i18n { - typedef std::map LocaleStrings; + typedef std::map LocaleStrings; class Locale { public: Locale ( const std::string& language, + const bool& rtl, const LocaleStrings& strings, const std::map>& plurals, std::function formula - ): m_Language (language), m_Strings (strings), m_Plurals (plurals), m_Formula (formula) { }; + ): m_Language (language), m_RTL (rtl), m_Strings (strings), m_Plurals (plurals), m_Formula (formula) { }; // Get activated language name for webconsole std::string GetLanguage() const @@ -36,6 +37,11 @@ namespace i18n return m_Language; } + bool GetRTL() const + { + return m_RTL; + } + std::string_view GetString (std::string_view arg) const { const auto it = m_Strings.find(arg); @@ -65,6 +71,7 @@ namespace i18n private: const std::string m_Language; + const bool m_RTL; const LocaleStrings m_Strings; const std::map> m_Plurals; std::function m_Formula; diff --git a/i18n/I18N_langs.h b/i18n/I18N_langs.h index 6426e2ce..b3d09af8 100644 --- a/i18n/I18N_langs.h +++ b/i18n/I18N_langs.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2021-2023, The PurpleI2P Project +* Copyright (c) 2021-2025, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -30,6 +30,8 @@ namespace i18n namespace english { std::shared_ptr GetLocale (); } namespace french { std::shared_ptr GetLocale (); } namespace german { std::shared_ptr GetLocale (); } + namespace hebrew { std::shared_ptr GetLocale (); } + namespace hindi { std::shared_ptr GetLocale (); } namespace italian { std::shared_ptr GetLocale (); } namespace polish { std::shared_ptr GetLocale (); } namespace portuguese { std::shared_ptr GetLocale (); } @@ -53,6 +55,8 @@ namespace i18n { "english", {"English", "en", i2p::i18n::english::GetLocale} }, { "french", {"Français", "fr", i2p::i18n::french::GetLocale} }, { "german", {"Deutsch", "de", i2p::i18n::german::GetLocale} }, + { "hebrew", {"עִבְרִית‎", "he", i2p::i18n::hebrew::GetLocale} }, + { "hindi", {"हिन्दी", "hi", i2p::i18n::hindi::GetLocale} }, { "italian", {"Italiano", "it", i2p::i18n::italian::GetLocale} }, { "polish", {"Polski", "pl", i2p::i18n::polish::GetLocale} }, { "portuguese", {"Português", "pt", i2p::i18n::portuguese::GetLocale} }, diff --git a/i18n/Italian.cpp b/i18n/Italian.cpp index 0ae26f21..339654ba 100644 --- a/i18n/Italian.cpp +++ b/i18n/Italian.cpp @@ -29,6 +29,9 @@ namespace italian // language namespace return n != 1 ? 1 : 0; } + // Right to Left language? + static bool rtl = false; + static const LocaleStrings strings { {"%.2f KiB", "%.2f KiB"}, @@ -215,7 +218,7 @@ namespace italian // language namespace std::shared_ptr GetLocale() { - return std::make_shared(language, strings, plurals, [] (int n)->int { return plural(n); }); + return std::make_shared(language, rtl, strings, plurals, [] (int n)->int { return plural(n); }); } } // language diff --git a/i18n/Polish.cpp b/i18n/Polish.cpp index 0e8df096..97422e45 100644 --- a/i18n/Polish.cpp +++ b/i18n/Polish.cpp @@ -29,6 +29,9 @@ namespace polish // language namespace return (n == 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2); } + // Right to Left language? + static bool rtl = false; + static const LocaleStrings strings { {"%.2f KiB", "%.2f KiB"}, @@ -215,7 +218,7 @@ namespace polish // language namespace std::shared_ptr GetLocale() { - return std::make_shared(language, strings, plurals, [] (int n)->int { return plural(n); }); + return std::make_shared(language, rtl, strings, plurals, [] (int n)->int { return plural(n); }); } } // language diff --git a/i18n/Portuguese.cpp b/i18n/Portuguese.cpp index 26204dc3..970a7b8f 100644 --- a/i18n/Portuguese.cpp +++ b/i18n/Portuguese.cpp @@ -29,6 +29,9 @@ namespace portuguese // language namespace return n != 1 ? 1 : 0; } + // Right to Left language? + static bool rtl = false; + static const LocaleStrings strings { {"%.2f KiB", "%.2f KiB"}, @@ -215,7 +218,7 @@ namespace portuguese // language namespace std::shared_ptr GetLocale() { - return std::make_shared(language, strings, plurals, [] (int n)->int { return plural(n); }); + return std::make_shared(language, rtl, strings, plurals, [] (int n)->int { return plural(n); }); } } // language diff --git a/i18n/Russian.cpp b/i18n/Russian.cpp index 235cc0ae..e5bcb0b0 100644 --- a/i18n/Russian.cpp +++ b/i18n/Russian.cpp @@ -29,6 +29,9 @@ namespace russian // language namespace return n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2; } + // Right to Left language? + static bool rtl = false; + static const LocaleStrings strings { {"%.2f KiB", "%.2f КиБ"}, @@ -215,7 +218,7 @@ namespace russian // language namespace std::shared_ptr GetLocale() { - return std::make_shared(language, strings, plurals, [] (int n)->int { return plural(n); }); + return std::make_shared(language, rtl, strings, plurals, [] (int n)->int { return plural(n); }); } } // language diff --git a/i18n/Spanish.cpp b/i18n/Spanish.cpp index 0e657fb4..5b51ce4d 100644 --- a/i18n/Spanish.cpp +++ b/i18n/Spanish.cpp @@ -29,6 +29,9 @@ namespace spanish // language namespace return n != 1 ? 1 : 0; } + // Right to Left language? + static bool rtl = false; + static const LocaleStrings strings { {"%.2f KiB", "%.2f KiB"}, @@ -196,7 +199,7 @@ namespace spanish // language namespace std::shared_ptr GetLocale() { - return std::make_shared(language, strings, plurals, [] (int n)->int { return plural(n); }); + return std::make_shared(language, rtl, strings, plurals, [] (int n)->int { return plural(n); }); } } // language diff --git a/i18n/Swedish.cpp b/i18n/Swedish.cpp index df13d22f..1dcb7e61 100644 --- a/i18n/Swedish.cpp +++ b/i18n/Swedish.cpp @@ -29,6 +29,9 @@ namespace swedish // language namespace return n != 1 ? 1 : 0; } + // Right to Left language? + static bool rtl = false; + static const LocaleStrings strings { {"%.2f KiB", "%.2f KiB"}, @@ -211,7 +214,7 @@ namespace swedish // language namespace std::shared_ptr GetLocale() { - return std::make_shared(language, strings, plurals, [] (int n)->int { return plural(n); }); + return std::make_shared(language, rtl, strings, plurals, [] (int n)->int { return plural(n); }); } } // language diff --git a/i18n/Turkish.cpp b/i18n/Turkish.cpp index 9946b336..139b004e 100644 --- a/i18n/Turkish.cpp +++ b/i18n/Turkish.cpp @@ -29,6 +29,9 @@ namespace turkish // language namespace return n != 1 ? 1 : 0; } + // Right to Left language? + static bool rtl = false; + static const LocaleStrings strings { {"%.2f KiB", "%.2f KiB"}, @@ -106,7 +109,7 @@ namespace turkish // language namespace std::shared_ptr GetLocale() { - return std::make_shared(language, strings, plurals, [] (int n)->int { return plural(n); }); + return std::make_shared(language, rtl, strings, plurals, [] (int n)->int { return plural(n); }); } } // language diff --git a/i18n/Turkmen.cpp b/i18n/Turkmen.cpp index 7efb8891..8cdcae52 100644 --- a/i18n/Turkmen.cpp +++ b/i18n/Turkmen.cpp @@ -29,6 +29,9 @@ namespace turkmen // language namespace return n != 1 ? 1 : 0; } + // Right to Left language? + static bool rtl = false; + static const LocaleStrings strings { {"%.2f KiB", "%.2f KiB"}, @@ -196,7 +199,7 @@ namespace turkmen // language namespace std::shared_ptr GetLocale() { - return std::make_shared(language, strings, plurals, [] (int n)->int { return plural(n); }); + return std::make_shared(language, rtl, strings, plurals, [] (int n)->int { return plural(n); }); } } // language diff --git a/i18n/Ukrainian.cpp b/i18n/Ukrainian.cpp index c1b6c772..3c3c44a4 100644 --- a/i18n/Ukrainian.cpp +++ b/i18n/Ukrainian.cpp @@ -29,6 +29,9 @@ namespace ukrainian // language namespace return n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2; } + // Right to Left language? + static bool rtl = false; + static const LocaleStrings strings { {"%.2f KiB", "%.2f КіБ"}, @@ -215,7 +218,7 @@ namespace ukrainian // language namespace std::shared_ptr GetLocale() { - return std::make_shared(language, strings, plurals, [] (int n)->int { return plural(n); }); + return std::make_shared(language, rtl, strings, plurals, [] (int n)->int { return plural(n); }); } } // language diff --git a/i18n/Uzbek.cpp b/i18n/Uzbek.cpp index 8e870772..681a8e19 100644 --- a/i18n/Uzbek.cpp +++ b/i18n/Uzbek.cpp @@ -29,6 +29,9 @@ namespace uzbek // language namespace return n > 1 ? 1 : 0; } + // Right to Left language? + static bool rtl = false; + static const LocaleStrings strings { {"%.2f KiB", "%.2f KiB"}, @@ -215,7 +218,7 @@ namespace uzbek // language namespace std::shared_ptr GetLocale() { - return std::make_shared(language, strings, plurals, [] (int n)->int { return plural(n); }); + return std::make_shared(language, rtl, strings, plurals, [] (int n)->int { return plural(n); }); } } // language From d440b5bf098f61e27dea3a2689e8a0c4ad5f6a13 Mon Sep 17 00:00:00 2001 From: nobs2p Date: Sun, 18 May 2025 00:24:25 +0300 Subject: [PATCH 1054/1171] Fix FORWARD session host handling in SAM; refactor SAMSocket::ProcessStreamForward - Fixed validation of HOST and PORT parameters for FORWARD sessions: - Improved IP address parsing with fallback to 127.0.0.1 if invalid - Added checks for required parameters (ID, HOST, PORT) - General cleanup and refactoring for improved readability and stability Signed-off-by: nobs2p --- libi2pd_client/SAM.cpp | 90 +++++++++++++++++++++++++++++++----------- 1 file changed, 66 insertions(+), 24 deletions(-) diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index f0df414c..96f2c2ee 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -637,53 +637,95 @@ namespace client SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); } - void SAMSocket::ProcessStreamForward (char * buf, size_t len) + void SAMSocket::ProcessStreamForward(char* buf, size_t len) { - LogPrint (eLogDebug, "SAM: Stream forward: ", buf); + LogPrint(eLogDebug, "SAM: Stream forward: ", buf); + std::map params; - ExtractParams (buf, params); - std::string& id = params[SAM_PARAM_ID]; - auto session = m_Owner.FindSession (id); + ExtractParams(buf, params); + + const auto itId = params.find(SAM_PARAM_ID); + if (itId == params.end()) + { + SendSessionI2PError("Missing ID"); + return; + } + const std::string& id = itId->second; + + auto session = m_Owner.FindSession(id); if (!session) { - SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); + SendMessageReply(SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); return; } - if (session->GetLocalDestination ()->IsAcceptingStreams ()) + if (session->GetLocalDestination()->IsAcceptingStreams()) { - SendSessionI2PError ("Already accepting"); + SendSessionI2PError("Already accepting"); return; } - auto it = params.find (SAM_PARAM_PORT); - if (it == params.end ()) + + const auto itPort = params.find(SAM_PARAM_PORT); + if (itPort == params.end()) { - SendSessionI2PError ("PORT is missing"); + SendSessionI2PError("PORT is missing"); return; } - auto port = std::stoi (it->second); + + const std::string& portStr = itPort->second; + if (!std::all_of(portStr.begin(), portStr.end(), ::isdigit)) + { + SendSessionI2PError("Port must be numeric"); + return; + } + + int port = std::stoi(portStr); if (port <= 0 || port >= 0xFFFF) { - SendSessionI2PError ("Invalid PORT"); + SendSessionI2PError("Invalid port"); return; } - boost::system::error_code ec; - auto ep = m_Socket.remote_endpoint (ec); - if (ec) + + boost::asio::ip::tcp::endpoint ep; + const auto itHost = params.find(SAM_PARAM_HOST); + + if (itHost != params.end()) { - SendSessionI2PError ("Socket error"); - return; + boost::system::error_code ec; + auto addr = boost::asio::ip::make_address(itHost->second, ec); + if (ec) + { + SendSessionI2PError("Invalid IP Address in HOST"); + return; + } + ep = boost::asio::ip::tcp::endpoint(addr, port); } - ep.port (port); + else + { + boost::system::error_code ec; + ep = m_Socket.remote_endpoint(ec); + if (ec) + { + SendSessionI2PError("Socket error: cannot get remote endpoint"); + return; + } + ep.port(port); + } + m_SocketType = eSAMSocketTypeForward; m_ID = id; m_IsAccepting = true; - std::string& silent = params[SAM_PARAM_SILENT]; - if (silent == SAM_VALUE_TRUE) m_IsSilent = true; - session->GetLocalDestination ()->AcceptStreams (std::bind (&SAMSocket::HandleI2PForward, - shared_from_this (), std::placeholders::_1, ep)); - SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); + + auto itSilent = params.find(SAM_PARAM_SILENT); + if (itSilent != params.end() && itSilent->second == SAM_VALUE_TRUE) + m_IsSilent = true; + + session->GetLocalDestination()->AcceptStreams( + std::bind(&SAMSocket::HandleI2PForward, shared_from_this(), std::placeholders::_1, ep)); + + SendMessageReply(SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); } + size_t SAMSocket::ProcessDatagramSend (char * buf, size_t len, const char * data) { LogPrint (eLogDebug, "SAM: Datagram send: ", buf, " ", len); From 4c6be3b85a0d2a4501a718201b869cc7cac74561 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 23 May 2025 21:26:44 -0400 Subject: [PATCH 1055/1171] disable loss-control --- libi2pd/Streaming.cpp | 125 ++++++++++++++++++++++-------------------- libi2pd/Streaming.h | 18 +++--- 2 files changed, 75 insertions(+), 68 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 25608cbc..4ac4e179 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -84,21 +84,21 @@ namespace stream Stream::Stream (boost::asio::io_context& service, StreamingDestination& local, std::shared_ptr remote, int port): m_Service (service), - m_SendStreamID (0), m_SequenceNumber (0), m_DropWindowDelaySequenceNumber (0), + m_SendStreamID (0), m_SequenceNumber (0), m_DropWindowDelaySequenceNumber (INITIAL_WINDOW_SIZE), m_TunnelsChangeSequenceNumber (0), m_LastReceivedSequenceNumber (-1), m_PreviousReceivedSequenceNumber (-1), m_LastConfirmedReceivedSequenceNumber (0), // for limit inbound speed m_Status (eStreamStatusNew), m_IsIncoming (false), m_IsAckSendScheduled (false), m_IsNAcked (false), m_IsFirstACK (false), - m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (false), m_IsClientChoked (false), - m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_IsRemoteLeaseChangeInProgress (false), m_DoubleWinIncCounter (false), m_LocalDestination (local), + m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (true), m_IsClientChoked (false), + m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_IsRemoteLeaseChangeInProgress (false), m_IsBufferEmpty (false), m_LocalDestination (local), m_RemoteLeaseSet (remote), m_ReceiveTimer (m_Service), m_SendTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (port), - m_RTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_SlowRTT2 (INITIAL_RTT), m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0), + m_RTT (INITIAL_RTT), m_MinRTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_FastRTT (INITIAL_RTT), m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0), m_WindowDropTargetSize (0), m_WindowIncCounter (0), m_RTO (INITIAL_RTO), - m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), m_PrevRTTSample (INITIAL_RTT), m_WindowSizeTail (0), + m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), m_PrevRTTSample (INITIAL_RTT), m_Jitter (0), m_MinPacingTime (0), m_PacingTime (INITIAL_PACING_TIME), m_PacingTimeRem (0), m_LastSendTime (0), m_LastACKRecieveTime (0), m_ACKRecieveInterval (local.GetOwner ()->GetStreamingAckDelay ()), m_RemoteLeaseChangeTime (0), m_LastWindowIncTime (0), m_LastACKSendTime (0), m_PacketACKInterval (1), m_PacketACKIntervalRem (0), // for limit inbound speed - m_NumResendAttempts (0), m_NumPacketsToSend (0), m_MTU (STREAMING_MTU) + m_NumResendAttempts (0), m_NumPacketsToSend (0), m_JitterAccum (0), m_JitterDiv (1), m_MTU (STREAMING_MTU) { RAND_bytes ((uint8_t *)&m_RecvStreamID, 4); m_RemoteIdentity = remote->GetIdentity (); @@ -112,20 +112,20 @@ namespace stream } Stream::Stream (boost::asio::io_context& service, StreamingDestination& local): - m_Service (service), m_SendStreamID (0), m_SequenceNumber (0), m_DropWindowDelaySequenceNumber (0), + m_Service (service), m_SendStreamID (0), m_SequenceNumber (0), m_DropWindowDelaySequenceNumber (INITIAL_WINDOW_SIZE), m_TunnelsChangeSequenceNumber (0), m_LastReceivedSequenceNumber (-1), m_PreviousReceivedSequenceNumber (-1), m_LastConfirmedReceivedSequenceNumber (0), // for limit inbound speed m_Status (eStreamStatusNew), m_IsIncoming (true), m_IsAckSendScheduled (false), m_IsNAcked (false), m_IsFirstACK (false), - m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (false), m_IsClientChoked (false), - m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_IsRemoteLeaseChangeInProgress (false), m_DoubleWinIncCounter (false), m_LocalDestination (local), + m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (true), m_IsClientChoked (false), + m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_IsRemoteLeaseChangeInProgress (false), m_IsBufferEmpty (false), m_LocalDestination (local), m_ReceiveTimer (m_Service), m_SendTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service), - m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (0), m_RTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_SlowRTT2 (INITIAL_RTT), + m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (0), m_RTT (INITIAL_RTT), m_MinRTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_FastRTT (INITIAL_RTT), m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0), m_WindowDropTargetSize (0), m_WindowIncCounter (0), m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), - m_PrevRTTSample (INITIAL_RTT), m_WindowSizeTail (0), m_Jitter (0), m_MinPacingTime (0), + m_PrevRTTSample (INITIAL_RTT), m_Jitter (0), m_MinPacingTime (0), m_PacingTime (INITIAL_PACING_TIME), m_PacingTimeRem (0), m_LastSendTime (0), m_LastACKRecieveTime (0), m_ACKRecieveInterval (local.GetOwner ()->GetStreamingAckDelay ()), m_RemoteLeaseChangeTime (0), m_LastWindowIncTime (0), m_LastACKSendTime (0), m_PacketACKInterval (1), m_PacketACKIntervalRem (0), // for limit inbound speed - m_NumResendAttempts (0), m_NumPacketsToSend (0), m_MTU (STREAMING_MTU) + m_NumResendAttempts (0), m_NumPacketsToSend (0), m_JitterAccum (0), m_JitterDiv (1), m_MTU (STREAMING_MTU) { RAND_bytes ((uint8_t *)&m_RecvStreamID, 4); auto outboundSpeed = local.GetOwner ()->GetStreamingOutboundSpeed (); @@ -389,6 +389,7 @@ namespace stream m_IsClientChoked = true; m_IsWinDropped = false; m_DropWindowDelaySequenceNumber = m_SequenceNumber; + m_IsFirstRttSample = true; UpdatePacingTime (); } } @@ -588,47 +589,53 @@ namespace stream if (m_IsFirstRttSample && !m_IsFirstACK) { m_RTT = rttSample; + m_MinRTT = m_RTT; m_SlowRTT = rttSample; - m_SlowRTT2 = rttSample; + m_FastRTT = rttSample; m_PrevRTTSample = rttSample; - m_Jitter = rttSample / 10; // 10% - m_Jitter += 15; // for low-latency connections + m_Jitter = rttSample / 5; // 20% + m_Jitter += 3; // for low-latency connections + m_JitterAccum = m_Jitter; + m_JitterDiv = 1; m_IsFirstRttSample = false; } else + { m_RTT = (m_PrevRTTSample + rttSample) / 2; + } if (!m_IsWinDropped) { m_SlowRTT = SLOWRTT_EWMA_ALPHA * m_RTT + (1.0 - SLOWRTT_EWMA_ALPHA) * m_SlowRTT; - m_SlowRTT2 = RTT_EWMA_ALPHA * m_RTT + (1.0 - RTT_EWMA_ALPHA) * m_SlowRTT2; + m_FastRTT = RTT_EWMA_ALPHA * m_RTT + (1.0 - RTT_EWMA_ALPHA) * m_FastRTT; // calculate jitter double jitter = 0; if (rttSample > m_PrevRTTSample) jitter = rttSample - m_PrevRTTSample; else if (rttSample < m_PrevRTTSample) jitter = m_PrevRTTSample - rttSample; - else - jitter = rttSample / 10; // 10% - jitter += 15; // for low-latency connections - m_Jitter = (0.05 * jitter) + (1.0 - 0.05) * m_Jitter; + if (jitter) + { + jitter += 3; // for low-latency connections + m_JitterAccum += jitter; + m_Jitter = m_JitterAccum / m_JitterDiv; + m_JitterDiv++; + } + if (m_MinRTT > m_RTT) + { + m_MinRTT = m_RTT; + m_FastRTT = m_MinRTT + m_Jitter; + m_SlowRTT = m_MinRTT + m_Jitter; + } } - if (rttSample > m_SlowRTT) + if (m_IsBufferEmpty || m_FastRTT >= m_MinRTT + m_Jitter*3 || m_RTT >= m_MinRTT + m_Jitter*3 || m_SlowRTT >= m_MinRTT + m_Jitter*3 || m_RTT > m_FastRTT) { incCounter = 0; - m_DoubleWinIncCounter = 1; - } - else if (rttSample < m_SlowRTT) - { - if (m_DoubleWinIncCounter) - { - incCounter = incCounter * 2; - m_DoubleWinIncCounter = 0; - } + m_WindowIncCounter = 0; } m_WindowIncCounter = m_WindowIncCounter + incCounter; // // delay-based CC - if ((m_SlowRTT2 > m_SlowRTT + m_Jitter && rttSample > m_SlowRTT2 && rttSample > m_PrevRTTSample) && !m_IsWinDropped && !m_IsClientChoked) // Drop window if RTT grows too fast, late detection + if ((m_SlowRTT > m_MinRTT + m_Jitter*6) && !m_IsWinDropped && !m_IsClientChoked) // Drop window if RTT grows too fast { LogPrint (eLogDebug, "Streaming: Congestion detected, reduce window size"); ProcessWindowDrop (); @@ -852,6 +859,8 @@ namespace stream packets.push_back (p); numMsgs--; } + if (m_SendBuffer.GetSize() == 0) m_IsBufferEmpty = true; + else m_IsBufferEmpty = false; if (packets.size () > 0) { if (m_SavedPackets.empty ()) // no NACKS @@ -1324,7 +1333,7 @@ namespace stream m_NumPacketsToSend = 1; m_PacingTimeRem = 0; } m_IsSendTime = true; - if (m_WindowIncCounter && (m_WindowSize < MAX_WINDOW_SIZE || m_WindowDropTargetSize) && !m_SendBuffer.IsEmpty () && m_PacingTime > m_MinPacingTime && m_RTT <= m_SlowRTT) + if (m_WindowIncCounter && (m_WindowSize < MAX_WINDOW_SIZE || m_WindowDropTargetSize) && !m_SendBuffer.IsEmpty () && m_PacingTime > m_MinPacingTime) { float winSize = m_WindowSize; if (m_WindowDropTargetSize) @@ -1372,14 +1381,9 @@ namespace stream else break; } - m_LastWindowIncTime = ts; UpdatePacingTime (); } - else if (m_WindowIncCounter && m_WindowSize == MAX_WINDOW_SIZE && !m_SendBuffer.IsEmpty () && m_PacingTime > m_MinPacingTime) - { - m_WindowSizeTail = m_WindowSizeTail + m_WindowIncCounter; - if (m_WindowSizeTail > MAX_WINDOW_SIZE) m_WindowSizeTail = MAX_WINDOW_SIZE; - } + m_LastWindowIncTime = ts; if (m_IsNAcked || m_IsResendNeeded || m_IsClientChoked) // resend packets ResendPacket (); else if (m_WindowSize > int(m_SentPackets.size ())) // send packets @@ -1445,7 +1449,7 @@ namespace stream { if (ts >= it->sendTime + m_RTO) { - if (ts < it->sendTime + m_RTO*2) + if (ts < it->sendTime + m_RTO*3) it->resent = true; else it->resent = false; @@ -1461,7 +1465,7 @@ namespace stream { if (ts >= it->sendTime + m_RTO) { - if (ts < it->sendTime + m_RTO*2) + if (ts < it->sendTime + m_RTO*3) it->resent = true; else it->resent = false; @@ -1483,7 +1487,18 @@ namespace stream if (!m_IsWinDropped && LOSS_BASED_CONTROL_ENABLED && !m_IsClientChoked) { LogPrint (eLogDebug, "Streaming: Packet loss, reduce window size"); - ProcessWindowDrop (); + if (m_WindowDropTargetSize) + m_LastWindowDropSize = m_WindowDropTargetSize; + else + m_LastWindowDropSize = m_WindowSize; + m_WindowDropTargetSize = m_LastWindowDropSize * 0.75; // -25% to drain queue + if (m_WindowDropTargetSize < MIN_WINDOW_SIZE) + m_WindowDropTargetSize = MIN_WINDOW_SIZE; + m_WindowIncCounter = 0; // disable window growth + m_DropWindowDelaySequenceNumber = m_SequenceNumber + int(m_WindowDropTargetSize); + m_IsFirstACK = true; // ignore first RTT sample + m_IsWinDropped = true; // don't drop window twice + UpdatePacingTime (); } } else if (m_IsTimeOutResend) @@ -1680,10 +1695,11 @@ namespace stream void Stream::UpdatePacingTime () { + double rtt = m_MinRTT + m_Jitter*2; if (m_WindowDropTargetSize) - m_PacingTime = std::round (m_RTT*1000/m_WindowDropTargetSize); + m_PacingTime = std::round (rtt*1000/m_WindowDropTargetSize); else - m_PacingTime = std::round (m_RTT*1000/m_WindowSize); + m_PacingTime = std::round (rtt*1000/m_WindowSize); if (m_MinPacingTime && m_PacingTime < m_MinPacingTime) m_PacingTime = m_MinPacingTime; } @@ -1691,28 +1707,16 @@ namespace stream void Stream::ProcessWindowDrop () { if (m_WindowDropTargetSize) - m_WindowDropTargetSize = (m_WindowDropTargetSize / 2) * 0.75; // congestion window size and -25% to drain queue + m_LastWindowDropSize = m_WindowDropTargetSize * ((m_MinRTT + m_Jitter*4) / m_FastRTT); else - { - if (m_WindowSize < m_LastWindowDropSize) - { - m_LastWindowDropSize = std::max ((m_WindowSize - MAX_WINDOW_SIZE_INC_PER_RTT), (m_WindowSize - (m_LastWindowDropSize - m_WindowSize))); - if (m_LastWindowDropSize < MIN_WINDOW_SIZE) m_LastWindowDropSize = MIN_WINDOW_SIZE; - } - else - { - m_LastWindowDropSize = std::max ((m_WindowSize - MAX_WINDOW_SIZE_INC_PER_RTT), ((m_LastWindowDropSize + m_WindowSize + m_WindowSizeTail) / 2)); - if (m_LastWindowDropSize > MAX_WINDOW_SIZE) m_LastWindowDropSize = MAX_WINDOW_SIZE; - } - m_WindowDropTargetSize = m_LastWindowDropSize * 0.75; // -25% to drain queue - } + m_LastWindowDropSize = m_WindowSize * ((m_MinRTT + m_Jitter*4) / m_FastRTT); + m_WindowDropTargetSize = m_LastWindowDropSize * 0.75; // -25% to drain queue if (m_WindowDropTargetSize < MIN_WINDOW_SIZE) m_WindowDropTargetSize = MIN_WINDOW_SIZE; m_WindowIncCounter = 0; // disable window growth m_DropWindowDelaySequenceNumber = m_SequenceNumber + int(m_WindowDropTargetSize); m_IsFirstACK = true; // ignore first RTT sample m_IsWinDropped = true; // don't drop window twice - m_WindowSizeTail = 0; UpdatePacingTime (); } @@ -1730,10 +1734,11 @@ namespace stream m_WindowSize = INITIAL_WINDOW_SIZE; } m_LastWindowDropSize = 0; - m_WindowIncCounter = 0; m_IsFirstRttSample = true; m_IsFirstACK = true; - m_WindowSizeTail = 0; + m_WindowIncCounter = 0; // disable window growth + m_DropWindowDelaySequenceNumber = m_SequenceNumber - int(m_SentPackets.size ()) + INITIAL_WINDOW_SIZE; + m_IsWinDropped = true; // don't drop window twice UpdatePacingTime (); } diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 570fdd1d..9fbcb178 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -61,10 +61,10 @@ namespace stream const int INITIAL_WINDOW_SIZE = 10; const int MIN_WINDOW_SIZE = 3; const int MAX_WINDOW_SIZE = 512; - const int MAX_WINDOW_SIZE_INC_PER_RTT = 16; - const double RTT_EWMA_ALPHA = 0.25; - const double SLOWRTT_EWMA_ALPHA = 0.05; - const double PREV_SPEED_KEEP_TIME_COEFF = 0.35; // 0.1 - 1 // how long will the window size stay around the previous drop level, less is longer + const int MAX_WINDOW_SIZE_INC_PER_RTT = 12; + const double RTT_EWMA_ALPHA = 0.1; + const double SLOWRTT_EWMA_ALPHA = 0.02; + const double PREV_SPEED_KEEP_TIME_COEFF = 0.2; // 0.1 - 1 // how long will the window size stay around the previous drop level, less is longer const int MIN_RTO = 20; // in milliseconds const int INITIAL_RTT = 1500; // in milliseconds const int INITIAL_RTO = 9000; // in milliseconds @@ -79,7 +79,7 @@ namespace stream const uint64_t SEND_INTERVAL_VARIANCE = 2000; // in microseconds const uint64_t REQUEST_IMMEDIATE_ACK_INTERVAL = 7500; // in milliseconds const uint64_t REQUEST_IMMEDIATE_ACK_INTERVAL_VARIANCE = 3200; // in milliseconds - const bool LOSS_BASED_CONTROL_ENABLED = 1; // 0/1 + const bool LOSS_BASED_CONTROL_ENABLED = 0; // 0/1 const uint64_t STREAMING_DESTINATION_POOLS_CLEANUP_INTERVAL = 646; // in seconds struct Packet @@ -281,7 +281,7 @@ namespace stream bool m_IsTimeOutResend; bool m_IsImmediateAckRequested; bool m_IsRemoteLeaseChangeInProgress; - bool m_DoubleWinIncCounter; + bool m_IsBufferEmpty; StreamingDestination& m_LocalDestination; std::shared_ptr m_RemoteIdentity; std::shared_ptr m_TransientVerifier; // in case of offline key @@ -299,14 +299,16 @@ namespace stream uint16_t m_Port; SendBufferQueue m_SendBuffer; - double m_RTT, m_SlowRTT, m_SlowRTT2; + double m_RTT, m_MinRTT, m_SlowRTT, m_FastRTT; float m_WindowSize, m_LastWindowDropSize, m_WindowDropTargetSize; - int m_WindowIncCounter, m_RTO, m_AckDelay, m_PrevRTTSample, m_WindowSizeTail; + int m_WindowIncCounter, m_RTO, m_AckDelay, m_PrevRTTSample; double m_Jitter; uint64_t m_MinPacingTime, m_PacingTime, m_PacingTimeRem, // microseconds m_LastSendTime, m_LastACKRecieveTime, m_ACKRecieveInterval, m_RemoteLeaseChangeTime, m_LastWindowIncTime; // milliseconds uint64_t m_LastACKSendTime, m_PacketACKInterval, m_PacketACKIntervalRem; // for limit inbound speed int m_NumResendAttempts, m_NumPacketsToSend; + uint64_t m_JitterAccum; + int m_JitterDiv; size_t m_MTU; }; From 606881898bdce1b37a8ab865b0508109bf595618 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 25 May 2025 14:49:58 -0400 Subject: [PATCH 1056/1171] fill phony record for inbound tunnel with x25519 public key --- libi2pd/Tunnel.cpp | 18 ++++++++--- libi2pd/Tunnel.h | 10 +++--- libi2pd/TunnelConfig.cpp | 68 +++++++++++++++++++++++++++++++++++++++- libi2pd/TunnelConfig.h | 40 ++++++++++++++--------- 4 files changed, 110 insertions(+), 26 deletions(-) diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 1b317121..1347b5b8 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -29,7 +29,7 @@ namespace i2p { namespace tunnel { - Tunnel::Tunnel (std::shared_ptr config): + Tunnel::Tunnel (std::shared_ptr config): TunnelBase (config->GetTunnelID (), config->GetNextTunnelID (), config->GetNextIdentHash ()), m_Config (config), m_IsShortBuildMessage (false), m_Pool (nullptr), m_State (eTunnelStatePending), m_FarEndTransports (i2p::data::RouterInfo::eAllTransports), @@ -44,7 +44,13 @@ namespace tunnel void Tunnel::Build (uint32_t replyMsgID, std::shared_ptr outboundTunnel) { auto numHops = m_Config->GetNumHops (); - const int numRecords = numHops <= STANDARD_NUM_RECORDS ? STANDARD_NUM_RECORDS : MAX_NUM_RECORDS; + bool insertPhonyRecord = m_Config->IsInbound() && numHops < MAX_NUM_RECORDS; + if (insertPhonyRecord) + { + m_Config->CreatePhonyHop (); + numHops++; + } + int numRecords = numHops <= STANDARD_NUM_RECORDS ? STANDARD_NUM_RECORDS : MAX_NUM_RECORDS; auto msg = numRecords <= STANDARD_NUM_RECORDS ? NewI2NPShortMessage () : NewI2NPMessage (); *msg->GetPayload () = numRecords; const size_t recordSize = m_Config->IsShort () ? SHORT_TUNNEL_BUILD_RECORD_SIZE : TUNNEL_BUILD_RECORD_SIZE; @@ -52,8 +58,7 @@ namespace tunnel // shuffle records std::vector recordIndicies; for (int i = 0; i < numRecords; i++) recordIndicies.push_back(i); - std::shuffle (recordIndicies.begin(), recordIndicies.end(), m_Pool ? m_Pool->GetRng () : std::mt19937(std::random_device()())); - + std::shuffle (recordIndicies.begin(), recordIndicies.end(), m_Pool ? m_Pool->GetRng () : std::mt19937(std::random_device()())); // create real records uint8_t * records = msg->GetPayload () + 1; TunnelHopConfig * hop = m_Config->GetFirstHop (); @@ -61,7 +66,7 @@ namespace tunnel while (hop) { uint32_t msgID; - if (hop->next) // we set replyMsgID for last hop only + if (hop->next && hop->next->ident) // we set replyMsgID for last non-phony hop only RAND_bytes ((uint8_t *)&msgID, 4); else msgID = replyMsgID; @@ -89,6 +94,9 @@ namespace tunnel } hop = hop->prev; } + // delete phony hop after encryption + if (insertPhonyRecord) m_Config->DeletePhonyHop (); + msg->FillI2NPMessageHeader (m_Config->IsShort () ? eI2NPShortTunnelBuild : eI2NPVariableTunnelBuild); auto s = shared_from_this (); msg->onDrop = [s]() diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index 5d21cd8b..78e2d124 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -81,12 +81,12 @@ namespace tunnel /** function for visiting a hops stored in a tunnel */ typedef std::function)> TunnelHopVisitor; - Tunnel (std::shared_ptr config); + Tunnel (std::shared_ptr config); ~Tunnel (); void Build (uint32_t replyMsgID, std::shared_ptr outboundTunnel = nullptr); - std::shared_ptr GetTunnelConfig () const { return m_Config; } + std::shared_ptr GetTunnelConfig () const { return m_Config; } std::vector > GetPeers () const; std::vector > GetInvertedPeers () const; bool IsShortBuildMessage () const { return m_IsShortBuildMessage; }; @@ -125,7 +125,7 @@ namespace tunnel private: - std::shared_ptr m_Config; + std::shared_ptr m_Config; std::vector m_Hops; bool m_IsShortBuildMessage; std::shared_ptr m_Pool; // pool, tunnel belongs to, or null @@ -139,7 +139,7 @@ namespace tunnel { public: - OutboundTunnel (std::shared_ptr config): + OutboundTunnel (std::shared_ptr config): Tunnel (config), m_Gateway (*this), m_EndpointIdentHash (config->GetLastIdentHash ()) {}; void SendTunnelDataMsgTo (const uint8_t * gwHash, uint32_t gwTunnel, std::shared_ptr msg); @@ -164,7 +164,7 @@ namespace tunnel { public: - InboundTunnel (std::shared_ptr config): Tunnel (config), m_Endpoint (true) {}; + InboundTunnel (std::shared_ptr config): Tunnel (config), m_Endpoint (true) {}; void HandleTunnelDataMsg (std::shared_ptr&& msg) override; virtual size_t GetNumReceivedBytes () const { return m_Endpoint.GetNumReceivedBytes (); }; bool IsInbound() const override { return true; } diff --git a/libi2pd/TunnelConfig.cpp b/libi2pd/TunnelConfig.cpp index fe0e8573..1ae8f3e9 100644 --- a/libi2pd/TunnelConfig.cpp +++ b/libi2pd/TunnelConfig.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2021, The PurpleI2P Project +* Copyright (c) 2013-2025, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -219,6 +219,42 @@ namespace tunnel return tag; } + void LongPhonyTunnelHopConfig::CreateBuildRequestRecord (uint8_t * records, uint32_t replyMsgID) + { + uint8_t * record = records + recordIndex*TUNNEL_BUILD_RECORD_SIZE; + memcpy (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)i2p::context.GetIdentHash (), 16); + memcpy (record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, i2p::transport::transports.GetNextX25519KeysPair ()->GetPublicKey (), 32); + RAND_bytes (record + 48, TUNNEL_BUILD_RECORD_SIZE - 48); + } + + void ShortPhonyTunnelHopConfig::CreateBuildRequestRecord (uint8_t * records, uint32_t replyMsgID) + { + uint8_t * record = records + recordIndex*SHORT_TUNNEL_BUILD_RECORD_SIZE; + memcpy (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)i2p::context.GetIdentHash (), 16); + memcpy (record + SHORT_REQUEST_RECORD_ENCRYPTED_OFFSET, i2p::transport::transports.GetNextX25519KeysPair ()->GetPublicKey (), 32); + RAND_bytes (record + 48, SHORT_TUNNEL_BUILD_RECORD_SIZE - 48); + } + + TunnelConfig::TunnelConfig (const std::vector >& peers, + bool isShort, i2p::data::RouterInfo::CompatibleTransports farEndTransports): + m_IsShort (isShort), m_FarEndTransports (farEndTransports) + { + // inbound + CreatePeers (peers); + m_LastHop->SetNextIdent (i2p::context.GetIdentHash ()); + } + + TunnelConfig::TunnelConfig (const std::vector >& peers, + uint32_t replyTunnelID, const i2p::data::IdentHash& replyIdent, bool isShort, + i2p::data::RouterInfo::CompatibleTransports farEndTransports): + m_IsShort (isShort), m_FarEndTransports (farEndTransports) + { + // outbound + CreatePeers (peers); + m_FirstHop->isGateway = false; + m_LastHop->SetReplyHop (replyTunnelID, replyIdent); + } + void TunnelConfig::CreatePeers (const std::vector >& peers) { TunnelHopConfig * prev = nullptr; @@ -245,5 +281,35 @@ namespace tunnel } m_LastHop = prev; } + + void TunnelConfig::CreatePhonyHop () + { + if (m_LastHop && m_LastHop->ident) + { + TunnelHopConfig * hop = nullptr; + if (m_IsShort) + hop = new ShortPhonyTunnelHopConfig (); + else + hop = new LongPhonyTunnelHopConfig (); + if (hop) + { + hop->prev = m_LastHop; + m_LastHop->next = hop; + m_LastHop = hop; + } + } + } + + void TunnelConfig::DeletePhonyHop () + { + if (m_LastHop && !m_LastHop->ident) + { + if (m_LastHop->prev) m_LastHop->prev->next = nullptr; + else m_FirstHop = nullptr; + auto tmp = m_LastHop; + m_LastHop = m_LastHop->prev; + delete tmp; + } + } } } \ No newline at end of file diff --git a/libi2pd/TunnelConfig.h b/libi2pd/TunnelConfig.h index 718a6fdb..a024f359 100644 --- a/libi2pd/TunnelConfig.h +++ b/libi2pd/TunnelConfig.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2024, The PurpleI2P Project +* Copyright (c) 2013-2025, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -77,28 +77,35 @@ namespace tunnel uint64_t GetGarlicKey (uint8_t * key) const override; }; + struct PhonyTunnelHopConfig: public ECIESTunnelHopConfig + { + PhonyTunnelHopConfig (): ECIESTunnelHopConfig (nullptr) {} + uint8_t GetRetCode (const uint8_t * records) const override { return 0; } + bool DecryptBuildResponseRecord (uint8_t * records) const override { return true; } + void DecryptRecord (uint8_t * records, int index) const override {} // do nothing + }; + + struct LongPhonyTunnelHopConfig: public PhonyTunnelHopConfig + { + void CreateBuildRequestRecord (uint8_t * records, uint32_t replyMsgID) override; + }; + + struct ShortPhonyTunnelHopConfig: public PhonyTunnelHopConfig + { + void CreateBuildRequestRecord (uint8_t * records, uint32_t replyMsgID) override; + }; + class TunnelConfig { public: TunnelConfig (const std::vector >& peers, - bool isShort, i2p::data::RouterInfo::CompatibleTransports farEndTransports = i2p::data::RouterInfo::eAllTransports): // inbound - m_IsShort (isShort), m_FarEndTransports (farEndTransports) - { - CreatePeers (peers); - m_LastHop->SetNextIdent (i2p::context.GetIdentHash ()); - } + bool isShort, i2p::data::RouterInfo::CompatibleTransports farEndTransports = i2p::data::RouterInfo::eAllTransports); // inbound TunnelConfig (const std::vector >& peers, uint32_t replyTunnelID, const i2p::data::IdentHash& replyIdent, bool isShort, - i2p::data::RouterInfo::CompatibleTransports farEndTransports = i2p::data::RouterInfo::eAllTransports): // outbound - m_IsShort (isShort), m_FarEndTransports (farEndTransports) - { - CreatePeers (peers); - m_FirstHop->isGateway = false; - m_LastHop->SetReplyHop (replyTunnelID, replyIdent); - } - + i2p::data::RouterInfo::CompatibleTransports farEndTransports = i2p::data::RouterInfo::eAllTransports); // outbound + virtual ~TunnelConfig () { TunnelHopConfig * hop = m_FirstHop; @@ -182,6 +189,9 @@ namespace tunnel } size_t GetRecordSize () const { return m_IsShort ? SHORT_TUNNEL_BUILD_RECORD_SIZE : TUNNEL_BUILD_RECORD_SIZE; }; + + void CreatePhonyHop (); + void DeletePhonyHop (); protected: From 35ba14d06a51b50cd161f66b90eba7f44af9e1d3 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 25 May 2025 18:23:22 -0400 Subject: [PATCH 1057/1171] increase message expiration timeout in SSU2 --- libi2pd/I2NPProtocol.h | 3 ++- libi2pd/SSU2Session.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libi2pd/I2NPProtocol.h b/libi2pd/I2NPProtocol.h index 911a53bf..39aed10f 100644 --- a/libi2pd/I2NPProtocol.h +++ b/libi2pd/I2NPProtocol.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2024, The PurpleI2P Project +* Copyright (c) 2013-2025, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -155,6 +155,7 @@ namespace tunnel const unsigned int I2NP_MESSAGE_LOCAL_EXPIRATION_TIMEOUT_FACTOR = 3; // multiples of RTT const unsigned int I2NP_MESSAGE_LOCAL_EXPIRATION_TIMEOUT_MIN = 200000; // in microseconds const unsigned int I2NP_MESSAGE_LOCAL_EXPIRATION_TIMEOUT_MAX = 2000000; // in microseconds + const unsigned int I2NP_MESSAGE_LOCAL_EXPIRATION_TIMEOUT_TRANSIT = 4000000; // in microseconds const unsigned int I2NP_MESSAGE_EXPIRATION_TIMEOUT = 8000; // in milliseconds (as initial RTT) const unsigned int I2NP_MESSAGE_CLOCK_SKEW = 60*1000; // 1 minute in milliseconds diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index cb10f848..8f58ec90 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -468,7 +468,7 @@ namespace transport while (!m_SendQueue.empty () && m_SentPackets.size () <= m_WindowSize) { auto msg = m_SendQueue.front (); - if (!msg || msg->IsExpired (ts) || msg->GetEnqueueTime() + m_MsgLocalExpirationTimeout < mts) + if (!msg || msg->IsExpired (ts) || msg->GetEnqueueTime() + I2NP_MESSAGE_LOCAL_EXPIRATION_TIMEOUT_TRANSIT < mts) { // drop null or expired message if (msg) msg->Drop (); From 9573b21c082c74fe9152f943738a7885223d6d8f Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 26 May 2025 17:35:59 -0400 Subject: [PATCH 1058/1171] changed log level frm warning to info for some messages --- libi2pd/Streaming.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 4ac4e179..1f849925 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -268,7 +268,7 @@ namespace stream if (receivedSeqn <= m_LastReceivedSequenceNumber) { // we have received duplicate - LogPrint (eLogWarning, "Streaming: Duplicate message ", receivedSeqn, " on sSID=", m_SendStreamID); + LogPrint (eLogInfo, "Streaming: Duplicate message ", receivedSeqn, " on sSID=", m_SendStreamID); if (receivedSeqn <= m_PreviousReceivedSequenceNumber || receivedSeqn == m_LastReceivedSequenceNumber) { m_CurrentOutboundTunnel = m_LocalDestination.GetOwner ()->GetTunnelPool ()->GetNextOutboundTunnel (m_CurrentOutboundTunnel); @@ -287,7 +287,7 @@ namespace stream } else { - LogPrint (eLogWarning, "Streaming: Missing messages on sSID=", m_SendStreamID, ": from ", m_LastReceivedSequenceNumber + 1, " to ", receivedSeqn - 1); + LogPrint (eLogInfo, "Streaming: Missing messages on sSID=", m_SendStreamID, ": from ", m_LastReceivedSequenceNumber + 1, " to ", receivedSeqn - 1); // save message and wait for missing message again SavePacket (packet); if (m_LastReceivedSequenceNumber >= 0) @@ -1828,7 +1828,7 @@ namespace stream if (it1 != m_IncomingStreams.end ()) { // already pending - LogPrint(eLogWarning, "Streaming: Incoming streaming with rSID=", receiveStreamID, " already exists"); + LogPrint(eLogInfo, "Streaming: Incoming streaming with rSID=", receiveStreamID, " already exists"); it1->second->ResetRoutingPath (); // Ack was not delivered, changing path DeletePacket (packet); // drop it, because previous should be connected return; From 7ec0c98036fb7d4091f2a6fbc4c38f433dd8b98c Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 28 May 2025 06:39:39 -0400 Subject: [PATCH 1059/1171] fixed newkeys crash --- libi2pd/Identity.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Identity.cpp b/libi2pd/Identity.cpp index 865beeb8..240862ae 100644 --- a/libi2pd/Identity.cpp +++ b/libi2pd/Identity.cpp @@ -496,7 +496,7 @@ namespace data m_Public = std::make_shared(Identity (keys)); memcpy (m_PrivateKey, keys.privateKey, 256); // 256 size_t keyLen = m_Public->GetSigningPrivateKeyLen (); - if (keyLen > 128) m_SigningPrivateKey.resize (keyLen); + m_SigningPrivateKey.resize (keyLen); memcpy (m_SigningPrivateKey.data (), keys.signingPrivateKey, keyLen); m_OfflineSignature.resize (0); m_TransientSignatureLen = 0; From 1b068618bab95a0309012cc25264e01c6171fa22 Mon Sep 17 00:00:00 2001 From: nobs2p Date: Thu, 29 May 2025 12:33:48 +0300 Subject: [PATCH 1060/1171] Add settunneltype parameter to BOB API for i2pd to configure proxy tunnel type This update introduces the settunneltype command to the BOB API, allowing users to specify the tunnel type as either SOCKS or HTTP proxy. When the tunnel type is set, the corresponding proxy service is automatically started. This enhances flexibility in tunnel configuration through the BOB interface. Signed-off-by: nobs2p --- libi2pd_client/BOB.cpp | 119 ++++++++++++++++++++++++++++++++++++++--- libi2pd_client/BOB.h | 18 +++++++ 2 files changed, 131 insertions(+), 6 deletions(-) diff --git a/libi2pd_client/BOB.cpp b/libi2pd_client/BOB.cpp index 8d94e94b..3f02f779 100644 --- a/libi2pd_client/BOB.cpp +++ b/libi2pd_client/BOB.cpp @@ -383,6 +383,15 @@ namespace client const auto destExists = [](const BOBDestination * const dest) { return dest != nullptr; }; const auto destReady = [](const BOBDestination * const dest) { return dest && dest->IsRunning(); }; const auto bool_str = [](const bool v) { return v ? "true" : "false"; }; // bool -> str + const auto getProxyType = [](const i2p::client::I2PService* proxy) -> std::string { + if (!proxy) return "NONE"; + if (dynamic_cast(proxy)) return "SOCKS"; + if (dynamic_cast(proxy)) return "HTTPPROXY"; + return "UNKNOWN"; + }; + const auto isProxyRunning = [](const i2p::client::I2PService* proxy) -> bool { + return proxy != nullptr; + }; // tunnel info const std::string nickname = currentTunnel ? m_Nickname : dest->GetNickname(); @@ -395,6 +404,10 @@ namespace client const bool starting = destExists(dest.get ()) && !destReady(dest.get ()); const bool running = destExists(dest.get ()) && destReady(dest.get ()); const bool stopping = false; + + const i2p::client::I2PService* proxy = m_Owner.GetProxy(nickname); + const std::string proxyType = getProxyType(proxy); + const bool proxyStatus = isProxyRunning(proxy); // build line std::stringstream ss; @@ -403,7 +416,8 @@ namespace client << "RUNNING: " << bool_str(running) << " " << "STOPPING: " << bool_str(stopping) << " " << "KEYS: " << bool_str(keys) << " " << "QUIET: " << bool_str(quiet) << " " << "INPORT: " << inport << " " << "INHOST: " << inhost << " " - << "OUTPORT: " << outport << " " << "OUTHOST: " << outhost; + << "OUTPORT: " << outport << " " << "OUTHOST: " << outhost << " " + << "PROXYTYPE: "<< proxyType << " " << "PROXYSTART: " << bool_str(proxyStatus); out = ss.str(); } @@ -468,11 +482,51 @@ namespace client m_Nickname, m_InHost, m_OutHost, m_InPort, m_OutPort, m_IsQuiet); m_Owner.AddDestination (m_Nickname, m_CurrentDestination); } - if (m_InPort) - m_CurrentDestination->CreateInboundTunnel (m_InPort, m_InHost); - if (m_OutPort && !m_OutHost.empty ()) - m_CurrentDestination->CreateOutboundTunnel (m_OutHost, m_OutPort, m_IsQuiet); - m_CurrentDestination->Start (); + if (!m_tunnelType.has_value()) + { + if (m_InPort) + m_CurrentDestination->CreateInboundTunnel (m_InPort, m_InHost); + if (m_OutPort && !m_OutHost.empty ()) + m_CurrentDestination->CreateOutboundTunnel (m_OutHost, m_OutPort, m_IsQuiet); + m_CurrentDestination->Start (); + } + else + { + switch (*m_tunnelType) + { + case TunnelType::SOCKS: + try + { + auto SocksProxy = std::make_unique(m_Nickname, m_InHost, m_InPort, + false, m_OutHost, m_OutPort, m_CurrentDestination->GetLocalDestination()); + SocksProxy->Start(); + m_Owner.SetProxy(m_Nickname, std::move(SocksProxy)); + } + catch (std::exception& e) + { + LogPrint(eLogCritical, "Clients: Exception in SOCKS Proxy: ", e.what()); + ThrowFatal ("Unable to start SOCKS Proxy at ", m_InHost, ":", m_InPort, ": ", e.what ()); + } + break; + case TunnelType::HTTP_PROXY: + try + { + auto HttpProxy = std::make_unique(m_Nickname, m_InHost, m_InPort, + m_OutHost, true, true, m_CurrentDestination->GetLocalDestination()); + HttpProxy->Start(); + m_Owner.SetProxy(m_Nickname, std::move(HttpProxy)); + } + catch (std::exception& e) + { + LogPrint(eLogCritical, "Clients: Exception in HTTP Proxy: ", e.what()); + ThrowFatal ("Unable to start HTTP Proxy at ", m_InHost, ":", m_InPort, ": ", e.what ()); + } + break; + default: + SendReplyError("Unsupported tunnel type."); + return; + } + } SendReplyOK ("Tunnel starting"); m_IsActive = true; } @@ -486,10 +540,15 @@ namespace client return; } auto dest = m_Owner.FindDestination (m_Nickname); + auto proxy = m_Owner.GetProxy (m_Nickname); if (dest) { dest->StopTunnels (); SendReplyOK ("Tunnel stopping"); + if (proxy) + { + m_Owner.RemoveProxy (m_Nickname); + } } else SendReplyError ("tunnel not found"); @@ -522,10 +581,13 @@ namespace client if(*operand) { m_CurrentDestination = m_Owner.FindDestination (operand); + auto proxy = m_Owner.GetProxy (operand); if (m_CurrentDestination) { m_Keys = m_CurrentDestination->GetKeys (); m_IsActive = m_CurrentDestination->IsRunning (); + if(proxy) + m_IsActive = true; m_Nickname = operand; } if (m_Nickname == operand) @@ -843,6 +905,27 @@ namespace client SendReplyError("No such command"); } } + + void BOBCommandSession::SetTunnelTypeCommandHandler (const char * operand, size_t len) + { + std::string_view sv(operand, len); + LogPrint (eLogDebug, "BOB: settunneltype ", operand); + if (sv == "socks") + { + m_tunnelType = TunnelType::SOCKS; + SendReplyOK ("tunnel type set to SOCKS"); + } + else if (sv == "httpproxy") + { + m_tunnelType = TunnelType::HTTP_PROXY; + SendReplyOK ("tunnel type set to HTTP proxy"); + } + else + { + m_tunnelType.reset(); + SendReplyError ("no tunnel type has been set"); + } + } BOBCommandChannel::BOBCommandChannel (const std::string& address, uint16_t port): RunnableService ("BOB"), @@ -871,6 +954,7 @@ namespace client m_CommandHandlers[BOB_COMMAND_OPTION] = &BOBCommandSession::OptionCommandHandler; m_CommandHandlers[BOB_COMMAND_STATUS] = &BOBCommandSession::StatusCommandHandler; m_CommandHandlers[BOB_COMMAND_HELP] = &BOBCommandSession::HelpCommandHandler; + m_CommandHandlers[BOB_COMMAND_SETTUNNELTYPE] = &BOBCommandSession::SetTunnelTypeCommandHandler; // command -> help string m_HelpStrings[BOB_COMMAND_ZAP] = BOB_HELP_ZAP; m_HelpStrings[BOB_COMMAND_QUIT] = BOB_HELP_QUIT; @@ -893,6 +977,7 @@ namespace client m_HelpStrings[BOB_COMMAND_OPTION] = BOB_HELP_OPTION; m_HelpStrings[BOB_COMMAND_STATUS] = BOB_HELP_STATUS; m_HelpStrings[BOB_COMMAND_HELP] = BOB_HELP_HELP; + m_HelpStrings[BOB_COMMAND_SETTUNNELTYPE] = BOB_HELP_SETTUNNELTYPE; } BOBCommandChannel::~BOBCommandChannel () @@ -937,6 +1022,28 @@ namespace client return it->second; return nullptr; } + + void BOBCommandChannel::SetProxy (const std::string& name, std::unique_ptr proxy) + { + m_proxy[name] = std::move(proxy); + } + + const I2PService* BOBCommandChannel::GetProxy(const std::string& name) const + { + auto it = m_proxy.find(name); + if (it != m_proxy.end() && it->second) + return it->second.get(); + return nullptr; + } + + void BOBCommandChannel::RemoveProxy(const std::string& name) + { + auto it = m_proxy.find (name); + if (it != m_proxy.end ()) + { + m_proxy.erase (it); + } + } void BOBCommandChannel::Accept () { diff --git a/libi2pd_client/BOB.h b/libi2pd_client/BOB.h index f5aefd0a..7b92c85d 100644 --- a/libi2pd_client/BOB.h +++ b/libi2pd_client/BOB.h @@ -14,12 +14,15 @@ #include #include #include +#include #include #include "util.h" #include "I2PTunnel.h" #include "I2PService.h" #include "Identity.h" #include "LeaseSet.h" +#include "SOCKS.h" +#include "HTTPProxy.h" namespace i2p { @@ -48,7 +51,9 @@ namespace client const char BOB_COMMAND_OPTION[] = "option"; const char BOB_COMMAND_STATUS[] = "status"; const char BOB_COMMAND_HELP[] = "help"; + const char BOB_COMMAND_SETTUNNELTYPE[] = "settunneltype"; + const char BOB_HELP_ZAP[] = "zap - Shuts down BOB."; const char BOB_HELP_QUIT[] = "quit - Quits this session with BOB."; const char BOB_HELP_START[] = "start - Starts the current nicknamed tunnel."; @@ -70,6 +75,7 @@ namespace client const char BOB_HELP_OPTION[] = "option = - Set an option. NOTE: Don't use any spaces."; const char BOB_HELP_STATUS[] = "status - Display status of a nicknamed tunnel."; const char BOB_HELP_HELP [] = "help - Get help on a command."; + const char BOB_HELP_SETTUNNELTYPE[] = "settunneltype - Sets socks or http proxy tunnel type."; class BOBI2PTunnelIncomingConnection: public I2PTunnelConnection { @@ -232,6 +238,7 @@ namespace client void OptionCommandHandler (const char * operand, size_t len); void StatusCommandHandler (const char * operand, size_t len); void HelpCommandHandler (const char * operand, size_t len); + void SetTunnelTypeCommandHandler (const char * operand, size_t len); private: @@ -258,6 +265,13 @@ namespace client i2p::data::PrivateKeys m_Keys; std::map m_Options; std::shared_ptr m_CurrentDestination; + + enum class TunnelType + { + SOCKS = 0, + HTTP_PROXY = 1 + }; + std::optional m_tunnelType; }; typedef void (BOBCommandSession::*BOBCommandHandler)(const char * operand, size_t len); @@ -275,6 +289,9 @@ namespace client void AddDestination (const std::string& name, std::shared_ptr dest); void DeleteDestination (const std::string& name); std::shared_ptr FindDestination (const std::string& name); + void SetProxy (const std::string& name, std::unique_ptr proxy); + const I2PService* GetProxy(const std::string& name) const; + void RemoveProxy(const std::string& name); private: @@ -287,6 +304,7 @@ namespace client std::map > m_Destinations; std::map m_CommandHandlers; std::map m_HelpStrings; + std::map> m_proxy; public: From 021431d97a70589b9cc352aff0494fb17266ed8d Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 1 Jun 2025 08:40:44 -0400 Subject: [PATCH 1061/1171] disable post-quantum for release --- libi2pd/Crypto.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index 125a217c..80650098 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -33,9 +33,9 @@ # if (!defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER != 0x030000000)) // 3.0.0, regression in SipHash, not implemented in LibreSSL # define OPENSSL_SIPHASH 1 # endif -# if (OPENSSL_VERSION_NUMBER >= 0x030500000) // 3.5.0 -# define OPENSSL_PQ 1 -# endif +//# if (OPENSSL_VERSION_NUMBER >= 0x030500000) // 3.5.0 +//# define OPENSSL_PQ 1 +//# endif #endif namespace i2p From 56bd94a1cb700a99c0ca48a5ee2f2a4bf1ddb583 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 1 Jun 2025 08:41:20 -0400 Subject: [PATCH 1062/1171] 2.57.0 --- ChangeLog | 28 ++++++++++++++++++++++++++++ contrib/rpm/i2pd-git.spec | 5 ++++- contrib/rpm/i2pd.spec | 5 ++++- debian/changelog | 6 ++++++ libi2pd/version.h | 4 ++-- 5 files changed, 44 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 23864c0e..e8d6daf7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,34 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog +## [2.57.0] - 2025-06-02 +### Added +- Local domain sockets for I2PControl +- "keys=shareddest" tunnel param to run on shared local destination +- HTTP and SOCKS proxy through BOB +- Localization to Hebrew and Hindi +- NTCP2 probing resistance +- Support SAM v1 datagram sessions without port +- OpenIndiana support +### Changed +- Don't request LeaseSet until I2CP destination is ready +- Keep receiving new data from I2PTunnel/SAM socket while previous is being sent to stream +- Insert phony record to inbound tunnel build message with real x25519 ephemeral key +- Set min peer test version to 0.9.62 +- Increase I2NP message expiration timeout in SSU2 +- Cleanup ECIESx25519 new session reply keys on Alice side +- Reduced router profile persist interval to 22 minutes +- SSU2 max padding size to 32 bytes +- Send SSU2 path challenge of 8 bytes. Add datetime and address blocks +- Don't delete trusted routers from netdb +- Disable loss-control in streaming +- Reseeds list +### Fixed +- Crash after SAM stream disconnect +- FORWARD session host handling in SAM +- x86 build for Haiku +- SSU2 session's remote endpoint after receiving path response + ## [2.56.0] - 2025-02-11 ### Added - Config params for shared local destination diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index 2083ba18..fd431347 100644 --- a/contrib/rpm/i2pd-git.spec +++ b/contrib/rpm/i2pd-git.spec @@ -1,7 +1,7 @@ %define git_hash %(git rev-parse HEAD | cut -c -7) Name: i2pd-git -Version: 2.56.0 +Version: 2.57.0 Release: git%{git_hash}%{?dist} Summary: I2P router written in C++ Conflicts: i2pd @@ -148,6 +148,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Mon Jun 02 2025 orignal - 2.57.0 +- update to 2.57.0 + * Tue Feb 11 2025 orignal - 2.56.0 - update to 2.56.0 diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 4eb558ba..2d3d4cbb 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,5 +1,5 @@ Name: i2pd -Version: 2.56.0 +Version: 2.57.0 Release: 1%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git @@ -146,6 +146,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Mon Jun 02 2025 orignal - 2.57.0 +- update to 2.57.0 + * Tue Feb 11 2025 orignal - 2.56.0 - update to 2.56.0 diff --git a/debian/changelog b/debian/changelog index d170f534..8b1e6237 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i2pd (2.57.0-1) unstable; urgency=medium + + * updated to version 2.57.0/0.9.66 + + -- orignal Mon, 02 Jun 2025 16:00:00 +0000 + i2pd (2.56.0-1) unstable; urgency=medium * updated to version 2.56.0/0.9.65 diff --git a/libi2pd/version.h b/libi2pd/version.h index 1e63ae08..45f209ac 100644 --- a/libi2pd/version.h +++ b/libi2pd/version.h @@ -18,7 +18,7 @@ #define MAKE_VERSION_NUMBER(a,b,c) ((a*100+b)*100+c) #define I2PD_VERSION_MAJOR 2 -#define I2PD_VERSION_MINOR 56 +#define I2PD_VERSION_MINOR 57 #define I2PD_VERSION_MICRO 0 #define I2PD_VERSION_PATCH 0 #ifdef GITVER @@ -33,7 +33,7 @@ #define I2P_VERSION_MAJOR 0 #define I2P_VERSION_MINOR 9 -#define I2P_VERSION_MICRO 65 +#define I2P_VERSION_MICRO 66 #define I2P_VERSION_PATCH 0 #define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO) #define I2P_VERSION_NUMBER MAKE_VERSION_NUMBER(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO) From 37fd4b4422cc0c1fbe8321d4de9fcaaff2220cdc Mon Sep 17 00:00:00 2001 From: Daniel Bermond Date: Mon, 2 Jun 2025 23:28:51 -0300 Subject: [PATCH 1063/1171] tests: fix test-base-64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit test-base-64 was not updated after the following commits: https://github.com/PurpleI2P/i2pd/commit/93cc810f2987cc90b7a4f8699655af43b36c6c23 https://github.com/PurpleI2P/i2pd/commit/bbf5c1655a5f331b36cc7e16ad0bba86bb36eed4 This leads to errors like: In file included from /usr/include/c++/15.1.1/cassert:46, from /build/i2pd/src/i2pd-2.57.0/tests/test-base-64.cpp:1: /build/i2pd/src/i2pd-2.57.0/tests/test-base-64.cpp: In function ‘int main()’: /build/i2pd/src/i2pd-2.57.0/tests/test-base-64.cpp:14:28: error: too many arguments to function ‘std::string i2p::data::ByteStreamToBase64(const uint8_t*, size_t)’ 14 | assert(ByteStreamToBase64(NULL, 0, NULL, 0) == 0); | ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~ and: In file included from /build/i2pd/src/i2pd-2.57.0/tests/test-base-64.cpp:4: /build/i2pd/src/i2pd-2.57.0/build/../libi2pd/Base.h:21:21: note: declared here 21 | std::string ByteStreamToBase64 (const uint8_t * InBuffer, size_t InCount); | ^~~~~~~~~~~~~~~~~~ /build/i2pd/src/i2pd-2.57.0/tests/test-base-64.cpp:14:47: error: no match for ‘operator==’ (operand types are ‘std::string’ {aka ‘std::__cxx11::basic_string’} and ‘int’) 14 | assert(ByteStreamToBase64(NULL, 0, NULL, 0) == 0); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^~ ~ | | | | | int | std::string {aka std::__cxx11::basic_string} among others. --- tests/test-base-64.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/test-base-64.cpp b/tests/test-base-64.cpp index 0ab46c06..63817bf4 100644 --- a/tests/test-base-64.cpp +++ b/tests/test-base-64.cpp @@ -11,8 +11,7 @@ int main() { char out[16]; /* bytes -> b64 */ - assert(ByteStreamToBase64(NULL, 0, NULL, 0) == 0); - assert(ByteStreamToBase64(NULL, 0, out, sizeof(out)) == 0); + assert(ByteStreamToBase64(NULL, 0) == ""); assert(Base64EncodingBufferSize(2) == 4); assert(Base64EncodingBufferSize(4) == 8); @@ -23,19 +22,20 @@ int main() { assert(Base64EncodingBufferSize(12) == 16); assert(Base64EncodingBufferSize(13) == 20); - assert(ByteStreamToBase64((uint8_t *) in, in_len, out, sizeof(out)) == 8); - assert(memcmp(out, "dGVzdA==", 8) == 0); + const std::string out_str(ByteStreamToBase64((uint8_t *) in, in_len)); + assert(out_str.size() == 8); + assert(out_str == "dGVzdA=="); /* b64 -> bytes */ - assert(Base64ToByteStream(NULL, 0, NULL, 0) == 0); - assert(Base64ToByteStream(NULL, 0, (uint8_t *) out, sizeof(out)) == 0); + assert(Base64ToByteStream("", NULL, 0) == 0); + assert(Base64ToByteStream("", (uint8_t *) out, sizeof(out)) == 0); in = "dGVzdA=="; /* valid b64 */ - assert(Base64ToByteStream(in, strlen(in), (uint8_t *) out, sizeof(out)) == 4); + assert(Base64ToByteStream(in, (uint8_t *) out, sizeof(out)) == 4); assert(memcmp(out, "test", 4) == 0); in = "dGVzdA="; /* invalid b64 : not padded */ - assert(Base64ToByteStream(in, strlen(in), (uint8_t *) out, sizeof(out)) == 0); + assert(Base64ToByteStream(in, (uint8_t *) out, sizeof(out)) == 0); in = "dG/z.A=="; /* invalid b64 : char not from alphabet */ // assert(Base64ToByteStream(in, strlen(in), (uint8_t *) out, sizeof(out)) == 0); From 2631255b467760d978f3cbd02e1d65e902b9e378 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 3 Jun 2025 07:57:08 -0400 Subject: [PATCH 1064/1171] enable post quantum back --- libi2pd/Crypto.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index 80650098..125a217c 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -33,9 +33,9 @@ # if (!defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER != 0x030000000)) // 3.0.0, regression in SipHash, not implemented in LibreSSL # define OPENSSL_SIPHASH 1 # endif -//# if (OPENSSL_VERSION_NUMBER >= 0x030500000) // 3.5.0 -//# define OPENSSL_PQ 1 -//# endif +# if (OPENSSL_VERSION_NUMBER >= 0x030500000) // 3.5.0 +# define OPENSSL_PQ 1 +# endif #endif namespace i2p From 6ad6a2501eac86623db303bceee70a1989e538e6 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 3 Jun 2025 07:58:31 -0400 Subject: [PATCH 1065/1171] fixed incorrect limit in strsplit --- libi2pd/HTTP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/HTTP.cpp b/libi2pd/HTTP.cpp index 3cd5c193..8c7c8491 100644 --- a/libi2pd/HTTP.cpp +++ b/libi2pd/HTTP.cpp @@ -55,7 +55,7 @@ namespace http static void strsplit(std::string_view line, std::vector &tokens, char delim, std::size_t limit = 0) { - size_t count = 0, pos; + size_t count = 1, pos; while ((pos = line.find (delim)) != line.npos) { count++; From cbb5250dd4f929f9b0f408186b4d74b745e7d49a Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 3 Jun 2025 18:46:22 -0400 Subject: [PATCH 1066/1171] don't schedule resend timer while choked --- libi2pd/Streaming.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 1f849925..8d125e6f 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -1416,6 +1416,7 @@ namespace stream m_SendTimer.cancel (); // if no ack's in RTO, disable fast retransmit m_IsTimeOutResend = true; m_IsNAcked = false; + m_IsClientChoked = false; m_IsResendNeeded = false; m_NumPacketsToSend = 1; ResendPacket (); // send one packet per RTO, waiting for ack @@ -1538,7 +1539,7 @@ namespace stream } else if (!m_IsClientChoked) SendBuffer (); - if (!m_IsNAcked && !m_IsResendNeeded) ScheduleResend (); + if (!m_IsNAcked && !m_IsResendNeeded && !m_IsClientChoked) ScheduleResend (); if (m_IsClientChoked) ScheduleSend (); } From 9c0051e73b9f56013ea613af621a53eab47d6ae5 Mon Sep 17 00:00:00 2001 From: r4sas Date: Wed, 4 Jun 2025 13:49:44 +0300 Subject: [PATCH 1067/1171] [rpm] fix build on centos 10, drop 7th support Signed-off-by: r4sas --- contrib/rpm/i2pd-git.spec | 34 +++++++++++----------------------- contrib/rpm/i2pd.spec | 34 +++++++++++----------------------- 2 files changed, 22 insertions(+), 46 deletions(-) diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index fd431347..d9393f47 100644 --- a/contrib/rpm/i2pd-git.spec +++ b/contrib/rpm/i2pd-git.spec @@ -10,11 +10,7 @@ License: BSD URL: https://github.com/PurpleI2P/i2pd Source0: https://github.com/PurpleI2P/i2pd/archive/openssl/i2pd-openssl.tar.gz -%if 0%{?rhel} == 7 -BuildRequires: cmake3 -%else BuildRequires: cmake -%endif BuildRequires: chrpath BuildRequires: gcc-c++ @@ -43,26 +39,18 @@ C++ implementation of I2P. %build cd build -%if 0%{?rhel} == 7 - %cmake3 \ - -DWITH_LIBRARY=OFF \ - -DWITH_UPNP=ON \ - -DWITH_HARDENING=ON \ - -DBUILD_SHARED_LIBS:BOOL=OFF +%cmake \ + -DWITH_LIBRARY=OFF \ + -DWITH_UPNP=ON \ + -DWITH_HARDENING=ON \ +%if 0%{?fedora} > 29 + -DBUILD_SHARED_LIBS:BOOL=OFF \ + . %else - %cmake \ - -DWITH_LIBRARY=OFF \ - -DWITH_UPNP=ON \ - -DWITH_HARDENING=ON \ - %if 0%{?fedora} > 29 - -DBUILD_SHARED_LIBS:BOOL=OFF \ - . - %else - -DBUILD_SHARED_LIBS:BOOL=OFF - %endif + -DBUILD_SHARED_LIBS:BOOL=OFF %endif -%if 0%{?rhel} == 9 || 0%{?fedora} >= 35 || 0%{?eln} +%if 0%{?rhel} >= 9 || 0%{?fedora} >= 35 || 0%{?eln} pushd redhat-linux-build %else %if 0%{?fedora} >= 33 @@ -76,7 +64,7 @@ cd build make %{?_smp_mflags} -%if 0%{?rhel} == 9 || 0%{?fedora} >= 33 || 0%{?mageia} > 7 +%if 0%{?rhel} >= 9 || 0%{?fedora} >= 33 || 0%{?mageia} > 7 popd %endif @@ -84,7 +72,7 @@ make %{?_smp_mflags} %install pushd build -%if 0%{?rhel} == 9 || 0%{?fedora} >= 35 || 0%{?eln} +%if 0%{?rhel} >= 9 || 0%{?fedora} >= 35 || 0%{?eln} pushd redhat-linux-build %else %if 0%{?fedora} >= 33 diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 2d3d4cbb..e094c3b7 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -8,11 +8,7 @@ License: BSD URL: https://github.com/PurpleI2P/i2pd Source0: https://github.com/PurpleI2P/i2pd/archive/%{version}/%name-%version.tar.gz -%if 0%{?rhel} == 7 -BuildRequires: cmake3 -%else BuildRequires: cmake -%endif BuildRequires: chrpath BuildRequires: gcc-c++ @@ -41,26 +37,18 @@ C++ implementation of I2P. %build cd build -%if 0%{?rhel} == 7 - %cmake3 \ - -DWITH_LIBRARY=OFF \ - -DWITH_UPNP=ON \ - -DWITH_HARDENING=ON \ - -DBUILD_SHARED_LIBS:BOOL=OFF +%cmake \ + -DWITH_LIBRARY=OFF \ + -DWITH_UPNP=ON \ + -DWITH_HARDENING=ON \ +%if 0%{?fedora} > 29 + -DBUILD_SHARED_LIBS:BOOL=OFF \ + . %else - %cmake \ - -DWITH_LIBRARY=OFF \ - -DWITH_UPNP=ON \ - -DWITH_HARDENING=ON \ - %if 0%{?fedora} > 29 - -DBUILD_SHARED_LIBS:BOOL=OFF \ - . - %else - -DBUILD_SHARED_LIBS:BOOL=OFF - %endif + -DBUILD_SHARED_LIBS:BOOL=OFF %endif -%if 0%{?rhel} == 9 || 0%{?fedora} >= 35 || 0%{?eln} +%if 0%{?rhel} >= 9 || 0%{?fedora} >= 35 || 0%{?eln} pushd redhat-linux-build %else %if 0%{?fedora} >= 33 @@ -74,7 +62,7 @@ cd build make %{?_smp_mflags} -%if 0%{?rhel} == 9 || 0%{?fedora} >= 33 || 0%{?mageia} > 7 +%if 0%{?rhel} >= 9 || 0%{?fedora} >= 33 || 0%{?mageia} > 7 popd %endif @@ -82,7 +70,7 @@ make %{?_smp_mflags} %install pushd build -%if 0%{?rhel} == 9 || 0%{?fedora} >= 35 || 0%{?eln} +%if 0%{?rhel} >= 9 || 0%{?fedora} >= 35 || 0%{?eln} pushd redhat-linux-build %else %if 0%{?fedora} >= 33 From 6363c9202f2e4816215e89548123f3aaee9f73c9 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 7 Jun 2025 11:28:21 -0400 Subject: [PATCH 1068/1171] drop crypto types higher than ours --- libi2pd/LeaseSet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index fc0e722d..bf07924f 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -417,7 +417,7 @@ namespace data if (keyType <= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) // skip PQ keys if not supported #endif { - if (keyType == preferredKeyType || !m_Encryptor || keyType > m_EncryptionType) + if (keyType == preferredKeyType || !m_Encryptor || (keyType > m_EncryptionType && keyType < preferredKeyType)) { auto encryptor = i2p::data::IdentityEx::CreateEncryptor (keyType, buf + offset); if (encryptor) From 9c393f50da3a8cb1d51af5992d302452d10c2d1a Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 7 Jun 2025 12:06:47 -0400 Subject: [PATCH 1069/1171] drop crypto types higher than ours --- libi2pd/LeaseSet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index bf07924f..eb337b63 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -417,7 +417,7 @@ namespace data if (keyType <= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) // skip PQ keys if not supported #endif { - if (keyType == preferredKeyType || !m_Encryptor || (keyType > m_EncryptionType && keyType < preferredKeyType)) + if (keyType <= preferredKeyType && (!m_Encryptor || keyType > m_EncryptionType)) { auto encryptor = i2p::data::IdentityEx::CreateEncryptor (keyType, buf + offset); if (encryptor) From ba0352e9a04e504529ab7ce0a7e40362543463de Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 7 Jun 2025 20:52:35 -0400 Subject: [PATCH 1070/1171] check for compatibility of LeaseSet encryption keys with local destination's encryption type --- daemon/HTTPServer.cpp | 2 +- libi2pd/Destination.cpp | 9 +++++---- libi2pd/LeaseSet.cpp | 33 +++++++++++++++++++-------------- libi2pd/LeaseSet.h | 30 +++++++++++++++++------------- libi2pd/NetDb.cpp | 2 +- 5 files changed, 43 insertions(+), 33 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index be1ec4ac..167b8c95 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -661,7 +661,7 @@ namespace http { else { ls.reset (new i2p::data::LeaseSet2 (storeType)); - ls->Update (leaseSet->GetBuffer(), leaseSet->GetBufferLen(), false); + ls->Update (leaseSet->GetBuffer(), leaseSet->GetBufferLen(), nullptr, false); } if (!ls) return; s << "
second; if (leaseSet->IsNewer (buf + offset, len - offset)) { - leaseSet->Update (buf + offset, len - offset); + leaseSet->Update (buf + offset, len - offset, shared_from_this(), true); if (leaseSet->IsValid () && leaseSet->GetIdentHash () == key && !leaseSet->IsExpired ()) LogPrint (eLogDebug, "Destination: Remote LeaseSet updated"); else @@ -471,7 +471,8 @@ namespace client else { leaseSet = std::make_shared (buf[DATABASE_STORE_TYPE_OFFSET], - buf + offset, len - offset, true, from ? from->GetRemoteStaticKeyType () : GetPreferredCryptoType () ); // LeaseSet2 + buf + offset, len - offset, true, shared_from_this (), + from ? from->GetRemoteStaticKeyType () : GetPreferredCryptoType () ); // LeaseSet2 if (from) { uint8_t pub[32]; @@ -511,8 +512,8 @@ namespace client if (request->requestedBlindedKey) { auto ls2 = std::make_shared (buf + offset, len - offset, - request->requestedBlindedKey, m_LeaseSetPrivKey ? ((const uint8_t *)*m_LeaseSetPrivKey) : nullptr, - GetPreferredCryptoType ()); + request->requestedBlindedKey, shared_from_this (), + m_LeaseSetPrivKey ? ((const uint8_t *)*m_LeaseSetPrivKey) : nullptr, GetPreferredCryptoType ()); if (ls2->IsValid () && !ls2->IsExpired ()) { leaseSet = ls2; diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index eb337b63..3001bdfb 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -36,7 +36,7 @@ namespace data ReadFromBuffer (); } - void LeaseSet::Update (const uint8_t * buf, size_t len, bool verifySignature) + void LeaseSet::Update (const uint8_t * buf, size_t len, std::shared_ptr dest, bool verifySignature) { SetBuffer (buf, len); ReadFromBuffer (false, verifySignature); @@ -281,28 +281,29 @@ namespace data LogPrint (eLogError, "LeaseSet2: Actual buffer size ", int(len) , " exceeds full buffer size ", int(m_BufferLen)); } - LeaseSet2::LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases, CryptoKeyType preferredCrypto): + LeaseSet2::LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, + bool storeLeases, std::shared_ptr dest, CryptoKeyType preferredCrypto): LeaseSet (storeLeases), m_StoreType (storeType), m_EncryptionType (preferredCrypto) { SetBuffer (buf, len); if (storeType == NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) - ReadFromBufferEncrypted (buf, len, nullptr, nullptr); + ReadFromBufferEncrypted (buf, len, nullptr, dest, nullptr); else - ReadFromBuffer (buf, len); + ReadFromBuffer (buf, len, dest); } LeaseSet2::LeaseSet2 (const uint8_t * buf, size_t len, std::shared_ptr key, - const uint8_t * secret, CryptoKeyType preferredCrypto): + std::shared_ptr dest, const uint8_t * secret, CryptoKeyType preferredCrypto): LeaseSet (true), m_StoreType (NETDB_STORE_TYPE_ENCRYPTED_LEASESET2), m_EncryptionType (preferredCrypto) { - ReadFromBufferEncrypted (buf, len, key, secret); + ReadFromBufferEncrypted (buf, len, key, dest, secret); } - void LeaseSet2::Update (const uint8_t * buf, size_t len, bool verifySignature) + void LeaseSet2::Update (const uint8_t * buf, size_t len, std::shared_ptr dest, bool verifySignature) { SetBuffer (buf, len); if (GetStoreType () != NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) - ReadFromBuffer (buf, len, false, verifySignature); + ReadFromBuffer (buf, len, dest, false, verifySignature); // TODO: implement encrypted } @@ -312,7 +313,8 @@ namespace data return ExtractPublishedTimestamp (buf, len, expiration) > m_PublishedTimestamp; } - void LeaseSet2::ReadFromBuffer (const uint8_t * buf, size_t len, bool readIdentity, bool verifySignature) + void LeaseSet2::ReadFromBuffer (const uint8_t * buf, size_t len, std::shared_ptr dest, + bool readIdentity, bool verifySignature) { // standard LS2 header std::shared_ptr identity; @@ -350,7 +352,7 @@ namespace data switch (m_StoreType) { case NETDB_STORE_TYPE_STANDARD_LEASESET2: - s = ReadStandardLS2TypeSpecificPart (buf + offset, len - offset); + s = ReadStandardLS2TypeSpecificPart (buf + offset, len - offset, dest); break; case NETDB_STORE_TYPE_META_LEASESET2: s = ReadMetaLS2TypeSpecificPart (buf + offset, len - offset); @@ -392,7 +394,8 @@ namespace data return verified; } - size_t LeaseSet2::ReadStandardLS2TypeSpecificPart (const uint8_t * buf, size_t len) + size_t LeaseSet2::ReadStandardLS2TypeSpecificPart (const uint8_t * buf, size_t len, + std::shared_ptr dest) { size_t offset = 0; // properties @@ -417,7 +420,8 @@ namespace data if (keyType <= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) // skip PQ keys if not supported #endif { - if (keyType <= preferredKeyType && (!m_Encryptor || keyType > m_EncryptionType)) + if ((keyType == preferredKeyType || !m_Encryptor || keyType > m_EncryptionType) && + (!dest || dest->SupportsEncryptionType (keyType))) { auto encryptor = i2p::data::IdentityEx::CreateEncryptor (keyType, buf + offset); if (encryptor) @@ -498,7 +502,8 @@ namespace data return offset; } - void LeaseSet2::ReadFromBufferEncrypted (const uint8_t * buf, size_t len, std::shared_ptr key, const uint8_t * secret) + void LeaseSet2::ReadFromBufferEncrypted (const uint8_t * buf, size_t len, + std::shared_ptr key, std::shared_ptr dest, const uint8_t * secret) { size_t offset = 0; // blinded key @@ -601,7 +606,7 @@ namespace data m_StoreType = innerPlainText[0]; SetBuffer (innerPlainText.data () + 1, lenInnerPlaintext - 1); // parse and verify Layer 2 - ReadFromBuffer (innerPlainText.data () + 1, lenInnerPlaintext - 1); + ReadFromBuffer (innerPlainText.data () + 1, lenInnerPlaintext - 1, dest); } else LogPrint (eLogError, "LeaseSet2: Unexpected LeaseSet type ", (int)innerPlainText[0], " inside encrypted LeaseSet"); diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index f5197eb5..f6f5f6da 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -76,7 +76,7 @@ namespace data LeaseSet (const uint8_t * buf, size_t len, bool storeLeases = true); virtual ~LeaseSet () { delete[] m_EncryptionKey; delete[] m_Buffer; }; - virtual void Update (const uint8_t * buf, size_t len, bool verifySignature = true); + virtual void Update (const uint8_t * buf, size_t len, std::shared_ptr dest, bool verifySignature); virtual bool IsNewer (const uint8_t * buf, size_t len) const; void PopulateLeases (); // from buffer @@ -155,15 +155,17 @@ namespace data public: LeaseSet2 (uint8_t storeType): LeaseSet (true), m_StoreType (storeType) {}; // for update - LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases = true, CryptoKeyType preferredCrypto = CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); - LeaseSet2 (const uint8_t * buf, size_t len, std::shared_ptr key, const uint8_t * secret = nullptr, CryptoKeyType preferredCrypto = CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); // store type 5, called from local netdb only - uint8_t GetStoreType () const { return m_StoreType; }; - uint32_t GetPublishedTimestamp () const { return m_PublishedTimestamp; }; + LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases = true, + std::shared_ptr dest = nullptr, CryptoKeyType preferredCrypto = CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); + LeaseSet2 (const uint8_t * buf, size_t len, std::shared_ptr key, + std::shared_ptr dest = nullptr, const uint8_t * secret = nullptr, CryptoKeyType preferredCrypto = CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); // store type 5, called from local netdb only + uint8_t GetStoreType () const override { return m_StoreType; }; + uint32_t GetPublishedTimestamp () const override { return m_PublishedTimestamp; }; bool IsPublic () const { return m_IsPublic; }; - bool IsPublishedEncrypted () const { return m_IsPublishedEncrypted; }; - std::shared_ptr GetTransientVerifier () const { return m_TransientVerifier; }; - void Update (const uint8_t * buf, size_t len, bool verifySignature); - bool IsNewer (const uint8_t * buf, size_t len) const; + bool IsPublishedEncrypted () const override { return m_IsPublishedEncrypted; }; + std::shared_ptr GetTransientVerifier () const override { return m_TransientVerifier; }; + void Update (const uint8_t * buf, size_t len, std::shared_ptr dest, bool verifySignature) override; + bool IsNewer (const uint8_t * buf, size_t len) const override; // implements RoutingDestination void Encrypt (const uint8_t * data, uint8_t * encrypted) const; @@ -171,15 +173,17 @@ namespace data private: - void ReadFromBuffer (const uint8_t * buf, size_t len, bool readIdentity = true, bool verifySignature = true); - void ReadFromBufferEncrypted (const uint8_t * buf, size_t len, std::shared_ptr key, const uint8_t * secret); - size_t ReadStandardLS2TypeSpecificPart (const uint8_t * buf, size_t len); + void ReadFromBuffer (const uint8_t * buf, size_t len, std::shared_ptr dest, + bool readIdentity = true, bool verifySignature = true); + void ReadFromBufferEncrypted (const uint8_t * buf, size_t len, std::shared_ptr key, + std::shared_ptr dest, const uint8_t * secret); + size_t ReadStandardLS2TypeSpecificPart (const uint8_t * buf, size_t len, std::shared_ptr dest); size_t ReadMetaLS2TypeSpecificPart (const uint8_t * buf, size_t len); template bool VerifySignature (Verifier& verifier, const uint8_t * buf, size_t len, size_t signatureOffset); - uint64_t ExtractExpirationTimestamp (const uint8_t * buf, size_t len) const; + uint64_t ExtractExpirationTimestamp (const uint8_t * buf, size_t len) const override; uint64_t ExtractPublishedTimestamp (const uint8_t * buf, size_t len, uint64_t& expiration) const; size_t ExtractClientAuthData (const uint8_t * buf, size_t len, const uint8_t * secret, const uint8_t * subcredential, uint8_t * authCookie) const; // subcredential is subcredential + timestamp, return length of autData without flag diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index e53738e5..cab40e43 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -361,7 +361,7 @@ namespace data { if(it->second->GetExpirationTime() < expires) { - it->second->Update (buf, len, false); // signature is verified already + it->second->Update (buf, len, nullptr, false); // signature is verified already if (CheckLogLevel (eLogInfo)) LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase32()); updated = true; From 46154dabd563852b332d97f98c8b35f960362315 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 8 Jun 2025 07:19:03 -0400 Subject: [PATCH 1071/1171] fixed warnings --- libi2pd/LeaseSet.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index f6f5f6da..46f40cb5 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -168,8 +168,8 @@ namespace data bool IsNewer (const uint8_t * buf, size_t len) const override; // implements RoutingDestination - void Encrypt (const uint8_t * data, uint8_t * encrypted) const; - CryptoKeyType GetEncryptionType () const { return m_EncryptionType; }; + void Encrypt (const uint8_t * data, uint8_t * encrypted) const override; + CryptoKeyType GetEncryptionType () const override { return m_EncryptionType; }; private: From 4828d93257769536aa6cacfc0013a61748f3385a Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 9 Jun 2025 16:05:56 -0400 Subject: [PATCH 1072/1171] implemented ssu2.firewalled4 and ssu2.firewalled6 params --- libi2pd/Config.cpp | 2 ++ libi2pd/SSU2.cpp | 5 ++++- libi2pd/SSU2.h | 2 ++ libi2pd/SSU2OutOfSession.cpp | 3 +++ 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 939cd9ff..3d88ff21 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -305,6 +305,8 @@ namespace config { ("ssu2.mtu4", value()->default_value(0), "MTU for ipv4 address (default: detect)") ("ssu2.mtu6", value()->default_value(0), "MTU for ipv6 address (default: detect)") ("ssu2.proxy", value()->default_value(""), "Socks5 proxy URL for SSU2 transport") + ("ssu2.firewalled4", value()->default_value(false), "Set ipv4 network status to Firewalled even if OK (default: disabled)") + ("ssu2.firewalled6", value()->default_value(false), "Set ipv6 network status to Firewalled even if OK (default: disabled)") ; options_description nettime("Time sync options"); diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index fc2355a5..4540b4d2 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -25,7 +25,8 @@ namespace transport m_TerminationTimer (GetService ()), m_CleanupTimer (GetService ()), m_ResendTimer (GetService ()), m_IntroducersUpdateTimer (GetService ()), m_IntroducersUpdateTimerV6 (GetService ()), m_IsPublished (true), m_IsSyncClockFromPeers (true), m_PendingTimeOffset (0), - m_Rng(i2p::util::GetMonotonicMicroseconds ()%1000000LL), m_IsThroughProxy (false) + m_Rng(i2p::util::GetMonotonicMicroseconds ()%1000000LL), m_IsForcedFirewalled4 (false), + m_IsForcedFirewalled6 (false), m_IsThroughProxy (false) { } @@ -79,6 +80,7 @@ namespace transport if (address->IsV4 ()) { found = true; + i2p::config::GetOption ("ssu2.firewalled4", m_IsForcedFirewalled4); LogPrint (eLogDebug, "SSU2: Opening IPv4 socket at Start"); OpenSocket (boost::asio::ip::udp::endpoint (m_AddressV4, port)); boost::asio::post (m_ReceiveService.GetService (), @@ -91,6 +93,7 @@ namespace transport if (address->IsV6 ()) { found = true; + i2p::config::GetOption ("ssu2.firewalled6", m_IsForcedFirewalled6); LogPrint (eLogDebug, "SSU2: Opening IPv6 socket at Start"); OpenSocket (boost::asio::ip::udp::endpoint (m_AddressV6, port)); boost::asio::post (m_ReceiveService.GetService (), diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index a8598ce3..b7214480 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -79,6 +79,7 @@ namespace transport bool UsesProxy () const { return m_IsThroughProxy; }; bool IsSupported (const boost::asio::ip::address& addr) const; uint16_t GetPort (bool v4) const; + bool IsForcedFirewalled (bool v4) const { return v4 ? m_IsForcedFirewalled4 : m_IsForcedFirewalled6; } bool IsConnectedRecently (const boost::asio::ip::udp::endpoint& ep, bool max = true); void AddConnectedRecently (const boost::asio::ip::udp::endpoint& ep, uint64_t ts); std::mt19937& GetRng () { return m_Rng; } @@ -208,6 +209,7 @@ namespace transport i2p::crypto::AEADChaCha20Poly1305Encryptor m_Encryptor; i2p::crypto::AEADChaCha20Poly1305Decryptor m_Decryptor; i2p::crypto::ChaCha20Context m_ChaCha20; + bool m_IsForcedFirewalled4, m_IsForcedFirewalled6; // proxy bool m_IsThroughProxy; diff --git a/libi2pd/SSU2OutOfSession.cpp b/libi2pd/SSU2OutOfSession.cpp index 3760e329..dc626b16 100644 --- a/libi2pd/SSU2OutOfSession.cpp +++ b/libi2pd/SSU2OutOfSession.cpp @@ -90,6 +90,9 @@ namespace transport if (htobe64 (((uint64_t)nonce << 32) | nonce) == GetSourceConnID ()) { m_PeerTestResendTimer.cancel (); // cancel delayed msg 6 if any + if (GetServer ().IsForcedFirewalled (GetRemoteEndpoint ().address().is_v4())) + // we assume that msg 5 was not received if forced firewalled + return; m_IsConnectedRecently = GetServer ().IsConnectedRecently (GetRemoteEndpoint ()); if (GetAddress ()) { From 660dbd27d1bedfc0c9b0741d68d7c27902ccead1 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 11 Jun 2025 21:11:06 -0400 Subject: [PATCH 1073/1171] use EVP interface for ECDSA signatures if openssl 3 --- libi2pd/Signature.cpp | 174 +++++++++++++++++++++++++++++++++++++++++- libi2pd/Signature.h | 117 ++++++++++++++++++++++++++-- 2 files changed, 285 insertions(+), 6 deletions(-) diff --git a/libi2pd/Signature.cpp b/libi2pd/Signature.cpp index 3e4b451b..aa712c9a 100644 --- a/libi2pd/Signature.cpp +++ b/libi2pd/Signature.cpp @@ -10,6 +10,7 @@ #include #if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 #include +#include #endif #include "Log.h" #include "Signature.h" @@ -174,7 +175,178 @@ namespace crypto DSA_free (dsa); } #endif - + +#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 + ECDSAVerifier::ECDSAVerifier (int curve, size_t keyLen, const EVP_MD * hash): + m_Curve(curve), m_KeyLen (keyLen), m_Hash (hash), m_PublicKey (nullptr) + { + } + + ECDSAVerifier::~ECDSAVerifier () + { + if (m_PublicKey) + EVP_PKEY_free (m_PublicKey); + } + + void ECDSAVerifier::SetPublicKey (const uint8_t * signingKey) + { + if (m_PublicKey) + { + EVP_PKEY_free (m_PublicKey); + m_PublicKey = nullptr; + } + auto plen = GetPublicKeyLen (); + std::vector pub(plen + 1); + pub[0] = POINT_CONVERSION_UNCOMPRESSED; + memcpy (pub.data() + 1, signingKey, plen); // 0x04|x|y + OSSL_PARAM_BLD * paramBld = OSSL_PARAM_BLD_new (); + OSSL_PARAM_BLD_push_utf8_string (paramBld, OSSL_PKEY_PARAM_GROUP_NAME, OBJ_nid2ln(m_Curve), 0); + OSSL_PARAM_BLD_push_octet_string (paramBld, OSSL_PKEY_PARAM_PUB_KEY, pub.data (), pub.size ()); + OSSL_PARAM * params = OSSL_PARAM_BLD_to_param(paramBld); + + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name (NULL, "EC", NULL); + if (ctx) + { + if (EVP_PKEY_fromdata_init (ctx) <= 0 || + EVP_PKEY_fromdata (ctx, &m_PublicKey, EVP_PKEY_PUBLIC_KEY, params) <= 0) + LogPrint (eLogError, "ECDSA can't create PKEY from params"); + EVP_PKEY_CTX_free (ctx); + } + else + LogPrint (eLogError, "ECDSA can't create PKEY context"); + + OSSL_PARAM_free (params); + OSSL_PARAM_BLD_free (paramBld); + } + + bool ECDSAVerifier::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const + { + bool ret = false; + EVP_PKEY_CTX * ctx = EVP_PKEY_CTX_new (m_PublicKey, NULL); + if (!ctx) + { + LogPrint (eLogError, "ECDSA can't create verification context"); + return false; + } + // digest + unsigned int digestLen = EVP_MD_size(m_Hash); + std::vector digest(digestLen), sign(GetSignatureLen () + 8); + EVP_MD_CTX * mdCtx = EVP_MD_CTX_create (); + EVP_DigestInit (mdCtx, m_Hash); + EVP_DigestUpdate (mdCtx, buf, len); + EVP_DigestFinal (mdCtx, digest.data (), &digestLen); + EVP_MD_CTX_destroy (mdCtx); + // signature + ECDSA_SIG * sig = ECDSA_SIG_new(); + ECDSA_SIG_set0 (sig, BN_bin2bn (signature, GetSignatureLen ()/2, NULL), + BN_bin2bn (signature + GetSignatureLen ()/2, GetSignatureLen ()/2, NULL)); + // to DER format + uint8_t * s = sign.data (); + auto l = i2d_ECDSA_SIG (sig, &s); + ECDSA_SIG_free(sig); + //verify + if (EVP_PKEY_verify_init (ctx) > 0 && EVP_PKEY_public_check (ctx) > 0) + { + if (EVP_PKEY_CTX_set_signature_md (ctx, m_Hash) > 0) + ret = EVP_PKEY_verify (ctx, sign.data (), l, digest.data (), digestLen); + else + LogPrint (eLogError, "ECDSA can't set signature md"); + } + else + LogPrint (eLogError, "ECDSA invalid public key"); + EVP_PKEY_CTX_free (ctx); + return ret; + } + + ECDSASigner::ECDSASigner (int curve, size_t keyLen, const EVP_MD * hash, const uint8_t * signingPrivateKey): + m_KeyLen (keyLen), m_Hash(hash), m_PrivateKey (nullptr) + { + BIGNUM * priv = BN_bin2bn (signingPrivateKey, keyLen/2, NULL); + OSSL_PARAM_BLD * paramBld = OSSL_PARAM_BLD_new (); + OSSL_PARAM_BLD_push_utf8_string (paramBld, OSSL_PKEY_PARAM_GROUP_NAME, OBJ_nid2ln(curve), 0); + OSSL_PARAM_BLD_push_BN (paramBld, OSSL_PKEY_PARAM_PRIV_KEY, priv); + OSSL_PARAM * params = OSSL_PARAM_BLD_to_param(paramBld); + + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name (NULL, "EC", NULL); + if (ctx) + { + if (EVP_PKEY_fromdata_init (ctx) <= 0 || + EVP_PKEY_fromdata (ctx, &m_PrivateKey, EVP_PKEY_KEYPAIR, params) <= 0) + LogPrint (eLogError, "ECDSA can't create PKEY from params"); + EVP_PKEY_CTX_free (ctx); + } + else + LogPrint (eLogError, "ECDSA can't create PKEY context"); + + OSSL_PARAM_free (params); + OSSL_PARAM_BLD_free (paramBld); + BN_free (priv); + } + + ECDSASigner::~ECDSASigner () + { + if (m_PrivateKey) + EVP_PKEY_free (m_PrivateKey); + } + + void ECDSASigner::Sign (const uint8_t * buf, int len, uint8_t * signature) const + { + unsigned int digestLen = EVP_MD_size(m_Hash); + std::vector digest(digestLen), sign(m_KeyLen + 8); + EVP_MD_CTX * mdCtx = EVP_MD_CTX_create (); + EVP_DigestInit (mdCtx, m_Hash); + EVP_DigestUpdate (mdCtx, buf, len); + EVP_DigestFinal (mdCtx, digest.data (), &digestLen); + EVP_MD_CTX_destroy (mdCtx); + + EVP_PKEY_CTX * ctx = EVP_PKEY_CTX_new (m_PrivateKey, NULL); + if (!ctx) + { + LogPrint (eLogError, "ECDSA can't create signing context"); + return; + } + if (EVP_PKEY_sign_init (ctx) > 0 && EVP_PKEY_private_check (ctx) > 0) + { + if (EVP_PKEY_CTX_set_signature_md (ctx, m_Hash) > 0) + { + size_t l = sign.size (); + EVP_PKEY_sign (ctx, sign.data (), &l, digest.data (), digest.size ()); + const uint8_t * s1 = sign.data (); + ECDSA_SIG * sig = d2i_ECDSA_SIG (NULL, &s1, l); + const BIGNUM * r, * s; + ECDSA_SIG_get0 (sig, &r, &s); + bn2buf (r, signature, m_KeyLen/2); + bn2buf (s, signature + m_KeyLen/2, m_KeyLen/2); + ECDSA_SIG_free(sig); + } + else + LogPrint (eLogError, "ECDSA can't set signature md"); + } + else + LogPrint (eLogError, "ECDSA invalid private key"); + EVP_PKEY_CTX_free (ctx); + } + + void CreateECDSARandomKeys (int curve, size_t keyLen, uint8_t * signingPrivateKey, uint8_t * signingPublicKey) + { + EVP_PKEY * pkey = EVP_EC_gen (OBJ_nid2ln(curve)); + // private + BIGNUM * priv = BN_new (); + EVP_PKEY_get_bn_param (pkey, OSSL_PKEY_PARAM_PRIV_KEY, &priv); + bn2buf (priv, signingPrivateKey, keyLen/2); + BN_free (priv); + // public + BIGNUM * x = BN_new (), * y = BN_new (); + EVP_PKEY_get_bn_param (pkey, OSSL_PKEY_PARAM_EC_PUB_X, &x); + EVP_PKEY_get_bn_param (pkey, OSSL_PKEY_PARAM_EC_PUB_Y, &y); + bn2buf (x, signingPublicKey, keyLen/2); + bn2buf (y, signingPublicKey + keyLen/2, keyLen/2); + BN_free (x); BN_free (y); + EVP_PKEY_free (pkey); + } + +#endif + #if OPENSSL_EDDSA EDDSA25519Verifier::EDDSA25519Verifier (): m_Pkey (nullptr) diff --git a/libi2pd/Signature.h b/libi2pd/Signature.h index 20c7e11b..bd704738 100644 --- a/libi2pd/Signature.h +++ b/libi2pd/Signature.h @@ -91,7 +91,116 @@ namespace crypto void CreateDSARandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey); - // ECDSA + // ECDSA + constexpr size_t ECDSAP256_KEY_LENGTH = 64; + constexpr size_t ECDSAP384_KEY_LENGTH = 96; + constexpr size_t ECDSAP521_KEY_LENGTH = 132; + +#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 + class ECDSAVerifier: public Verifier + { + public: + + ECDSAVerifier (int curve, size_t keyLen, const EVP_MD * hash); + ~ECDSAVerifier (); + + void SetPublicKey (const uint8_t * signingKey); + bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const; + + size_t GetPublicKeyLen () const { return m_KeyLen; }; + size_t GetSignatureLen () const { return m_KeyLen; }; // signature length = key length + + private: + + int m_Curve; + size_t m_KeyLen; + const EVP_MD * m_Hash; + EVP_PKEY * m_PublicKey; + }; + + class ECDSASigner: public Signer + { + public: + + ECDSASigner (int curve, size_t keyLen, const EVP_MD * hash, const uint8_t * signingPrivateKey); + ~ECDSASigner (); + + void Sign (const uint8_t * buf, int len, uint8_t * signature) const; + + private: + + size_t m_KeyLen; + const EVP_MD * m_Hash; + EVP_PKEY * m_PrivateKey; + }; + + void CreateECDSARandomKeys (int curve, size_t keyLen, uint8_t * signingPrivateKey, uint8_t * signingPublicKey); + +// ECDSA_SHA256_P256 + class ECDSAP256Verifier: public ECDSAVerifier + { + public: + + ECDSAP256Verifier (): ECDSAVerifier (NID_X9_62_prime256v1, ECDSAP256_KEY_LENGTH, EVP_sha256()) {}; + }; + + class ECDSAP256Signer: public ECDSASigner + { + public: + + ECDSAP256Signer (const uint8_t * signingPrivateKey): + ECDSASigner (NID_X9_62_prime256v1, ECDSAP256_KEY_LENGTH, EVP_sha256(), signingPrivateKey) {}; + }; + + inline void CreateECDSAP256RandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey) + { + CreateECDSARandomKeys (NID_X9_62_prime256v1, ECDSAP256_KEY_LENGTH, signingPrivateKey, signingPublicKey); + } + +// ECDSA_SHA384_P384 + class ECDSAP384Verifier: public ECDSAVerifier + { + public: + + ECDSAP384Verifier (): ECDSAVerifier (NID_secp384r1, ECDSAP384_KEY_LENGTH, EVP_sha384()) {}; + }; + + class ECDSAP384Signer: public ECDSASigner + { + public: + + ECDSAP384Signer (const uint8_t * signingPrivateKey): + ECDSASigner (NID_secp384r1, ECDSAP384_KEY_LENGTH, EVP_sha384(), signingPrivateKey) {}; + }; + + inline void CreateECDSAP384RandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey) + { + CreateECDSARandomKeys (NID_secp384r1, ECDSAP384_KEY_LENGTH, signingPrivateKey, signingPublicKey); + } + +// ECDSA_SHA512_P521 + class ECDSAP521Verifier: public ECDSAVerifier + { + public: + + ECDSAP521Verifier (): ECDSAVerifier (NID_secp521r1, ECDSAP521_KEY_LENGTH, EVP_sha512()) {}; + }; + + class ECDSAP521Signer: public ECDSASigner + { + public: + + ECDSAP521Signer (const uint8_t * signingPrivateKey): + ECDSASigner (NID_secp521r1, ECDSAP521_KEY_LENGTH, EVP_sha512(), signingPrivateKey) {}; + }; + + inline void CreateECDSAP521RandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey) + { + CreateECDSARandomKeys (NID_secp521r1, ECDSAP521_KEY_LENGTH, signingPrivateKey, signingPublicKey); + } + +#else + struct SHA256Hash { static void CalculateHash (const uint8_t * buf, size_t len, uint8_t * digest) @@ -217,7 +326,6 @@ namespace crypto } // ECDSA_SHA256_P256 - const size_t ECDSAP256_KEY_LENGTH = 64; typedef ECDSAVerifier ECDSAP256Verifier; typedef ECDSASigner ECDSAP256Signer; @@ -227,7 +335,6 @@ namespace crypto } // ECDSA_SHA384_P384 - const size_t ECDSAP384_KEY_LENGTH = 96; typedef ECDSAVerifier ECDSAP384Verifier; typedef ECDSASigner ECDSAP384Signer; @@ -237,7 +344,6 @@ namespace crypto } // ECDSA_SHA512_P521 - const size_t ECDSAP521_KEY_LENGTH = 132; typedef ECDSAVerifier ECDSAP521Verifier; typedef ECDSASigner ECDSAP521Signer; @@ -245,7 +351,8 @@ namespace crypto { CreateECDSARandomKeys (NID_secp521r1, ECDSAP521_KEY_LENGTH, signingPrivateKey, signingPublicKey); } - + +#endif // EdDSA class EDDSA25519Verifier: public Verifier From d2296f81ad77bbf1c7742cefe5a1d750e0f6765f Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 12 Jun 2025 09:44:55 -0400 Subject: [PATCH 1074/1171] use EVP functions to extract RSA keys if openssl 3 --- libi2pd/Reseed.cpp | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/libi2pd/Reseed.cpp b/libi2pd/Reseed.cpp index e58e898b..23dae8ff 100644 --- a/libi2pd/Reseed.cpp +++ b/libi2pd/Reseed.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2024, The PurpleI2P Project +* Copyright (c) 2013-2025, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -14,6 +14,9 @@ #include #include #include +#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 +#include +#endif #include #include "Crypto.h" @@ -480,15 +483,31 @@ namespace data if (terminator) terminator[0] = 0; } // extract RSA key (we need n only, e = 65537) - const RSA * key = EVP_PKEY_get0_RSA (X509_get_pubkey (cert)); - const BIGNUM * n, * e, * d; + EVP_PKEY * pubKey = X509_get_pubkey (cert); + const BIGNUM * n = nullptr; +#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 + BIGNUM * n1 = BN_new (); + if (EVP_PKEY_get_bn_param (pubKey, OSSL_PKEY_PARAM_RSA_N, &n1) > 0) + n = n1; +#else + const RSA * key = EVP_PKEY_get0_RSA (pubKey); + const BIGNUM * e, * d; RSA_get0_key(key, &n, &e, &d); - PublicKey value; - i2p::crypto::bn2buf (n, value, 512); - if (cn) - m_SigningKeys[cn] = value; +#endif + if (n) + { + PublicKey value; + i2p::crypto::bn2buf (n, value, 512); + if (cn) + m_SigningKeys[cn] = value; + else + LogPrint (eLogError, "Reseed: Can't find CN field in ", filename); + } else - LogPrint (eLogError, "Reseed: Can't find CN field in ", filename); + LogPrint (eLogError, "Reseed: Can't extract RSA key from ", filename); +#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 + BN_free (n1); +#endif } SSL_free (ssl); } From 5bef9875292f15c08b9d2155f8b308dbeac70f78 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 12 Jun 2025 11:22:39 -0400 Subject: [PATCH 1075/1171] stop suporting openssl below 1.1.1 --- libi2pd/Crypto.cpp | 15 --------------- libi2pd/Crypto.h | 14 +++++--------- libi2pd/Signature.cpp | 34 ---------------------------------- libi2pd/Signature.h | 18 ------------------ 4 files changed, 5 insertions(+), 76 deletions(-) diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index c41b4c10..94f47ca9 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -16,9 +16,7 @@ #include #include "TunnelBase.h" #include -#if OPENSSL_HKDF #include -#endif #if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 #include #include @@ -784,7 +782,6 @@ namespace crypto void HKDF (const uint8_t * salt, const uint8_t * key, size_t keyLen, const std::string& info, uint8_t * out, size_t outLen) { -#if OPENSSL_HKDF EVP_PKEY_CTX * pctx = EVP_PKEY_CTX_new_id (EVP_PKEY_HKDF, nullptr); EVP_PKEY_derive_init (pctx); EVP_PKEY_CTX_set_hkdf_md (pctx, EVP_sha256()); @@ -805,18 +802,6 @@ namespace crypto EVP_PKEY_CTX_add1_hkdf_info (pctx, (const uint8_t *)info.c_str (), info.length ()); EVP_PKEY_derive (pctx, out, &outLen); EVP_PKEY_CTX_free (pctx); -#else - uint8_t prk[32]; unsigned int len; - HMAC(EVP_sha256(), salt, 32, key, keyLen, prk, &len); - auto l = info.length (); - memcpy (out, info.c_str (), l); out[l] = 0x01; - HMAC(EVP_sha256(), prk, 32, out, l + 1, out, &len); - if (outLen > 32) // 64 - { - memcpy (out + 32, info.c_str (), l); out[l + 32] = 0x02; - HMAC(EVP_sha256(), prk, 32, out, l + 33, out + 32, &len); - } -#endif } // Noise diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index 125a217c..5bf4d534 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -27,15 +27,11 @@ #include "Tag.h" // recognize openssl version and features -#if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1 -# define OPENSSL_HKDF 1 -# define OPENSSL_EDDSA 1 -# if (!defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER != 0x030000000)) // 3.0.0, regression in SipHash, not implemented in LibreSSL -# define OPENSSL_SIPHASH 1 -# endif -# if (OPENSSL_VERSION_NUMBER >= 0x030500000) // 3.5.0 -# define OPENSSL_PQ 1 -# endif +#if (!defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER != 0x030000000)) // 3.0.0, regression in SipHash, not implemented in LibreSSL +# define OPENSSL_SIPHASH 1 +#endif +#if (OPENSSL_VERSION_NUMBER >= 0x030500000) // 3.5.0 +# define OPENSSL_PQ 1 #endif namespace i2p diff --git a/libi2pd/Signature.cpp b/libi2pd/Signature.cpp index aa712c9a..24374e5b 100644 --- a/libi2pd/Signature.cpp +++ b/libi2pd/Signature.cpp @@ -347,7 +347,6 @@ namespace crypto #endif -#if OPENSSL_EDDSA EDDSA25519Verifier::EDDSA25519Verifier (): m_Pkey (nullptr) { @@ -379,37 +378,6 @@ namespace crypto return false; } -#else - EDDSA25519Verifier::EDDSA25519Verifier () - { - } - - EDDSA25519Verifier::~EDDSA25519Verifier () - { - } - - void EDDSA25519Verifier::SetPublicKey (const uint8_t * signingKey) - { - memcpy (m_PublicKeyEncoded, signingKey, EDDSA25519_PUBLIC_KEY_LENGTH); - BN_CTX * ctx = BN_CTX_new (); - m_PublicKey = GetEd25519 ()->DecodePublicKey (m_PublicKeyEncoded, ctx); - BN_CTX_free (ctx); - } - - bool EDDSA25519Verifier::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const - { - uint8_t digest[64]; - SHA512_CTX ctx; - SHA512_Init (&ctx); - SHA512_Update (&ctx, signature, EDDSA25519_SIGNATURE_LENGTH/2); // R - SHA512_Update (&ctx, m_PublicKeyEncoded, EDDSA25519_PUBLIC_KEY_LENGTH); // public key - SHA512_Update (&ctx, buf, len); // data - SHA512_Final (digest, &ctx); - - return GetEd25519 ()->Verify (m_PublicKey, digest, signature); - } -#endif - EDDSA25519SignerCompat::EDDSA25519SignerCompat (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey) { // expand key @@ -439,7 +407,6 @@ namespace crypto GetEd25519 ()->Sign (m_ExpandedPrivateKey, m_PublicKeyEncoded, buf, len, signature); } -#if OPENSSL_EDDSA EDDSA25519Signer::EDDSA25519Signer (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey): m_Pkey (nullptr), m_Fallback (nullptr) { @@ -481,7 +448,6 @@ namespace crypto else LogPrint (eLogError, "EdDSA signing key is not set"); } -#endif #if (OPENSSL_VERSION_NUMBER >= 0x030000000) static const OSSL_PARAM EDDSA25519phParams[] = diff --git a/libi2pd/Signature.h b/libi2pd/Signature.h index bd704738..b1942d0c 100644 --- a/libi2pd/Signature.h +++ b/libi2pd/Signature.h @@ -369,18 +369,12 @@ namespace crypto size_t GetSignatureLen () const { return EDDSA25519_SIGNATURE_LENGTH; }; private: - -#if OPENSSL_EDDSA EVP_PKEY * m_Pkey; protected: EVP_PKEY * GetPkey () const { return m_Pkey; }; -#else - EDDSAPoint m_PublicKey; - uint8_t m_PublicKeyEncoded[EDDSA25519_PUBLIC_KEY_LENGTH]; -#endif }; #if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 @@ -409,7 +403,6 @@ namespace crypto uint8_t m_PublicKeyEncoded[EDDSA25519_PUBLIC_KEY_LENGTH]; }; -#if OPENSSL_EDDSA class EDDSA25519Signer: public Signer { public: @@ -429,11 +422,6 @@ namespace crypto EVP_PKEY * m_Pkey; EDDSA25519SignerCompat * m_Fallback; }; -#else - - typedef EDDSA25519SignerCompat EDDSA25519Signer; - -#endif #if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 class EDDSA25519phSigner: public EDDSA25519Signer @@ -449,7 +437,6 @@ namespace crypto inline void CreateEDDSA25519RandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey) { -#if OPENSSL_EDDSA EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id (EVP_PKEY_ED25519, NULL); EVP_PKEY_keygen_init (pctx); @@ -460,11 +447,6 @@ namespace crypto len = EDDSA25519_PRIVATE_KEY_LENGTH; EVP_PKEY_get_raw_private_key (pkey, signingPrivateKey, &len); EVP_PKEY_free (pkey); -#else - RAND_bytes (signingPrivateKey, EDDSA25519_PRIVATE_KEY_LENGTH); - EDDSA25519Signer signer (signingPrivateKey); - memcpy (signingPublicKey, signer.GetPublicKey (), EDDSA25519_PUBLIC_KEY_LENGTH); -#endif } From 5974d2b5ac65222560499d2680880afdb160cc85 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 12 Jun 2025 13:35:47 -0400 Subject: [PATCH 1076/1171] use EVP_DigestVerify/EVP_DigestSign for ECDSA and DSA signatures if openssl 3 --- libi2pd/Signature.cpp | 108 +++++++++++++----------------------------- 1 file changed, 32 insertions(+), 76 deletions(-) diff --git a/libi2pd/Signature.cpp b/libi2pd/Signature.cpp index 24374e5b..b8cfaf2c 100644 --- a/libi2pd/Signature.cpp +++ b/libi2pd/Signature.cpp @@ -42,22 +42,19 @@ namespace crypto bool DSAVerifier::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const { - // calculate SHA1 digest - uint8_t digest[20], sign[48]; - SHA1 (buf, len, digest); // signature DSA_SIG * sig = DSA_SIG_new(); DSA_SIG_set0 (sig, BN_bin2bn (signature, DSA_SIGNATURE_LENGTH/2, NULL), BN_bin2bn (signature + DSA_SIGNATURE_LENGTH/2, DSA_SIGNATURE_LENGTH/2, NULL)); // to DER format + uint8_t sign[DSA_SIGNATURE_LENGTH + 8]; uint8_t * s = sign; auto l = i2d_DSA_SIG (sig, &s); DSA_SIG_free(sig); // verify - auto ctx = EVP_PKEY_CTX_new (m_PublicKey, NULL); - EVP_PKEY_verify_init(ctx); - EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha1()); - bool ret = EVP_PKEY_verify(ctx, sign, l, digest, 20); - EVP_PKEY_CTX_free(ctx); + EVP_MD_CTX * ctx = EVP_MD_CTX_create (); + EVP_DigestVerifyInit (ctx, NULL, EVP_sha1(), NULL, m_PublicKey); + auto ret = EVP_DigestVerify (ctx, sign, l, buf, len); + EVP_MD_CTX_destroy (ctx); return ret; } @@ -76,13 +73,13 @@ namespace crypto void DSASigner::Sign (const uint8_t * buf, int len, uint8_t * signature) const { - uint8_t digest[20], sign[48]; - SHA1 (buf, len, digest); - auto ctx = EVP_PKEY_CTX_new (m_PrivateKey, NULL); - EVP_PKEY_sign_init(ctx); - EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha1()); - size_t l = 48; - EVP_PKEY_sign(ctx, sign, &l, digest, 20); + uint8_t sign[DSA_SIGNATURE_LENGTH + 8]; + size_t l = DSA_SIGNATURE_LENGTH + 8; + EVP_MD_CTX * ctx = EVP_MD_CTX_create (); + EVP_DigestSignInit (ctx, NULL, EVP_sha1(), NULL, m_PrivateKey); + EVP_DigestSign (ctx, sign, &l, buf, len); + EVP_MD_CTX_destroy (ctx); + // decode r and s const uint8_t * s1 = sign; DSA_SIG * sig = d2i_DSA_SIG (NULL, &s1, l); const BIGNUM * r, * s; @@ -90,7 +87,6 @@ namespace crypto bn2buf (r, signature, DSA_SIGNATURE_LENGTH/2); bn2buf (s, signature + DSA_SIGNATURE_LENGTH/2, DSA_SIGNATURE_LENGTH/2); DSA_SIG_free(sig); - EVP_PKEY_CTX_free(ctx); } void CreateDSARandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey) @@ -221,40 +217,20 @@ namespace crypto bool ECDSAVerifier::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const { - bool ret = false; - EVP_PKEY_CTX * ctx = EVP_PKEY_CTX_new (m_PublicKey, NULL); - if (!ctx) - { - LogPrint (eLogError, "ECDSA can't create verification context"); - return false; - } - // digest - unsigned int digestLen = EVP_MD_size(m_Hash); - std::vector digest(digestLen), sign(GetSignatureLen () + 8); - EVP_MD_CTX * mdCtx = EVP_MD_CTX_create (); - EVP_DigestInit (mdCtx, m_Hash); - EVP_DigestUpdate (mdCtx, buf, len); - EVP_DigestFinal (mdCtx, digest.data (), &digestLen); - EVP_MD_CTX_destroy (mdCtx); // signature ECDSA_SIG * sig = ECDSA_SIG_new(); ECDSA_SIG_set0 (sig, BN_bin2bn (signature, GetSignatureLen ()/2, NULL), BN_bin2bn (signature + GetSignatureLen ()/2, GetSignatureLen ()/2, NULL)); // to DER format + std::vector sign(GetSignatureLen () + 8); uint8_t * s = sign.data (); auto l = i2d_ECDSA_SIG (sig, &s); ECDSA_SIG_free(sig); - //verify - if (EVP_PKEY_verify_init (ctx) > 0 && EVP_PKEY_public_check (ctx) > 0) - { - if (EVP_PKEY_CTX_set_signature_md (ctx, m_Hash) > 0) - ret = EVP_PKEY_verify (ctx, sign.data (), l, digest.data (), digestLen); - else - LogPrint (eLogError, "ECDSA can't set signature md"); - } - else - LogPrint (eLogError, "ECDSA invalid public key"); - EVP_PKEY_CTX_free (ctx); + // verify + EVP_MD_CTX * ctx = EVP_MD_CTX_create (); + EVP_DigestVerifyInit (ctx, NULL, m_Hash, NULL, m_PublicKey); + auto ret = EVP_DigestVerify (ctx, sign.data (), l, buf, len); + EVP_MD_CTX_destroy (ctx); return ret; } @@ -291,40 +267,20 @@ namespace crypto void ECDSASigner::Sign (const uint8_t * buf, int len, uint8_t * signature) const { - unsigned int digestLen = EVP_MD_size(m_Hash); - std::vector digest(digestLen), sign(m_KeyLen + 8); - EVP_MD_CTX * mdCtx = EVP_MD_CTX_create (); - EVP_DigestInit (mdCtx, m_Hash); - EVP_DigestUpdate (mdCtx, buf, len); - EVP_DigestFinal (mdCtx, digest.data (), &digestLen); - EVP_MD_CTX_destroy (mdCtx); - - EVP_PKEY_CTX * ctx = EVP_PKEY_CTX_new (m_PrivateKey, NULL); - if (!ctx) - { - LogPrint (eLogError, "ECDSA can't create signing context"); - return; - } - if (EVP_PKEY_sign_init (ctx) > 0 && EVP_PKEY_private_check (ctx) > 0) - { - if (EVP_PKEY_CTX_set_signature_md (ctx, m_Hash) > 0) - { - size_t l = sign.size (); - EVP_PKEY_sign (ctx, sign.data (), &l, digest.data (), digest.size ()); - const uint8_t * s1 = sign.data (); - ECDSA_SIG * sig = d2i_ECDSA_SIG (NULL, &s1, l); - const BIGNUM * r, * s; - ECDSA_SIG_get0 (sig, &r, &s); - bn2buf (r, signature, m_KeyLen/2); - bn2buf (s, signature + m_KeyLen/2, m_KeyLen/2); - ECDSA_SIG_free(sig); - } - else - LogPrint (eLogError, "ECDSA can't set signature md"); - } - else - LogPrint (eLogError, "ECDSA invalid private key"); - EVP_PKEY_CTX_free (ctx); + std::vector sign(m_KeyLen + 8); + size_t l = sign.size (); + EVP_MD_CTX * ctx = EVP_MD_CTX_create (); + EVP_DigestSignInit (ctx, NULL, m_Hash, NULL, m_PrivateKey); + EVP_DigestSign (ctx, sign.data(), &l, buf, len); + EVP_MD_CTX_destroy (ctx); + // decode r and s + const uint8_t * s1 = sign.data (); + ECDSA_SIG * sig = d2i_ECDSA_SIG (NULL, &s1, l); + const BIGNUM * r, * s; + ECDSA_SIG_get0 (sig, &r, &s); + bn2buf (r, signature, m_KeyLen/2); + bn2buf (s, signature + m_KeyLen/2, m_KeyLen/2); + ECDSA_SIG_free(sig); } void CreateECDSARandomKeys (int curve, size_t keyLen, uint8_t * signingPrivateKey, uint8_t * signingPublicKey) From bb2b34ff4fd186ac55bd3654f265415a1691b7ab Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 12 Jun 2025 16:05:17 -0400 Subject: [PATCH 1077/1171] check more precise result of EVP_DigestVerify --- libi2pd/Signature.cpp | 10 +++++----- libi2pd/Signature.h | 2 +- tests/test-eddsa.cpp | 2 -- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/libi2pd/Signature.cpp b/libi2pd/Signature.cpp index b8cfaf2c..cad7d484 100644 --- a/libi2pd/Signature.cpp +++ b/libi2pd/Signature.cpp @@ -53,7 +53,7 @@ namespace crypto // verify EVP_MD_CTX * ctx = EVP_MD_CTX_create (); EVP_DigestVerifyInit (ctx, NULL, EVP_sha1(), NULL, m_PublicKey); - auto ret = EVP_DigestVerify (ctx, sign, l, buf, len); + auto ret = EVP_DigestVerify (ctx, sign, l, buf, len) == 1; EVP_MD_CTX_destroy (ctx); return ret; } @@ -132,7 +132,7 @@ namespace crypto DSA_SIG * sig = DSA_SIG_new(); DSA_SIG_set0 (sig, BN_bin2bn (signature, DSA_SIGNATURE_LENGTH/2, NULL), BN_bin2bn (signature + DSA_SIGNATURE_LENGTH/2, DSA_SIGNATURE_LENGTH/2, NULL)); // DSA verification - int ret = DSA_do_verify (digest, 20, sig, m_PublicKey); + int ret = DSA_do_verify (digest, 20, sig, m_PublicKey) == 1; DSA_SIG_free(sig); return ret; } @@ -229,7 +229,7 @@ namespace crypto // verify EVP_MD_CTX * ctx = EVP_MD_CTX_create (); EVP_DigestVerifyInit (ctx, NULL, m_Hash, NULL, m_PublicKey); - auto ret = EVP_DigestVerify (ctx, sign.data (), l, buf, len); + auto ret = EVP_DigestVerify (ctx, sign.data (), l, buf, len) == 1; EVP_MD_CTX_destroy (ctx); return ret; } @@ -325,7 +325,7 @@ namespace crypto { EVP_MD_CTX * ctx = EVP_MD_CTX_create (); EVP_DigestVerifyInit (ctx, NULL, NULL, NULL, m_Pkey); - auto ret = EVP_DigestVerify (ctx, signature, 64, buf, len); + auto ret = EVP_DigestVerify (ctx, signature, 64, buf, len) == 1; EVP_MD_CTX_destroy (ctx); return ret; } @@ -509,7 +509,7 @@ namespace crypto OSSL_PARAM_END }; EVP_PKEY_verify_message_init (vctx, sig, params); - ret = EVP_PKEY_verify (vctx, signature, GetSignatureLen (), buf, len); + ret = EVP_PKEY_verify (vctx, signature, GetSignatureLen (), buf, len) == 1; EVP_SIGNATURE_free (sig); } EVP_PKEY_CTX_free (vctx); diff --git a/libi2pd/Signature.h b/libi2pd/Signature.h index b1942d0c..43f706bd 100644 --- a/libi2pd/Signature.h +++ b/libi2pd/Signature.h @@ -263,7 +263,7 @@ namespace crypto auto s = BN_bin2bn (signature + GetSignatureLen ()/2, GetSignatureLen ()/2, NULL); ECDSA_SIG_set0(sig, r, s); // ECDSA verification - int ret = ECDSA_do_verify (digest, Hash::hashLen, sig, m_PublicKey); + int ret = ECDSA_do_verify (digest, Hash::hashLen, sig, m_PublicKey) == 1; ECDSA_SIG_free(sig); return ret; } diff --git a/tests/test-eddsa.cpp b/tests/test-eddsa.cpp index b3895e2b..9de2c088 100644 --- a/tests/test-eddsa.cpp +++ b/tests/test-eddsa.cpp @@ -58,9 +58,7 @@ int main () uint8_t s[64]; i2p::crypto::EDDSA25519Signer signer (key); signer.Sign (msg, 1023, s); -#if OPENSSL_EDDSA assert(memcmp (s, sig, 64) == 0); -#endif i2p::crypto::EDDSA25519Verifier verifier; verifier.SetPublicKey (pub); From 06c9a255fb4f5dbb5670f3872f77cb525a0a1211 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 12 Jun 2025 18:58:37 -0400 Subject: [PATCH 1078/1171] use EVP_DigestSign/EVP_DigestVerify for family signatures --- libi2pd/Family.cpp | 90 ++++++++++++++++++++++++++++++---------------- 1 file changed, 60 insertions(+), 30 deletions(-) diff --git a/libi2pd/Family.cpp b/libi2pd/Family.cpp index 300a50ab..3a4e8890 100644 --- a/libi2pd/Family.cpp +++ b/libi2pd/Family.cpp @@ -51,11 +51,24 @@ namespace data auto pkey = X509_get_pubkey (cert); if (pkey) { - if (!m_SigningKeys.emplace (cn, std::make_pair(pkey, (int)m_SigningKeys.size () + 1)).second) - { - EVP_PKEY_free (pkey); - LogPrint (eLogError, "Family: Duplicated family name ", cn); - } + int curve = 0; +#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 + char groupName[20]; + if (EVP_PKEY_get_group_name(pkey, groupName, sizeof(groupName), NULL) == 1) + curve = OBJ_txt2nid (groupName); + else + curve = -1; +#endif + if (!curve || curve == NID_X9_62_prime256v1) + { + if (!m_SigningKeys.emplace (cn, std::make_pair(pkey, (int)m_SigningKeys.size () + 1)).second) + { + EVP_PKEY_free (pkey); + LogPrint (eLogError, "Family: Duplicated family name ", cn); + } + } + else + LogPrint (eLogWarning, "Family: elliptic curve ", curve, " is not supported"); } } } @@ -106,11 +119,17 @@ namespace data memcpy (buf + len, (const uint8_t *)ident, 32); len += 32; auto signatureBufLen = Base64ToByteStream (signature, signatureBuf, 64); - if (signatureBufLen) + if (signatureBufLen == 64) { + ECDSA_SIG * sig = ECDSA_SIG_new(); + ECDSA_SIG_set0 (sig, BN_bin2bn (signatureBuf, 32, NULL), BN_bin2bn (signatureBuf + 32, 32, NULL)); + uint8_t sign[72]; + uint8_t * s = sign; + auto l = i2d_ECDSA_SIG (sig, &s); + ECDSA_SIG_free(sig); EVP_MD_CTX * ctx = EVP_MD_CTX_create (); - EVP_DigestVerifyInit (ctx, NULL, NULL, NULL, it->second.first); - auto ret = EVP_DigestVerify (ctx, signatureBuf, signatureBufLen, buf, len); + EVP_DigestVerifyInit (ctx, NULL, EVP_sha256(), NULL, it->second.first); + auto ret = EVP_DigestVerify (ctx, sign, l, buf, len) == 1; EVP_MD_CTX_destroy (ctx); return ret; } @@ -137,29 +156,40 @@ namespace data { SSL * ssl = SSL_new (ctx); EVP_PKEY * pkey = SSL_get_privatekey (ssl); - EC_KEY * ecKey = EVP_PKEY_get1_EC_KEY (pkey); - if (ecKey) + int curve = 0; +#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 + char groupName[20]; + if (EVP_PKEY_get_group_name(pkey, groupName, sizeof(groupName), NULL) == 1) + curve = OBJ_txt2nid (groupName); + else + curve = -1; +#endif + if (!curve || curve == NID_X9_62_prime256v1) { - auto group = EC_KEY_get0_group (ecKey); - if (group) - { - int curve = EC_GROUP_get_curve_name (group); - if (curve == NID_X9_62_prime256v1) - { - uint8_t signingPrivateKey[32], buf[50], signature[64]; - i2p::crypto::bn2buf (EC_KEY_get0_private_key (ecKey), signingPrivateKey, 32); - i2p::crypto::ECDSAP256Signer signer (signingPrivateKey); - size_t len = family.length (); - memcpy (buf, family.c_str (), len); - memcpy (buf + len, (const uint8_t *)ident, 32); - len += 32; - signer.Sign (buf, len, signature); - sig = ByteStreamToBase64 (signature, 64); - } - else - LogPrint (eLogWarning, "Family: elliptic curve ", curve, " is not supported"); - } - } + uint8_t buf[100], sign[72], signature[64]; + size_t len = family.length (); + memcpy (buf, family.c_str (), len); + memcpy (buf + len, (const uint8_t *)ident, 32); + len += 32; + + size_t l = 72; + EVP_MD_CTX * mdctx = EVP_MD_CTX_create (); + EVP_DigestSignInit (mdctx, NULL, EVP_sha256(), NULL, pkey); + EVP_DigestSign (mdctx, sign, &l, buf, len); + EVP_MD_CTX_destroy (mdctx); + + const uint8_t * s1 = sign; + ECDSA_SIG * sig1 = d2i_ECDSA_SIG (NULL, &s1, l); + const BIGNUM * r, * s; + ECDSA_SIG_get0 (sig1, &r, &s); + i2p::crypto::bn2buf (r, signature, 32); + i2p::crypto::bn2buf (s, signature + 32, 32); + ECDSA_SIG_free(sig1); + sig = ByteStreamToBase64 (signature, 64); + } + else + LogPrint (eLogWarning, "Family: elliptic curve ", curve, " is not supported"); + SSL_free (ssl); } else From 588108d7d0e19516eadbd8f22e16df6a4608d146 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 13 Jun 2025 12:48:25 -0400 Subject: [PATCH 1079/1171] use EVP_RSA_gen if openssl 3 --- daemon/I2PControl.cpp | 78 +++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 36 deletions(-) diff --git a/daemon/I2PControl.cpp b/daemon/I2PControl.cpp index 6261a14c..9babce93 100644 --- a/daemon/I2PControl.cpp +++ b/daemon/I2PControl.cpp @@ -437,48 +437,54 @@ namespace client void I2PControlService::CreateCertificate (const char *crt_path, const char *key_path) { FILE *f = NULL; +#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 + EVP_PKEY * pkey = EVP_RSA_gen(4096); // e = 65537 +#else EVP_PKEY * pkey = EVP_PKEY_new (); RSA * rsa = RSA_new (); BIGNUM * e = BN_dup (i2p::crypto::GetRSAE ()); RSA_generate_key_ex (rsa, 4096, e, NULL); - BN_free (e); - if (rsa) - { - EVP_PKEY_assign_RSA (pkey, rsa); - X509 * x509 = X509_new (); - ASN1_INTEGER_set (X509_get_serialNumber (x509), 1); - X509_gmtime_adj (X509_getm_notBefore (x509), 0); - X509_gmtime_adj (X509_getm_notAfter (x509), I2P_CONTROL_CERTIFICATE_VALIDITY*24*60*60); // expiration - X509_set_pubkey (x509, pkey); // public key - X509_NAME * name = X509_get_subject_name (x509); - X509_NAME_add_entry_by_txt (name, "C", MBSTRING_ASC, (unsigned char *)"A1", -1, -1, 0); // country (Anonymous proxy) - X509_NAME_add_entry_by_txt (name, "O", MBSTRING_ASC, (unsigned char *)I2P_CONTROL_CERTIFICATE_ORGANIZATION, -1, -1, 0); // organization - X509_NAME_add_entry_by_txt (name, "CN", MBSTRING_ASC, (unsigned char *)I2P_CONTROL_CERTIFICATE_COMMON_NAME, -1, -1, 0); // common name - X509_set_issuer_name (x509, name); // set issuer to ourselves - X509_sign (x509, pkey, EVP_sha1 ()); // sign, last param must be NULL for EdDSA - - // save cert - if ((f = fopen (crt_path, "wb")) != NULL) { - LogPrint (eLogInfo, "I2PControl: Saving new cert to ", crt_path); - PEM_write_X509 (f, x509); - fclose (f); - } else { - LogPrint (eLogError, "I2PControl: Can't write cert: ", strerror(errno)); - } - - // save key - if ((f = fopen (key_path, "wb")) != NULL) { - LogPrint (eLogInfo, "I2PControl: saving cert key to ", key_path); - PEM_write_PrivateKey (f, pkey, NULL, NULL, 0, NULL, NULL); - fclose (f); - } else { - LogPrint (eLogError, "I2PControl: Can't write key: ", strerror(errno)); - } - - X509_free (x509); - } else { + BN_free (e); + if (rsa) EVP_PKEY_assign_RSA (pkey, rsa); + else + { LogPrint (eLogError, "I2PControl: Can't create RSA key for certificate"); + EVP_PKEY_free (pkey); + return; + } +#endif + X509 * x509 = X509_new (); + ASN1_INTEGER_set (X509_get_serialNumber (x509), 1); + X509_gmtime_adj (X509_getm_notBefore (x509), 0); + X509_gmtime_adj (X509_getm_notAfter (x509), I2P_CONTROL_CERTIFICATE_VALIDITY*24*60*60); // expiration + X509_set_pubkey (x509, pkey); // public key + X509_NAME * name = X509_get_subject_name (x509); + X509_NAME_add_entry_by_txt (name, "C", MBSTRING_ASC, (unsigned char *)"A1", -1, -1, 0); // country (Anonymous proxy) + X509_NAME_add_entry_by_txt (name, "O", MBSTRING_ASC, (unsigned char *)I2P_CONTROL_CERTIFICATE_ORGANIZATION, -1, -1, 0); // organization + X509_NAME_add_entry_by_txt (name, "CN", MBSTRING_ASC, (unsigned char *)I2P_CONTROL_CERTIFICATE_COMMON_NAME, -1, -1, 0); // common name + X509_set_issuer_name (x509, name); // set issuer to ourselves + X509_sign (x509, pkey, EVP_sha1 ()); // sign, last param must be NULL for EdDSA + + // save cert + if ((f = fopen (crt_path, "wb")) != NULL) + { + LogPrint (eLogInfo, "I2PControl: Saving new cert to ", crt_path); + PEM_write_X509 (f, x509); + fclose (f); + } + else + LogPrint (eLogError, "I2PControl: Can't write cert: ", strerror(errno)); + X509_free (x509); + + // save key + if ((f = fopen (key_path, "wb")) != NULL) + { + LogPrint (eLogInfo, "I2PControl: saving cert key to ", key_path); + PEM_write_PrivateKey (f, pkey, NULL, NULL, 0, NULL, NULL); + fclose (f); } + else + LogPrint (eLogError, "I2PControl: Can't write key: ", strerror(errno)); EVP_PKEY_free (pkey); } } From 61588777beb8b2bc3865476ee8670ddb93572c64 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 15 Jun 2025 08:06:34 -0400 Subject: [PATCH 1080/1171] set default transit tunnels limit to 10000 --- contrib/i2pd.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/i2pd.conf b/contrib/i2pd.conf index c26f8af0..fa6b1f8b 100644 --- a/contrib/i2pd.conf +++ b/contrib/i2pd.conf @@ -246,9 +246,9 @@ verify = true # subscriptions = http://reg.i2p/hosts.txt,http://identiguy.i2p/hosts.txt,http://stats.i2p/cgi-bin/newhosts.txt [limits] -## Maximum active transit sessions (default: 5000) +## Maximum active transit sessions (default: 10000) ## This value is doubled if floodfill mode is enabled! -# transittunnels = 5000 +# transittunnels = 10000 ## Limit number of open file descriptors (0 - use system limit) # openfiles = 0 ## Maximum size of corefile in Kb (0 - use system limit) From 5f0262ea2f60cf50dc600929ae6db738a0a19020 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 18 Jun 2025 13:19:49 -0400 Subject: [PATCH 1081/1171] use EVP_Digest_ insted deprecated SHA512_ functions --- libi2pd/Ed25519.cpp | 56 ++++++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/libi2pd/Ed25519.cpp b/libi2pd/Ed25519.cpp index 47edb755..55d7711d 100644 --- a/libi2pd/Ed25519.cpp +++ b/libi2pd/Ed25519.cpp @@ -1,12 +1,12 @@ /* -* Copyright (c) 2013-2024, The PurpleI2P Project +* Copyright (c) 2013-2025, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * * See full license text in LICENSE file at top of project tree */ -#include +#include #include "Log.h" #include "Crypto.h" #include "Ed25519.h" @@ -134,22 +134,27 @@ namespace crypto { BN_CTX * bnCtx = BN_CTX_new (); // calculate r - SHA512_CTX ctx; - SHA512_Init (&ctx); - SHA512_Update (&ctx, expandedPrivateKey + EDDSA25519_PRIVATE_KEY_LENGTH, EDDSA25519_PRIVATE_KEY_LENGTH); // right half of expanded key - SHA512_Update (&ctx, buf, len); // data + EVP_MD_CTX * ctx = EVP_MD_CTX_create (); + EVP_DigestInit_ex (ctx, EVP_sha512(), NULL); + EVP_DigestUpdate (ctx, expandedPrivateKey + EDDSA25519_PRIVATE_KEY_LENGTH, EDDSA25519_PRIVATE_KEY_LENGTH); // right half of expanded key + EVP_DigestUpdate (ctx, buf, len); // data uint8_t digest[64]; - SHA512_Final (digest, &ctx); + unsigned int dl = 64; + EVP_DigestFinal_ex (ctx, digest, &dl); + EVP_MD_CTX_destroy (ctx); BIGNUM * r = DecodeBN<32> (digest); // DecodeBN<64> (digest); // for test vectors // calculate R uint8_t R[EDDSA25519_SIGNATURE_LENGTH/2]; // we must use separate buffer because signature might be inside buf EncodePoint (Normalize (MulB (digest, bnCtx), bnCtx), R); // EncodePoint (Mul (B, r, bnCtx), R); // for test vectors // calculate S - SHA512_Init (&ctx); - SHA512_Update (&ctx, R, EDDSA25519_SIGNATURE_LENGTH/2); // R - SHA512_Update (&ctx, publicKeyEncoded, EDDSA25519_PUBLIC_KEY_LENGTH); // public key - SHA512_Update (&ctx, buf, len); // data - SHA512_Final (digest, &ctx); + ctx = EVP_MD_CTX_create (); + EVP_DigestInit_ex (ctx, EVP_sha512(), NULL); + EVP_DigestUpdate (ctx, R, EDDSA25519_SIGNATURE_LENGTH/2); // R + EVP_DigestUpdate (ctx, publicKeyEncoded, EDDSA25519_PUBLIC_KEY_LENGTH); // public key + EVP_DigestUpdate (ctx, buf, len); // data + dl = 64; + EVP_DigestFinal_ex (ctx, digest, &dl); + EVP_MD_CTX_destroy (ctx); BIGNUM * h = DecodeBN<64> (digest); // S = (r + h*a) % l BIGNUM * a = DecodeBN (expandedPrivateKey); // left half of expanded key @@ -169,13 +174,15 @@ namespace crypto uint8_t T[80]; RAND_bytes (T, 80); // calculate r = H*(T || publickey || data) - SHA512_CTX ctx; - SHA512_Init (&ctx); - SHA512_Update (&ctx, T, 80); - SHA512_Update (&ctx, publicKeyEncoded, 32); - SHA512_Update (&ctx, buf, len); // data + EVP_MD_CTX * ctx = EVP_MD_CTX_create (); + EVP_DigestInit_ex (ctx, EVP_sha512(), NULL); + EVP_DigestUpdate (ctx, T, 80); + EVP_DigestUpdate (ctx, publicKeyEncoded, 32); + EVP_DigestUpdate (ctx, buf, len); // data uint8_t digest[64]; - SHA512_Final (digest, &ctx); + unsigned int dl = 64; + EVP_DigestFinal_ex (ctx, digest, &dl); + EVP_MD_CTX_destroy (ctx); BIGNUM * r = DecodeBN<64> (digest); BN_mod (r, r, l, bnCtx); // % l EncodeBN (r, digest, 32); @@ -183,11 +190,14 @@ namespace crypto uint8_t R[EDDSA25519_SIGNATURE_LENGTH/2]; // we must use separate buffer because signature might be inside buf EncodePoint (Normalize (MulB (digest, bnCtx), bnCtx), R); // calculate S - SHA512_Init (&ctx); - SHA512_Update (&ctx, R, EDDSA25519_SIGNATURE_LENGTH/2); // R - SHA512_Update (&ctx, publicKeyEncoded, EDDSA25519_PUBLIC_KEY_LENGTH); // public key - SHA512_Update (&ctx, buf, len); // data - SHA512_Final (digest, &ctx); + ctx = EVP_MD_CTX_create (); + EVP_DigestInit_ex (ctx, EVP_sha512(), NULL); + EVP_DigestUpdate (ctx, R, EDDSA25519_SIGNATURE_LENGTH/2); // R + EVP_DigestUpdate (ctx, publicKeyEncoded, EDDSA25519_PUBLIC_KEY_LENGTH); // public key + EVP_DigestUpdate (ctx, buf, len); // data + dl = 64; + EVP_DigestFinal_ex (ctx, digest, &dl); + EVP_MD_CTX_destroy (ctx); BIGNUM * h = DecodeBN<64> (digest); // S = (r + h*a) % l BIGNUM * a = DecodeBN (privateKey); From 78357c23d22f8a62290b02f745e97f9e987cb166 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 18 Jun 2025 20:39:48 -0400 Subject: [PATCH 1082/1171] don't verify signature in incoming SYN packet if came from ECIESx25519 session. Compare static key instead --- libi2pd/Destination.cpp | 7 ++-- libi2pd/Destination.h | 4 +- libi2pd/Streaming.cpp | 83 ++++++++++++++++++++++++++++------------- libi2pd/Streaming.h | 6 ++- libi2pd_client/I2CP.cpp | 3 +- libi2pd_client/I2CP.h | 2 +- 6 files changed, 70 insertions(+), 35 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 52418471..e1ccbc92 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -388,7 +388,7 @@ namespace client switch (typeID) { case eI2NPData: - HandleDataMessage (payload, len); + HandleDataMessage (payload, len, from); break; case eI2NPDeliveryStatus: HandleDeliveryStatusMessage (bufbe32toh (payload + DELIVERY_STATUS_MSGID_OFFSET)); @@ -1158,7 +1158,8 @@ namespace client LogPrint(eLogDebug, "Destination: -> Stopping done"); } - void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len) + void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len, + i2p::garlic::ECIESX25519AEADRatchetSession * from) { uint32_t length = bufbe32toh (buf); if(length > len - 4) @@ -1183,7 +1184,7 @@ namespace client m_LastPort = toPort; } if (m_LastStreamingDestination) - m_LastStreamingDestination->HandleDataMessagePayload (buf, length); + m_LastStreamingDestination->HandleDataMessagePayload (buf, length, from); else LogPrint (eLogError, "Destination: Missing streaming destination"); } diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 35557859..f2bef491 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -174,7 +174,7 @@ namespace client virtual void CleanupDestination () {}; // additional clean up in derived classes virtual i2p::data::CryptoKeyType GetPreferredCryptoType () const = 0; // I2CP - virtual void HandleDataMessage (const uint8_t * buf, size_t len) = 0; + virtual void HandleDataMessage (const uint8_t * buf, size_t len, i2p::garlic::ECIESX25519AEADRatchetSession * from) = 0; virtual void CreateNewLeaseSet (const std::vector >& tunnels) = 0; private: @@ -288,7 +288,7 @@ namespace client void CleanupDestination () override; i2p::data::CryptoKeyType GetPreferredCryptoType () const override { return m_PreferredCryptoType; } // I2CP - void HandleDataMessage (const uint8_t * buf, size_t len) override; + void HandleDataMessage (const uint8_t * buf, size_t len, i2p::garlic::ECIESX25519AEADRatchetSession * from) override; void CreateNewLeaseSet (const std::vector >& tunnels) override; private: diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 8d125e6f..cb401b06 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -397,6 +397,7 @@ namespace stream optionData += 2; } + bool sessionVerified = false; if (flags & PACKET_FLAG_FROM_INCLUDED) { if (m_RemoteLeaseSet) m_RemoteIdentity = m_RemoteLeaseSet->GetIdentity (); @@ -409,7 +410,29 @@ namespace stream } optionData += m_RemoteIdentity->GetFullLen (); if (!m_RemoteLeaseSet) - LogPrint (eLogDebug, "Streaming: Incoming stream from ", m_RemoteIdentity->GetIdentHash ().ToBase64 (), ", sSID=", m_SendStreamID, ", rSID=", m_RecvStreamID); + { + LogPrint (eLogDebug, "Streaming: Incoming stream from ", m_RemoteIdentity->GetIdentHash ().ToBase32 (), ", sSID=", m_SendStreamID, ", rSID=", m_RecvStreamID); + if (packet->from) + { + // stream came from ratchets session and static key must match one from LeaseSet + m_RemoteLeaseSet = m_LocalDestination.GetOwner ()->FindLeaseSet (m_RemoteIdentity->GetIdentHash ()); + if (!m_RemoteLeaseSet) + { + LogPrint (eLogInfo, "Streaming: Incoming stream from ", m_RemoteIdentity->GetIdentHash ().ToBase32 (), + " without LeaseSet. sSID=", m_SendStreamID, ", rSID=", m_RecvStreamID); + return false; + } + uint8_t staticKey[32]; + m_RemoteLeaseSet->Encrypt (nullptr, staticKey); + if (memcmp (packet->from->GetRemoteStaticKey (), staticKey, 32)) + { + LogPrint (eLogError, "Streaming: Remote LeaseSet static key mismatch for incoming stream from ", + m_RemoteIdentity->GetIdentHash ().ToBase32 ()); + return false; + } + sessionVerified = true; + } + } } if (flags & PACKET_FLAG_MAX_PACKET_SIZE_INCLUDED) @@ -451,35 +474,39 @@ namespace stream if (flags & PACKET_FLAG_SIGNATURE_INCLUDED) { - bool verified = false; auto signatureLen = m_TransientVerifier ? m_TransientVerifier->GetSignatureLen () : m_RemoteIdentity->GetSignatureLen (); if (signatureLen > packet->GetLength ()) { LogPrint (eLogError, "Streaming: Signature too big, ", signatureLen, " bytes"); return false; } - if(signatureLen <= 256) - { - // standard - uint8_t signature[256]; - memcpy (signature, optionData, signatureLen); - memset (const_cast(optionData), 0, signatureLen); - verified = m_TransientVerifier ? - m_TransientVerifier->Verify (packet->GetBuffer (), packet->GetLength (), signature) : - m_RemoteIdentity->Verify (packet->GetBuffer (), packet->GetLength (), signature); - if (verified) - memcpy (const_cast(optionData), signature, signatureLen); - } - else - { - // post quantum - std::vector signature(signatureLen); - memcpy (signature.data (), optionData, signatureLen); - memset (const_cast(optionData), 0, signatureLen); - verified = m_TransientVerifier ? - m_TransientVerifier->Verify (packet->GetBuffer (), packet->GetLength (), signature.data ()) : - m_RemoteIdentity->Verify (packet->GetBuffer (), packet->GetLength (), signature.data ()); - } + bool verified = sessionVerified; + if (!verified) // packet was not verified through session + { + // verify actual signature + if (signatureLen <= 256) + { + // standard + uint8_t signature[256]; + memcpy (signature, optionData, signatureLen); + memset (const_cast(optionData), 0, signatureLen); + verified = m_TransientVerifier ? + m_TransientVerifier->Verify (packet->GetBuffer (), packet->GetLength (), signature) : + m_RemoteIdentity->Verify (packet->GetBuffer (), packet->GetLength (), signature); + if (verified) + memcpy (const_cast(optionData), signature, signatureLen); + } + else + { + // post quantum + std::vector signature(signatureLen); + memcpy (signature.data (), optionData, signatureLen); + memset (const_cast(optionData), 0, signatureLen); + verified = m_TransientVerifier ? + m_TransientVerifier->Verify (packet->GetBuffer (), packet->GetLength (), signature.data ()) : + m_RemoteIdentity->Verify (packet->GetBuffer (), packet->GetLength (), signature.data ()); + } + } if (verified) optionData += signatureLen; else @@ -812,7 +839,7 @@ namespace stream { // initial packet m_Status = eStreamStatusOpen; - if (!m_RemoteLeaseSet) m_RemoteLeaseSet = m_LocalDestination.GetOwner ()->FindLeaseSet (m_RemoteIdentity->GetIdentHash ());; + if (!m_RemoteLeaseSet) m_RemoteLeaseSet = m_LocalDestination.GetOwner ()->FindLeaseSet (m_RemoteIdentity->GetIdentHash ()); if (m_RemoteLeaseSet) { m_RoutingSession = m_LocalDestination.GetOwner ()->GetRoutingSession (m_RemoteLeaseSet, true, !m_IsIncoming); @@ -2054,14 +2081,18 @@ namespace stream } } - void StreamingDestination::HandleDataMessagePayload (const uint8_t * buf, size_t len) + void StreamingDestination::HandleDataMessagePayload (const uint8_t * buf, size_t len, + i2p::garlic::ECIESX25519AEADRatchetSession * from) { // unzip it Packet * uncompressed = NewPacket (); uncompressed->offset = 0; uncompressed->len = m_Inflator.Inflate (buf, len, uncompressed->buf, MAX_PACKET_SIZE); if (uncompressed->len) + { + uncompressed->from = from; HandleNextPacket (uncompressed); + } else DeletePacket (uncompressed); } diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 9fbcb178..eae43c0e 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -27,6 +27,7 @@ #include "Garlic.h" #include "Tunnel.h" #include "util.h" // MemoryPool +#include "ECIESX25519AEADRatchetSession.h" namespace i2p { @@ -88,8 +89,9 @@ namespace stream uint8_t buf[MAX_PACKET_SIZE]; uint64_t sendTime; bool resent; + i2p::garlic::ECIESX25519AEADRatchetSession * from; - Packet (): len (0), offset (0), sendTime (0), resent (false) {}; + Packet (): len (0), offset (0), sendTime (0), resent (false), from (nullptr) {}; uint8_t * GetBuffer () { return buf + offset; }; size_t GetLength () const { return len > offset ? len - offset : 0; }; @@ -340,7 +342,7 @@ namespace stream void SetOwner (std::shared_ptr owner) { m_Owner = owner; }; uint16_t GetLocalPort () const { return m_LocalPort; }; - void HandleDataMessagePayload (const uint8_t * buf, size_t len); + void HandleDataMessagePayload (const uint8_t * buf, size_t len, i2p::garlic::ECIESX25519AEADRatchetSession * from); std::shared_ptr CreateDataMessage (const uint8_t * payload, size_t len, uint16_t toPort, bool checksum = true, bool gzip = false); Packet * NewPacket () { return m_PacketsPool.Acquire(); } diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index 11278e7a..f2e9be57 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -86,7 +86,8 @@ namespace client return i2p::data::CRYPTO_KEY_TYPE_ELGAMAL; } - void I2CPDestination::HandleDataMessage (const uint8_t * buf, size_t len) + void I2CPDestination::HandleDataMessage (const uint8_t * buf, size_t len, + i2p::garlic::ECIESX25519AEADRatchetSession * from) { uint32_t length = bufbe32toh (buf); if (length > len - 4) length = len - 4; diff --git a/libi2pd_client/I2CP.h b/libi2pd_client/I2CP.h index 37c14dbb..0bfa49f2 100644 --- a/libi2pd_client/I2CP.h +++ b/libi2pd_client/I2CP.h @@ -117,7 +117,7 @@ namespace client void CleanupDestination () override; i2p::data::CryptoKeyType GetPreferredCryptoType () const override; // I2CP - void HandleDataMessage (const uint8_t * buf, size_t len) override; + void HandleDataMessage (const uint8_t * buf, size_t len, i2p::garlic::ECIESX25519AEADRatchetSession * from) override; void CreateNewLeaseSet (const std::vector >& tunnels) override; private: From a6bf6baf1ba8ebecda82001fdcab0d1422caded4 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 19 Jun 2025 18:32:43 -0400 Subject: [PATCH 1083/1171] don't verify signature for SYN-ACK if comes from ECIESx25519 session --- libi2pd/Streaming.cpp | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index cb401b06..ae14a38d 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -412,26 +412,21 @@ namespace stream if (!m_RemoteLeaseSet) { LogPrint (eLogDebug, "Streaming: Incoming stream from ", m_RemoteIdentity->GetIdentHash ().ToBase32 (), ", sSID=", m_SendStreamID, ", rSID=", m_RecvStreamID); - if (packet->from) - { - // stream came from ratchets session and static key must match one from LeaseSet + if (packet->from) // try to obtain LeaseSet if came from ratchets session m_RemoteLeaseSet = m_LocalDestination.GetOwner ()->FindLeaseSet (m_RemoteIdentity->GetIdentHash ()); - if (!m_RemoteLeaseSet) - { - LogPrint (eLogInfo, "Streaming: Incoming stream from ", m_RemoteIdentity->GetIdentHash ().ToBase32 (), - " without LeaseSet. sSID=", m_SendStreamID, ", rSID=", m_RecvStreamID); - return false; - } - uint8_t staticKey[32]; - m_RemoteLeaseSet->Encrypt (nullptr, staticKey); - if (memcmp (packet->from->GetRemoteStaticKey (), staticKey, 32)) - { - LogPrint (eLogError, "Streaming: Remote LeaseSet static key mismatch for incoming stream from ", - m_RemoteIdentity->GetIdentHash ().ToBase32 ()); - return false; - } - sessionVerified = true; + } + if (packet->from && m_RemoteLeaseSet) + { + // stream came from ratchets session and static key must match one from LeaseSet + uint8_t staticKey[32]; + m_RemoteLeaseSet->Encrypt (nullptr, staticKey); + if (memcmp (packet->from->GetRemoteStaticKey (), staticKey, 32)) + { + LogPrint (eLogError, "Streaming: Remote LeaseSet static key mismatch for stream from ", + m_RemoteIdentity->GetIdentHash ().ToBase32 ()); + return false; } + sessionVerified = true; } } From 6b519c36c5f1f2f47286d9625af4a37760478fcf Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 20 Jun 2025 13:34:20 -0400 Subject: [PATCH 1084/1171] increased number of floodfills threshold --- libi2pd/NetDb.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index f2a7019b..8d17628f 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -41,7 +41,7 @@ namespace data const int NETDB_MIN_ROUTERS = 90; const int NETDB_MIN_FLOODFILLS = 5; const int NETDB_MIN_TRANSPORTS = 10 ; // otherwise assume offline - const int NETDB_NUM_FLOODFILLS_THRESHOLD = 1200; + const int NETDB_NUM_FLOODFILLS_THRESHOLD = 1500; const int NETDB_NUM_ROUTERS_THRESHOLD = 4*NETDB_NUM_FLOODFILLS_THRESHOLD; const int NETDB_TUNNEL_CREATION_RATE_THRESHOLD = 10; // in % const int NETDB_CHECK_FOR_EXPIRATION_UPTIME = 600; // 10 minutes, in seconds From 9efdc230a912f51fafe577d4a2cb91d216870685 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 21 Jun 2025 22:07:59 -0400 Subject: [PATCH 1085/1171] don't check destination if first packet comes from ECIESx25519 session --- libi2pd/Streaming.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index ae14a38d..e2790288 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -187,7 +187,7 @@ namespace stream if (!m_SendStreamID) { m_SendStreamID = packet->GetReceiveStreamID (); - if (!m_RemoteIdentity && packet->GetNACKCount () == 8 && // first incoming packet + if (!m_RemoteIdentity && !packet->from && packet->GetNACKCount () == 8 && // first incoming packet memcmp (packet->GetNACKs (), m_LocalDestination.GetOwner ()->GetIdentHash (), 32)) { LogPrint (eLogWarning, "Streaming: Destination mismatch for ", m_LocalDestination.GetOwner ()->GetIdentHash ().ToBase32 ()); From 75dd0d72c66c9c86d71ee6efbd2b58103bea7589 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 23 Jun 2025 21:53:44 -0400 Subject: [PATCH 1086/1171] skip transient signature verification if verified through ECIESx25519 session --- libi2pd/Streaming.cpp | 47 +++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index e2790288..66c8919d 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -444,27 +444,44 @@ namespace stream LogPrint (eLogInfo, "Streaming: offline signature without identity"); return false; } - // if we have it in LeaseSet already we don't need to parse it again - if (m_RemoteLeaseSet) m_TransientVerifier = m_RemoteLeaseSet->GetTransientVerifier (); - if (m_TransientVerifier) + if (sessionVerified) { - // skip option data - optionData += 6; // timestamp and key type - optionData += m_TransientVerifier->GetPublicKeyLen (); // public key + // skip offline signature + optionData += 4; // timestamp + uint16_t keyType = bufbe16toh (optionData); optionData += 2; // key type + std::unique_ptr transientVerifier (i2p::data::IdentityEx::CreateVerifier (keyType)); + if (!transientVerifier) + { + LogPrint (eLogInfo, "Streaming: Unknown offline signature key type ", (int)keyType); + return false; + } + optionData += transientVerifier->GetPublicKeyLen (); // public key optionData += m_RemoteIdentity->GetSignatureLen (); // signature } else - { - // transient key - size_t offset = 0; - m_TransientVerifier = i2p::data::ProcessOfflineSignature (m_RemoteIdentity, optionData, optionSize - (optionData - packet->GetOptionData ()), offset); - optionData += offset; - if (!m_TransientVerifier) + { + // if we have it in LeaseSet already we don't need to parse it again + if (m_RemoteLeaseSet) m_TransientVerifier = m_RemoteLeaseSet->GetTransientVerifier (); + if (m_TransientVerifier) { - LogPrint (eLogError, "Streaming: offline signature failed"); - return false; + // skip option data + optionData += 6; // timestamp and key type + optionData += m_TransientVerifier->GetPublicKeyLen (); // public key + optionData += m_RemoteIdentity->GetSignatureLen (); // signature } - } + else + { + // transient key + size_t offset = 0; + m_TransientVerifier = i2p::data::ProcessOfflineSignature (m_RemoteIdentity, optionData, optionSize - (optionData - packet->GetOptionData ()), offset); + optionData += offset; + if (!m_TransientVerifier) + { + LogPrint (eLogError, "Streaming: offline signature failed"); + return false; + } + } + } } if (flags & PACKET_FLAG_SIGNATURE_INCLUDED) From 40b90ccea4750f579b02289fae0a6fbce3e9eb48 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 24 Jun 2025 18:00:02 -0400 Subject: [PATCH 1087/1171] recognize and verify datagram3 --- libi2pd/Datagram.cpp | 52 +++++++++++++++++++++++++++++++++++++---- libi2pd/Datagram.h | 12 ++++++---- libi2pd/Destination.cpp | 12 ++++------ libi2pd/Destination.h | 2 ++ 4 files changed, 61 insertions(+), 17 deletions(-) diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp index 732efca7..1903f7ae 100644 --- a/libi2pd/Datagram.cpp +++ b/libi2pd/Datagram.cpp @@ -126,6 +126,34 @@ namespace datagram LogPrint (eLogWarning, "DatagramDestination: no receiver for raw datagram"); } + void DatagramDestination::HandleDatagram3 (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len, + i2p::garlic::ECIESX25519AEADRatchetSession * from) + { + if (from) + { + i2p::data::IdentHash ident(buf); + auto ls = m_Owner->FindLeaseSet (ident); + if (ls) + { + uint8_t staticKey[32]; + ls->Encrypt (nullptr, staticKey); + if (!memcmp (from->GetRemoteStaticKey (), staticKey, 32)) + { + auto session = ObtainSession (ident); + session->SetRemoteLeaseSet (ls); + session->Ack (); + // TODO: + } + else + LogPrint (eLogError, "Datagram: Remote LeaseSet static key mismatch for datagram3 from ", ident.ToBase32 ()); + } + else + LogPrint (eLogError, "Datagram: No remote LeaseSet for ", ident.ToBase32 ()); + } + else + LogPrint (eLogInfo, "Datagram: datagram3 received from non-ratchets session"); + } + void DatagramDestination::SetReceiver (const Receiver& receiver, uint16_t port) { std::lock_guard lock(m_ReceiversMutex); @@ -194,17 +222,31 @@ namespace datagram return r; } - void DatagramDestination::HandleDataMessagePayload (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len, bool isRaw) + void DatagramDestination::HandleDataMessagePayload (uint16_t fromPort, uint16_t toPort, + const uint8_t * buf, size_t len, uint8_t protocolType, i2p::garlic::ECIESX25519AEADRatchetSession * from) { // unzip it uint8_t uncompressed[MAX_DATAGRAM_SIZE]; size_t uncompressedLen = m_Inflator.Inflate (buf, len, uncompressed, MAX_DATAGRAM_SIZE); if (uncompressedLen) { - if (isRaw) - HandleRawDatagram (fromPort, toPort, uncompressed, uncompressedLen); - else - HandleDatagram (fromPort, toPort, uncompressed, uncompressedLen); + switch (protocolType) + { + case i2p::client::PROTOCOL_TYPE_RAW: + HandleRawDatagram (fromPort, toPort, uncompressed, uncompressedLen); + break; + case i2p::client::PROTOCOL_TYPE_DATAGRAM3: + HandleDatagram3 (fromPort, toPort, uncompressed, uncompressedLen, from); + break; + case i2p::client::PROTOCOL_TYPE_DATAGRAM: + HandleDatagram (fromPort, toPort, uncompressed, uncompressedLen); + break; + case i2p::client::PROTOCOL_TYPE_DATAGRAM2: + // TODO: + break; + default: + LogPrint (eLogInfo, "Datagram: unknown protocol type ", protocolType); + }; } else LogPrint (eLogWarning, "Datagram: decompression failed"); diff --git a/libi2pd/Datagram.h b/libi2pd/Datagram.h index dd358434..d68bdd07 100644 --- a/libi2pd/Datagram.h +++ b/libi2pd/Datagram.h @@ -20,6 +20,7 @@ #include "LeaseSet.h" #include "I2NPProtocol.h" #include "Garlic.h" +#include "ECIESX25519AEADRatchetSession.h" namespace i2p { @@ -64,8 +65,9 @@ namespace datagram /** get the last time in milliseconds for when we used this datagram session */ uint64_t LastActivity() const { return m_LastUse; } - bool IsRatchets () const { return m_RoutingSession && m_RoutingSession->IsRatchets (); } - + bool IsRatchets () const { return m_RoutingSession && m_RoutingSession->IsRatchets (); } + void SetRemoteLeaseSet (std::shared_ptr ls) { m_RemoteLeaseSet = ls; } + struct Info { std::shared_ptr IBGW; @@ -124,8 +126,8 @@ namespace datagram void SendRawDatagram (std::shared_ptr session, const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort); void FlushSendQueue (std::shared_ptr session); - void HandleDataMessagePayload (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len, bool isRaw = false); - + void HandleDataMessagePayload (uint16_t fromPort, uint16_t toPort, + const uint8_t * buf, size_t len, uint8_t protocolType, i2p::garlic::ECIESX25519AEADRatchetSession * from); void SetReceiver (const Receiver& receiver, uint16_t port); void ResetReceiver (uint16_t port); @@ -147,6 +149,8 @@ namespace datagram void HandleDatagram (uint16_t fromPort, uint16_t toPort, uint8_t *const& buf, size_t len); void HandleRawDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); + void HandleDatagram3 (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len, + i2p::garlic::ECIESX25519AEADRatchetSession * from); Receiver FindReceiver(uint16_t port); RawReceiver FindRawReceiver(uint16_t port); diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index e1ccbc92..4ce825a6 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1190,19 +1190,15 @@ namespace client } break; case PROTOCOL_TYPE_DATAGRAM: + case PROTOCOL_TYPE_RAW: + case PROTOCOL_TYPE_DATAGRAM2: + case PROTOCOL_TYPE_DATAGRAM3: // datagram protocol if (m_DatagramDestination) - m_DatagramDestination->HandleDataMessagePayload (fromPort, toPort, buf, length); + m_DatagramDestination->HandleDataMessagePayload (fromPort, toPort, buf, length, buf[9], from); else LogPrint (eLogError, "Destination: Missing datagram destination"); break; - case PROTOCOL_TYPE_RAW: - // raw datagram - if (m_DatagramDestination) - m_DatagramDestination->HandleDataMessagePayload (fromPort, toPort, buf, length, true); - else - LogPrint (eLogError, "Destination: Missing raw datagram destination"); - break; default: LogPrint (eLogError, "Destination: Data: Unexpected protocol ", buf[9]); } diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index f2bef491..717f35ce 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -37,6 +37,8 @@ namespace client const uint8_t PROTOCOL_TYPE_STREAMING = 6; const uint8_t PROTOCOL_TYPE_DATAGRAM = 17; const uint8_t PROTOCOL_TYPE_RAW = 18; + const uint8_t PROTOCOL_TYPE_DATAGRAM2 = 19; + const uint8_t PROTOCOL_TYPE_DATAGRAM3 = 20; const int PUBLISH_CONFIRMATION_TIMEOUT = 1800; // in milliseconds const int PUBLISH_VERIFICATION_TIMEOUT = 5; // in seconds after successful publish const int PUBLISH_VERIFICATION_TIMEOUT_VARIANCE = 3; // in seconds From 8c89c8368af4d8739024956f5d63096f2e6f637b Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 24 Jun 2025 22:06:36 -0400 Subject: [PATCH 1088/1171] handle Datagram3 --- libi2pd/Datagram.cpp | 22 +++++++++++++++++++++- libi2pd/Datagram.h | 2 ++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp index 1903f7ae..de4b5674 100644 --- a/libi2pd/Datagram.cpp +++ b/libi2pd/Datagram.cpp @@ -129,6 +129,11 @@ namespace datagram void DatagramDestination::HandleDatagram3 (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len, i2p::garlic::ECIESX25519AEADRatchetSession * from) { + if (len < 34) + { + LogPrint (eLogWarning, "Datagram: datagram3 is too short ", len); + return; + } if (from) { i2p::data::IdentHash ident(buf); @@ -142,7 +147,22 @@ namespace datagram auto session = ObtainSession (ident); session->SetRemoteLeaseSet (ls); session->Ack (); - // TODO: + auto r = FindReceiver(toPort); + if (r) + { + uint16_t flags = bufbe16toh (buf + 32); + size_t offset = 34; + if (flags & DATAGRAM3_FLAG_OPTIONS) + offset += bufbe16toh (buf + offset) + 2; + if (offset > len) + { + LogPrint (eLogWarning, "Datagram: datagram3 is too short ", len, " expected ", offset); + return; + } + r(*ls->GetIdentity (), fromPort, toPort, buf + offset, len - offset); + } + else + LogPrint (eLogWarning, "Datagram: no receiver for port ", toPort); } else LogPrint (eLogError, "Datagram: Remote LeaseSet static key mismatch for datagram3 from ", ident.ToBase32 ()); diff --git a/libi2pd/Datagram.h b/libi2pd/Datagram.h index d68bdd07..a293c84b 100644 --- a/libi2pd/Datagram.h +++ b/libi2pd/Datagram.h @@ -45,6 +45,8 @@ namespace datagram const uint64_t DATAGRAM_MAX_FLUSH_INTERVAL = 5; // in milliseconds const int DATAGRAM_SESSION_ACK_REQUEST_INTERVAL = 5500; // in milliseconds + constexpr uint16_t DATAGRAM3_FLAG_OPTIONS = 0x10; + class DatagramSession : public std::enable_shared_from_this { From 31b6f07b788e6813ca128149cb25878f2edef72c Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 26 Jun 2025 18:01:03 -0400 Subject: [PATCH 1089/1171] set ECIESx25519 session's destination from LeaseSet --- libi2pd/Destination.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 4ce825a6..394435c5 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -489,7 +489,9 @@ namespace client if (leaseSet->GetIdentHash () != GetIdentHash ()) { LogPrint (eLogDebug, "Destination: New remote LeaseSet added"); - m_RemoteLeaseSets[key] = leaseSet; + m_RemoteLeaseSets.insert_or_assign (key, leaseSet); + if (from) + from->SetDestination (key); } else LogPrint (eLogDebug, "Destination: Own remote LeaseSet dropped"); From 0445a5d775ec9c5cfb140baef5e47d393826ac16 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 30 Jun 2025 15:47:19 -0400 Subject: [PATCH 1090/1171] send actual version in SetDate --- libi2pd_client/I2CP.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index f2e9be57..5603697d 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -624,17 +624,14 @@ namespace client void I2CPSession::GetDateMessageHandler (const uint8_t * buf, size_t len) { - // get version - auto version = ExtractString (buf, len); - auto l = version.length () + 1 + 8; - uint8_t * payload = new uint8_t[l]; + constexpr std::string_view version(I2P_VERSION); + std::array payload; // set date auto ts = i2p::util::GetMillisecondsSinceEpoch (); - htobe64buf (payload, ts); - // echo vesrion back - PutString (payload + 8, l - 8, version); - SendI2CPMessage (I2CP_SET_DATE_MESSAGE, payload, l); - delete[] payload; + htobe64buf (payload.data(), ts); + // send our version back + PutString (payload.data() + 8, payload.size() - 8, version); + SendI2CPMessage (I2CP_SET_DATE_MESSAGE, payload.data(), payload.size()); } void I2CPSession::CreateSessionMessageHandler (const uint8_t * buf, size_t len) From f230c110aa25bebe63be175ccb9825c8d6bfa0bf Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 30 Jun 2025 15:49:42 -0400 Subject: [PATCH 1091/1171] send actual version in SetDate --- libi2pd_client/I2CP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index 5603697d..85c58c48 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -625,7 +625,7 @@ namespace client void I2CPSession::GetDateMessageHandler (const uint8_t * buf, size_t len) { constexpr std::string_view version(I2P_VERSION); - std::array payload; + std::array payload; // set date auto ts = i2p::util::GetMillisecondsSinceEpoch (); htobe64buf (payload.data(), ts); From a5631bd1b5169a8fd60fc30ddfc8b18cf8bb6e50 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 30 Jun 2025 15:57:17 -0400 Subject: [PATCH 1092/1171] send Datagram3 --- libi2pd/Datagram.cpp | 38 ++++++++++++++++++++++++-------------- libi2pd/Datagram.h | 13 ++++++++++++- 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp index de4b5674..2f3d5eef 100644 --- a/libi2pd/Datagram.cpp +++ b/libi2pd/Datagram.cpp @@ -58,25 +58,35 @@ namespace datagram { if (session) { - if (m_Owner->GetIdentity ()->GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1) + if (session->GetVersion () == eDatagramV3) { - uint8_t hash[32]; - SHA256(payload, len, hash); - m_Owner->Sign (hash, 32, m_Signature.data ()); + constexpr uint8_t flags[] = { 0x00, 0x03 }; // datagram3, no options + auto msg = CreateDataMessage ({{m_Owner->GetIdentity ()->GetIdentHash (), 32}, + {flags, 2}, {payload, len}}, fromPort, toPort, i2p::client::PROTOCOL_TYPE_DATAGRAM3, false); // datagram3 + session->SendMsg(msg); } else - m_Owner->Sign (payload, len, m_Signature.data ()); + { + if (m_Owner->GetIdentity ()->GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1) + { + uint8_t hash[32]; + SHA256(payload, len, hash); + m_Owner->Sign (hash, 32, m_Signature.data ()); + } + else + m_Owner->Sign (payload, len, m_Signature.data ()); - auto msg = CreateDataMessage ({{m_From.data (), m_From.size ()}, {m_Signature.data (), m_Signature.size ()}, {payload, len}}, - fromPort, toPort, false, !session->IsRatchets ()); // datagram - session->SendMsg(msg); + auto msg = CreateDataMessage ({{m_From.data (), m_From.size ()}, {m_Signature.data (), m_Signature.size ()}, {payload, len}}, + fromPort, toPort, i2p::client::PROTOCOL_TYPE_DATAGRAM, !session->IsRatchets ()); // datagram1 + session->SendMsg(msg); + } } } void DatagramDestination::SendRawDatagram (std::shared_ptr session, const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort) { if (session) - session->SendMsg(CreateDataMessage ({{payload, len}}, fromPort, toPort, true, !session->IsRatchets ())); // raw + session->SendMsg(CreateDataMessage ({{payload, len}}, fromPort, toPort, i2p::client::PROTOCOL_TYPE_RAW, !session->IsRatchets ())); // raw } void DatagramDestination::FlushSendQueue (std::shared_ptr session) @@ -145,6 +155,7 @@ namespace datagram if (!memcmp (from->GetRemoteStaticKey (), staticKey, 32)) { auto session = ObtainSession (ident); + session->SetVersion (eDatagramV3); session->SetRemoteLeaseSet (ls); session->Ack (); auto r = FindReceiver(toPort); @@ -274,7 +285,7 @@ namespace datagram std::shared_ptr DatagramDestination::CreateDataMessage ( const std::vector >& payloads, - uint16_t fromPort, uint16_t toPort, bool isRaw, bool checksum) + uint16_t fromPort, uint16_t toPort, uint8_t protocolType, bool checksum) { size_t size; auto msg = m_I2NPMsgsPool.AcquireShared (); @@ -290,8 +301,8 @@ namespace datagram { htobe32buf (msg->GetPayload (), size); // length htobe16buf (buf + 4, fromPort); // source port - htobe16buf (buf + 6, toPort); // destination port - buf[9] = isRaw ? i2p::client::PROTOCOL_TYPE_RAW : i2p::client::PROTOCOL_TYPE_DATAGRAM; // raw or datagram protocol + htobe16buf (buf + 6, toPort); // destination port + buf[9] = protocolType; // raw or datagram protocol msg->len += size + 4; msg->FillI2NPMessageHeader (eI2NPData, 0, checksum); } @@ -350,8 +361,7 @@ namespace datagram DatagramSession::DatagramSession(std::shared_ptr localDestination, const i2p::data::IdentHash & remoteIdent) : m_LocalDestination(localDestination), m_RemoteIdent(remoteIdent), - m_LastUse (0), m_LastFlush (0), - m_RequestingLS(false) + m_LastUse (0), m_LastFlush (0), m_RequestingLS (false), m_Version (eDatagramV1) { } diff --git a/libi2pd/Datagram.h b/libi2pd/Datagram.h index a293c84b..a6fc130d 100644 --- a/libi2pd/Datagram.h +++ b/libi2pd/Datagram.h @@ -45,6 +45,13 @@ namespace datagram const uint64_t DATAGRAM_MAX_FLUSH_INTERVAL = 5; // in milliseconds const int DATAGRAM_SESSION_ACK_REQUEST_INTERVAL = 5500; // in milliseconds + enum DatagramVersion + { + eDatagramV1 = 1, + eDatagramV2 = 2, + eDatagramV3 = 3, + }; + constexpr uint16_t DATAGRAM3_FLAG_OPTIONS = 0x10; class DatagramSession : public std::enable_shared_from_this @@ -69,6 +76,9 @@ namespace datagram bool IsRatchets () const { return m_RoutingSession && m_RoutingSession->IsRatchets (); } void SetRemoteLeaseSet (std::shared_ptr ls) { m_RemoteLeaseSet = ls; } + + DatagramVersion GetVersion () const { return m_Version; } + void SetVersion (DatagramVersion version) { m_Version = version; } struct Info { @@ -104,6 +114,7 @@ namespace datagram std::vector > m_SendQueue; uint64_t m_LastUse, m_LastFlush; // milliseconds bool m_RequestingLS; + DatagramVersion m_Version; }; typedef std::shared_ptr DatagramSession_ptr; @@ -147,7 +158,7 @@ namespace datagram std::shared_ptr ObtainSession(const i2p::data::IdentHash & ident); std::shared_ptr CreateDataMessage (const std::vector >& payloads, - uint16_t fromPort, uint16_t toPort, bool isRaw = false, bool checksum = true); + uint16_t fromPort, uint16_t toPort, uint8_t protocolType, bool checksum = true); void HandleDatagram (uint16_t fromPort, uint16_t toPort, uint8_t *const& buf, size_t len); void HandleRawDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); From 1a6051e79b811fcb9313af43db563e43969fc45f Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 3 Jul 2025 20:40:39 -0400 Subject: [PATCH 1093/1171] don't verify signature of Datagram1 if comes from ECIESx25519 session --- libi2pd/Datagram.cpp | 42 +++++++++++++++++++++++++++++++++--------- libi2pd/Datagram.h | 3 ++- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp index 2f3d5eef..029ab42d 100644 --- a/libi2pd/Datagram.cpp +++ b/libi2pd/Datagram.cpp @@ -95,26 +95,50 @@ namespace datagram session->FlushSendQueue (); } - void DatagramDestination::HandleDatagram (uint16_t fromPort, uint16_t toPort,uint8_t * const &buf, size_t len) + void DatagramDestination::HandleDatagram (uint16_t fromPort, uint16_t toPort, + const uint8_t * buf, size_t len, i2p::garlic::ECIESX25519AEADRatchetSession * from) { i2p::data::IdentityEx identity; size_t identityLen = identity.FromBuffer (buf, len); + if (!identityLen) return; const uint8_t * signature = buf + identityLen; size_t headerLen = identityLen + identity.GetSignatureLen (); + std::shared_ptr ls; bool verified = false; - if (identity.GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1) + if (from) { - uint8_t hash[32]; - SHA256(buf + headerLen, len - headerLen, hash); - verified = identity.Verify (hash, 32, signature); - } - else - verified = identity.Verify (buf + headerLen, len - headerLen, signature); + ls = m_Owner->FindLeaseSet (identity.GetIdentHash ()); + if (ls) + { + uint8_t staticKey[32]; + ls->Encrypt (nullptr, staticKey); + if (!memcmp (from->GetRemoteStaticKey (), staticKey, 32)) + verified = true; + else + { + LogPrint (eLogError, "Datagram: Remote LeaseSet static key mismatch for datagram from ", + identity.GetIdentHash ().ToBase32 ()); + return; + } + } + } + if (!verified) + { + if (identity.GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1) + { + uint8_t hash[32]; + SHA256(buf + headerLen, len - headerLen, hash); + verified = identity.Verify (hash, 32, signature); + } + else + verified = identity.Verify (buf + headerLen, len - headerLen, signature); + } if (verified) { auto session = ObtainSession (identity.GetIdentHash()); + if (ls) session->SetRemoteLeaseSet (ls); session->Ack(); auto r = FindReceiver(toPort); if(r) @@ -270,7 +294,7 @@ namespace datagram HandleDatagram3 (fromPort, toPort, uncompressed, uncompressedLen, from); break; case i2p::client::PROTOCOL_TYPE_DATAGRAM: - HandleDatagram (fromPort, toPort, uncompressed, uncompressedLen); + HandleDatagram (fromPort, toPort, uncompressed, uncompressedLen, from); break; case i2p::client::PROTOCOL_TYPE_DATAGRAM2: // TODO: diff --git a/libi2pd/Datagram.h b/libi2pd/Datagram.h index a6fc130d..4ff2ef00 100644 --- a/libi2pd/Datagram.h +++ b/libi2pd/Datagram.h @@ -160,7 +160,8 @@ namespace datagram std::shared_ptr CreateDataMessage (const std::vector >& payloads, uint16_t fromPort, uint16_t toPort, uint8_t protocolType, bool checksum = true); - void HandleDatagram (uint16_t fromPort, uint16_t toPort, uint8_t *const& buf, size_t len); + void HandleDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len, + i2p::garlic::ECIESX25519AEADRatchetSession * from); void HandleRawDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); void HandleDatagram3 (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len, i2p::garlic::ECIESX25519AEADRatchetSession * from); From 59d1695ee53f078768a16c4534347c448556f3b1 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 5 Jul 2025 21:06:49 -0400 Subject: [PATCH 1094/1171] use std::string_view to extract params --- libi2pd_client/SAM.cpp | 170 +++++++++++++++++++++-------------------- libi2pd_client/SAM.h | 31 ++++---- 2 files changed, 103 insertions(+), 98 deletions(-) diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 96f2c2ee..90a1937f 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -11,6 +11,7 @@ #ifdef _MSC_VER #include #endif +#include #include "Base.h" #include "Identity.h" #include "Log.h" @@ -126,8 +127,7 @@ namespace client if (separator) { separator++; - std::map params; - ExtractParams (separator, params); + auto params = ExtractParams (separator); auto it = params.find (SAM_PARAM_MAX); if (it != params.end ()) maxver = it->second; @@ -172,7 +172,7 @@ namespace client } } - bool SAMSocket::IsSession(const std::string & id) const + bool SAMSocket::IsSession(std::string_view id) const { return id == m_ID; } @@ -314,7 +314,7 @@ namespace client } } - static bool IsAcceptableSessionName(const std::string & str) + static bool IsAcceptableSessionName(std::string_view str) { auto itr = str.begin(); while(itr != str.end()) @@ -330,11 +330,10 @@ namespace client void SAMSocket::ProcessSessionCreate (char * buf, size_t len) { LogPrint (eLogDebug, "SAM: Session create: ", buf); - std::map params; - ExtractParams (buf, params); - std::string& style = params[SAM_PARAM_STYLE]; - std::string& id = params[SAM_PARAM_ID]; - std::string& destination = params[SAM_PARAM_DESTINATION]; + auto params = ExtractParams (buf); + std::string_view style = params[SAM_PARAM_STYLE]; + std::string_view id = params[SAM_PARAM_ID]; + std::string_view destination = params[SAM_PARAM_DESTINATION]; if(!IsAcceptableSessionName(id)) { @@ -377,8 +376,10 @@ namespace client return; } - auto port = std::stoi(params[SAM_PARAM_PORT]); - if (port == -1) + uint16_t port = 0; + std::string_view p = params[SAM_PARAM_PORT]; + auto res = std::from_chars(p.data(), p.data() + p.size(), port); + if (res.ec != std::errc()) { SendSessionI2PError("Invalid port"); return; @@ -405,7 +406,7 @@ namespace client } // create destination - auto session = m_Owner.CreateSession (id, type, destination == SAM_VALUE_TRANSIENT ? "" : destination, ¶ms); + auto session = m_Owner.CreateSession (id, type, destination == SAM_VALUE_TRANSIENT ? "" : destination, params); if (session) { m_SocketType = eSAMSocketTypeSession; @@ -413,7 +414,13 @@ namespace client { session->UDPEndpoint = forward; auto dest = session->GetLocalDestination ()->CreateDatagramDestination (); - auto port = forward ? std::stoi(params[SAM_PARAM_PORT]) : 0; + uint16_t port = 0; + if (forward) + { + std::string_view p = params[SAM_PARAM_PORT]; + auto res = std::from_chars(p.data(), p.data() + p.size(), port); + if (res.ec != std::errc()) port = 0; + } if (type == eSAMSessionTypeDatagram) dest->SetReceiver (std::bind (&SAMSocket::HandleI2PDatagramReceive, shared_from_this (), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5), @@ -486,11 +493,10 @@ namespace client SendSessionI2PError ("Socket already in use"); return; } - std::map params; - ExtractParams (buf, params); - std::string& id = params[SAM_PARAM_ID]; - std::string& destination = params[SAM_PARAM_DESTINATION]; - std::string& silent = params[SAM_PARAM_SILENT]; + auto params = ExtractParams (buf); + std::string_view id = params[SAM_PARAM_ID]; + std::string_view destination = params[SAM_PARAM_DESTINATION]; + std::string_view silent = params[SAM_PARAM_SILENT]; if (silent == SAM_VALUE_TRUE) m_IsSilent = true; m_ID = id; auto session = m_Owner.FindSession (id); @@ -594,10 +600,9 @@ namespace client SendSessionI2PError ("Socket already in use"); return; } - std::map params; - ExtractParams (buf, params); - std::string& id = params[SAM_PARAM_ID]; - std::string& silent = params[SAM_PARAM_SILENT]; + auto params = ExtractParams (buf); + std::string_view id = params[SAM_PARAM_ID]; + std::string_view silent = params[SAM_PARAM_SILENT]; if (silent == SAM_VALUE_TRUE) m_IsSilent = true; m_ID = id; auto session = m_Owner.FindSession (id); @@ -640,17 +645,15 @@ namespace client void SAMSocket::ProcessStreamForward(char* buf, size_t len) { LogPrint(eLogDebug, "SAM: Stream forward: ", buf); - - std::map params; - ExtractParams(buf, params); - + + auto params = ExtractParams(buf); const auto itId = params.find(SAM_PARAM_ID); if (itId == params.end()) { SendSessionI2PError("Missing ID"); return; } - const std::string& id = itId->second; + std::string_view id = itId->second; auto session = m_Owner.FindSession(id); if (!session) @@ -671,15 +674,16 @@ namespace client return; } - const std::string& portStr = itPort->second; + std::string_view portStr = itPort->second; if (!std::all_of(portStr.begin(), portStr.end(), ::isdigit)) { SendSessionI2PError("Port must be numeric"); return; } - int port = std::stoi(portStr); - if (port <= 0 || port >= 0xFFFF) + uint16_t port = 0; + auto res = std::from_chars(portStr.data(), portStr.data() + portStr.size(), port); + if (res.ec != std::errc()) { SendSessionI2PError("Invalid port"); return; @@ -729,9 +733,12 @@ namespace client size_t SAMSocket::ProcessDatagramSend (char * buf, size_t len, const char * data) { LogPrint (eLogDebug, "SAM: Datagram send: ", buf, " ", len); - std::map params; - ExtractParams (buf, params); - size_t size = std::stoi(params[SAM_PARAM_SIZE]), offset = data - buf; + auto params = ExtractParams (buf); + size_t size = 0; + std::string_view sizeStr = params[SAM_PARAM_SIZE]; + auto res = std::from_chars(sizeStr.data(), sizeStr.data() + sizeStr.size(), size); + if (res.ec != std::errc()) size = 0; + size_t offset = data - buf; if (offset + size <= len) { auto session = m_Owner.FindSession(m_ID); @@ -764,8 +771,7 @@ namespace client void SAMSocket::ProcessDestGenerate (char * buf, size_t len) { LogPrint (eLogDebug, "SAM: Dest generate"); - std::map params; - ExtractParams (buf, params); + auto params = ExtractParams (buf); // extract signature type i2p::data::SigningKeyType signatureType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1; i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL; @@ -780,7 +786,7 @@ namespace client { try { - cryptoType = std::stoi(it->second); + cryptoType = std::stoi(std::string (it->second)); } catch (const std::exception& ex) { @@ -801,9 +807,8 @@ namespace client void SAMSocket::ProcessNamingLookup (char * buf, size_t len) { LogPrint (eLogDebug, "SAM: Naming lookup: ", buf); - std::map params; - ExtractParams (buf, params); - std::string& name = params[SAM_PARAM_NAME]; + auto params = ExtractParams (buf); + std::string name (params[SAM_PARAM_NAME]); std::shared_ptr identity; std::shared_ptr addr; auto session = m_Owner.FindSession(m_ID); @@ -848,16 +853,15 @@ namespace client { LogPrint (eLogDebug, "SAM: Subsession add: ", buf); auto masterSession = std::static_pointer_cast(session); - std::map params; - ExtractParams (buf, params); - std::string& id = params[SAM_PARAM_ID]; + auto params = ExtractParams (buf); + std::string_view id = params[SAM_PARAM_ID]; if (masterSession->subsessions.count (id) > 1) { // session exists SendMessageReply (SAM_SESSION_CREATE_DUPLICATED_ID, strlen(SAM_SESSION_CREATE_DUPLICATED_ID), false); return; } - std::string& style = params[SAM_PARAM_STYLE]; + std::string_view style = params[SAM_PARAM_STYLE]; SAMSessionType type = eSAMSessionTypeUnknown; if (style == SAM_VALUE_STREAM) type = eSAMSessionTypeStream; // TODO: implement other styles @@ -867,7 +871,7 @@ namespace client SendSessionI2PError("Unsupported STYLE"); return; } - auto fromPort = std::stoi(params[SAM_PARAM_FROM_PORT]); + auto fromPort = std::stoi(std::string (params[SAM_PARAM_FROM_PORT])); if (fromPort == -1) { SendSessionI2PError("Invalid from port"); @@ -876,7 +880,7 @@ namespace client auto subsession = std::make_shared(masterSession, id, type, fromPort); if (m_Owner.AddSession (subsession)) { - masterSession->subsessions.insert (id); + masterSession->subsessions.insert (std::string (id)); SendSessionCreateReplyOk (); } else @@ -893,9 +897,8 @@ namespace client { LogPrint (eLogDebug, "SAM: Subsession remove: ", buf); auto masterSession = std::static_pointer_cast(session); - std::map params; - ExtractParams (buf, params); - std::string& id = params[SAM_PARAM_ID]; + auto params = ExtractParams (buf); + std::string id(params[SAM_PARAM_ID]); if (!masterSession->subsessions.erase (id)) { SendMessageReply (SAM_SESSION_STATUS_INVALID_KEY, strlen(SAM_SESSION_STATUS_INVALID_KEY), false); @@ -965,8 +968,9 @@ namespace client SendMessageReply (m_Buffer, l, false); } - void SAMSocket::ExtractParams (char * buf, std::map& params) + const std::map SAMSocket::ExtractParams (char * buf) { + std::map params; char * separator; do { @@ -977,11 +981,12 @@ namespace client { *value = 0; value++; - params[buf] = value; + params.emplace (buf, value); } buf = separator + 1; } while (separator); + return params; } void SAMSocket::Receive () @@ -1289,7 +1294,7 @@ namespace client boost::asio::post (m_Owner.GetService (), std::bind( !ec ? &SAMSocket::Receive : &SAMSocket::TerminateClose, shared_from_this())); } - SAMSession::SAMSession (SAMBridge & parent, const std::string & id, SAMSessionType type): + SAMSession::SAMSession (SAMBridge & parent, std::string_view id, SAMSessionType type): m_Bridge(parent), Name(id), Type (type), UDPEndpoint(nullptr) { } @@ -1302,7 +1307,7 @@ namespace client } } - SAMSingleSession::SAMSingleSession (SAMBridge & parent, const std::string & name, SAMSessionType type, std::shared_ptr dest): + SAMSingleSession::SAMSingleSession (SAMBridge & parent, std::string_view name, SAMSessionType type, std::shared_ptr dest): SAMSession (parent, name, type), localDestination (dest) { @@ -1331,7 +1336,7 @@ namespace client subsessions.clear (); } - SAMSubSession::SAMSubSession (std::shared_ptr master, const std::string& name, SAMSessionType type, uint16_t port): + SAMSubSession::SAMSubSession (std::shared_ptr master, std::string_view name, SAMSessionType type, uint16_t port): SAMSession (master->m_Bridge, name, type), masterSession (master), inPort (port) { if (Type == eSAMSessionTypeStream) @@ -1452,37 +1457,38 @@ namespace client Accept (); } - std::shared_ptr SAMBridge::CreateSession (const std::string& id, SAMSessionType type, - const std::string& destination, const std::map * params) + std::shared_ptr SAMBridge::CreateSession (std::string_view id, SAMSessionType type, + std::string_view destination, const std::map& params) { + std::map p(params.begin (), params.end ()); std::shared_ptr localDestination = nullptr; if (destination != "") { i2p::data::PrivateKeys keys; if (!keys.FromBase64 (destination)) return nullptr; localDestination = m_IsSingleThread ? - i2p::client::context.CreateNewLocalDestination (GetIOService (), keys, true, params) : - i2p::client::context.CreateNewLocalDestination (keys, true, params); + i2p::client::context.CreateNewLocalDestination (GetIOService (), keys, true, &p) : + i2p::client::context.CreateNewLocalDestination (keys, true, &p); } else // transient { // extract signature type i2p::data::SigningKeyType signatureType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1; i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL; - if (params) + if (!params.empty ()) { - auto it = params->find (SAM_PARAM_SIGNATURE_TYPE); - if (it != params->end ()) + auto it = params.find (SAM_PARAM_SIGNATURE_TYPE); + if (it != params.end ()) { if (!ResolveSignatureType (it->second, signatureType)) LogPrint (eLogWarning, "SAM: ", SAM_PARAM_SIGNATURE_TYPE, " is invalid ", it->second); } - it = params->find (SAM_PARAM_CRYPTO_TYPE); - if (it != params->end ()) + it = params.find (SAM_PARAM_CRYPTO_TYPE); + if (it != params.end ()) { try { - cryptoType = std::stoi(it->second); + cryptoType = std::stoi(std::string (it->second)); } catch (const std::exception& ex) { @@ -1491,8 +1497,8 @@ namespace client } } localDestination = m_IsSingleThread ? - i2p::client::context.CreateNewLocalDestination (GetIOService (), true, signatureType, cryptoType, params) : - i2p::client::context.CreateNewLocalDestination (true, signatureType, cryptoType, params); + i2p::client::context.CreateNewLocalDestination (GetIOService (), true, signatureType, cryptoType, &p) : + i2p::client::context.CreateNewLocalDestination (true, signatureType, cryptoType, &p); } if (localDestination) { @@ -1500,7 +1506,7 @@ namespace client auto session = (type == eSAMSessionTypeMaster) ? std::make_shared(*this, id, localDestination) : std::make_shared(*this, id, type, localDestination); std::unique_lock l(m_SessionsMutex); - auto ret = m_Sessions.insert (std::make_pair(id, session)); + auto ret = m_Sessions.emplace (id, session); if (!ret.second) LogPrint (eLogWarning, "SAM: Session ", id, " already exists"); return ret.first->second; @@ -1515,7 +1521,7 @@ namespace client return ret.second; } - void SAMBridge::CloseSession (const std::string& id) + void SAMBridge::CloseSession (std::string_view id) { std::shared_ptr session; { @@ -1565,7 +1571,7 @@ namespace client // session's destructor is called here unless rescheduled } - std::shared_ptr SAMBridge::FindSession (const std::string& id) const + std::shared_ptr SAMBridge::FindSession (std::string_view id) const { std::unique_lock l(m_SessionsMutex); auto it = m_Sessions.find (id); @@ -1574,7 +1580,7 @@ namespace client return nullptr; } - std::list > SAMBridge::ListSockets(const std::string & id) const + std::list > SAMBridge::ListSockets(std::string_view id) const { std::list > list; { @@ -1654,25 +1660,23 @@ namespace client LogPrint (eLogError, "SAM: Datagram receive error: ", ecode.message ()); } - bool SAMBridge::ResolveSignatureType (const std::string& name, i2p::data::SigningKeyType& type) const + bool SAMBridge::ResolveSignatureType (std::string_view name, i2p::data::SigningKeyType& type) const { - try + auto res = std::from_chars(name.data(), name.data() + name.size(), type); + if (res.ec != std::errc()) { - type = std::stoi (name); - } - catch (const std::invalid_argument& ex) - { - // name is not numeric, resolving - auto it = m_SignatureTypes.find (name); - if (it != m_SignatureTypes.end ()) - type = it->second; + if (res.ec == std::errc::invalid_argument) + { + // name is not numeric, resolving + auto it = m_SignatureTypes.find (name); + if (it != m_SignatureTypes.end ()) + type = it->second; + else + return false; + } else return false; } - catch (const std::exception& ex) - { - return false; - } // name has been resolved return true; } diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index cd619678..acc17e20 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -116,7 +117,7 @@ namespace client void Terminate (const char* reason); - bool IsSession(const std::string & id) const; + bool IsSession(std::string_view id) const; private: @@ -151,7 +152,7 @@ namespace client void SendStreamI2PError(const std::string & msg); void SendStreamCantReachPeer(const std::string & msg); size_t ProcessDatagramSend (char * buf, size_t len, const char * data); // from SAM 1.0 - void ExtractParams (char * buf, std::map& params); + const std::map ExtractParams (char * buf); void Connect (std::shared_ptr remote, std::shared_ptr session = nullptr); void HandleConnectLeaseSetRequestComplete (std::shared_ptr leaseSet); @@ -199,7 +200,7 @@ namespace client std::shared_ptr UDPEndpoint; // TODO: move std::list, uint64_t> > acceptQueue; // socket, receive time in seconds - SAMSession (SAMBridge & parent, const std::string & name, SAMSessionType type); + SAMSession (SAMBridge & parent, std::string_view name, SAMSessionType type); virtual ~SAMSession () {}; virtual std::shared_ptr GetLocalDestination () = 0; @@ -213,7 +214,7 @@ namespace client { std::shared_ptr localDestination; - SAMSingleSession (SAMBridge & parent, const std::string & name, SAMSessionType type, std::shared_ptr dest); + SAMSingleSession (SAMBridge & parent, std::string_view name, SAMSessionType type, std::shared_ptr dest); ~SAMSingleSession (); std::shared_ptr GetLocalDestination () { return localDestination; }; @@ -222,8 +223,8 @@ namespace client struct SAMMasterSession: public SAMSingleSession { - std::set subsessions; - SAMMasterSession (SAMBridge & parent, const std::string & name, std::shared_ptr dest): + std::set > subsessions; + SAMMasterSession (SAMBridge & parent, std::string_view name, std::shared_ptr dest): SAMSingleSession (parent, name, eSAMSessionTypeMaster, dest) {}; void Close (); }; @@ -233,7 +234,7 @@ namespace client std::shared_ptr masterSession; uint16_t inPort; - SAMSubSession (std::shared_ptr master, const std::string& name, SAMSessionType type, uint16_t port); + SAMSubSession (std::shared_ptr master, std::string_view name, SAMSessionType type, uint16_t port); // implements SAMSession std::shared_ptr GetLocalDestination (); void StopLocalDestination (); @@ -250,13 +251,13 @@ namespace client void Stop (); auto& GetService () { return GetIOService (); }; - std::shared_ptr CreateSession (const std::string& id, SAMSessionType type, const std::string& destination, // empty string means transient - const std::map * params); + std::shared_ptr CreateSession (std::string_view id, SAMSessionType type, std::string_view destination, // empty string means transient + const std::map& params); bool AddSession (std::shared_ptr session); - void CloseSession (const std::string& id); - std::shared_ptr FindSession (const std::string& id) const; + void CloseSession (std::string_view id); + std::shared_ptr FindSession (std::string_view id) const; - std::list > ListSockets(const std::string & id) const; + std::list > ListSockets(std::string_view id) const; /** send raw data to remote endpoint from our UDP Socket */ void SendTo (const std::vector& bufs, const boost::asio::ip::udp::endpoint& ep); @@ -264,7 +265,7 @@ namespace client void AddSocket(std::shared_ptr socket); void RemoveSocket(const std::shared_ptr & socket); - bool ResolveSignatureType (const std::string& name, i2p::data::SigningKeyType& type) const; + bool ResolveSignatureType (std::string_view name, i2p::data::SigningKeyType& type) const; private: @@ -285,11 +286,11 @@ namespace client boost::asio::ip::udp::endpoint m_DatagramEndpoint, m_SenderEndpoint; boost::asio::ip::udp::socket m_DatagramSocket; mutable std::mutex m_SessionsMutex; - std::map > m_Sessions; + std::map, std::less<>> m_Sessions; mutable std::mutex m_OpenSocketsMutex; std::list > m_OpenSockets; uint8_t m_DatagramReceiveBuffer[i2p::datagram::MAX_DATAGRAM_SIZE+1]; - std::map m_SignatureTypes; + const std::map m_SignatureTypes; public: From 88375bf9c007582d607ca9e4da3fd079299cabfc Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 5 Jul 2025 21:41:35 -0400 Subject: [PATCH 1095/1171] fixed build for older gcc --- libi2pd_client/SAM.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 90a1937f..fad7ea2d 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -1460,7 +1460,13 @@ namespace client std::shared_ptr SAMBridge::CreateSession (std::string_view id, SAMSessionType type, std::string_view destination, const std::map& params) { +#if __GNUC__ < 10 // TODO: remove when older versions discontinued + std::map p; + for (auto it: params) + p.emplace (std::string (it.first), std::string (it.second)); +#else std::map p(params.begin (), params.end ()); +#endif std::shared_ptr localDestination = nullptr; if (destination != "") { From 1862f28a98e336b62f79346fa25ab53ba86acf1e Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 6 Jul 2025 16:45:47 -0400 Subject: [PATCH 1096/1171] extract params from std::string_view --- libi2pd_client/SAM.cpp | 32 ++++++++++++++++++-------------- libi2pd_client/SAM.h | 2 +- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index fad7ea2d..89beb538 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -968,24 +968,28 @@ namespace client SendMessageReply (m_Buffer, l, false); } - const std::map SAMSocket::ExtractParams (char * buf) + const std::map SAMSocket::ExtractParams (std::string_view buf) { std::map params; - char * separator; - do - { - separator = strchr (buf, ' '); - if (separator) *separator = 0; - char * value = strchr (buf, '='); - if (value) - { - *value = 0; - value++; - params.emplace (buf, value); + size_t pos = 0; + while (pos < buf.length ()) + { + std::string_view field; + auto separator = buf.find (' ', pos); + if (separator != std::string_view::npos) + { + field = buf.substr (pos, separator - pos); + pos = separator + 1; } - buf = separator + 1; + else + { + field = buf.substr (pos); + pos = buf.length (); + } + auto value = field.find ('='); + if (value != std::string_view::npos) + params.emplace (field.substr (0, value), field.substr (value + 1)); } - while (separator); return params; } diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index acc17e20..6ff0ef02 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -152,7 +152,7 @@ namespace client void SendStreamI2PError(const std::string & msg); void SendStreamCantReachPeer(const std::string & msg); size_t ProcessDatagramSend (char * buf, size_t len, const char * data); // from SAM 1.0 - const std::map ExtractParams (char * buf); + const std::map ExtractParams (std::string_view buf); void Connect (std::shared_ptr remote, std::shared_ptr session = nullptr); void HandleConnectLeaseSetRequestComplete (std::shared_ptr leaseSet); From 181edce55a7d97a5cdbee13669e83a98858b5f6d Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 6 Jul 2025 18:47:52 -0400 Subject: [PATCH 1097/1171] pass buffer as std::string_stream --- libi2pd_client/SAM.cpp | 28 ++++++++++++++-------------- libi2pd_client/SAM.h | 14 +++++++------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 89beb538..e67f29f7 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -257,21 +257,21 @@ namespace client separator = eol; if (!strcmp (m_Buffer, SAM_SESSION_CREATE)) - ProcessSessionCreate (separator + 1, bytes_transferred - (separator - m_Buffer) - 1); + ProcessSessionCreate (separator + 1); else if (!strcmp (m_Buffer, SAM_STREAM_CONNECT)) ProcessStreamConnect (separator + 1, bytes_transferred - (separator - m_Buffer) - 1, bytes_transferred - (eol - m_Buffer) - 1); else if (!strcmp (m_Buffer, SAM_STREAM_ACCEPT)) - ProcessStreamAccept (separator + 1, bytes_transferred - (separator - m_Buffer) - 1); + ProcessStreamAccept (separator + 1); else if (!strcmp (m_Buffer, SAM_STREAM_FORWARD)) - ProcessStreamForward (separator + 1, bytes_transferred - (separator - m_Buffer) - 1); + ProcessStreamForward (separator + 1); else if (!strcmp (m_Buffer, SAM_DEST_GENERATE)) - ProcessDestGenerate (separator + 1, bytes_transferred - (separator - m_Buffer) - 1); + ProcessDestGenerate (separator + 1); else if (!strcmp (m_Buffer, SAM_NAMING_LOOKUP)) - ProcessNamingLookup (separator + 1, bytes_transferred - (separator - m_Buffer) - 1); + ProcessNamingLookup (separator + 1); else if (!strcmp (m_Buffer, SAM_SESSION_ADD)) - ProcessSessionAdd (separator + 1, bytes_transferred - (separator - m_Buffer) - 1); + ProcessSessionAdd (separator + 1); else if (!strcmp (m_Buffer, SAM_SESSION_REMOVE)) - ProcessSessionRemove (separator + 1, bytes_transferred - (separator - m_Buffer) - 1); + ProcessSessionRemove (separator + 1); else if (!strcmp (m_Buffer, SAM_DATAGRAM_SEND) || !strcmp (m_Buffer, SAM_RAW_SEND)) { size_t len = bytes_transferred - (separator - m_Buffer) - 1; @@ -327,7 +327,7 @@ namespace client return true; } - void SAMSocket::ProcessSessionCreate (char * buf, size_t len) + void SAMSocket::ProcessSessionCreate (std::string_view buf) { LogPrint (eLogDebug, "SAM: Session create: ", buf); auto params = ExtractParams (buf); @@ -592,7 +592,7 @@ namespace client } } - void SAMSocket::ProcessStreamAccept (char * buf, size_t len) + void SAMSocket::ProcessStreamAccept (std::string_view buf) { LogPrint (eLogDebug, "SAM: Stream accept: ", buf); if ( m_SocketType != eSAMSocketTypeUnknown) @@ -642,7 +642,7 @@ namespace client SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); } - void SAMSocket::ProcessStreamForward(char* buf, size_t len) + void SAMSocket::ProcessStreamForward (std::string_view buf) { LogPrint(eLogDebug, "SAM: Stream forward: ", buf); @@ -768,7 +768,7 @@ namespace client return offset + size; } - void SAMSocket::ProcessDestGenerate (char * buf, size_t len) + void SAMSocket::ProcessDestGenerate (std::string_view buf) { LogPrint (eLogDebug, "SAM: Dest generate"); auto params = ExtractParams (buf); @@ -804,7 +804,7 @@ namespace client SendMessageReply (m_Buffer, l, false); } - void SAMSocket::ProcessNamingLookup (char * buf, size_t len) + void SAMSocket::ProcessNamingLookup (std::string_view buf) { LogPrint (eLogDebug, "SAM: Naming lookup: ", buf); auto params = ExtractParams (buf); @@ -846,7 +846,7 @@ namespace client } } - void SAMSocket::ProcessSessionAdd (char * buf, size_t len) + void SAMSocket::ProcessSessionAdd (std::string_view buf) { auto session = m_Owner.FindSession(m_ID); if (session && session->Type == eSAMSessionTypeMaster) @@ -890,7 +890,7 @@ namespace client SendSessionI2PError ("Wrong session type"); } - void SAMSocket::ProcessSessionRemove (char * buf, size_t len) + void SAMSocket::ProcessSessionRemove (std::string_view buf) { auto session = m_Owner.FindSession(m_ID); if (session && session->Type == eSAMSessionTypeMaster) diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index 6ff0ef02..c10afe98 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -139,14 +139,14 @@ namespace client void HandleI2PDatagramReceive (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); void HandleI2PRawDatagramReceive (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); - void ProcessSessionCreate (char * buf, size_t len); + void ProcessSessionCreate (std::string_view buf); void ProcessStreamConnect (char * buf, size_t len, size_t rem); - void ProcessStreamAccept (char * buf, size_t len); - void ProcessStreamForward (char * buf, size_t len); - void ProcessDestGenerate (char * buf, size_t len); - void ProcessNamingLookup (char * buf, size_t len); - void ProcessSessionAdd (char * buf, size_t len); - void ProcessSessionRemove (char * buf, size_t len); + void ProcessStreamAccept (std::string_view buf); + void ProcessStreamForward (std::string_view buf); + void ProcessDestGenerate (std::string_view buf); + void ProcessNamingLookup (std::string_view buf); + void ProcessSessionAdd (std::string_view buf); + void ProcessSessionRemove (std::string_view buf); void SendReplyWithMessage (const char * reply, const std::string & msg); void SendSessionI2PError(const std::string & msg); void SendStreamI2PError(const std::string & msg); From 99e4bda6851a9d9d9b8c8ef375c9e10511cfb58f Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 8 Jul 2025 13:18:54 -0400 Subject: [PATCH 1098/1171] pass actual string size to Process* methods --- libi2pd_client/SAM.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index e67f29f7..12b7e286 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -257,21 +257,21 @@ namespace client separator = eol; if (!strcmp (m_Buffer, SAM_SESSION_CREATE)) - ProcessSessionCreate (separator + 1); + ProcessSessionCreate ({ separator + 1, bytes_transferred - (separator - m_Buffer) - 1 }); else if (!strcmp (m_Buffer, SAM_STREAM_CONNECT)) ProcessStreamConnect (separator + 1, bytes_transferred - (separator - m_Buffer) - 1, bytes_transferred - (eol - m_Buffer) - 1); else if (!strcmp (m_Buffer, SAM_STREAM_ACCEPT)) - ProcessStreamAccept (separator + 1); + ProcessStreamAccept ({ separator + 1, bytes_transferred - (separator - m_Buffer) - 1 }); else if (!strcmp (m_Buffer, SAM_STREAM_FORWARD)) - ProcessStreamForward (separator + 1); + ProcessStreamForward ({ separator + 1, bytes_transferred - (separator - m_Buffer) - 1 }); else if (!strcmp (m_Buffer, SAM_DEST_GENERATE)) - ProcessDestGenerate (separator + 1); + ProcessDestGenerate ({ separator + 1, bytes_transferred - (separator - m_Buffer) - 1 }); else if (!strcmp (m_Buffer, SAM_NAMING_LOOKUP)) - ProcessNamingLookup (separator + 1); + ProcessNamingLookup ({ separator + 1, bytes_transferred - (separator - m_Buffer) - 1 }); else if (!strcmp (m_Buffer, SAM_SESSION_ADD)) - ProcessSessionAdd (separator + 1); + ProcessSessionAdd ({ separator + 1, bytes_transferred - (separator - m_Buffer) - 1 }); else if (!strcmp (m_Buffer, SAM_SESSION_REMOVE)) - ProcessSessionRemove (separator + 1); + ProcessSessionRemove ({ separator + 1, bytes_transferred - (separator - m_Buffer) - 1 }); else if (!strcmp (m_Buffer, SAM_DATAGRAM_SEND) || !strcmp (m_Buffer, SAM_RAW_SEND)) { size_t len = bytes_transferred - (separator - m_Buffer) - 1; @@ -303,7 +303,6 @@ namespace client Terminate ("malformed message"); } } - else { LogPrint (eLogWarning, "SAM: Incomplete message ", bytes_transferred); From ccb466646f5bb9297cb4e93898c39530eb5a1d92 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 8 Jul 2025 14:32:37 -0400 Subject: [PATCH 1099/1171] don't create PQ signature if not supported --- libi2pd_client/ClientContext.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index d26e33ab..2d36cc11 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -596,6 +596,9 @@ namespace client std::string address = section.second.get (I2P_CLIENT_TUNNEL_ADDRESS, "127.0.0.1"); uint16_t destinationPort = section.second.get (I2P_CLIENT_TUNNEL_DESTINATION_PORT, 0); i2p::data::SigningKeyType sigType = section.second.get (I2P_CLIENT_TUNNEL_SIGNATURE_TYPE, i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519); +#if !OPENSSL_PQ + if (sigType >= i2p::data::SIGNING_KEY_TYPE_MLDSA44) sigType = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519; +#endif i2p::data::CryptoKeyType cryptoType = section.second.get (I2P_CLIENT_TUNNEL_CRYPTO_TYPE, i2p::data::CRYPTO_KEY_TYPE_ELGAMAL); // I2CP std::map options; @@ -752,6 +755,9 @@ namespace client std::string webircpass = section.second.get (I2P_SERVER_TUNNEL_WEBIRC_PASSWORD, ""); bool gzip = section.second.get (I2P_SERVER_TUNNEL_GZIP, false); i2p::data::SigningKeyType sigType = section.second.get (I2P_SERVER_TUNNEL_SIGNATURE_TYPE, i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519); +#if !OPENSSL_PQ + if (sigType >= i2p::data::SIGNING_KEY_TYPE_MLDSA44) sigType = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519; +#endif i2p::data::CryptoKeyType cryptoType = section.second.get (I2P_CLIENT_TUNNEL_CRYPTO_TYPE, i2p::data::CRYPTO_KEY_TYPE_ELGAMAL); std::string address = section.second.get (I2P_SERVER_TUNNEL_ADDRESS, ""); @@ -911,6 +917,9 @@ namespace client if (httpAddresshelper) i2p::config::GetOption("addressbook.enabled", httpAddresshelper); // addresshelper is not supported without address book i2p::data::SigningKeyType sigType; i2p::config::GetOption("httpproxy.signaturetype", sigType); +#if !OPENSSL_PQ + if (sigType >= i2p::data::SIGNING_KEY_TYPE_MLDSA44) sigType = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519; +#endif LogPrint(eLogInfo, "Clients: Starting HTTP Proxy at ", httpProxyAddr, ":", httpProxyPort); if (httpProxyKeys == "shareddest") { @@ -960,6 +969,9 @@ namespace client std::string socksOutProxyAddr; i2p::config::GetOption("socksproxy.outproxy", socksOutProxyAddr); uint16_t socksOutProxyPort; i2p::config::GetOption("socksproxy.outproxyport", socksOutProxyPort); i2p::data::SigningKeyType sigType; i2p::config::GetOption("socksproxy.signaturetype", sigType); +#if !OPENSSL_PQ + if (sigType >= i2p::data::SIGNING_KEY_TYPE_MLDSA44) sigType = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519; +#endif LogPrint(eLogInfo, "Clients: Starting SOCKS Proxy at ", socksProxyAddr, ":", socksProxyPort); if (socksProxyKeys == "shareddest") { From 2e167fe33424ade55a99e3d757961dcb6fdc6520 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 9 Jul 2025 13:21:04 -0400 Subject: [PATCH 1100/1171] pass std::string_view to HKDF --- libi2pd/Crypto.cpp | 4 ++-- libi2pd/Crypto.h | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index 94f47ca9..add9aa7a 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -779,7 +779,7 @@ namespace crypto ChaCha20 (m_Ctx, msg, msgLen, key, nonce, out); } - void HKDF (const uint8_t * salt, const uint8_t * key, size_t keyLen, const std::string& info, + void HKDF (const uint8_t * salt, const uint8_t * key, size_t keyLen, std::string_view info, uint8_t * out, size_t outLen) { EVP_PKEY_CTX * pctx = EVP_PKEY_CTX_new_id (EVP_PKEY_HKDF, nullptr); @@ -799,7 +799,7 @@ namespace crypto EVP_PKEY_CTX_set1_hkdf_key (pctx, tempKey, len); } if (info.length () > 0) - EVP_PKEY_CTX_add1_hkdf_info (pctx, (const uint8_t *)info.c_str (), info.length ()); + EVP_PKEY_CTX_add1_hkdf_info (pctx, (const uint8_t *)info.data (), info.length ()); EVP_PKEY_derive (pctx, out, &outLen); EVP_PKEY_CTX_free (pctx); } diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index 5bf4d534..3b9dfb93 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -244,7 +245,7 @@ namespace crypto // HKDF - void HKDF (const uint8_t * salt, const uint8_t * key, size_t keyLen, const std::string& info, uint8_t * out, size_t outLen = 64); // salt - 32, out - 32 or 64, info <= 32 + void HKDF (const uint8_t * salt, const uint8_t * key, size_t keyLen, std::string_view info, uint8_t * out, size_t outLen = 64); // salt - 32, out - 32 or 64, info <= 32 // Noise From 18b03c6c9e436692a8c2e7160b13bd86c7357195 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Thu, 10 Jul 2025 20:58:49 +0300 Subject: [PATCH 1101/1171] [gha] remove debian buster build --- .github/workflows/build-deb.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 597dc211..31b8f522 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -28,7 +28,7 @@ jobs: strategy: fail-fast: false matrix: - dist: ['buster', 'bullseye', 'bookworm'] + dist: ['bullseye', 'bookworm'] steps: - name: Checkout From 090e972fa969518a12a702ca6e25a5f6a1295a1b Mon Sep 17 00:00:00 2001 From: R4SAS Date: Thu, 10 Jul 2025 21:00:15 +0300 Subject: [PATCH 1102/1171] [gha] add debian trixie build --- .github/workflows/build-deb.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml index 31b8f522..32698498 100644 --- a/.github/workflows/build-deb.yml +++ b/.github/workflows/build-deb.yml @@ -28,7 +28,7 @@ jobs: strategy: fail-fast: false matrix: - dist: ['bullseye', 'bookworm'] + dist: ['bullseye', 'bookworm', 'trixie'] steps: - name: Checkout From 00c23cba38379ebdfa4d6c04d8a0ea763c565ee0 Mon Sep 17 00:00:00 2001 From: Houkime <> Date: Mon, 14 Jul 2025 08:43:28 +0000 Subject: [PATCH 1103/1171] Update deprecated openssl functions and remove warning suppression see https://docs.openssl.org/3.0/man7/migration_guide/ --- Makefile | 1 - libi2pd/Blinding.cpp | 31 ++++++++++++++++++------------- libi2pd/Crypto.cpp | 42 +++++++++++++++++++++++------------------- libi2pd/CryptoKey.cpp | 8 ++++---- libi2pd/Gost.cpp | 8 ++++---- 5 files changed, 49 insertions(+), 41 deletions(-) diff --git a/Makefile b/Makefile index 0d4ca48c..ab98a4e0 100644 --- a/Makefile +++ b/Makefile @@ -77,7 +77,6 @@ else # not supported endif INCFLAGS += -I$(LIB_SRC_DIR) -I$(LIB_CLIENT_SRC_DIR) -I$(LANG_SRC_DIR) -DEFINES += -DOPENSSL_SUPPRESS_DEPRECATED NEEDED_CXXFLAGS += -MMD -MP ifeq ($(USE_GIT_VERSION),yes) diff --git a/libi2pd/Blinding.cpp b/libi2pd/Blinding.cpp index a661b428..2006462a 100644 --- a/libi2pd/Blinding.cpp +++ b/libi2pd/Blinding.cpp @@ -6,10 +6,12 @@ * See full license text in LICENSE file at top of project tree */ +#include #include // for crc32 #include #include #include +#include #include #include "Base.h" #include "Crypto.h" @@ -65,10 +67,10 @@ namespace data BIGNUM * x = BN_bin2bn (pub, publicKeyLen/2, NULL); BIGNUM * y = BN_bin2bn (pub + publicKeyLen/2, publicKeyLen/2, NULL); EC_POINT * p = EC_POINT_new (group); - EC_POINT_set_affine_coordinates_GFp (group, p, x, y, NULL); + EC_POINT_set_affine_coordinates (group, p, x, y, NULL); EC_POINT * p1 = BlindPublicKeyECDSA (group, p, seed); EC_POINT_free (p); - EC_POINT_get_affine_coordinates_GFp (group, p1, x, y, NULL); + EC_POINT_get_affine_coordinates (group, p1, x, y, NULL); EC_POINT_free (p1); i2p::crypto::bn2buf (x, blindedPub, publicKeyLen/2); i2p::crypto::bn2buf (y, blindedPub + publicKeyLen/2, publicKeyLen/2); @@ -88,7 +90,7 @@ namespace data BN_CTX_free (ctx); BN_free (a1); BIGNUM * x = BN_new(), * y = BN_new(); - EC_POINT_get_affine_coordinates_GFp (group, p, x, y, NULL); + EC_POINT_get_affine_coordinates (group, p, x, y, NULL); EC_POINT_free (p); i2p::crypto::bn2buf (x, blindedPub, publicKeyLen/2); i2p::crypto::bn2buf (y, blindedPub + publicKeyLen/2, publicKeyLen/2); @@ -295,12 +297,14 @@ namespace data void BlindedPublicKey::H (const std::string& p, const std::vector >& bufs, uint8_t * hash) const { - SHA256_CTX ctx; - SHA256_Init (&ctx); - SHA256_Update (&ctx, p.c_str (), p.length ()); + EVP_MD_CTX *ctx = EVP_MD_CTX_new (); + + EVP_DigestInit_ex(ctx, EVP_sha256 (), NULL); + EVP_DigestUpdate (ctx, p.c_str (), p.length ()); for (const auto& it: bufs) - SHA256_Update (&ctx, it.first, it.second); - SHA256_Final (hash, &ctx); + EVP_DigestUpdate (ctx, it.first, it.second); + EVP_DigestFinal_ex (ctx, (uint8_t * )hash, nullptr); + EVP_MD_CTX_free (ctx); } i2p::data::IdentHash BlindedPublicKey::GetStoreHash (const char * date) const @@ -319,11 +323,12 @@ namespace data if (publicKeyLength) { auto stA1 = htobe16 (m_BlindedSigType); - SHA256_CTX ctx; - SHA256_Init (&ctx); - SHA256_Update (&ctx, (const uint8_t *)&stA1, 2); - SHA256_Update (&ctx, blinded, publicKeyLength); - SHA256_Final ((uint8_t *)hash, &ctx); + EVP_MD_CTX *ctx = EVP_MD_CTX_new (); + EVP_DigestInit_ex(ctx, EVP_sha256(), NULL); + EVP_DigestUpdate (ctx, (const uint8_t *)&stA1, 2); + EVP_DigestUpdate (ctx, blinded, publicKeyLength); + EVP_DigestFinal_ex (ctx, (uint8_t * )hash, nullptr); + EVP_MD_CTX_free(ctx); } else LogPrint (eLogError, "Blinding: Blinded key type ", (int)m_BlindedSigType, " is not supported"); diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index add9aa7a..dd43d045 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -456,14 +456,14 @@ namespace crypto auto p = EC_POINT_new (curve); EC_POINT_mul (curve, p, k, nullptr, nullptr, ctx); BIGNUM * x = BN_CTX_get (ctx), * y = BN_CTX_get (ctx); - EC_POINT_get_affine_coordinates_GFp (curve, p, x, y, nullptr); + EC_POINT_get_affine_coordinates (curve, p, x, y, nullptr); encrypted[0] = 0; bn2buf (x, encrypted + 1, len); bn2buf (y, encrypted + 1 + len, len); RAND_bytes (encrypted + 1 + 2*len, 256 - 2*len); // encryption key and iv EC_POINT_mul (curve, p, nullptr, key, k, ctx); - EC_POINT_get_affine_coordinates_GFp (curve, p, x, y, nullptr); + EC_POINT_get_affine_coordinates (curve, p, x, y, nullptr); uint8_t keyBuf[64], iv[64], shared[32]; bn2buf (x, keyBuf, len); bn2buf (y, iv, len); @@ -496,11 +496,11 @@ namespace crypto BN_bin2bn (encrypted + 1, len, x); BN_bin2bn (encrypted + 1 + len, len, y); auto p = EC_POINT_new (curve); - if (EC_POINT_set_affine_coordinates_GFp (curve, p, x, y, nullptr)) + if (EC_POINT_set_affine_coordinates (curve, p, x, y, nullptr)) { auto s = EC_POINT_new (curve); EC_POINT_mul (curve, s, nullptr, p, key, ctx); - EC_POINT_get_affine_coordinates_GFp (curve, s, x, y, nullptr); + EC_POINT_get_affine_coordinates (curve, s, x, y, nullptr); EC_POINT_free (s); uint8_t keyBuf[64], iv[64], shared[32]; bn2buf (x, keyBuf, len); @@ -810,31 +810,35 @@ namespace crypto { // pub is Bob's public static key, hh = SHA256(h) memcpy (m_CK, ck, 32); - SHA256_CTX ctx; - SHA256_Init (&ctx); - SHA256_Update (&ctx, hh, 32); - SHA256_Update (&ctx, pub, 32); - SHA256_Final (m_H, &ctx); // h = MixHash(pub) = SHA256(hh || pub) + + EVP_MD_CTX *ctx = EVP_MD_CTX_new (); + EVP_DigestInit_ex(ctx, EVP_sha256 (), NULL); + EVP_DigestUpdate (ctx, hh, 32); + EVP_DigestUpdate (ctx, pub, 32); + EVP_DigestFinal_ex (ctx, m_H, nullptr); // h = MixHash(pub) = SHA256(hh || pub) + EVP_MD_CTX_free (ctx); m_N = 0; } void NoiseSymmetricState::MixHash (const uint8_t * buf, size_t len) { - SHA256_CTX ctx; - SHA256_Init (&ctx); - SHA256_Update (&ctx, m_H, 32); - SHA256_Update (&ctx, buf, len); - SHA256_Final (m_H, &ctx); + EVP_MD_CTX *ctx = EVP_MD_CTX_new (); + EVP_DigestInit_ex(ctx, EVP_sha256 (), NULL); + EVP_DigestUpdate (ctx, m_H, 32); + EVP_DigestUpdate (ctx, buf, len); + EVP_DigestFinal_ex (ctx, m_H, nullptr); + EVP_MD_CTX_free (ctx); } void NoiseSymmetricState::MixHash (const std::vector >& bufs) { - SHA256_CTX ctx; - SHA256_Init (&ctx); - SHA256_Update (&ctx, m_H, 32); + EVP_MD_CTX *ctx = EVP_MD_CTX_new (); + EVP_DigestInit_ex(ctx, EVP_sha256 (), NULL); + EVP_DigestUpdate (ctx, m_H, 32); for (const auto& it: bufs) - SHA256_Update (&ctx, it.first, it.second); - SHA256_Final (m_H, &ctx); + EVP_DigestUpdate (ctx, it.first, it.second); + EVP_DigestFinal_ex (ctx, m_H, nullptr); + EVP_MD_CTX_free (ctx); } void NoiseSymmetricState::MixKey (const uint8_t * sharedSecret) diff --git a/libi2pd/CryptoKey.cpp b/libi2pd/CryptoKey.cpp index e37d4039..1a448ed1 100644 --- a/libi2pd/CryptoKey.cpp +++ b/libi2pd/CryptoKey.cpp @@ -41,7 +41,7 @@ namespace crypto m_PublicKey = EC_POINT_new (m_Curve); BIGNUM * x = BN_bin2bn (pub, 32, nullptr); BIGNUM * y = BN_bin2bn (pub + 32, 32, nullptr); - if (!EC_POINT_set_affine_coordinates_GFp (m_Curve, m_PublicKey, x, y, nullptr)) + if (!EC_POINT_set_affine_coordinates (m_Curve, m_PublicKey, x, y, nullptr)) LogPrint (eLogError, "ECICS P256 invalid public key"); BN_free (x); BN_free (y); } @@ -87,7 +87,7 @@ namespace crypto RAND_bytes (priv + 32, 224); BN_free (key); BIGNUM * x = BN_new (), * y = BN_new (); - EC_POINT_get_affine_coordinates_GFp (curve, p, x, y, NULL); + EC_POINT_get_affine_coordinates (curve, p, x, y, NULL); bn2buf (x, pub, 32); bn2buf (y, pub + 32, 32); RAND_bytes (pub + 64, 192); @@ -102,7 +102,7 @@ namespace crypto m_PublicKey = EC_POINT_new (curve->GetGroup ()); BIGNUM * x = BN_bin2bn (pub, 32, nullptr); BIGNUM * y = BN_bin2bn (pub + 32, 32, nullptr); - if (!EC_POINT_set_affine_coordinates_GFp (curve->GetGroup (), m_PublicKey, x, y, nullptr)) + if (!EC_POINT_set_affine_coordinates (curve->GetGroup (), m_PublicKey, x, y, nullptr)) LogPrint (eLogError, "ECICS GOST R 34.10 invalid public key"); BN_free (x); BN_free (y); } @@ -146,7 +146,7 @@ namespace crypto RAND_bytes (priv + 32, 224); BN_free (key); BIGNUM * x = BN_new (), * y = BN_new (); - EC_POINT_get_affine_coordinates_GFp (curve->GetGroup (), p, x, y, NULL); + EC_POINT_get_affine_coordinates (curve->GetGroup (), p, x, y, NULL); bn2buf (x, pub, 32); bn2buf (y, pub + 32, 32); RAND_bytes (pub + 64, 192); diff --git a/libi2pd/Gost.cpp b/libi2pd/Gost.cpp index 2dafc9ae..6bce3428 100644 --- a/libi2pd/Gost.cpp +++ b/libi2pd/Gost.cpp @@ -27,7 +27,7 @@ namespace crypto BN_CTX * ctx = BN_CTX_new (); m_Group = EC_GROUP_new_curve_GFp (p, a, b, ctx); EC_POINT * P = EC_POINT_new (m_Group); - EC_POINT_set_affine_coordinates_GFp (m_Group, P, x, y, ctx); + EC_POINT_set_affine_coordinates (m_Group, P, x, y, ctx); EC_GROUP_set_generator (m_Group, P, q, nullptr); EC_GROUP_set_curve_name (m_Group, NID_id_GostR3410_2001); EC_POINT_free(P); @@ -50,13 +50,13 @@ namespace crypto bool GOSTR3410Curve::GetXY (const EC_POINT * p, BIGNUM * x, BIGNUM * y) const { - return EC_POINT_get_affine_coordinates_GFp (m_Group, p, x, y, nullptr); + return EC_POINT_get_affine_coordinates (m_Group, p, x, y, nullptr); } EC_POINT * GOSTR3410Curve::CreatePoint (const BIGNUM * x, const BIGNUM * y) const { EC_POINT * p = EC_POINT_new (m_Group); - EC_POINT_set_affine_coordinates_GFp (m_Group, p, x, y, nullptr); + EC_POINT_set_affine_coordinates (m_Group, p, x, y, nullptr); return p; } @@ -112,7 +112,7 @@ namespace crypto BN_CTX_start (ctx); EC_POINT * C = EC_POINT_new (m_Group); // C = k*P = (rx, ry) EC_POINT * Q = nullptr; - if (EC_POINT_set_compressed_coordinates_GFp (m_Group, C, r, isNegativeY ? 1 : 0, ctx)) + if (EC_POINT_set_compressed_coordinates (m_Group, C, r, isNegativeY ? 1 : 0, ctx)) { EC_POINT * S = EC_POINT_new (m_Group); // S = s*P EC_POINT_mul (m_Group, S, s, nullptr, nullptr, ctx); From edc27d5bcb0ec2a1f73f4b04ec6e48a7961b48ba Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 14 Jul 2025 19:23:26 -0400 Subject: [PATCH 1104/1171] drop is choked --- libi2pd/Streaming.cpp | 80 +++++++++++++++++++++++++++++++++---------- libi2pd/Streaming.h | 3 ++ 2 files changed, 65 insertions(+), 18 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 66c8919d..f0469719 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -88,7 +88,7 @@ namespace stream m_TunnelsChangeSequenceNumber (0), m_LastReceivedSequenceNumber (-1), m_PreviousReceivedSequenceNumber (-1), m_LastConfirmedReceivedSequenceNumber (0), // for limit inbound speed m_Status (eStreamStatusNew), m_IsIncoming (false), m_IsAckSendScheduled (false), m_IsNAcked (false), m_IsFirstACK (false), - m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (true), m_IsClientChoked (false), + m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (true), m_IsChoking2 (false), m_IsClientChoked (false), m_IsClientChoked2 (false), m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_IsRemoteLeaseChangeInProgress (false), m_IsBufferEmpty (false), m_LocalDestination (local), m_RemoteLeaseSet (remote), m_ReceiveTimer (m_Service), m_SendTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (port), @@ -116,7 +116,7 @@ namespace stream m_TunnelsChangeSequenceNumber (0), m_LastReceivedSequenceNumber (-1), m_PreviousReceivedSequenceNumber (-1), m_LastConfirmedReceivedSequenceNumber (0), // for limit inbound speed m_Status (eStreamStatusNew), m_IsIncoming (true), m_IsAckSendScheduled (false), m_IsNAcked (false), m_IsFirstACK (false), - m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (true), m_IsClientChoked (false), + m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (true), m_IsChoking2 (false), m_IsClientChoked (false), m_IsClientChoked2 (false), m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_IsRemoteLeaseChangeInProgress (false), m_IsBufferEmpty (false), m_LocalDestination (local), m_ReceiveTimer (m_Service), m_SendTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (0), m_RTT (INITIAL_RTT), m_MinRTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_FastRTT (INITIAL_RTT), @@ -288,8 +288,41 @@ namespace stream else { LogPrint (eLogInfo, "Streaming: Missing messages on sSID=", m_SendStreamID, ": from ", m_LastReceivedSequenceNumber + 1, " to ", receivedSeqn - 1); - // save message and wait for missing message again - SavePacket (packet); + if ((receivedSeqn - m_LastReceivedSequenceNumber) >= MAX_WINDOW_SIZE*3) + { + m_LocalDestination.DeletePacket (packet); + m_IsChoking2 = true; + } + else if (m_SavedPackets.empty () && (receivedSeqn - m_LastReceivedSequenceNumber) >= 256) + { + m_LocalDestination.DeletePacket (packet); + m_IsChoking2 = true; + } + else if (!m_SavedPackets.empty ()) + { + uint8_t numNacks = 0; + auto lastSavedSeq = 0; + auto nextSeqn = m_LastReceivedSequenceNumber + 1; + for (auto it: m_SavedPackets) + { + auto seqn = it->GetSeqn (); + if ((int)seqn > lastSavedSeq) lastSavedSeq = seqn; + for (uint32_t i = nextSeqn; i < seqn; i++) numNacks++; + nextSeqn = seqn + 1; + } + + if (numNacks + (receivedSeqn - lastSavedSeq) >= 256) + { + m_LocalDestination.DeletePacket (packet); + m_IsChoking2 = true; + } + else + // save message and wait for missing message again + SavePacket (packet); + } + else + // save message and wait for missing message again + SavePacket (packet); if (m_LastReceivedSequenceNumber >= 0) { if (!m_IsAckSendScheduled) @@ -380,7 +413,12 @@ namespace stream } if (delayRequested >= DELAY_CHOKING) { - if (!m_IsClientChoked) + if (delayRequested == 65535) + { + m_IsClientChoked2 = true; + m_DropWindowDelaySequenceNumber = m_SequenceNumber-1; + } + else if (!m_IsClientChoked) { LogPrint (eLogDebug, "Streaming: Client choked, set min. window size"); m_WindowDropTargetSize = MIN_WINDOW_SIZE; @@ -388,7 +426,7 @@ namespace stream m_WindowIncCounter = 0; m_IsClientChoked = true; m_IsWinDropped = false; - m_DropWindowDelaySequenceNumber = m_SequenceNumber; + m_DropWindowDelaySequenceNumber = m_SequenceNumber-1; m_IsFirstRttSample = true; UpdatePacingTime (); } @@ -690,6 +728,8 @@ namespace stream } if (m_IsClientChoked && (ackThrough >= m_DropWindowDelaySequenceNumber || m_SentPackets.empty ())) m_IsClientChoked = false; + if (m_IsClientChoked2 && (ackThrough >= m_DropWindowDelaySequenceNumber || m_SentPackets.empty ())) + m_IsClientChoked2 = false; if (m_IsWinDropped && ackThrough > m_DropWindowDelaySequenceNumber) { m_IsFirstRttSample = true; @@ -993,7 +1033,7 @@ namespace stream htobe32buf (packet + size, lastReceivedSeqn); size += 4; // ack Through uint8_t numNacks = 0; - bool choking = false; + bool choking = m_IsChoking2; if (lastReceivedSeqn > m_LastReceivedSequenceNumber) { // fill NACKs @@ -1043,7 +1083,10 @@ namespace stream if (choking || requestImmediateAck) { htobe16buf (packet + size, 2); // 2 bytes delay interval - htobe16buf (packet + size + 2, choking ? DELAY_CHOKING : 0); // set choking or immediate ack interval + if (m_IsChoking2) + htobe16buf (packet + size + 2, DELAY_CHOKING_2); // set choking2 + else + htobe16buf (packet + size + 2, choking ? DELAY_CHOKING : 0); // set choking or immediate ack interval size += 2; if (requestImmediateAck) // ack request sent { @@ -1059,6 +1102,7 @@ namespace stream SendPackets (std::vector { &p }); m_LastACKSendTime = ts; // for limit inbound speed m_LastConfirmedReceivedSequenceNumber = lastReceivedSeqn; // for limit inbound speed + m_IsChoking2 = false; LogPrint (eLogDebug, "Streaming: Quick Ack sent. ", (int)numNacks, " NACKs"); } @@ -1423,7 +1467,7 @@ namespace stream UpdatePacingTime (); } m_LastWindowIncTime = ts; - if (m_IsNAcked || m_IsResendNeeded || m_IsClientChoked) // resend packets + if (m_IsNAcked || m_IsResendNeeded || m_IsClientChoked || m_IsClientChoked2) // resend packets ResendPacket (); else if (m_WindowSize > int(m_SentPackets.size ())) // send packets SendBuffer (); @@ -1455,7 +1499,6 @@ namespace stream m_SendTimer.cancel (); // if no ack's in RTO, disable fast retransmit m_IsTimeOutResend = true; m_IsNAcked = false; - m_IsClientChoked = false; m_IsResendNeeded = false; m_NumPacketsToSend = 1; ResendPacket (); // send one packet per RTO, waiting for ack @@ -1483,7 +1526,7 @@ namespace stream // collect packets to resend auto ts = i2p::util::GetMillisecondsSinceEpoch (); std::vector packets; - if (m_IsNAcked) + if (m_IsNAcked && !m_IsClientChoked && !m_IsClientChoked2) { for (auto it : m_NACKedPackets) { @@ -1511,6 +1554,8 @@ namespace stream it->resent = false; it->sendTime = ts; packets.push_back (it); + if (m_IsClientChoked2 && it->GetSeqn () == m_DropWindowDelaySequenceNumber) + m_IsClientChoked2 = false; if ((int)packets.size () >= m_NumPacketsToSend) break; } } @@ -1531,7 +1576,7 @@ namespace stream m_LastWindowDropSize = m_WindowDropTargetSize; else m_LastWindowDropSize = m_WindowSize; - m_WindowDropTargetSize = m_LastWindowDropSize * 0.75; // -25% to drain queue + m_WindowDropTargetSize = m_LastWindowDropSize * 0.5; // -50% to drain queue if (m_WindowDropTargetSize < MIN_WINDOW_SIZE) m_WindowDropTargetSize = MIN_WINDOW_SIZE; m_WindowIncCounter = 0; // disable window growth @@ -1543,7 +1588,6 @@ namespace stream } else if (m_IsTimeOutResend) { - m_IsTimeOutResend = false; m_RTO = INITIAL_RTO; // drop RTO to initial upon tunnels pair change m_WindowDropTargetSize = INITIAL_WINDOW_SIZE; m_LastWindowDropSize = 0; @@ -1574,12 +1618,12 @@ namespace stream SendPackets (packets); m_LastSendTime = ts; m_IsSendTime = false; - if (m_IsNAcked || m_IsResendNeeded || m_IsClientChoked) ScheduleSend (); } - else if (!m_IsClientChoked) + else if (!m_IsClientChoked && !m_IsClientChoked2) SendBuffer (); - if (!m_IsNAcked && !m_IsResendNeeded && !m_IsClientChoked) ScheduleResend (); - if (m_IsClientChoked) ScheduleSend (); + m_IsSendTime = false; + if (m_IsTimeOutResend) ScheduleResend (); // ^ m_IsTimeOutResend = false + else if (m_IsNAcked || m_IsResendNeeded || m_IsClientChoked || m_IsClientChoked2) ScheduleSend (); } void Stream::ScheduleAck (int timeout) @@ -1750,7 +1794,7 @@ namespace stream m_LastWindowDropSize = m_WindowDropTargetSize * ((m_MinRTT + m_Jitter*4) / m_FastRTT); else m_LastWindowDropSize = m_WindowSize * ((m_MinRTT + m_Jitter*4) / m_FastRTT); - m_WindowDropTargetSize = m_LastWindowDropSize * 0.75; // -25% to drain queue + m_WindowDropTargetSize = m_LastWindowDropSize * 0.5; // -50% to drain queue if (m_WindowDropTargetSize < MIN_WINDOW_SIZE) m_WindowDropTargetSize = MIN_WINDOW_SIZE; m_WindowIncCounter = 0; // disable window growth diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index eae43c0e..a3f9734e 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -76,6 +76,7 @@ namespace stream const int PENDING_INCOMING_TIMEOUT = 10; // in seconds const int MAX_RECEIVE_TIMEOUT = 20; // in seconds const uint16_t DELAY_CHOKING = 60000; // in milliseconds + const uint16_t DELAY_CHOKING_2 = 65535; // in milliseconds const uint64_t SEND_INTERVAL = 10000; // in microseconds const uint64_t SEND_INTERVAL_VARIANCE = 2000; // in microseconds const uint64_t REQUEST_IMMEDIATE_ACK_INTERVAL = 7500; // in milliseconds @@ -279,7 +280,9 @@ namespace stream bool m_IsFirstRttSample; bool m_IsSendTime; bool m_IsWinDropped; + bool m_IsChoking2; bool m_IsClientChoked; + bool m_IsClientChoked2; bool m_IsTimeOutResend; bool m_IsImmediateAckRequested; bool m_IsRemoteLeaseChangeInProgress; From 3a18e7ab9167445e74db897886640c2300b77ecc Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 16 Jul 2025 22:05:42 -0400 Subject: [PATCH 1105/1171] handle multiple ECIESx25519 encryption keys --- libi2pd_client/I2CP.cpp | 89 +++++++++++++++++++++++++++++------------ libi2pd_client/I2CP.h | 15 ++----- 2 files changed, 68 insertions(+), 36 deletions(-) diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index 85c58c48..2c2b6801 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -28,8 +28,7 @@ namespace client std::shared_ptr identity, bool isPublic, bool isSameThread, const std::map& params): LeaseSetDestination (service, isPublic, ¶ms), - m_Owner (owner), m_Identity (identity), m_EncryptionKeyType (m_Identity->GetCryptoKeyType ()), - m_IsCreatingLeaseSet (false), m_IsSameThread (isSameThread), + m_Owner (owner), m_Identity (identity), m_IsCreatingLeaseSet (false), m_IsSameThread (isSameThread), m_LeaseSetCreationTimer (service), m_ReadinessCheckTimer (service) { } @@ -42,26 +41,59 @@ namespace client m_Owner = nullptr; } - void I2CPDestination::SetEncryptionPrivateKey (const uint8_t * key) + void I2CPDestination::SetEncryptionPrivateKey (i2p::data::CryptoKeyType keyType, const uint8_t * key) { - m_Decryptor = i2p::data::PrivateKeys::CreateDecryptor (m_Identity->GetCryptoKeyType (), key); + bool exist = false; + auto it = m_EncryptionKeys.find (keyType); + if (it != m_EncryptionKeys.end () && !memcmp (it->second->priv.data (), key, it->second->priv.size ())) // new key? + exist = true; + if (!exist) + { + auto encryptionKey = std::make_shared (keyType); + memcpy (encryptionKey->priv.data (), key, encryptionKey->priv.size ()); + encryptionKey->CreateDecryptor (); // from private key + m_EncryptionKeys.insert_or_assign (keyType, encryptionKey); + } } - void I2CPDestination::SetECIESx25519EncryptionPrivateKey (const uint8_t * key) + void I2CPDestination::SetECIESx25519EncryptionPrivateKey (i2p::data::CryptoKeyType keyType, const uint8_t * key) { - if (!m_ECIESx25519Decryptor || memcmp (m_ECIESx25519PrivateKey, key, 32)) // new key? + bool exist = false; + auto it = m_EncryptionKeys.find (keyType); + if (it != m_EncryptionKeys.end () && !memcmp (it->second->priv.data (), key, it->second->priv.size ())) // new key? + exist = true; + if (!exist) { - m_ECIESx25519Decryptor = std::make_shared(key, true); // calculate public - memcpy (m_ECIESx25519PrivateKey, key, 32); + auto encryptionKey = std::make_shared (keyType); + memcpy (encryptionKey->priv.data (), key, encryptionKey->priv.size ()); + // create decryptor manually + auto decryptor = std::make_shared(key, true); // calculate publicKey + encryptionKey->decryptor = decryptor; + // assign public key from decryptor + memcpy (encryptionKey->pub.data (), decryptor->GetPubicKey (), encryptionKey->pub.size ()); + // insert or replace new + m_EncryptionKeys.insert_or_assign (keyType, encryptionKey); } } bool I2CPDestination::Decrypt (const uint8_t * encrypted, uint8_t * data, i2p::data::CryptoKeyType preferredCrypto) const { - if (preferredCrypto == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD && m_ECIESx25519Decryptor) - return m_ECIESx25519Decryptor->Decrypt (encrypted, data); - if (m_Decryptor) - return m_Decryptor->Decrypt (encrypted, data); + std::shared_ptr encryptionKey; + if (!m_EncryptionKeys.empty ()) + { + if (m_EncryptionKeys.rbegin ()->first == preferredCrypto) + encryptionKey = m_EncryptionKeys.rbegin ()->second; + else + { + auto it = m_EncryptionKeys.find (preferredCrypto); + if (it != m_EncryptionKeys.end ()) + encryptionKey = it->second; + } + if (!encryptionKey) + encryptionKey = m_EncryptionKeys.rbegin ()->second; + } + if (encryptionKey) + return encryptionKey->decryptor->Decrypt (encrypted, data); else LogPrint (eLogError, "I2CP: Decryptor is not set"); return false; @@ -69,22 +101,32 @@ namespace client const uint8_t * I2CPDestination::GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const { - if (keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD && m_ECIESx25519Decryptor) - return m_ECIESx25519Decryptor->GetPubicKey (); + auto it = m_EncryptionKeys.find (keyType); + if (it != m_EncryptionKeys.end ()) + return it->second->pub.data (); return nullptr; } bool I2CPDestination::SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const { - return keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD ? (bool)m_ECIESx25519Decryptor : m_EncryptionKeyType == keyType; +#if __cplusplus >= 202002L // C++20 + return m_EncryptionKeys.contains (keyType); +#else + return m_EncryptionKeys.count (keyType) > 0; +#endif } i2p::data::CryptoKeyType I2CPDestination::GetPreferredCryptoType () const { - if (m_ECIESx25519Decryptor) - return i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD; - return i2p::data::CRYPTO_KEY_TYPE_ELGAMAL; + return !m_EncryptionKeys.empty () ? m_EncryptionKeys.rbegin ()->first : 0; } + + i2p::data::CryptoKeyType I2CPDestination::GetRatchetsHighestCryptoType () const + { + if (m_EncryptionKeys.empty ()) return 0; + auto cryptoType = m_EncryptionKeys.rbegin ()->first; + return cryptoType >= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD ? cryptoType : 0; + } void I2CPDestination::HandleDataMessage (const uint8_t * buf, size_t len, i2p::garlic::ECIESX25519AEADRatchetSession * from) @@ -813,7 +855,7 @@ namespace client // we always assume this field as 20 bytes (DSA) regardless actual size // instead of //offset += m_Destination->GetIdentity ()->GetSigningPrivateKeyLen (); - m_Destination->SetEncryptionPrivateKey (buf + offset); + m_Destination->SetEncryptionPrivateKey (i2p::data::CRYPTO_KEY_TYPE_ELGAMAL, buf + offset); offset += 256; m_Destination->LeaseSetCreated (buf + offset, len - offset); } @@ -846,13 +888,10 @@ namespace client uint16_t keyType = bufbe16toh (buf + offset); offset += 2; // encryption type uint16_t keyLen = bufbe16toh (buf + offset); offset += 2; // private key length if (offset + keyLen > len) return; - if (keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) - m_Destination->SetECIESx25519EncryptionPrivateKey (buf + offset); + if (keyType >= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) + m_Destination->SetECIESx25519EncryptionPrivateKey (keyType, buf + offset); else - { - m_Destination->SetEncryptionType (keyType); - m_Destination->SetEncryptionPrivateKey (buf + offset); - } + m_Destination->SetEncryptionPrivateKey (keyType, buf + offset); // from identity offset += keyLen; } diff --git a/libi2pd_client/I2CP.h b/libi2pd_client/I2CP.h index 0bfa49f2..102fc554 100644 --- a/libi2pd_client/I2CP.h +++ b/libi2pd_client/I2CP.h @@ -92,9 +92,8 @@ namespace client void Stop () override; - void SetEncryptionPrivateKey (const uint8_t * key); - void SetEncryptionType (i2p::data::CryptoKeyType keyType) { m_EncryptionKeyType = keyType; }; - void SetECIESx25519EncryptionPrivateKey (const uint8_t * key); + void SetEncryptionPrivateKey (i2p::data::CryptoKeyType keyType, const uint8_t * key); + void SetECIESx25519EncryptionPrivateKey (i2p::data::CryptoKeyType keyType, const uint8_t * key); void LeaseSetCreated (const uint8_t * buf, size_t len); // called from I2CPSession void LeaseSet2Created (uint8_t storeType, const uint8_t * buf, size_t len); // called from I2CPSession void SendMsgTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident, uint32_t nonce); // called from I2CPSession @@ -109,10 +108,7 @@ namespace client protected: // GarlicDestination - i2p::data::CryptoKeyType GetRatchetsHighestCryptoType () const override - { - return m_ECIESx25519Decryptor ? i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD : 0; - } + i2p::data::CryptoKeyType GetRatchetsHighestCryptoType () const override; // LeaseSetDestination void CleanupDestination () override; i2p::data::CryptoKeyType GetPreferredCryptoType () const override; @@ -134,10 +130,7 @@ namespace client std::shared_ptr m_Owner; std::shared_ptr m_Identity; - i2p::data::CryptoKeyType m_EncryptionKeyType; - std::shared_ptr m_Decryptor; // standard - std::shared_ptr m_ECIESx25519Decryptor; - uint8_t m_ECIESx25519PrivateKey[32]; + std::map > m_EncryptionKeys; // last is most preferable uint64_t m_LeaseSetExpirationTime; bool m_IsCreatingLeaseSet, m_IsSameThread; boost::asio::deadline_timer m_LeaseSetCreationTimer, m_ReadinessCheckTimer; From 86366a6f73beadc7045ab59f8b05b5bd88c343a1 Mon Sep 17 00:00:00 2001 From: nonlin-lin-chaos-order-etc-etal Date: Fri, 18 Jul 2025 02:25:49 +0800 Subject: [PATCH 1106/1171] Add more errors diagnostics to understand malformed configs --- libi2pd/Destination.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 394435c5..64b84783 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1085,6 +1085,7 @@ namespace client m_StreamingInboundSpeed = std::stoi(it->second); if (it != params->end ()) m_StreamingMaxConcurrentStreams = std::stoi(it->second); + LogPrint (eLogDebug, "Destination: Reading parameter ", I2CP_PARAM_STREAMING_ANSWER_PINGS); it = params->find (I2CP_PARAM_STREAMING_ANSWER_PINGS); if (it != params->end ()) m_IsStreamingAnswerPings = std::stoi (it->second); // 1 for true From bfc9540c24aae8105e40ffe031b8eb0579b3a32a Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 17 Jul 2025 17:11:54 -0400 Subject: [PATCH 1107/1171] recongnize explicit boolen values of i2p.streaming.answerPings --- libi2pd/Destination.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 64b84783..f2717772 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1085,10 +1085,17 @@ namespace client m_StreamingInboundSpeed = std::stoi(it->second); if (it != params->end ()) m_StreamingMaxConcurrentStreams = std::stoi(it->second); - LogPrint (eLogDebug, "Destination: Reading parameter ", I2CP_PARAM_STREAMING_ANSWER_PINGS); it = params->find (I2CP_PARAM_STREAMING_ANSWER_PINGS); if (it != params->end ()) - m_IsStreamingAnswerPings = std::stoi (it->second); // 1 for true + { + LogPrint (eLogDebug, "Destination: Reading parameter ", I2CP_PARAM_STREAMING_ANSWER_PINGS, " value ", it->second); + if (it->second == "true") + m_IsStreamingAnswerPings = true; + else if (it->second == "false") + m_IsStreamingAnswerPings = false; + else + m_IsStreamingAnswerPings = std::stoi (it->second); // 1 for true + } if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) { From 8c204a4c10d8b76cbb4688f7ee88ee17139ac003 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 18 Jul 2025 22:39:21 -0400 Subject: [PATCH 1108/1171] use std::string_view for I2P HTTP headers. constexpr for ecxluded headers list --- libi2pd_client/I2PTunnel.cpp | 4 ++-- libi2pd_client/I2PTunnel.h | 13 +++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index fe83d47f..c1cf247a 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -428,7 +428,7 @@ namespace client else { // strip up some headers - static const std::array excluded // list of excluded headers + static constexpr std::array excluded // list of excluded headers { "Keep-Alive:", "X-I2P" }; @@ -511,7 +511,7 @@ namespace client if (line == "\r") endOfHeader = true; else { - static const std::array excluded // list of excluded headers + static constexpr std::array excluded // list of excluded headers { "Server:", "Date:", "X-Runtime:", "X-Powered-By:", "Proxy" }; diff --git a/libi2pd_client/I2PTunnel.h b/libi2pd_client/I2PTunnel.h index 9abae09a..3fb98c5c 100644 --- a/libi2pd_client/I2PTunnel.h +++ b/libi2pd_client/I2PTunnel.h @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -30,13 +31,13 @@ namespace client constexpr size_t I2P_TUNNEL_CONNECTION_BUFFER_SIZE = 8192; constexpr size_t I2P_TUNNEL_CONNECTION_STREAM_MAX_SEND_BUFFER_SIZE = 8*I2P_TUNNEL_CONNECTION_BUFFER_SIZE; constexpr size_t I2P_TUNNEL_CONNECTION_STREAM_BUFFER_SIZE = 16384; - const int I2P_TUNNEL_CONNECTION_MAX_IDLE = 3600; // in seconds - const int I2P_TUNNEL_DESTINATION_REQUEST_TIMEOUT = 10; // in seconds + constexpr int I2P_TUNNEL_CONNECTION_MAX_IDLE = 3600; // in seconds + constexpr int I2P_TUNNEL_DESTINATION_REQUEST_TIMEOUT = 10; // in seconds // for HTTP tunnels - constexpr char X_I2P_DEST_HASH[] = "X-I2P-DestHash"; // hash in base64 - constexpr char X_I2P_DEST_B64[] = "X-I2P-DestB64"; // full address in base64 - constexpr char X_I2P_DEST_B32[] = "X-I2P-DestB32"; // .b32.i2p address - const int I2P_TUNNEL_HTTP_MAX_HEADER_SIZE = 8192; + constexpr std::string_view X_I2P_DEST_HASH { "X-I2P-DestHash" }; // hash in base64 + constexpr std::string_view X_I2P_DEST_B64 { "X-I2P-DestB64" }; // full address in base64 + constexpr std::string_view X_I2P_DEST_B32 { "X-I2P-DestB32" }; // .b32.i2p address + constexpr int I2P_TUNNEL_HTTP_MAX_HEADER_SIZE = 8192; class I2PTunnelConnection: public I2PServiceHandler, public std::enable_shared_from_this { From 253a892b0fec69409bab050ab58c3499753769cb Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 19 Jul 2025 09:25:51 -0400 Subject: [PATCH 1109/1171] limit number of outbound packets if the peer can't handle it --- libi2pd/Garlic.h | 4 +++- libi2pd/Streaming.cpp | 35 ++++++++++++++++++++++++----------- libi2pd/Streaming.h | 4 +++- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index 25106c45..055c778d 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -87,8 +87,10 @@ namespace garlic { std::shared_ptr outboundTunnel; std::shared_ptr remoteLease; + // for streaming only int rtt; // RTT uint32_t updateTime; // seconds since epoch + bool isJava; // based on choked value }; class GarlicDestination; @@ -129,7 +131,7 @@ namespace garlic std::shared_ptr GetSharedRoutingPath (); void SetSharedRoutingPath (std::shared_ptr path); - + GarlicDestination * GetOwner () const { return m_Owner; } void SetOwner (GarlicDestination * owner) { m_Owner = owner; } diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index f0469719..4c676e86 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -89,10 +89,10 @@ namespace stream m_LastConfirmedReceivedSequenceNumber (0), // for limit inbound speed m_Status (eStreamStatusNew), m_IsIncoming (false), m_IsAckSendScheduled (false), m_IsNAcked (false), m_IsFirstACK (false), m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (true), m_IsChoking2 (false), m_IsClientChoked (false), m_IsClientChoked2 (false), - m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_IsRemoteLeaseChangeInProgress (false), m_IsBufferEmpty (false), m_LocalDestination (local), + m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_IsRemoteLeaseChangeInProgress (false), m_IsBufferEmpty (false), m_IsJavaClient (false), m_LocalDestination (local), m_RemoteLeaseSet (remote), m_ReceiveTimer (m_Service), m_SendTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (port), - m_RTT (INITIAL_RTT), m_MinRTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_FastRTT (INITIAL_RTT), m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0), + m_RTT (INITIAL_RTT), m_MinRTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_FastRTT (INITIAL_RTT), m_WindowSize (INITIAL_WINDOW_SIZE), m_MaxWindowSize (MAX_WINDOW_SIZE), m_LastWindowDropSize (0), m_WindowDropTargetSize (0), m_WindowIncCounter (0), m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), m_PrevRTTSample (INITIAL_RTT), m_Jitter (0), m_MinPacingTime (0), @@ -117,10 +117,10 @@ namespace stream m_LastConfirmedReceivedSequenceNumber (0), // for limit inbound speed m_Status (eStreamStatusNew), m_IsIncoming (true), m_IsAckSendScheduled (false), m_IsNAcked (false), m_IsFirstACK (false), m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (true), m_IsChoking2 (false), m_IsClientChoked (false), m_IsClientChoked2 (false), - m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_IsRemoteLeaseChangeInProgress (false), m_IsBufferEmpty (false), m_LocalDestination (local), + m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_IsRemoteLeaseChangeInProgress (false), m_IsBufferEmpty (false), m_IsJavaClient (false), m_LocalDestination (local), m_ReceiveTimer (m_Service), m_SendTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (0), m_RTT (INITIAL_RTT), m_MinRTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_FastRTT (INITIAL_RTT), - m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0), m_WindowDropTargetSize (0), m_WindowIncCounter (0), + m_WindowSize (INITIAL_WINDOW_SIZE), m_MaxWindowSize (MAX_WINDOW_SIZE), m_LastWindowDropSize (0), m_WindowDropTargetSize (0), m_WindowIncCounter (0), m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), m_PrevRTTSample (INITIAL_RTT), m_Jitter (0), m_MinPacingTime (0), m_PacingTime (INITIAL_PACING_TIME), m_PacingTimeRem (0), m_LastSendTime (0), m_LastACKRecieveTime (0), m_ACKRecieveInterval (local.GetOwner ()->GetStreamingAckDelay ()), m_RemoteLeaseChangeTime (0), m_LastWindowIncTime (0), @@ -421,6 +421,17 @@ namespace stream else if (!m_IsClientChoked) { LogPrint (eLogDebug, "Streaming: Client choked, set min. window size"); + if (delayRequested == DELAY_CHOKING_JAVA) // java detected + { + LogPrint (eLogDebug, "Streaming: limit window size for java client"); + m_MaxWindowSize = 32; + m_IsJavaClient = true; + if (m_RoutingSession) + { + auto path = m_RoutingSession->GetSharedRoutingPath (); + if (path) path->isJava = true; + } + } m_WindowDropTargetSize = MIN_WINDOW_SIZE; m_LastWindowDropSize = 0; m_WindowIncCounter = 0; @@ -646,7 +657,7 @@ namespace stream m_SentPackets.erase (it++); m_LocalDestination.DeletePacket (sentPacket); acknowledged = true; - if (m_WindowIncCounter < MAX_WINDOW_SIZE && !m_IsFirstACK && !m_IsWinDropped) + if (m_WindowIncCounter < m_MaxWindowSize && !m_IsFirstACK && !m_IsWinDropped) incCounter++; } else @@ -761,7 +772,7 @@ namespace stream if (m_RoutingSession) m_RoutingSession->SetSharedRoutingPath ( std::make_shared ( - i2p::garlic::GarlicRoutingPath{m_CurrentOutboundTunnel, m_CurrentRemoteLease, (int)m_RTT, 0})); + i2p::garlic::GarlicRoutingPath{m_CurrentOutboundTunnel, m_CurrentRemoteLease, (int)m_RTT, 0, false})); m_IsFirstACK = false; } if (acknowledged) @@ -1276,6 +1287,8 @@ namespace stream m_CurrentOutboundTunnel = routingPath->outboundTunnel; m_CurrentRemoteLease = routingPath->remoteLease; m_RTT = routingPath->rtt; + m_IsJavaClient = routingPath->isJava; + if (m_IsJavaClient) m_MaxWindowSize = 32; } } @@ -1416,12 +1429,12 @@ namespace stream m_NumPacketsToSend = 1; m_PacingTimeRem = 0; } m_IsSendTime = true; - if (m_WindowIncCounter && (m_WindowSize < MAX_WINDOW_SIZE || m_WindowDropTargetSize) && !m_SendBuffer.IsEmpty () && m_PacingTime > m_MinPacingTime) + if (m_WindowIncCounter && (m_WindowSize < m_MaxWindowSize || m_WindowDropTargetSize) && !m_SendBuffer.IsEmpty () && m_PacingTime > m_MinPacingTime) { float winSize = m_WindowSize; if (m_WindowDropTargetSize) winSize = m_WindowDropTargetSize; - float maxWinSize = MAX_WINDOW_SIZE; + float maxWinSize = m_MaxWindowSize; if (m_LastWindowIncTime) maxWinSize = (ts - m_LastWindowIncTime) / (m_RTT / MAX_WINDOW_SIZE_INC_PER_RTT) + winSize; for (int i = 0; i < m_NumPacketsToSend; i++) @@ -1436,7 +1449,7 @@ namespace stream m_WindowDropTargetSize += (m_WindowDropTargetSize - (m_LastWindowDropSize - PREV_SPEED_KEEP_TIME_COEFF)) / m_WindowDropTargetSize; // some magic here else m_WindowDropTargetSize += (m_WindowDropTargetSize - (1 - PREV_SPEED_KEEP_TIME_COEFF)) / m_WindowDropTargetSize; - if (m_WindowDropTargetSize > MAX_WINDOW_SIZE) m_WindowDropTargetSize = MAX_WINDOW_SIZE; + if (m_WindowDropTargetSize > m_MaxWindowSize) m_WindowDropTargetSize = m_MaxWindowSize; m_WindowIncCounter--; if (m_WindowDropTargetSize >= maxWinSize) { @@ -1452,7 +1465,7 @@ namespace stream m_WindowSize += (m_WindowSize - (m_LastWindowDropSize - PREV_SPEED_KEEP_TIME_COEFF)) / m_WindowSize; // some magic here else m_WindowSize += (m_WindowSize - (1 - PREV_SPEED_KEEP_TIME_COEFF)) / m_WindowSize; - if (m_WindowSize > MAX_WINDOW_SIZE) m_WindowSize = MAX_WINDOW_SIZE; + if (m_WindowSize > m_MaxWindowSize) m_WindowSize = m_MaxWindowSize; m_WindowIncCounter--; if (m_WindowSize >= maxWinSize) { @@ -1555,7 +1568,7 @@ namespace stream it->sendTime = ts; packets.push_back (it); if (m_IsClientChoked2 && it->GetSeqn () == m_DropWindowDelaySequenceNumber) - m_IsClientChoked2 = false; + m_IsClientChoked2 = false; if ((int)packets.size () >= m_NumPacketsToSend) break; } } diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index a3f9734e..91cb59f7 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -76,6 +76,7 @@ namespace stream const int PENDING_INCOMING_TIMEOUT = 10; // in seconds const int MAX_RECEIVE_TIMEOUT = 20; // in seconds const uint16_t DELAY_CHOKING = 60000; // in milliseconds + const uint16_t DELAY_CHOKING_JAVA = 61000; // in milliseconds const uint16_t DELAY_CHOKING_2 = 65535; // in milliseconds const uint64_t SEND_INTERVAL = 10000; // in microseconds const uint64_t SEND_INTERVAL_VARIANCE = 2000; // in microseconds @@ -287,6 +288,7 @@ namespace stream bool m_IsImmediateAckRequested; bool m_IsRemoteLeaseChangeInProgress; bool m_IsBufferEmpty; + bool m_IsJavaClient; StreamingDestination& m_LocalDestination; std::shared_ptr m_RemoteIdentity; std::shared_ptr m_TransientVerifier; // in case of offline key @@ -305,7 +307,7 @@ namespace stream SendBufferQueue m_SendBuffer; double m_RTT, m_MinRTT, m_SlowRTT, m_FastRTT; - float m_WindowSize, m_LastWindowDropSize, m_WindowDropTargetSize; + float m_WindowSize, m_MaxWindowSize, m_LastWindowDropSize, m_WindowDropTargetSize; int m_WindowIncCounter, m_RTO, m_AckDelay, m_PrevRTTSample; double m_Jitter; uint64_t m_MinPacingTime, m_PacingTime, m_PacingTimeRem, // microseconds From 27b005a9b2099f948ca01780c8d2d26486af8fdd Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 19 Jul 2025 10:00:47 -0400 Subject: [PATCH 1110/1171] store shared routing path and with Java separately --- libi2pd/Garlic.cpp | 2 +- libi2pd/Garlic.h | 5 ++++- libi2pd/Streaming.cpp | 12 ++++-------- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 8c8602e8..b8794753 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -28,7 +28,7 @@ namespace garlic { GarlicRoutingSession::GarlicRoutingSession (GarlicDestination * owner, bool attachLeaseSet): m_Owner (owner), m_LeaseSetUpdateStatus (attachLeaseSet ? eLeaseSetUpdated : eLeaseSetDoNotSend), - m_LeaseSetUpdateMsgID (0) + m_LeaseSetUpdateMsgID (0), m_IsWithJava (false) { } diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index 055c778d..6479710e 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -90,7 +90,6 @@ namespace garlic // for streaming only int rtt; // RTT uint32_t updateTime; // seconds since epoch - bool isJava; // based on choked value }; class GarlicDestination; @@ -131,6 +130,9 @@ namespace garlic std::shared_ptr GetSharedRoutingPath (); void SetSharedRoutingPath (std::shared_ptr path); + + bool IsWithJava () const { return m_IsWithJava; } + void SetIsWithJava (bool isWithJava) { m_IsWithJava = isWithJava; } GarlicDestination * GetOwner () const { return m_Owner; } void SetOwner (GarlicDestination * owner) { m_Owner = owner; } @@ -154,6 +156,7 @@ namespace garlic uint64_t m_LeaseSetSubmissionTime; // in milliseconds std::shared_ptr m_SharedRoutingPath; + bool m_IsWithJava; // based on choked value from streaming public: diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 4c676e86..c9d97a2e 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -426,11 +426,7 @@ namespace stream LogPrint (eLogDebug, "Streaming: limit window size for java client"); m_MaxWindowSize = 32; m_IsJavaClient = true; - if (m_RoutingSession) - { - auto path = m_RoutingSession->GetSharedRoutingPath (); - if (path) path->isJava = true; - } + if (m_RoutingSession) m_RoutingSession->SetIsWithJava (true); } m_WindowDropTargetSize = MIN_WINDOW_SIZE; m_LastWindowDropSize = 0; @@ -772,7 +768,7 @@ namespace stream if (m_RoutingSession) m_RoutingSession->SetSharedRoutingPath ( std::make_shared ( - i2p::garlic::GarlicRoutingPath{m_CurrentOutboundTunnel, m_CurrentRemoteLease, (int)m_RTT, 0, false})); + i2p::garlic::GarlicRoutingPath{m_CurrentOutboundTunnel, m_CurrentRemoteLease, (int)m_RTT, 0})); m_IsFirstACK = false; } if (acknowledged) @@ -1287,9 +1283,9 @@ namespace stream m_CurrentOutboundTunnel = routingPath->outboundTunnel; m_CurrentRemoteLease = routingPath->remoteLease; m_RTT = routingPath->rtt; - m_IsJavaClient = routingPath->isJava; - if (m_IsJavaClient) m_MaxWindowSize = 32; } + m_IsJavaClient = m_RoutingSession->IsWithJava (); + if (m_IsJavaClient) m_MaxWindowSize = 32; } auto ts = i2p::util::GetMillisecondsSinceEpoch (); From 2fafca1571e29a78dfe0aefd32ce556e7a245662 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 20 Jul 2025 08:42:39 -0400 Subject: [PATCH 1111/1171] limit simultinously sent streaming packets --- libi2pd/Garlic.cpp | 2 +- libi2pd/Garlic.h | 4 ++++ libi2pd/Streaming.cpp | 45 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index b8794753..a61359f1 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -28,7 +28,7 @@ namespace garlic { GarlicRoutingSession::GarlicRoutingSession (GarlicDestination * owner, bool attachLeaseSet): m_Owner (owner), m_LeaseSetUpdateStatus (attachLeaseSet ? eLeaseSetUpdated : eLeaseSetDoNotSend), - m_LeaseSetUpdateMsgID (0), m_IsWithJava (false) + m_LeaseSetUpdateMsgID (0), m_IsWithJava (false), m_NumSentPackets (0) { } diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index 6479710e..1fdffdae 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -133,6 +133,9 @@ namespace garlic bool IsWithJava () const { return m_IsWithJava; } void SetIsWithJava (bool isWithJava) { m_IsWithJava = isWithJava; } + + int NumSentPackets () const { return m_NumSentPackets; } + void SetNumSentPackets (int numSentPackets) { m_NumSentPackets = numSentPackets; } GarlicDestination * GetOwner () const { return m_Owner; } void SetOwner (GarlicDestination * owner) { m_Owner = owner; } @@ -157,6 +160,7 @@ namespace garlic std::shared_ptr m_SharedRoutingPath; bool m_IsWithJava; // based on choked value from streaming + int m_NumSentPackets; // for limit number of sent messages in streaming public: diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index c9d97a2e..2a28f955 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -156,7 +156,16 @@ namespace stream } void Stream::CleanUp () - { + { + if (m_RoutingSession && !m_SentPackets.empty ()) // free up space in shared window + { + int numPackets = m_SentPackets.size (); + int numSentPackets = m_RoutingSession->NumSentPackets (); + numSentPackets -= numPackets; + if (numSentPackets < 0) numSentPackets = 0; + m_RoutingSession->SetNumSentPackets (numSentPackets); + } + m_SendBuffer.CleanUp (); while (!m_ReceiveQueue.empty ()) { @@ -612,6 +621,7 @@ namespace stream } int rttSample = INT_MAX; int incCounter = 0; + int ackPacketsCounter = 0; m_IsNAcked = false; m_IsResendNeeded = false; int nackCount = packet->GetNACKCount (); @@ -653,6 +663,7 @@ namespace stream m_SentPackets.erase (it++); m_LocalDestination.DeletePacket (sentPacket); acknowledged = true; + ackPacketsCounter++; if (m_WindowIncCounter < m_MaxWindowSize && !m_IsFirstACK && !m_IsWinDropped) incCounter++; } @@ -773,6 +784,13 @@ namespace stream } if (acknowledged) { + if (m_RoutingSession) + { + int numSentPackets = m_RoutingSession->NumSentPackets (); + numSentPackets -= ackPacketsCounter; + if (numSentPackets < 0) numSentPackets = 0; + m_RoutingSession->SetNumSentPackets (numSentPackets); + } m_NumResendAttempts = 0; m_IsTimeOutResend = false; SendBuffer (); @@ -860,6 +878,18 @@ namespace stream } else if (numMsgs > m_NumPacketsToSend) numMsgs = m_NumPacketsToSend; + if (m_RoutingSession) + { + int numSentPackets = m_RoutingSession->NumSentPackets (); + int numPacketsToSend = m_MaxWindowSize - numSentPackets; + if (numPacketsToSend <= 0) // shared window is full + { + m_LastSendTime = ts; + return; + } + else if (numMsgs > numPacketsToSend) + numMsgs = numPacketsToSend; + } bool isNoAck = m_LastReceivedSequenceNumber < 0; // first packet std::vector packets; while ((m_Status == eStreamStatusNew) || (IsEstablished () && !m_SendBuffer.IsEmpty () && numMsgs > 0)) @@ -947,6 +977,7 @@ namespace stream } if (m_SendBuffer.GetSize() == 0) m_IsBufferEmpty = true; else m_IsBufferEmpty = false; + int numPackets = packets.size (); if (packets.size () > 0) { if (m_SavedPackets.empty ()) // no NACKS @@ -963,7 +994,12 @@ namespace stream } SendPackets (packets); m_LastSendTime = ts; - m_IsSendTime = false; + m_IsSendTime = false; + if (m_RoutingSession) + { + int numSentPackets = m_RoutingSession->NumSentPackets (); + m_RoutingSession->SetNumSentPackets (numSentPackets + numPackets); + } if (m_Status == eStreamStatusClosing && m_SendBuffer.IsEmpty ()) SendClose (); if (isEmpty) @@ -1209,6 +1245,11 @@ namespace stream p->len = size; boost::asio::post (m_Service, std::bind (&Stream::SendPacket, shared_from_this (), p)); + if (m_RoutingSession) + { + int numSentPackets = m_RoutingSession->NumSentPackets (); + m_RoutingSession->SetNumSentPackets (numSentPackets + 1); + } LogPrint (eLogDebug, "Streaming: FIN sent, sSID=", m_SendStreamID); } From 49569d36e5e8c78d926b1c03df0f216e9bc2ae14 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 21 Jul 2025 12:51:40 -0400 Subject: [PATCH 1112/1171] calculate message size properly --- libi2pd_client/SAM.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 12b7e286..9986ca5f 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -250,28 +250,32 @@ namespace client char * separator = strchr (m_Buffer, ' '); if (separator) { + size_t l = 0; separator = strchr (separator + 1, ' '); if (separator) + { *separator = 0; + l = eol - separator - 1; + } else separator = eol; if (!strcmp (m_Buffer, SAM_SESSION_CREATE)) - ProcessSessionCreate ({ separator + 1, bytes_transferred - (separator - m_Buffer) - 1 }); + ProcessSessionCreate ({ separator + 1, l }); else if (!strcmp (m_Buffer, SAM_STREAM_CONNECT)) ProcessStreamConnect (separator + 1, bytes_transferred - (separator - m_Buffer) - 1, bytes_transferred - (eol - m_Buffer) - 1); else if (!strcmp (m_Buffer, SAM_STREAM_ACCEPT)) - ProcessStreamAccept ({ separator + 1, bytes_transferred - (separator - m_Buffer) - 1 }); + ProcessStreamAccept ({ separator + 1, l }); else if (!strcmp (m_Buffer, SAM_STREAM_FORWARD)) - ProcessStreamForward ({ separator + 1, bytes_transferred - (separator - m_Buffer) - 1 }); + ProcessStreamForward ({ separator + 1, l }); else if (!strcmp (m_Buffer, SAM_DEST_GENERATE)) - ProcessDestGenerate ({ separator + 1, bytes_transferred - (separator - m_Buffer) - 1 }); + ProcessDestGenerate ({ separator + 1, l }); else if (!strcmp (m_Buffer, SAM_NAMING_LOOKUP)) - ProcessNamingLookup ({ separator + 1, bytes_transferred - (separator - m_Buffer) - 1 }); + ProcessNamingLookup ({ separator + 1, l }); else if (!strcmp (m_Buffer, SAM_SESSION_ADD)) - ProcessSessionAdd ({ separator + 1, bytes_transferred - (separator - m_Buffer) - 1 }); + ProcessSessionAdd ({ separator + 1, l }); else if (!strcmp (m_Buffer, SAM_SESSION_REMOVE)) - ProcessSessionRemove ({ separator + 1, bytes_transferred - (separator - m_Buffer) - 1 }); + ProcessSessionRemove ({ separator + 1, l }); else if (!strcmp (m_Buffer, SAM_DATAGRAM_SEND) || !strcmp (m_Buffer, SAM_RAW_SEND)) { size_t len = bytes_transferred - (separator - m_Buffer) - 1; From e47cc8495b11cd7a810a034f5c42d5f0dc62a96e Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 21 Jul 2025 21:19:53 -0400 Subject: [PATCH 1113/1171] handle Datagram2 --- libi2pd/Datagram.cpp | 72 +++++++++++++++++++++++++++++++++++++++++++- libi2pd/Datagram.h | 6 +++- 2 files changed, 76 insertions(+), 2 deletions(-) diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp index 029ab42d..bfcc04a7 100644 --- a/libi2pd/Datagram.cpp +++ b/libi2pd/Datagram.cpp @@ -160,6 +160,76 @@ namespace datagram LogPrint (eLogWarning, "DatagramDestination: no receiver for raw datagram"); } + void DatagramDestination::HandleDatagram2 (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len, + i2p::garlic::ECIESX25519AEADRatchetSession * from) + { + if (len < 433) + { + LogPrint (eLogWarning, "Datagram: datagram2 is too short ", len); + return; + } + i2p::data::IdentityEx identity; + size_t identityLen = identity.FromBuffer (buf, len); + if (!identityLen) return; + size_t signatureLen = identity.GetSignatureLen (); + if (signatureLen + identityLen > len) return; + + std::shared_ptr ls; + bool verified = false; + if (from) + { + ls = m_Owner->FindLeaseSet (identity.GetIdentHash ()); + if (ls) + { + uint8_t staticKey[32]; + ls->Encrypt (nullptr, staticKey); + if (!memcmp (from->GetRemoteStaticKey (), staticKey, 32)) + verified = true; + else + { + LogPrint (eLogError, "Datagram: Remote LeaseSet static key mismatch for datagram2 from ", + identity.GetIdentHash ().ToBase32 ()); + return; + } + } + } + if (!verified) + { + std::vector signedData (len + 32 - identityLen - signatureLen); + memcpy (signedData.data (), identity.GetIdentHash (), 32); + memcpy (signedData.data () + 32, buf + identityLen, signedData.size () - 32); + if (!identity.Verify (signedData.data (), signedData.size (), buf + len - signatureLen)) + { + LogPrint (eLogWarning, "Datagram: datagram2 signature verification failed"); + return; + } + } + uint16_t flags = bufbe16toh (buf + identityLen); + size_t offset = identityLen + 2; + if (flags & DATAGRAM2_FLAG_OPTIONS) + offset += bufbe16toh (buf + offset) + 2; + if (offset > len - signatureLen) + { + LogPrint (eLogWarning, "Datagram: datagram2 is too short ", len - signatureLen, " expected ", offset); + return; + } + if (flags & DATAGRAM2_FLAG_OFFLINE_SIGNATURE) + { + LogPrint (eLogWarning, "Datagram: datagram2 offline signature is not supported"); + return; + } + + auto session = ObtainSession (identity.GetIdentHash()); + session->SetVersion (eDatagramV2); + if (ls) session->SetRemoteLeaseSet (ls); + session->Ack(); + auto r = FindReceiver(toPort); + if(r) + r(identity, fromPort, toPort, buf + offset, len - offset - signatureLen); + else + LogPrint (eLogWarning, "DatagramDestination: no receiver for port ", toPort); + } + void DatagramDestination::HandleDatagram3 (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len, i2p::garlic::ECIESX25519AEADRatchetSession * from) { @@ -297,7 +367,7 @@ namespace datagram HandleDatagram (fromPort, toPort, uncompressed, uncompressedLen, from); break; case i2p::client::PROTOCOL_TYPE_DATAGRAM2: - // TODO: + HandleDatagram2 (fromPort, toPort, uncompressed, uncompressedLen, from); break; default: LogPrint (eLogInfo, "Datagram: unknown protocol type ", protocolType); diff --git a/libi2pd/Datagram.h b/libi2pd/Datagram.h index 4ff2ef00..e3475225 100644 --- a/libi2pd/Datagram.h +++ b/libi2pd/Datagram.h @@ -51,7 +51,9 @@ namespace datagram eDatagramV2 = 2, eDatagramV3 = 3, }; - + + constexpr uint16_t DATAGRAM2_FLAG_OPTIONS = 0x10; + constexpr uint16_t DATAGRAM2_FLAG_OFFLINE_SIGNATURE = 0x20; constexpr uint16_t DATAGRAM3_FLAG_OPTIONS = 0x10; class DatagramSession : public std::enable_shared_from_this @@ -163,6 +165,8 @@ namespace datagram void HandleDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len, i2p::garlic::ECIESX25519AEADRatchetSession * from); void HandleRawDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); + void HandleDatagram2 (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len, + i2p::garlic::ECIESX25519AEADRatchetSession * from); void HandleDatagram3 (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len, i2p::garlic::ECIESX25519AEADRatchetSession * from); From c554f47c4d13b0e70cf7ec9f96431e8b8996d93e Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 22 Jul 2025 16:07:24 -0400 Subject: [PATCH 1114/1171] datagramversion param for UDP client tunnel --- libi2pd/Datagram.cpp | 16 ++++++++++------ libi2pd/Datagram.h | 3 ++- libi2pd/Destination.cpp | 7 ++++--- libi2pd/Destination.h | 3 ++- libi2pd_client/ClientContext.cpp | 11 ++++++++--- libi2pd_client/ClientContext.h | 4 +++- libi2pd_client/UDPTunnel.cpp | 8 ++++---- libi2pd_client/UDPTunnel.h | 5 +++-- 8 files changed, 36 insertions(+), 21 deletions(-) diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp index bfcc04a7..e1c9ec7d 100644 --- a/libi2pd/Datagram.cpp +++ b/libi2pd/Datagram.cpp @@ -18,8 +18,10 @@ namespace i2p { namespace datagram { - DatagramDestination::DatagramDestination (std::shared_ptr owner, bool gzip): - m_Owner (owner), m_DefaultReceiver (nullptr), m_DefaultRawReceiver (nullptr), m_Gzip (gzip) + DatagramDestination::DatagramDestination (std::shared_ptr owner, + bool gzip, DatagramVersion version): + m_Owner (owner), m_DefaultReceiver (nullptr), m_DefaultRawReceiver (nullptr), + m_Gzip (gzip), m_Version (version) { if (m_Gzip) m_Deflator.reset (new i2p::data::GzipDeflator); @@ -431,14 +433,16 @@ namespace datagram std::shared_ptr session = nullptr; std::lock_guard lock(m_SessionsMutex); auto itr = m_Sessions.find(identity); - if (itr == m_Sessions.end()) { + if (itr == m_Sessions.end()) + { // not found, create new session session = std::make_shared(m_Owner, identity); + session->SetVersion (m_Version); session->Start (); - m_Sessions[identity] = session; - } else { + m_Sessions.emplace (identity, session); + } + else session = itr->second; - } return session; } diff --git a/libi2pd/Datagram.h b/libi2pd/Datagram.h index e3475225..f962d402 100644 --- a/libi2pd/Datagram.h +++ b/libi2pd/Datagram.h @@ -129,7 +129,7 @@ namespace datagram public: - DatagramDestination (std::shared_ptr owner, bool gzip); + DatagramDestination (std::shared_ptr owner, bool gzip, DatagramVersion version); ~DatagramDestination (); void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0); @@ -190,6 +190,7 @@ namespace datagram std::unordered_map m_RawReceiversByPorts; bool m_Gzip; // gzip compression of data messages + DatagramVersion m_Version; // default for destination i2p::data::GzipInflator m_Inflator; std::unique_ptr m_Deflator; std::vector m_From, m_Signature; diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index f2717772..dfb8ef05 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1397,10 +1397,11 @@ namespace client return nullptr; } - i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination (bool gzip) + i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination (bool gzip, + i2p::datagram::DatagramVersion version) { - if (m_DatagramDestination == nullptr) - m_DatagramDestination = new i2p::datagram::DatagramDestination (GetSharedFromThis (), gzip); + if (!m_DatagramDestination) + m_DatagramDestination = new i2p::datagram::DatagramDestination (GetSharedFromThis (), gzip, version); return m_DatagramDestination; } diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 717f35ce..2f700d53 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -274,7 +274,8 @@ namespace client // datagram i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; }; - i2p::datagram::DatagramDestination * CreateDatagramDestination (bool gzip = true); + i2p::datagram::DatagramDestination * CreateDatagramDestination (bool gzip = true, + i2p::datagram::DatagramVersion version = i2p::datagram::eDatagramV1); // implements LocalDestination bool Decrypt (const uint8_t * encrypted, uint8_t * data, i2p::data::CryptoKeyType preferredCrypto) const override; diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index 2d36cc11..f60909f1 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -636,7 +636,8 @@ namespace client } } - if (type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT) { + if (type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT) + { // udp client // TODO: hostnames boost::asio::ip::udp::endpoint end (boost::asio::ip::make_address(address), port); @@ -644,7 +645,9 @@ namespace client localDestination = m_SharedLocalDestination; bool gzip = section.second.get (I2P_CLIENT_TUNNEL_GZIP, true); - auto clientTunnel = std::make_shared (name, dest, end, localDestination, destinationPort, gzip); + int datagramVersion = (i2p::datagram::DatagramVersion)section.second.get (UDP_CLIENT_TUNNEL_DATAGRAM_VERSION, (int)i2p::datagram::eDatagramV1); + auto clientTunnel = std::make_shared (name, dest, end, + localDestination, destinationPort, gzip, (i2p::datagram::DatagramVersion)datagramVersion); auto ins = m_ClientForwards.insert (std::make_pair (end, clientTunnel)); if (ins.second) @@ -666,7 +669,9 @@ namespace client LogPrint(eLogError, "Clients: I2P Client forward for endpoint ", end, " already exists"); } - } else { + } + else + { boost::asio::ip::tcp::endpoint clientEndpoint; std::shared_ptr clientTunnel; if (type == I2P_TUNNELS_SECTION_TYPE_SOCKS) diff --git a/libi2pd_client/ClientContext.h b/libi2pd_client/ClientContext.h index 3f7eaf9a..52790836 100644 --- a/libi2pd_client/ClientContext.h +++ b/libi2pd_client/ClientContext.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include "Destination.h" #include "I2PService.h" @@ -61,7 +62,8 @@ namespace client const char I2P_SERVER_TUNNEL_ADDRESS[] = "address"; const char I2P_SERVER_TUNNEL_ENABLE_UNIQUE_LOCAL[] = "enableuniquelocal"; const char I2P_SERVER_TUNNEL_SSL[] = "ssl"; - + const char UDP_CLIENT_TUNNEL_DATAGRAM_VERSION[] = "datagramversion"; + class ClientContext { public: diff --git a/libi2pd_client/UDPTunnel.cpp b/libi2pd_client/UDPTunnel.cpp index b173fc0f..ade7ec75 100644 --- a/libi2pd_client/UDPTunnel.cpp +++ b/libi2pd_client/UDPTunnel.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2024, The PurpleI2P Project +* Copyright (c) 2013-2025, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -224,10 +224,10 @@ namespace client I2PUDPClientTunnel::I2PUDPClientTunnel (const std::string & name, const std::string &remoteDest, const boost::asio::ip::udp::endpoint& localEndpoint, std::shared_ptr localDestination, - uint16_t remotePort, bool gzip) : + uint16_t remotePort, bool gzip, i2p::datagram::DatagramVersion datagramVersion) : m_Name (name), m_RemoteDest (remoteDest), m_LocalDest (localDestination), m_LocalEndpoint (localEndpoint), m_ResolveThread (nullptr), m_LocalSocket (nullptr), RemotePort (remotePort), - m_LastPort (0), m_cancel_resolve (false), m_Gzip (gzip) + m_LastPort (0), m_cancel_resolve (false), m_Gzip (gzip), m_DatagramVersion (datagramVersion) { } @@ -245,7 +245,7 @@ namespace client m_LocalSocket->set_option (boost::asio::socket_base::receive_buffer_size (I2P_UDP_MAX_MTU)); m_LocalSocket->set_option (boost::asio::socket_base::reuse_address (true)); - auto dgram = m_LocalDest->CreateDatagramDestination (m_Gzip); + auto dgram = m_LocalDest->CreateDatagramDestination (m_Gzip, m_DatagramVersion); dgram->SetReceiver (std::bind (&I2PUDPClientTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, diff --git a/libi2pd_client/UDPTunnel.h b/libi2pd_client/UDPTunnel.h index 5650124c..7303aa9a 100644 --- a/libi2pd_client/UDPTunnel.h +++ b/libi2pd_client/UDPTunnel.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2024, The PurpleI2P Project +* Copyright (c) 2013-2025, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -130,7 +130,7 @@ namespace client I2PUDPClientTunnel (const std::string & name, const std::string &remoteDest, const boost::asio::ip::udp::endpoint& localEndpoint, std::shared_ptr localDestination, - uint16_t remotePort, bool gzip); + uint16_t remotePort, bool gzip, i2p::datagram::DatagramVersion datagramVersion); ~I2PUDPClientTunnel (); void Start (); @@ -175,6 +175,7 @@ namespace client uint16_t RemotePort, m_LastPort; bool m_cancel_resolve; bool m_Gzip; + i2p::datagram::DatagramVersion m_DatagramVersion; std::shared_ptr m_LastSession; public: From 6b9278fdd328536569b2092ebe178fefb3b9cf87 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 22 Jul 2025 18:41:24 -0400 Subject: [PATCH 1115/1171] request ack more often --- libi2pd/Streaming.cpp | 26 +++++++++++++++++++------- libi2pd/Streaming.h | 2 +- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 2a28f955..1b369516 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -96,7 +96,7 @@ namespace stream m_WindowDropTargetSize (0), m_WindowIncCounter (0), m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), m_PrevRTTSample (INITIAL_RTT), m_Jitter (0), m_MinPacingTime (0), - m_PacingTime (INITIAL_PACING_TIME), m_PacingTimeRem (0), m_LastSendTime (0), m_LastACKRecieveTime (0), m_ACKRecieveInterval (local.GetOwner ()->GetStreamingAckDelay ()), m_RemoteLeaseChangeTime (0), m_LastWindowIncTime (0), + m_PacingTime (INITIAL_PACING_TIME), m_PacingTimeRem (0), m_LastSendTime (0), m_LastACKRecieveTime (0), m_ACKRecieveInterval (local.GetOwner ()->GetStreamingAckDelay ()), m_RemoteLeaseChangeTime (0), m_LastWindowIncTime (0), m_LastACKRequestTime (0), m_LastACKSendTime (0), m_PacketACKInterval (1), m_PacketACKIntervalRem (0), // for limit inbound speed m_NumResendAttempts (0), m_NumPacketsToSend (0), m_JitterAccum (0), m_JitterDiv (1), m_MTU (STREAMING_MTU) { @@ -123,7 +123,7 @@ namespace stream m_WindowSize (INITIAL_WINDOW_SIZE), m_MaxWindowSize (MAX_WINDOW_SIZE), m_LastWindowDropSize (0), m_WindowDropTargetSize (0), m_WindowIncCounter (0), m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), m_PrevRTTSample (INITIAL_RTT), m_Jitter (0), m_MinPacingTime (0), - m_PacingTime (INITIAL_PACING_TIME), m_PacingTimeRem (0), m_LastSendTime (0), m_LastACKRecieveTime (0), m_ACKRecieveInterval (local.GetOwner ()->GetStreamingAckDelay ()), m_RemoteLeaseChangeTime (0), m_LastWindowIncTime (0), + m_PacingTime (INITIAL_PACING_TIME), m_PacingTimeRem (0), m_LastSendTime (0), m_LastACKRecieveTime (0), m_ACKRecieveInterval (local.GetOwner ()->GetStreamingAckDelay ()), m_RemoteLeaseChangeTime (0), m_LastWindowIncTime (0), m_LastACKRequestTime (0), m_LastACKSendTime (0), m_PacketACKInterval (1), m_PacketACKIntervalRem (0), // for limit inbound speed m_NumResendAttempts (0), m_NumPacketsToSend (0), m_JitterAccum (0), m_JitterDiv (1), m_MTU (STREAMING_MTU) { @@ -433,7 +433,7 @@ namespace stream if (delayRequested == DELAY_CHOKING_JAVA) // java detected { LogPrint (eLogDebug, "Streaming: limit window size for java client"); - m_MaxWindowSize = 32; + m_MaxWindowSize = 64; m_IsJavaClient = true; if (m_RoutingSession) m_RoutingSession->SetIsWithJava (true); } @@ -965,9 +965,21 @@ namespace stream else { // follow on packet - htobuf16 (packet + size, 0); - size += 2; // flags - htobuf16 (packet + size, 0); // no options + if (m_IsJavaClient && (!m_LastACKRequestTime || ts - m_LastACKRequestTime > m_MinRTT / 10)) + { + m_LastACKRequestTime = ts; + htobe16buf (packet + size, PACKET_FLAG_DELAY_REQUESTED); + size += 2; // flags + htobe16buf (packet + size, 2); // 2 bytes delay interval + htobe16buf (packet + size + 2, 0); // set immediate ack interval + size += 2; + } + else + { + htobuf16 (packet + size, 0); + size += 2; // flags + htobuf16 (packet + size, 0); // no options + } size += 2; // options size size += m_SendBuffer.Get(packet + size, m_MTU); // payload } @@ -1326,7 +1338,7 @@ namespace stream m_RTT = routingPath->rtt; } m_IsJavaClient = m_RoutingSession->IsWithJava (); - if (m_IsJavaClient) m_MaxWindowSize = 32; + if (m_IsJavaClient) m_MaxWindowSize = 64; } auto ts = i2p::util::GetMillisecondsSinceEpoch (); diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 91cb59f7..b33102e4 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -311,7 +311,7 @@ namespace stream int m_WindowIncCounter, m_RTO, m_AckDelay, m_PrevRTTSample; double m_Jitter; uint64_t m_MinPacingTime, m_PacingTime, m_PacingTimeRem, // microseconds - m_LastSendTime, m_LastACKRecieveTime, m_ACKRecieveInterval, m_RemoteLeaseChangeTime, m_LastWindowIncTime; // milliseconds + m_LastSendTime, m_LastACKRecieveTime, m_ACKRecieveInterval, m_RemoteLeaseChangeTime, m_LastWindowIncTime, m_LastACKRequestTime; // milliseconds uint64_t m_LastACKSendTime, m_PacketACKInterval, m_PacketACKIntervalRem; // for limit inbound speed int m_NumResendAttempts, m_NumPacketsToSend; uint64_t m_JitterAccum; From d5769080c83b7cef6b3adc9c280f524ae19d4d8a Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 23 Jul 2025 12:54:46 -0400 Subject: [PATCH 1116/1171] handle session with STYLE=DATAGRAM2 and STYLE=DATAGRAM3 --- libi2pd_client/SAM.cpp | 23 +++++++++++++++++++++-- libi2pd_client/SAM.h | 11 ++++++----- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 9986ca5f..5956e4f7 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -353,8 +353,27 @@ namespace client } SAMSessionType type = eSAMSessionTypeUnknown; + i2p::datagram::DatagramVersion datagramVersion = i2p::datagram::eDatagramV1; if (style == SAM_VALUE_STREAM) type = eSAMSessionTypeStream; - else if (style == SAM_VALUE_DATAGRAM) type = eSAMSessionTypeDatagram; +#if __cplusplus >= 202002L // C++20 + else if (style.starts_with (SAM_VALUE_DATAGRAM)) +#else + else if (style.substr (0, SAM_VALUE_DATAGRAM.size ()) == SAM_VALUE_DATAGRAM) +#endif + { + // DATAGRAM, DATAGRAM1, DATAGRAM2, DATAGRAM3 + type = eSAMSessionTypeDatagram; + if (style.size () > SAM_VALUE_DATAGRAM.size ()) + { + switch (style[SAM_VALUE_DATAGRAM.size ()]) + { + case '1': datagramVersion = i2p::datagram::eDatagramV1; break; + case '2': datagramVersion = i2p::datagram::eDatagramV2; break; + case '3': datagramVersion = i2p::datagram::eDatagramV3; break; + default: type = eSAMSessionTypeUnknown; + } + } + } else if (style == SAM_VALUE_RAW) type = eSAMSessionTypeRaw; else if (style == SAM_VALUE_MASTER) type = eSAMSessionTypeMaster; if (type == eSAMSessionTypeUnknown) @@ -416,7 +435,7 @@ namespace client if (type == eSAMSessionTypeDatagram || type == eSAMSessionTypeRaw) { session->UDPEndpoint = forward; - auto dest = session->GetLocalDestination ()->CreateDatagramDestination (); + auto dest = session->GetLocalDestination ()->CreateDatagramDestination (false, datagramVersion); uint16_t port = 0; if (forward) { diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index c10afe98..d33ebab6 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -83,13 +83,14 @@ namespace client const char SAM_PARAM_PORT[] = "PORT"; const char SAM_PARAM_FROM_PORT[] = "FROM_PORT"; const char SAM_VALUE_TRANSIENT[] = "TRANSIENT"; - const char SAM_VALUE_STREAM[] = "STREAM"; - const char SAM_VALUE_DATAGRAM[] = "DATAGRAM"; - const char SAM_VALUE_RAW[] = "RAW"; - const char SAM_VALUE_MASTER[] = "MASTER"; const char SAM_VALUE_TRUE[] = "true"; const char SAM_VALUE_FALSE[] = "false"; - + + constexpr std::string_view SAM_VALUE_STREAM { "STREAM" }; + constexpr std::string_view SAM_VALUE_DATAGRAM { "DATAGRAM" }; + constexpr std::string_view SAM_VALUE_RAW { "RAW" }; + constexpr std::string_view SAM_VALUE_MASTER { "MASTER" }; + enum SAMSocketType { eSAMSocketTypeUnknown, From f1ca24fec246664b9a147bfa90c10599ab512a4f Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 26 Jul 2025 16:05:57 -0400 Subject: [PATCH 1117/1171] handle offline signature for Datagram2 --- libi2pd/Datagram.cpp | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp index e1c9ec7d..1ccf67c3 100644 --- a/libi2pd/Datagram.cpp +++ b/libi2pd/Datagram.cpp @@ -195,31 +195,39 @@ namespace datagram } } } - if (!verified) - { - std::vector signedData (len + 32 - identityLen - signatureLen); - memcpy (signedData.data (), identity.GetIdentHash (), 32); - memcpy (signedData.data () + 32, buf + identityLen, signedData.size () - 32); - if (!identity.Verify (signedData.data (), signedData.size (), buf + len - signatureLen)) - { - LogPrint (eLogWarning, "Datagram: datagram2 signature verification failed"); - return; - } - } uint16_t flags = bufbe16toh (buf + identityLen); size_t offset = identityLen + 2; if (flags & DATAGRAM2_FLAG_OPTIONS) offset += bufbe16toh (buf + offset) + 2; - if (offset > len - signatureLen) + if (offset > len) { - LogPrint (eLogWarning, "Datagram: datagram2 is too short ", len - signatureLen, " expected ", offset); + LogPrint (eLogWarning, "Datagram: datagram2 is too short ", len, " expected ", offset); return; } - if (flags & DATAGRAM2_FLAG_OFFLINE_SIGNATURE) + if (!verified) { - LogPrint (eLogWarning, "Datagram: datagram2 offline signature is not supported"); - return; - } + std::shared_ptr transientVerifier; + if (flags & DATAGRAM2_FLAG_OFFLINE_SIGNATURE) + { + transientVerifier = i2p::data::ProcessOfflineSignature (&identity, buf, len, offset); + if (!transientVerifier) + { + LogPrint (eLogWarning, "Datagram: datagram2 offline signature failed"); + return; + } + signatureLen = transientVerifier->GetSignatureLen (); + } + std::vector signedData (len + 32 - identityLen - signatureLen); + memcpy (signedData.data (), identity.GetIdentHash (), 32); + memcpy (signedData.data () + 32, buf + identityLen, signedData.size () - 32); + verified = transientVerifier ? transientVerifier->Verify (signedData.data (), signedData.size (), buf + len - signatureLen) : + identity.Verify (signedData.data (), signedData.size (), buf + len - signatureLen); + if (!verified) + { + LogPrint (eLogWarning, "Datagram: datagram2 signature verification failed"); + return; + } + } auto session = ObtainSession (identity.GetIdentHash()); session->SetVersion (eDatagramV2); From 977967f7934bc85b36b6f4ec6fc5c88c2d238b78 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 28 Jul 2025 15:51:47 -0400 Subject: [PATCH 1118/1171] try to resolve host again in server tunnel if failed before --- libi2pd_client/I2PTunnel.cpp | 59 ++++++++++++++++++++++++------------ libi2pd_client/I2PTunnel.h | 5 ++- 2 files changed, 43 insertions(+), 21 deletions(-) diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index c1cf247a..6fc7d1bc 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -738,17 +738,10 @@ namespace client boost::system::error_code ec; auto addr = boost::asio::ip::make_address (m_Address, ec); if (!ec) - { m_Endpoint.address (addr); - Accept (); - } else - { - auto resolver = std::make_shared(GetService ()); - resolver->async_resolve (m_Address, "", - std::bind (&I2PServerTunnel::HandleResolve, this, - std::placeholders::_1, std::placeholders::_2, resolver)); - } + Resolve (nullptr); + Accept (); } void I2PServerTunnel::Stop () @@ -758,13 +751,26 @@ namespace client auto localDestination = GetLocalDestination (); if (localDestination) localDestination->StopAcceptingStreams (); - + if (m_Resolver) + m_Resolver->cancel (); + ClearHandlers (); } - void I2PServerTunnel::HandleResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::results_type endpoints, - std::shared_ptr resolver) + bool I2PServerTunnel::Resolve (std::shared_ptr stream) { + if (m_Resolver) return false; // already resolving + m_Resolver = std::make_shared(GetService ()); + m_Resolver->async_resolve (m_Address, "", + std::bind (&I2PServerTunnel::HandleResolve, this, + std::placeholders::_1, std::placeholders::_2, stream)); + return true; + } + + void I2PServerTunnel::HandleResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::results_type endpoints, + std::shared_ptr stream) + { + m_Resolver = nullptr; if (!ecode) { bool found = false; @@ -808,7 +814,8 @@ namespace client auto addr = ep.address (); LogPrint (eLogInfo, "I2PTunnel: Server tunnel ", (*endpoints.begin ()).host_name (), " has been resolved to ", addr); m_Endpoint.address (addr); - Accept (); + if (stream) + Connect (stream); } else LogPrint (eLogError, "I2PTunnel: Unable to resolve server tunnel address ", m_Address, ": ", ecode.message ()); @@ -869,16 +876,28 @@ namespace client return; } } - // new connection - auto conn = CreateI2PConnection (stream); - AddHandler (conn); - if (m_LocalAddress) - conn->Connect (*m_LocalAddress); - else - conn->Connect (m_IsUniqueLocal); + if (!m_Endpoint.address ().is_unspecified ()) + Connect (stream); + else if (!Resolve (stream)) + { + LogPrint (eLogWarning, "I2PTunnel: Address ", m_Address, " cann't be resolved. Incoming connection dropped"); + stream->Close (); + return; + } } } + void I2PServerTunnel::Connect (std::shared_ptr stream) + { + // new connection + auto conn = CreateI2PConnection (stream); + AddHandler (conn); + if (m_LocalAddress) + conn->Connect (*m_LocalAddress); + else + conn->Connect (m_IsUniqueLocal); + } + std::shared_ptr I2PServerTunnel::CreateI2PConnection (std::shared_ptr stream) { return std::make_shared (this, stream, GetEndpoint (), m_SSLCtx); diff --git a/libi2pd_client/I2PTunnel.h b/libi2pd_client/I2PTunnel.h index 3fb98c5c..00b95726 100644 --- a/libi2pd_client/I2PTunnel.h +++ b/libi2pd_client/I2PTunnel.h @@ -212,11 +212,13 @@ namespace client private: + bool Resolve (std::shared_ptr stream); void HandleResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::results_type endpoints, - std::shared_ptr resolver); + std::shared_ptr stream); void Accept (); void HandleAccept (std::shared_ptr stream); + void Connect (std::shared_ptr stream); virtual std::shared_ptr CreateI2PConnection (std::shared_ptr stream); private: @@ -230,6 +232,7 @@ namespace client bool m_IsAccessList; std::unique_ptr m_LocalAddress; std::shared_ptr m_SSLCtx; + std::shared_ptr m_Resolver; }; class I2PServerTunnelHTTP: public I2PServerTunnel From 44b4fccefe3faf7adff6f017ffca884908407b34 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 29 Jul 2025 18:37:44 -0400 Subject: [PATCH 1119/1171] non-blocking UDP sockets --- libi2pd_client/UDPTunnel.cpp | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/libi2pd_client/UDPTunnel.cpp b/libi2pd_client/UDPTunnel.cpp index ade7ec75..54c4a21d 100644 --- a/libi2pd_client/UDPTunnel.cpp +++ b/libi2pd_client/UDPTunnel.cpp @@ -20,8 +20,12 @@ namespace client { if (!m_LastSession || m_LastSession->Identity.GetLL()[0] != from.GetIdentHash ().GetLL()[0] || fromPort != m_LastSession->RemotePort) m_LastSession = ObtainUDPSession(from, toPort, fromPort); - m_LastSession->IPSocket.send_to(boost::asio::buffer(buf, len), m_RemoteEndpoint); - m_LastSession->LastActivity = i2p::util::GetMillisecondsSinceEpoch(); + boost::system::error_code ec; + m_LastSession->IPSocket.send_to(boost::asio::buffer(buf, len), m_RemoteEndpoint, 0, ec); + if (!ec) + m_LastSession->LastActivity = i2p::util::GetMillisecondsSinceEpoch(); + else + LogPrint (eLogInfo, "UDP Server: Send exception: ", ec.message (), " to ", m_RemoteEndpoint); } void I2PUDPServerTunnel::HandleRecvFromI2PRaw (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) @@ -37,8 +41,12 @@ namespace client } if (m_LastSession) { - m_LastSession->IPSocket.send_to(boost::asio::buffer(buf, len), m_RemoteEndpoint); - m_LastSession->LastActivity = i2p::util::GetMillisecondsSinceEpoch(); + boost::system::error_code ec; + m_LastSession->IPSocket.send_to(boost::asio::buffer(buf, len), m_RemoteEndpoint, 0, ec); + if (!ec) + m_LastSession->LastActivity = i2p::util::GetMillisecondsSinceEpoch(); + else + LogPrint (eLogInfo, "UDP Server: Send exception: ", ec.message (), " to ", m_RemoteEndpoint); } } @@ -121,6 +129,7 @@ namespace client RemotePort(theirPort) { IPSocket.set_option (boost::asio::socket_base::receive_buffer_size (I2P_UDP_MAX_MTU )); + IPSocket.non_blocking (true); Receive(); } @@ -244,6 +253,7 @@ namespace client m_LocalSocket.reset (new boost::asio::ip::udp::socket (m_LocalDest->GetService (), m_LocalEndpoint)); m_LocalSocket->set_option (boost::asio::socket_base::receive_buffer_size (I2P_UDP_MAX_MTU)); m_LocalSocket->set_option (boost::asio::socket_base::reuse_address (true)); + m_LocalSocket->non_blocking (true); auto dgram = m_LocalDest->CreateDatagramDestination (m_Gzip, m_DatagramVersion); dgram->SetReceiver (std::bind (&I2PUDPClientTunnel::HandleRecvFromI2P, this, @@ -400,9 +410,13 @@ namespace client if (len > 0) { LogPrint (eLogDebug, "UDP Client: Got ", len, "B from ", m_RemoteAddr ? m_RemoteAddr->identHash.ToBase32 () : ""); - m_LocalSocket->send_to (boost::asio::buffer (buf, len), itr->second->first); - // mark convo as active - itr->second->second = i2p::util::GetMillisecondsSinceEpoch (); + boost::system::error_code ec; + m_LocalSocket->send_to (boost::asio::buffer (buf, len), itr->second->first, 0, ec); + if (!ec) + // mark convo as active + itr->second->second = i2p::util::GetMillisecondsSinceEpoch (); + else + LogPrint (eLogInfo, "UDP Client: Send exception: ", ec.message (), " to ", itr->second->first); } } else From d811ac47dca4b1c4252b1e5ea55fbe1cdc37af3e Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 29 Jul 2025 19:10:40 -0400 Subject: [PATCH 1120/1171] Client compatibility check more often --- libi2pd/Streaming.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 1b369516..007f96e0 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -880,6 +880,8 @@ namespace stream numMsgs = m_NumPacketsToSend; if (m_RoutingSession) { + m_IsJavaClient = m_RoutingSession->IsWithJava (); + if (m_IsJavaClient) m_MaxWindowSize = 64; int numSentPackets = m_RoutingSession->NumSentPackets (); int numPacketsToSend = m_MaxWindowSize - numSentPackets; if (numPacketsToSend <= 0) // shared window is full @@ -1337,8 +1339,6 @@ namespace stream m_CurrentRemoteLease = routingPath->remoteLease; m_RTT = routingPath->rtt; } - m_IsJavaClient = m_RoutingSession->IsWithJava (); - if (m_IsJavaClient) m_MaxWindowSize = 64; } auto ts = i2p::util::GetMillisecondsSinceEpoch (); From 6c41cf178a2828ac7a0b153c4d542612f52479bd Mon Sep 17 00:00:00 2001 From: nonlin-lin-chaos-order-etc-etal <19966907+nonlin-lin-chaos-order-etc-etal@users.noreply.github.com> Date: Thu, 31 Jul 2025 08:16:28 +0800 Subject: [PATCH 1121/1171] Remove Android CI badge @ README.md as github free tier fails to build (OutOfMemory) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ce25c8f2..9ec24d63 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ Build instructions: * Docker image - [![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) +* Android * iOS Using i2pd From 6b9232452d4541028a4ac0d4e176e3dcd78bd378 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 31 Jul 2025 19:30:41 -0400 Subject: [PATCH 1122/1171] i2p.streaming.maxWindowSize param --- libi2pd/Config.cpp | 3 ++- libi2pd/Destination.cpp | 9 +++++++++ libi2pd/Destination.h | 4 +++- libi2pd/Streaming.cpp | 24 +++++++++++++++--------- libi2pd_client/ClientContext.cpp | 3 +++ 5 files changed, 32 insertions(+), 11 deletions(-) diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 3d88ff21..50f4c8a5 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -124,7 +124,7 @@ namespace config { ("httpproxy.i2p.streaming.maxOutboundSpeed", value()->default_value("1730000000"), "Max outbound speed of HTTP proxy stream in bytes/sec") ("httpproxy.i2p.streaming.maxInboundSpeed", value()->default_value("1730000000"), "Max inbound speed of HTTP proxy stream in bytes/sec") ("httpproxy.i2p.streaming.profile", value()->default_value("1"), "HTTP Proxy bandwidth usage profile. 1 - bulk(high), 2- interactive(low)") - + ("httpproxy.i2p.streaming.maxWindowSize", value()->default_value("512"), "HTTP Proxy stream max window size. 512 by default") ; options_description socksproxy("SOCKS Proxy options"); @@ -152,6 +152,7 @@ namespace config { ("socksproxy.i2p.streaming.maxOutboundSpeed", value()->default_value("1730000000"), "Max outbound speed of SOCKS proxy stream in bytes/sec") ("socksproxy.i2p.streaming.maxInboundSpeed", value()->default_value("1730000000"), "Max inbound speed of SOCKS proxy stream in bytes/sec") ("socksproxy.i2p.streaming.profile", value()->default_value("1"), "SOCKS Proxy bandwidth usage profile. 1 - bulk(high), 2- interactive(low)") + ("socksproxy.i2p.streaming.maxWindowSize", value()->default_value("512"), "SOCKS Proxy stream max window size. 512 by default") ; options_description shareddest("Shared local destination options"); diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index dfb8ef05..1493df6b 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1009,6 +1009,7 @@ namespace client m_StreamingOutboundSpeed (DEFAULT_MAX_OUTBOUND_SPEED), m_StreamingInboundSpeed (DEFAULT_MAX_INBOUND_SPEED), m_StreamingMaxConcurrentStreams (DEFAULT_MAX_CONCURRENT_STREAMS), + m_StreamingMaxWindowSize (i2p::stream::MAX_WINDOW_SIZE), m_IsStreamingAnswerPings (DEFAULT_ANSWER_PINGS), m_LastPort (0), m_DatagramDestination (nullptr), m_RefCounter (0), m_LastPublishedTimestamp (0), m_ReadyChecker(service) @@ -1083,8 +1084,16 @@ namespace client it = params->find (I2CP_PARAM_STREAMING_MAX_INBOUND_SPEED); if (it != params->end ()) m_StreamingInboundSpeed = std::stoi(it->second); + it = params->find (I2CP_PARAM_STREAMING_MAX_CONCURRENT_STREAMS); if (it != params->end ()) m_StreamingMaxConcurrentStreams = std::stoi(it->second); + it = params->find (I2CP_PARAM_STREAMING_MAX_WINDOW_SIZE); + if (it != params->end ()) + { + m_StreamingMaxWindowSize = std::stoi(it->second); + if (m_StreamingMaxWindowSize < i2p::stream::MIN_WINDOW_SIZE) + m_StreamingMaxWindowSize = i2p::stream::MIN_WINDOW_SIZE; + } it = params->find (I2CP_PARAM_STREAMING_ANSWER_PINGS); if (it != params->end ()) { diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 2f700d53..87859657 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -101,6 +101,7 @@ namespace client const int DEFAULT_STREAMING_PROFILE = STREAMING_PROFILE_BULK; const char I2CP_PARAM_STREAMING_MAX_CONCURRENT_STREAMS[] = "i2p.streaming.maxConcurrentStreams"; const int DEFAULT_MAX_CONCURRENT_STREAMS = 2048; + const char I2CP_PARAM_STREAMING_MAX_WINDOW_SIZE[] = "i2p.streaming.maxWindowSize"; typedef std::function stream)> StreamRequestComplete; @@ -271,6 +272,7 @@ namespace client int GetStreamingInboundSpeed () const { return m_StreamingInboundSpeed; } int GetStreamingMaxConcurrentStreams () const { return m_StreamingMaxConcurrentStreams; } bool IsStreamingAnswerPings () const { return m_IsStreamingAnswerPings; } + int GetStreamingMaxWindowSize () const { return m_StreamingMaxWindowSize; } // datagram i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; }; @@ -311,7 +313,7 @@ namespace client std::map > m_EncryptionKeys; // last is most preferable i2p::data::CryptoKeyType m_PreferredCryptoType; - int m_StreamingAckDelay,m_StreamingOutboundSpeed, m_StreamingInboundSpeed, m_StreamingMaxConcurrentStreams; + int m_StreamingAckDelay,m_StreamingOutboundSpeed, m_StreamingInboundSpeed, m_StreamingMaxConcurrentStreams, m_StreamingMaxWindowSize; bool m_IsStreamingAnswerPings; std::shared_ptr m_StreamingDestination; // default std::map > m_StreamingDestinationsByPorts; diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 007f96e0..df284788 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -88,12 +88,15 @@ namespace stream m_TunnelsChangeSequenceNumber (0), m_LastReceivedSequenceNumber (-1), m_PreviousReceivedSequenceNumber (-1), m_LastConfirmedReceivedSequenceNumber (0), // for limit inbound speed m_Status (eStreamStatusNew), m_IsIncoming (false), m_IsAckSendScheduled (false), m_IsNAcked (false), m_IsFirstACK (false), - m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (true), m_IsChoking2 (false), m_IsClientChoked (false), m_IsClientChoked2 (false), - m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_IsRemoteLeaseChangeInProgress (false), m_IsBufferEmpty (false), m_IsJavaClient (false), m_LocalDestination (local), + m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), + m_IsWinDropped (true), m_IsChoking2 (false), m_IsClientChoked (false), m_IsClientChoked2 (false), + m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_IsRemoteLeaseChangeInProgress (false), + m_IsBufferEmpty (false), m_IsJavaClient (false), m_LocalDestination (local), m_RemoteLeaseSet (remote), m_ReceiveTimer (m_Service), m_SendTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (port), - m_RTT (INITIAL_RTT), m_MinRTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_FastRTT (INITIAL_RTT), m_WindowSize (INITIAL_WINDOW_SIZE), m_MaxWindowSize (MAX_WINDOW_SIZE), m_LastWindowDropSize (0), - m_WindowDropTargetSize (0), m_WindowIncCounter (0), m_RTO (INITIAL_RTO), + m_RTT (INITIAL_RTT), m_MinRTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_FastRTT (INITIAL_RTT), + m_WindowSize (INITIAL_WINDOW_SIZE), m_MaxWindowSize (local.GetOwner ()->GetStreamingMaxWindowSize ()), + m_LastWindowDropSize (0), m_WindowDropTargetSize (0), m_WindowIncCounter (0), m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), m_PrevRTTSample (INITIAL_RTT), m_Jitter (0), m_MinPacingTime (0), m_PacingTime (INITIAL_PACING_TIME), m_PacingTimeRem (0), m_LastSendTime (0), m_LastACKRecieveTime (0), m_ACKRecieveInterval (local.GetOwner ()->GetStreamingAckDelay ()), m_RemoteLeaseChangeTime (0), m_LastWindowIncTime (0), m_LastACKRequestTime (0), @@ -116,11 +119,14 @@ namespace stream m_TunnelsChangeSequenceNumber (0), m_LastReceivedSequenceNumber (-1), m_PreviousReceivedSequenceNumber (-1), m_LastConfirmedReceivedSequenceNumber (0), // for limit inbound speed m_Status (eStreamStatusNew), m_IsIncoming (true), m_IsAckSendScheduled (false), m_IsNAcked (false), m_IsFirstACK (false), - m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (true), m_IsChoking2 (false), m_IsClientChoked (false), m_IsClientChoked2 (false), - m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_IsRemoteLeaseChangeInProgress (false), m_IsBufferEmpty (false), m_IsJavaClient (false), m_LocalDestination (local), + m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), + m_IsWinDropped (true), m_IsChoking2 (false), m_IsClientChoked (false), m_IsClientChoked2 (false), + m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_IsRemoteLeaseChangeInProgress (false), + m_IsBufferEmpty (false), m_IsJavaClient (false), m_LocalDestination (local), m_ReceiveTimer (m_Service), m_SendTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (0), m_RTT (INITIAL_RTT), m_MinRTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_FastRTT (INITIAL_RTT), - m_WindowSize (INITIAL_WINDOW_SIZE), m_MaxWindowSize (MAX_WINDOW_SIZE), m_LastWindowDropSize (0), m_WindowDropTargetSize (0), m_WindowIncCounter (0), + m_WindowSize (INITIAL_WINDOW_SIZE), m_MaxWindowSize (local.GetOwner ()->GetStreamingMaxWindowSize ()), + m_LastWindowDropSize (0), m_WindowDropTargetSize (0), m_WindowIncCounter (0), m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), m_PrevRTTSample (INITIAL_RTT), m_Jitter (0), m_MinPacingTime (0), m_PacingTime (INITIAL_PACING_TIME), m_PacingTimeRem (0), m_LastSendTime (0), m_LastACKRecieveTime (0), m_ACKRecieveInterval (local.GetOwner ()->GetStreamingAckDelay ()), m_RemoteLeaseChangeTime (0), m_LastWindowIncTime (0), m_LastACKRequestTime (0), @@ -297,7 +303,7 @@ namespace stream else { LogPrint (eLogInfo, "Streaming: Missing messages on sSID=", m_SendStreamID, ": from ", m_LastReceivedSequenceNumber + 1, " to ", receivedSeqn - 1); - if ((receivedSeqn - m_LastReceivedSequenceNumber) >= MAX_WINDOW_SIZE*3) + if ((receivedSeqn - m_LastReceivedSequenceNumber) >= m_MaxWindowSize*3) { m_LocalDestination.DeletePacket (packet); m_IsChoking2 = true; @@ -1895,7 +1901,7 @@ namespace stream } StreamingDestination::StreamingDestination (std::shared_ptr owner, uint16_t localPort, bool gzip): - m_Owner (owner), m_LocalPort (localPort), m_Gzip (gzip), + m_Owner (owner), m_LocalPort (localPort), m_Gzip (gzip), m_PendingIncomingTimer (m_Owner->GetService ()), m_LastCleanupTime (i2p::util::GetSecondsSinceEpoch ()) { diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index f60909f1..58c8d431 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -477,6 +477,7 @@ namespace client options[I2CP_PARAM_STREAMING_MAX_CONCURRENT_STREAMS] = GetI2CPOption(section, I2CP_PARAM_STREAMING_MAX_CONCURRENT_STREAMS, DEFAULT_MAX_CONCURRENT_STREAMS); options[I2CP_PARAM_STREAMING_ANSWER_PINGS] = GetI2CPOption(section, I2CP_PARAM_STREAMING_ANSWER_PINGS, isServer ? DEFAULT_ANSWER_PINGS : false); options[I2CP_PARAM_STREAMING_PROFILE] = GetI2CPOption(section, I2CP_PARAM_STREAMING_PROFILE, DEFAULT_STREAMING_PROFILE); + options[I2CP_PARAM_STREAMING_MAX_WINDOW_SIZE] = GetI2CPOption(section, I2CP_PARAM_STREAMING_MAX_WINDOW_SIZE, i2p::stream::MAX_WINDOW_SIZE); options[I2CP_PARAM_LEASESET_TYPE] = GetI2CPOption(section, I2CP_PARAM_LEASESET_TYPE, DEFAULT_LEASESET_TYPE); std::string encType = GetI2CPStringOption(section, I2CP_PARAM_LEASESET_ENCRYPTION_TYPE, isServer ? "4" : "0,4"); if (encType.length () > 0) options[I2CP_PARAM_LEASESET_ENCRYPTION_TYPE] = encType; @@ -524,6 +525,8 @@ namespace client options[I2CP_PARAM_LEASESET_PRIV_KEY] = value; if (i2p::config::GetOption(prefix + I2CP_PARAM_STREAMING_PROFILE, value)) options[I2CP_PARAM_STREAMING_PROFILE] = value; + if (i2p::config::GetOption(prefix + I2CP_PARAM_STREAMING_MAX_WINDOW_SIZE, value)) + options[I2CP_PARAM_STREAMING_MAX_WINDOW_SIZE] = value; } void ClientContext::ReadTunnels () From b6f53082426b40cddccaf5631000b97bfd7fc990 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 2 Aug 2025 11:31:26 -0400 Subject: [PATCH 1123/1171] used enum class for SAMSocketType and SAMSessionType --- daemon/HTTPServer.cpp | 8 ++-- daemon/I2PControlHandlers.cpp | 4 +- libi2pd_client/SAM.cpp | 84 +++++++++++++++++------------------ libi2pd_client/SAM.h | 6 +-- 4 files changed, 51 insertions(+), 51 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 167b8c95..c9371ab6 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -982,10 +982,10 @@ namespace http { s << "
"; switch (it->GetSocketType ()) { - case i2p::client::eSAMSocketTypeSession : s << "session"; break; - case i2p::client::eSAMSocketTypeStream : s << "stream"; break; - case i2p::client::eSAMSocketTypeAcceptor : s << "acceptor"; break; - case i2p::client::eSAMSocketTypeForward : s << "forward"; break; + case i2p::client::SAMSocketType::eSAMSocketTypeSession : s << "session"; break; + case i2p::client::SAMSocketType::eSAMSocketTypeStream : s << "stream"; break; + case i2p::client::SAMSocketType::eSAMSocketTypeAcceptor : s << "acceptor"; break; + case i2p::client::SAMSocketType::eSAMSocketTypeForward : s << "forward"; break; default: s << "unknown"; break; } s << " [" << it->GetSocket ().remote_endpoint() << "]"; diff --git a/daemon/I2PControlHandlers.cpp b/daemon/I2PControlHandlers.cpp index f3ea7f61..c94887a3 100644 --- a/daemon/I2PControlHandlers.cpp +++ b/daemon/I2PControlHandlers.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2022, The PurpleI2P Project +* Copyright (c) 2013-2025, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -340,7 +340,7 @@ namespace client for (const auto& socket: sam->ListSockets(it.first)) { boost::property_tree::ptree stream; - stream.put("type", socket->GetSocketType ()); + stream.put("type", (int)socket->GetSocketType ()); stream.put("peer", socket->GetSocket ().remote_endpoint()); sam_session_sockets.push_back(std::make_pair("", stream)); diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 5956e4f7..52ef1b10 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -27,7 +27,7 @@ namespace client SAMSocket::SAMSocket (SAMBridge& owner): m_Owner (owner), m_Socket(owner.GetService()), m_Timer (m_Owner.GetService ()), m_BufferOffset (0), - m_SocketType (eSAMSocketTypeUnknown), m_IsSilent (false), + m_SocketType (SAMSocketType::eSAMSocketTypeUnknown), m_IsSilent (false), m_IsAccepting (false), m_IsReceiving (false) { } @@ -46,13 +46,13 @@ namespace client } switch (m_SocketType) { - case eSAMSocketTypeSession: + case SAMSocketType::eSAMSocketTypeSession: m_Owner.CloseSession (m_ID); break; - case eSAMSocketTypeStream: + case SAMSocketType::eSAMSocketTypeStream: break; - case eSAMSocketTypeAcceptor: - case eSAMSocketTypeForward: + case SAMSocketType::eSAMSocketTypeAcceptor: + case SAMSocketType::eSAMSocketTypeForward: { auto session = m_Owner.FindSession(m_ID); if (session) @@ -64,7 +64,7 @@ namespace client } default: ; } - m_SocketType = eSAMSocketTypeTerminated; + m_SocketType = SAMSocketType::eSAMSocketTypeTerminated; if (m_Socket.is_open ()) { boost::system::error_code ec; @@ -197,7 +197,7 @@ namespace client { LogPrint (eLogDebug, "SAMSocket::SendMessageReply, close=",close?"true":"false", " reason: ", msg); - if (!m_IsSilent || m_SocketType == eSAMSocketTypeForward) + if (!m_IsSilent || m_SocketType == SAMSocketType::eSAMSocketTypeForward) boost::asio::async_write (m_Socket, boost::asio::buffer (msg, len), boost::asio::transfer_all (), std::bind(&SAMSocket::HandleMessageReplySent, shared_from_this (), std::placeholders::_1, std::placeholders::_2, close)); @@ -235,7 +235,7 @@ namespace client if (ecode != boost::asio::error::operation_aborted) Terminate ("SAM: read error"); } - else if (m_SocketType == eSAMSocketTypeStream) + else if (m_SocketType == SAMSocketType::eSAMSocketTypeStream) HandleReceived (ecode, bytes_transferred); else { @@ -352,9 +352,9 @@ namespace client return; } - SAMSessionType type = eSAMSessionTypeUnknown; + SAMSessionType type = SAMSessionType::eSAMSessionTypeUnknown; i2p::datagram::DatagramVersion datagramVersion = i2p::datagram::eDatagramV1; - if (style == SAM_VALUE_STREAM) type = eSAMSessionTypeStream; + if (style == SAM_VALUE_STREAM) type = SAMSessionType::eSAMSessionTypeStream; #if __cplusplus >= 202002L // C++20 else if (style.starts_with (SAM_VALUE_DATAGRAM)) #else @@ -362,7 +362,7 @@ namespace client #endif { // DATAGRAM, DATAGRAM1, DATAGRAM2, DATAGRAM3 - type = eSAMSessionTypeDatagram; + type = SAMSessionType::eSAMSessionTypeDatagram; if (style.size () > SAM_VALUE_DATAGRAM.size ()) { switch (style[SAM_VALUE_DATAGRAM.size ()]) @@ -370,13 +370,13 @@ namespace client case '1': datagramVersion = i2p::datagram::eDatagramV1; break; case '2': datagramVersion = i2p::datagram::eDatagramV2; break; case '3': datagramVersion = i2p::datagram::eDatagramV3; break; - default: type = eSAMSessionTypeUnknown; + default: type = SAMSessionType::eSAMSessionTypeUnknown; } } } - else if (style == SAM_VALUE_RAW) type = eSAMSessionTypeRaw; - else if (style == SAM_VALUE_MASTER) type = eSAMSessionTypeMaster; - if (type == eSAMSessionTypeUnknown) + else if (style == SAM_VALUE_RAW) type = SAMSessionType::eSAMSessionTypeRaw; + else if (style == SAM_VALUE_MASTER) type = SAMSessionType::eSAMSessionTypeMaster; + if (type == SAMSessionType::eSAMSessionTypeUnknown) { // unknown style SendSessionI2PError("Unknown STYLE"); @@ -384,7 +384,7 @@ namespace client } std::shared_ptr forward = nullptr; - if ((type == eSAMSessionTypeDatagram || type == eSAMSessionTypeRaw) && + if ((type == SAMSessionType::eSAMSessionTypeDatagram || type == SAMSessionType::eSAMSessionTypeRaw) && params.find(SAM_PARAM_HOST) != params.end() && params.find(SAM_PARAM_PORT) != params.end()) { // udp forward selected @@ -431,11 +431,11 @@ namespace client auto session = m_Owner.CreateSession (id, type, destination == SAM_VALUE_TRANSIENT ? "" : destination, params); if (session) { - m_SocketType = eSAMSocketTypeSession; - if (type == eSAMSessionTypeDatagram || type == eSAMSessionTypeRaw) + m_SocketType = SAMSocketType::eSAMSocketTypeSession; + if (type == SAMSessionType::eSAMSessionTypeDatagram || type == SAMSessionType::eSAMSessionTypeRaw) { session->UDPEndpoint = forward; - auto dest = session->GetLocalDestination ()->CreateDatagramDestination (false, datagramVersion); + auto dest = session->GetLocalDestination ()->CreateDatagramDestination (true, datagramVersion); uint16_t port = 0; if (forward) { @@ -443,7 +443,7 @@ namespace client auto res = std::from_chars(p.data(), p.data() + p.size(), port); if (res.ec != std::errc()) port = 0; } - if (type == eSAMSessionTypeDatagram) + if (type == SAMSessionType::eSAMSessionTypeDatagram) dest->SetReceiver (std::bind (&SAMSocket::HandleI2PDatagramReceive, shared_from_this (), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5), port @@ -510,7 +510,7 @@ namespace client void SAMSocket::ProcessStreamConnect (char * buf, size_t len, size_t rem) { LogPrint (eLogDebug, "SAM: Stream connect: ", buf); - if ( m_SocketType != eSAMSocketTypeUnknown) + if ( m_SocketType != SAMSocketType::eSAMSocketTypeUnknown) { SendSessionI2PError ("Socket already in use"); return; @@ -584,7 +584,7 @@ namespace client { if (session->GetLocalDestination ()->SupportsEncryptionType (remote->GetEncryptionType ())) { - m_SocketType = eSAMSocketTypeStream; + m_SocketType = SAMSocketType::eSAMSocketTypeStream; m_Stream = session->GetLocalDestination ()->CreateStream (remote); if (m_Stream) { @@ -617,7 +617,7 @@ namespace client void SAMSocket::ProcessStreamAccept (std::string_view buf) { LogPrint (eLogDebug, "SAM: Stream accept: ", buf); - if ( m_SocketType != eSAMSocketTypeUnknown) + if ( m_SocketType != SAMSocketType::eSAMSocketTypeUnknown) { SendSessionI2PError ("Socket already in use"); return; @@ -630,7 +630,7 @@ namespace client auto session = m_Owner.FindSession (id); if (session) { - m_SocketType = eSAMSocketTypeAcceptor; + m_SocketType = SAMSocketType::eSAMSocketTypeAcceptor; if (!session->GetLocalDestination ()->IsAcceptingStreams ()) { m_IsAccepting = true; @@ -737,7 +737,7 @@ namespace client ep.port(port); } - m_SocketType = eSAMSocketTypeForward; + m_SocketType = SAMSocketType::eSAMSocketTypeForward; m_ID = id; m_IsAccepting = true; @@ -771,7 +771,7 @@ namespace client { i2p::data::IdentityEx dest; dest.FromBase64 (params[SAM_PARAM_DESTINATION]); - if (session->Type == eSAMSessionTypeDatagram) + if (session->Type == SAMSessionType::eSAMSessionTypeDatagram) d->SendDatagramTo ((const uint8_t *)data, size, dest.GetIdentHash ()); else // raw d->SendRawDatagramTo ((const uint8_t *)data, size, dest.GetIdentHash ()); @@ -871,7 +871,7 @@ namespace client void SAMSocket::ProcessSessionAdd (std::string_view buf) { auto session = m_Owner.FindSession(m_ID); - if (session && session->Type == eSAMSessionTypeMaster) + if (session && session->Type == SAMSessionType::eSAMSessionTypeMaster) { LogPrint (eLogDebug, "SAM: Subsession add: ", buf); auto masterSession = std::static_pointer_cast(session); @@ -884,10 +884,10 @@ namespace client return; } std::string_view style = params[SAM_PARAM_STYLE]; - SAMSessionType type = eSAMSessionTypeUnknown; - if (style == SAM_VALUE_STREAM) type = eSAMSessionTypeStream; + SAMSessionType type = SAMSessionType::eSAMSessionTypeUnknown; + if (style == SAM_VALUE_STREAM) type = SAMSessionType::eSAMSessionTypeStream; // TODO: implement other styles - if (type == eSAMSessionTypeUnknown) + if (type == SAMSessionType::eSAMSessionTypeUnknown) { // unknown style SendSessionI2PError("Unsupported STYLE"); @@ -915,7 +915,7 @@ namespace client void SAMSocket::ProcessSessionRemove (std::string_view buf) { auto session = m_Owner.FindSession(m_ID); - if (session && session->Type == eSAMSessionTypeMaster) + if (session && session->Type == SAMSessionType::eSAMSessionTypeMaster) { LogPrint (eLogDebug, "SAM: Subsession remove: ", buf); auto masterSession = std::static_pointer_cast(session); @@ -1017,7 +1017,7 @@ namespace client void SAMSocket::Receive () { - if (m_SocketType == eSAMSocketTypeStream) + if (m_SocketType == SAMSocketType::eSAMSocketTypeStream) { if (m_IsReceiving) return; size_t bufSize = SAM_SOCKET_BUFFER_SIZE; @@ -1137,7 +1137,7 @@ namespace client } else { - if (m_SocketType != eSAMSocketTypeTerminated) + if (m_SocketType != SAMSocketType::eSAMSocketTypeTerminated) { if (bytes_transferred > 0) { @@ -1168,7 +1168,7 @@ namespace client if (stream) { LogPrint (eLogDebug, "SAM: Incoming I2P connection for session ", m_ID); - m_SocketType = eSAMSocketTypeStream; + m_SocketType = SAMSocketType::eSAMSocketTypeStream; m_IsAccepting = false; m_Stream = stream; context.GetAddressBook ().InsertFullAddress (stream->GetRemoteIdentity ()); @@ -1188,7 +1188,7 @@ namespace client { auto socket = session->acceptQueue.front ().first; session->acceptQueue.pop_front (); - if (socket && socket->GetSocketType () == eSAMSocketTypeAcceptor) + if (socket && socket->GetSocketType () == SAMSocketType::eSAMSocketTypeAcceptor) { socket->m_IsAccepting = true; session->GetLocalDestination ()->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, socket, std::placeholders::_1)); @@ -1197,7 +1197,7 @@ namespace client } if (!m_IsSilent) { - if (m_SocketType != eSAMSocketTypeTerminated) + if (m_SocketType != SAMSocketType::eSAMSocketTypeTerminated) { // get remote peer address auto ident = std::make_shared(stream->GetRemoteIdentity()->ToBase64 ()); // we need to keep it until sent @@ -1224,7 +1224,7 @@ namespace client { LogPrint (eLogDebug, "SAM: Incoming forward I2P connection for session ", m_ID); auto newSocket = std::make_shared(m_Owner); - newSocket->SetSocketType (eSAMSocketTypeStream); + newSocket->SetSocketType (SAMSocketType::eSAMSocketTypeStream); auto s = shared_from_this (); newSocket->GetSocket ().async_connect (ep, [s, newSocket, stream](const boost::system::error_code& ecode) @@ -1365,7 +1365,7 @@ namespace client SAMSubSession::SAMSubSession (std::shared_ptr master, std::string_view name, SAMSessionType type, uint16_t port): SAMSession (master->m_Bridge, name, type), masterSession (master), inPort (port) { - if (Type == eSAMSessionTypeStream) + if (Type == SAMSessionType::eSAMSessionTypeStream) { auto d = masterSession->GetLocalDestination ()->CreateStreamingDestination (inPort); if (d) d->Start (); @@ -1381,7 +1381,7 @@ namespace client void SAMSubSession::StopLocalDestination () { auto dest = GetLocalDestination (); - if (dest && Type == eSAMSessionTypeStream) + if (dest && Type == SAMSessionType::eSAMSessionTypeStream) { auto d = dest->RemoveStreamingDestination (inPort); if (d) d->Stop (); @@ -1535,7 +1535,7 @@ namespace client if (localDestination) { localDestination->Acquire (); - auto session = (type == eSAMSessionTypeMaster) ? std::make_shared(*this, id, localDestination) : + auto session = (type == SAMSessionType::eSAMSessionTypeMaster) ? std::make_shared(*this, id, localDestination) : std::make_shared(*this, id, type, localDestination); std::unique_lock l(m_SessionsMutex); auto ret = m_Sessions.emplace (id, session); @@ -1665,9 +1665,9 @@ namespace client { i2p::data::IdentityEx dest; dest.FromBase64 (destination); - if (session->Type == eSAMSessionTypeDatagram) + if (session->Type == SAMSessionType::eSAMSessionTypeDatagram) datagramDest->SendDatagramTo ((uint8_t *)eol, payloadLen, dest.GetIdentHash ()); - else if (session->Type == eSAMSessionTypeRaw) + else if (session->Type == SAMSessionType::eSAMSessionTypeRaw) datagramDest->SendRawDatagramTo ((uint8_t *)eol, payloadLen, dest.GetIdentHash ()); else LogPrint (eLogError, "SAM: Unexpected session type ", (int)session->Type, "for session ", sessionID); diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index d33ebab6..a0ea924d 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -91,7 +91,7 @@ namespace client constexpr std::string_view SAM_VALUE_RAW { "RAW" }; constexpr std::string_view SAM_VALUE_MASTER { "MASTER" }; - enum SAMSocketType + enum class SAMSocketType { eSAMSocketTypeUnknown, eSAMSocketTypeSession, @@ -184,7 +184,7 @@ namespace client std::shared_ptr m_Stream; }; - enum SAMSessionType + enum class SAMSessionType { eSAMSessionTypeUnknown, eSAMSessionTypeStream, @@ -226,7 +226,7 @@ namespace client { std::set > subsessions; SAMMasterSession (SAMBridge & parent, std::string_view name, std::shared_ptr dest): - SAMSingleSession (parent, name, eSAMSessionTypeMaster, dest) {}; + SAMSingleSession (parent, name, SAMSessionType::eSAMSessionTypeMaster, dest) {}; void Close (); }; From f38612b8e93293b3fe5581288cc3852e5160deb9 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 2 Aug 2025 14:57:48 -0400 Subject: [PATCH 1124/1171] Exclude 'R' cap if proxy --- libi2pd/RouterContext.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 33fb5487..9eb0f9a5 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -354,7 +354,7 @@ namespace i2p m_RouterInfo.UpdateCaps (m_RouterInfo.GetCaps () | i2p::data::RouterInfo::eReachable); break; case eRouterStatusProxy: - m_RouterInfo.UpdateCaps (m_RouterInfo.GetCaps () | i2p::data::RouterInfo::eUnreachable); + m_RouterInfo.UpdateCaps ((m_RouterInfo.GetCaps () | i2p::data::RouterInfo::eUnreachable) & ~i2p::data::RouterInfo::eReachable); break; default: ; From 643a94a441c78425798057792e97dbe13a86449e Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 3 Aug 2025 16:33:07 -0400 Subject: [PATCH 1125/1171] increased number of floodfills threshold --- libi2pd/NetDb.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index 8d17628f..df831be8 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -41,7 +41,7 @@ namespace data const int NETDB_MIN_ROUTERS = 90; const int NETDB_MIN_FLOODFILLS = 5; const int NETDB_MIN_TRANSPORTS = 10 ; // otherwise assume offline - const int NETDB_NUM_FLOODFILLS_THRESHOLD = 1500; + const int NETDB_NUM_FLOODFILLS_THRESHOLD = 1800; const int NETDB_NUM_ROUTERS_THRESHOLD = 4*NETDB_NUM_FLOODFILLS_THRESHOLD; const int NETDB_TUNNEL_CREATION_RATE_THRESHOLD = 10; // in % const int NETDB_CHECK_FOR_EXPIRATION_UPTIME = 600; // 10 minutes, in seconds From aeca4c3fc7e97b17a70b972f1e8c664ab091a87a Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 3 Aug 2025 16:34:31 -0400 Subject: [PATCH 1126/1171] fixed #2215. Check streaming destination during cleanup --- libi2pd_client/SAM.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 52ef1b10..09c2dfe9 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -1590,14 +1590,17 @@ namespace client if (dest) { auto streamingDest = dest->GetStreamingDestination (); - auto numStreams = streamingDest->GetNumStreams (); - if (numStreams > 0) - { - LogPrint (eLogInfo, "SAM: Session ", session->Name, " still has ", numStreams, " streams"); - ScheduleSessionCleanupTimer (session); + if (streamingDest) + { + auto numStreams = streamingDest->GetNumStreams (); + if (numStreams > 0) + { + LogPrint (eLogInfo, "SAM: Session ", session->Name, " still has ", numStreams, " streams"); + ScheduleSessionCleanupTimer (session); + } + else + LogPrint (eLogDebug, "SAM: Session ", session->Name, " terminated"); } - else - LogPrint (eLogDebug, "SAM: Session ", session->Name, " terminated"); } } // session's destructor is called here unless rescheduled From 28996583e49a4dea59b012296d5822a0ee0639cc Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 3 Aug 2025 16:35:23 -0400 Subject: [PATCH 1127/1171] Handle links with UTF8 SAM session name --- daemon/HTTPServer.cpp | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index c9371ab6..58166e56 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -947,7 +947,8 @@ namespace http { for (auto& it: sam->GetSessions ()) { auto& name = it.second->GetLocalDestination ()->GetNickname (); - s << "\r\n"; @@ -959,13 +960,26 @@ namespace http { void ShowSAMSession (std::stringstream& s, const std::string& id) { auto sam = i2p::client::context.GetSAMBridge (); - if (!sam) { + if (!sam) + { ShowError(s, tr("SAM disabled")); return; } - - auto session = sam->FindSession (id); - if (!session) { + if (id.empty ()) + { + ShowError(s, tr("No sam_id")); + return; + } + std::vector sam_id(id.length ()); // id is in base64 + size_t l = i2p::data::Base64ToByteStream (id, sam_id.data (), sam_id.size ()); + if (!l) + { + ShowError(s, tr("Invalid sam_id")); + return; + } + auto session = sam->FindSession ( { (const char *)sam_id.data (), l }); + if (!session) + { ShowError(s, tr("SAM session not found")); return; } @@ -977,7 +991,7 @@ namespace http { s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "
\r\n"; s << "
\r\n"; s << "" << tr("Streams") << ":
\r\n
\r\n"; - for (const auto& it: sam->ListSockets(id)) + for (const auto& it: sam->ListSockets({ (const char *)sam_id.data (), l })) { s << "
"; switch (it->GetSocketType ()) From f0c4203f5a9ef0d55c497bddded409c060314799 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 4 Aug 2025 18:25:07 -0400 Subject: [PATCH 1128/1171] read bool param --- libi2pd/Destination.cpp | 33 +++++++++++++++++++++------------ libi2pd/Destination.h | 1 + 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 1493df6b..0be5890a 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "Crypto.h" #include "ECIESX25519AEADRatchetSession.h" @@ -93,10 +94,8 @@ namespace client } it = params->find (I2CP_PARAM_DONT_PUBLISH_LEASESET); if (it != params->end ()) - { // override isPublic - m_IsPublic = (it->second != "true"); - } + m_IsPublic = GetBoolParamValue (it->second); it = params->find (I2CP_PARAM_LEASESET_TYPE); if (it != params->end ()) m_LeaseSetType = std::stoi(it->second); @@ -188,6 +187,24 @@ namespace client CleanUp (); // GarlicDestination } + bool LeaseSetDestination::GetBoolParamValue (std::string_view value) + { + bool ret = false; + if (value == "true") + ret = true; + else if (value == "false") + ret = false; + else + { + int v = 0; + auto res = std::from_chars(value.data(), value.data() + value.size(), v); + if (res.ec != std::errc()) + LogPrint (eLogError, "Destination: Unable to parse bool param value ", value, ": ", std::make_error_code (res.ec).message ()); + ret = v; + } + return ret; + } + bool LeaseSetDestination::Reconfigure(std::map params) { auto itr = params.find("i2cp.dontPublishLeaseSet"); @@ -1096,15 +1113,7 @@ namespace client } it = params->find (I2CP_PARAM_STREAMING_ANSWER_PINGS); if (it != params->end ()) - { - LogPrint (eLogDebug, "Destination: Reading parameter ", I2CP_PARAM_STREAMING_ANSWER_PINGS, " value ", it->second); - if (it->second == "true") - m_IsStreamingAnswerPings = true; - else if (it->second == "false") - m_IsStreamingAnswerPings = false; - else - m_IsStreamingAnswerPings = std::stoi (it->second); // 1 for true - } + m_IsStreamingAnswerPings = GetBoolParamValue (it->second); if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) { diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 87859657..d387a900 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -174,6 +174,7 @@ namespace client int GetLeaseSetType () const { return m_LeaseSetType; }; void SetLeaseSetType (int leaseSetType) { m_LeaseSetType = leaseSetType; }; int GetAuthType () const { return m_AuthType; }; + static bool GetBoolParamValue (std::string_view value); virtual void CleanupDestination () {}; // additional clean up in derived classes virtual i2p::data::CryptoKeyType GetPreferredCryptoType () const = 0; // I2CP From f5b57283b365c9c2079583d3d551ae344f593ee1 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 5 Aug 2025 19:21:07 -0400 Subject: [PATCH 1129/1171] i2p.streaming.dontSign tunnel param --- libi2pd/Destination.cpp | 11 ++-- libi2pd/Destination.h | 5 +- libi2pd/Streaming.cpp | 98 ++++++++++++++++++++------------ libi2pd/Streaming.h | 20 ++----- libi2pd_client/ClientContext.cpp | 1 + 5 files changed, 77 insertions(+), 58 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 0be5890a..c24ef1db 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1027,9 +1027,9 @@ namespace client m_StreamingInboundSpeed (DEFAULT_MAX_INBOUND_SPEED), m_StreamingMaxConcurrentStreams (DEFAULT_MAX_CONCURRENT_STREAMS), m_StreamingMaxWindowSize (i2p::stream::MAX_WINDOW_SIZE), - m_IsStreamingAnswerPings (DEFAULT_ANSWER_PINGS), m_LastPort (0), - m_DatagramDestination (nullptr), m_RefCounter (0), m_LastPublishedTimestamp (0), - m_ReadyChecker(service) + m_IsStreamingAnswerPings (DEFAULT_ANSWER_PINGS), m_IsStreamingDontSign (DEFAULT_DONT_SIGN), + m_LastPort (0), m_DatagramDestination (nullptr), m_RefCounter (0), + m_LastPublishedTimestamp (0), m_ReadyChecker(service) { if (keys.IsOfflineSignature () && GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET) SetLeaseSetType (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2); // offline keys can be published with LS2 only @@ -1114,7 +1114,10 @@ namespace client it = params->find (I2CP_PARAM_STREAMING_ANSWER_PINGS); if (it != params->end ()) m_IsStreamingAnswerPings = GetBoolParamValue (it->second); - + it = params->find (I2CP_PARAM_STREAMING_DONT_SIGN); + if (it != params->end ()) + m_IsStreamingDontSign = GetBoolParamValue (it->second); + if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) { // authentication for encrypted LeaseSet diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index d387a900..f7ba269f 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -102,6 +102,8 @@ namespace client const char I2CP_PARAM_STREAMING_MAX_CONCURRENT_STREAMS[] = "i2p.streaming.maxConcurrentStreams"; const int DEFAULT_MAX_CONCURRENT_STREAMS = 2048; const char I2CP_PARAM_STREAMING_MAX_WINDOW_SIZE[] = "i2p.streaming.maxWindowSize"; + const char I2CP_PARAM_STREAMING_DONT_SIGN[] = "i2p.streaming.dontSign"; + const int DEFAULT_DONT_SIGN = false; typedef std::function stream)> StreamRequestComplete; @@ -273,6 +275,7 @@ namespace client int GetStreamingInboundSpeed () const { return m_StreamingInboundSpeed; } int GetStreamingMaxConcurrentStreams () const { return m_StreamingMaxConcurrentStreams; } bool IsStreamingAnswerPings () const { return m_IsStreamingAnswerPings; } + bool IsStreamingDontSign () const { return m_IsStreamingDontSign; } int GetStreamingMaxWindowSize () const { return m_StreamingMaxWindowSize; } // datagram @@ -315,7 +318,7 @@ namespace client i2p::data::CryptoKeyType m_PreferredCryptoType; int m_StreamingAckDelay,m_StreamingOutboundSpeed, m_StreamingInboundSpeed, m_StreamingMaxConcurrentStreams, m_StreamingMaxWindowSize; - bool m_IsStreamingAnswerPings; + bool m_IsStreamingAnswerPings, m_IsStreamingDontSign; std::shared_ptr m_StreamingDestination; // default std::map > m_StreamingDestinationsByPorts; std::shared_ptr m_LastStreamingDestination; uint16_t m_LastPort; // for server tunnels diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index df284788..a2018a4e 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -91,16 +91,18 @@ namespace stream m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (true), m_IsChoking2 (false), m_IsClientChoked (false), m_IsClientChoked2 (false), m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_IsRemoteLeaseChangeInProgress (false), - m_IsBufferEmpty (false), m_IsJavaClient (false), m_LocalDestination (local), - m_RemoteLeaseSet (remote), m_ReceiveTimer (m_Service), m_SendTimer (m_Service), m_ResendTimer (m_Service), - m_AckSendTimer (m_Service), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (port), - m_RTT (INITIAL_RTT), m_MinRTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_FastRTT (INITIAL_RTT), - m_WindowSize (INITIAL_WINDOW_SIZE), m_MaxWindowSize (local.GetOwner ()->GetStreamingMaxWindowSize ()), - m_LastWindowDropSize (0), m_WindowDropTargetSize (0), m_WindowIncCounter (0), m_RTO (INITIAL_RTO), + m_IsBufferEmpty (false), m_IsJavaClient (false), m_DontSign (local.GetOwner ()->IsStreamingDontSign ()), + m_LocalDestination (local), m_RemoteLeaseSet (remote), m_ReceiveTimer (m_Service), + m_SendTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service), m_NumSentBytes (0), + m_NumReceivedBytes (0), m_Port (port), m_RTT (INITIAL_RTT), m_MinRTT (INITIAL_RTT), + m_SlowRTT (INITIAL_RTT), m_FastRTT (INITIAL_RTT), m_WindowSize (INITIAL_WINDOW_SIZE), + m_MaxWindowSize (local.GetOwner ()->GetStreamingMaxWindowSize ()), m_LastWindowDropSize (0), + m_WindowDropTargetSize (0), m_WindowIncCounter (0), m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), m_PrevRTTSample (INITIAL_RTT), - m_Jitter (0), m_MinPacingTime (0), - m_PacingTime (INITIAL_PACING_TIME), m_PacingTimeRem (0), m_LastSendTime (0), m_LastACKRecieveTime (0), m_ACKRecieveInterval (local.GetOwner ()->GetStreamingAckDelay ()), m_RemoteLeaseChangeTime (0), m_LastWindowIncTime (0), m_LastACKRequestTime (0), - m_LastACKSendTime (0), m_PacketACKInterval (1), m_PacketACKIntervalRem (0), // for limit inbound speed + m_Jitter (0), m_MinPacingTime (0), m_PacingTime (INITIAL_PACING_TIME), m_PacingTimeRem (0), + m_LastSendTime (0), m_LastACKRecieveTime (0), m_ACKRecieveInterval (local.GetOwner ()->GetStreamingAckDelay ()), + m_RemoteLeaseChangeTime (0), m_LastWindowIncTime (0), m_LastACKRequestTime (0), m_LastACKSendTime (0), + m_PacketACKInterval (1), m_PacketACKIntervalRem (0), // for limit inbound speed m_NumResendAttempts (0), m_NumPacketsToSend (0), m_JitterAccum (0), m_JitterDiv (1), m_MTU (STREAMING_MTU) { RAND_bytes ((uint8_t *)&m_RecvStreamID, 4); @@ -122,14 +124,16 @@ namespace stream m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (true), m_IsChoking2 (false), m_IsClientChoked (false), m_IsClientChoked2 (false), m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_IsRemoteLeaseChangeInProgress (false), - m_IsBufferEmpty (false), m_IsJavaClient (false), m_LocalDestination (local), - m_ReceiveTimer (m_Service), m_SendTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service), - m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (0), m_RTT (INITIAL_RTT), m_MinRTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_FastRTT (INITIAL_RTT), + m_IsBufferEmpty (false), m_IsJavaClient (false), m_DontSign (local.GetOwner ()->IsStreamingDontSign ()), + m_LocalDestination (local),m_ReceiveTimer (m_Service), m_SendTimer (m_Service), + m_ResendTimer (m_Service), m_AckSendTimer (m_Service),m_NumSentBytes (0), m_NumReceivedBytes (0), + m_Port (0), m_RTT (INITIAL_RTT), m_MinRTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_FastRTT (INITIAL_RTT), m_WindowSize (INITIAL_WINDOW_SIZE), m_MaxWindowSize (local.GetOwner ()->GetStreamingMaxWindowSize ()), - m_LastWindowDropSize (0), m_WindowDropTargetSize (0), m_WindowIncCounter (0), - m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), - m_PrevRTTSample (INITIAL_RTT), m_Jitter (0), m_MinPacingTime (0), - m_PacingTime (INITIAL_PACING_TIME), m_PacingTimeRem (0), m_LastSendTime (0), m_LastACKRecieveTime (0), m_ACKRecieveInterval (local.GetOwner ()->GetStreamingAckDelay ()), m_RemoteLeaseChangeTime (0), m_LastWindowIncTime (0), m_LastACKRequestTime (0), + m_LastWindowDropSize (0), m_WindowDropTargetSize (0), m_WindowIncCounter (0), m_RTO (INITIAL_RTO), + m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()),m_PrevRTTSample (INITIAL_RTT), m_Jitter (0), + m_MinPacingTime (0), m_PacingTime (INITIAL_PACING_TIME), m_PacingTimeRem (0), m_LastSendTime (0), + m_LastACKRecieveTime (0), m_ACKRecieveInterval (local.GetOwner ()->GetStreamingAckDelay ()), + m_RemoteLeaseChangeTime (0), m_LastWindowIncTime (0), m_LastACKRequestTime (0), m_LastACKSendTime (0), m_PacketACKInterval (1), m_PacketACKIntervalRem (0), // for limit inbound speed m_NumResendAttempts (0), m_NumPacketsToSend (0), m_JitterAccum (0), m_JitterDiv (1), m_MTU (STREAMING_MTU) { @@ -487,7 +491,9 @@ namespace stream return false; } sessionVerified = true; - } + if (!(flags & PACKET_FLAG_SIGNATURE_INCLUDED)) + m_DontSign = true; // don't sign if the remote didn't sign + } } if (flags & PACKET_FLAG_MAX_PACKET_SIZE_INCLUDED) @@ -942,8 +948,8 @@ namespace stream m_RoutingSession = m_LocalDestination.GetOwner ()->GetRoutingSession (m_RemoteLeaseSet, true, !m_IsIncoming); m_MTU = (m_RoutingSession && m_RoutingSession->IsRatchets ()) ? STREAMING_MTU_RATCHETS : STREAMING_MTU; } - uint16_t flags = PACKET_FLAG_SYNCHRONIZE | PACKET_FLAG_FROM_INCLUDED | - PACKET_FLAG_SIGNATURE_INCLUDED | PACKET_FLAG_MAX_PACKET_SIZE_INCLUDED; + uint16_t flags = PACKET_FLAG_SYNCHRONIZE | PACKET_FLAG_FROM_INCLUDED | PACKET_FLAG_MAX_PACKET_SIZE_INCLUDED; + if (!m_DontSign) flags |= PACKET_FLAG_SIGNATURE_INCLUDED; if (isNoAck) flags |= PACKET_FLAG_NO_ACK; bool isOfflineSignature = m_LocalDestination.GetOwner ()->GetPrivateKeys ().IsOfflineSignature (); if (isOfflineSignature) flags |= PACKET_FLAG_OFFLINE_SIGNATURE; @@ -957,18 +963,26 @@ namespace stream size += identityLen; // from htobe16buf (packet + size, m_MTU); size += 2; // max packet size - if (isOfflineSignature) + if (m_DontSign) { - const auto& offlineSignature = m_LocalDestination.GetOwner ()->GetPrivateKeys ().GetOfflineSignature (); - memcpy (packet + size, offlineSignature.data (), offlineSignature.size ()); - size += offlineSignature.size (); // offline signature + htobe16buf (optionsSize, packet + size - 2 - optionsSize); // actual options size + size += m_SendBuffer.Get (packet + size, m_MTU); // payload } - uint8_t * signature = packet + size; // set it later - memset (signature, 0, signatureLen); // zeroes for now - size += signatureLen; // signature - htobe16buf (optionsSize, packet + size - 2 - optionsSize); // actual options size - size += m_SendBuffer.Get (packet + size, m_MTU); // payload - m_LocalDestination.GetOwner ()->Sign (packet, size, signature); + else + { + if (isOfflineSignature) + { + const auto& offlineSignature = m_LocalDestination.GetOwner ()->GetPrivateKeys ().GetOfflineSignature (); + memcpy (packet + size, offlineSignature.data (), offlineSignature.size ()); + size += offlineSignature.size (); // offline signature + } + uint8_t * signature = packet + size; // set it later + memset (signature, 0, signatureLen); // zeroes for now + size += signatureLen; // signature + htobe16buf (optionsSize, packet + size - 2 - optionsSize); // actual options size + size += m_SendBuffer.Get (packet + size, m_MTU); // payload + m_LocalDestination.GetOwner ()->Sign (packet, size, signature); + } } else { @@ -1253,15 +1267,25 @@ namespace stream size++; // NACK count packet[size] = 0; size++; // resend delay - htobe16buf (packet + size, PACKET_FLAG_CLOSE | PACKET_FLAG_SIGNATURE_INCLUDED); + uint16_t flags = PACKET_FLAG_CLOSE; + if (!m_DontSign) flags |= PACKET_FLAG_SIGNATURE_INCLUDED; + htobe16buf (packet + size, flags); size += 2; // flags - size_t signatureLen = m_LocalDestination.GetOwner ()->GetPrivateKeys ().GetSignatureLen (); - htobe16buf (packet + size, signatureLen); // signature only - size += 2; // options size - uint8_t * signature = packet + size; - memset (packet + size, 0, signatureLen); - size += signatureLen; // signature - m_LocalDestination.GetOwner ()->Sign (packet, size, signature); + if (m_DontSign) + { + memset (packet + size, 0, 2); // no options + size += 2; // options size + } + else + { + size_t signatureLen = m_LocalDestination.GetOwner ()->GetPrivateKeys ().GetSignatureLen (); + htobe16buf (packet + size, signatureLen); // signature only + size += 2; // options size + uint8_t * signature = packet + size; + memset (packet + size, 0, signatureLen); + size += signatureLen; // signature + m_LocalDestination.GetOwner ()->Sign (packet, size, signature); + } p->len = size; boost::asio::post (m_Service, std::bind (&Stream::SendPacket, shared_from_this (), p)); diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index b33102e4..5aeced26 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -273,22 +273,10 @@ namespace stream int32_t m_PreviousReceivedSequenceNumber; int32_t m_LastConfirmedReceivedSequenceNumber; // for limit inbound speed StreamStatus m_Status; - bool m_IsIncoming; - bool m_IsAckSendScheduled; - bool m_IsNAcked; - bool m_IsFirstACK; - bool m_IsResendNeeded; - bool m_IsFirstRttSample; - bool m_IsSendTime; - bool m_IsWinDropped; - bool m_IsChoking2; - bool m_IsClientChoked; - bool m_IsClientChoked2; - bool m_IsTimeOutResend; - bool m_IsImmediateAckRequested; - bool m_IsRemoteLeaseChangeInProgress; - bool m_IsBufferEmpty; - bool m_IsJavaClient; + bool m_IsIncoming, m_IsAckSendScheduled, m_IsNAcked, m_IsFirstACK, m_IsResendNeeded, + m_IsFirstRttSample, m_IsSendTime, m_IsWinDropped, m_IsChoking2, m_IsClientChoked, + m_IsClientChoked2, m_IsTimeOutResend, m_IsImmediateAckRequested, + m_IsRemoteLeaseChangeInProgress, m_IsBufferEmpty, m_IsJavaClient, m_DontSign; StreamingDestination& m_LocalDestination; std::shared_ptr m_RemoteIdentity; std::shared_ptr m_TransientVerifier; // in case of offline key diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index 58c8d431..8bee52ae 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -476,6 +476,7 @@ namespace client options[I2CP_PARAM_STREAMING_MAX_INBOUND_SPEED] = GetI2CPOption(section, I2CP_PARAM_STREAMING_MAX_INBOUND_SPEED, DEFAULT_MAX_INBOUND_SPEED); options[I2CP_PARAM_STREAMING_MAX_CONCURRENT_STREAMS] = GetI2CPOption(section, I2CP_PARAM_STREAMING_MAX_CONCURRENT_STREAMS, DEFAULT_MAX_CONCURRENT_STREAMS); options[I2CP_PARAM_STREAMING_ANSWER_PINGS] = GetI2CPOption(section, I2CP_PARAM_STREAMING_ANSWER_PINGS, isServer ? DEFAULT_ANSWER_PINGS : false); + options[I2CP_PARAM_STREAMING_DONT_SIGN] = GetI2CPOption(section, I2CP_PARAM_STREAMING_DONT_SIGN, DEFAULT_DONT_SIGN); options[I2CP_PARAM_STREAMING_PROFILE] = GetI2CPOption(section, I2CP_PARAM_STREAMING_PROFILE, DEFAULT_STREAMING_PROFILE); options[I2CP_PARAM_STREAMING_MAX_WINDOW_SIZE] = GetI2CPOption(section, I2CP_PARAM_STREAMING_MAX_WINDOW_SIZE, i2p::stream::MAX_WINDOW_SIZE); options[I2CP_PARAM_LEASESET_TYPE] = GetI2CPOption(section, I2CP_PARAM_LEASESET_TYPE, DEFAULT_LEASESET_TYPE); From aca5f35fa027e6622bd88574ce182b10e5470d33 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 6 Aug 2025 10:50:10 -0400 Subject: [PATCH 1130/1171] don't verify signature for close and reset packets if came from ECIESx25519 session --- libi2pd/Streaming.cpp | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index a2018a4e..8fefb0f2 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -461,9 +461,10 @@ namespace stream optionData += 2; } - bool sessionVerified = false; + bool verified = true; if (flags & PACKET_FLAG_FROM_INCLUDED) { + verified = false; if (m_RemoteLeaseSet) m_RemoteIdentity = m_RemoteLeaseSet->GetIdentity (); if (!m_RemoteIdentity) m_RemoteIdentity = std::make_shared(optionData, optionSize); @@ -490,7 +491,7 @@ namespace stream m_RemoteIdentity->GetIdentHash ().ToBase32 ()); return false; } - sessionVerified = true; + verified = true; if (!(flags & PACKET_FLAG_SIGNATURE_INCLUDED)) m_DontSign = true; // don't sign if the remote didn't sign } @@ -503,6 +504,27 @@ namespace stream optionData += 2; } + if (flags & (PACKET_FLAG_CLOSE | PACKET_FLAG_RESET)) + { + verified = false; + if (packet->from && !m_RemoteLeaseSet && m_RemoteIdentity) + m_RemoteLeaseSet = m_LocalDestination.GetOwner ()->FindLeaseSet (m_RemoteIdentity->GetIdentHash ()); + if (m_RemoteLeaseSet) + { + uint8_t staticKey[32]; + m_RemoteLeaseSet->Encrypt (nullptr, staticKey); + if (memcmp (packet->from->GetRemoteStaticKey (), staticKey, 32)) + { + LogPrint (eLogError, "Streaming: Remote LeaseSet static key mismatch for stream from ", + m_RemoteIdentity->GetIdentHash ().ToBase32 ()); + return false; + } + verified = true; + } + else // invalid stream, safe to close + verified = true; + } + if (flags & PACKET_FLAG_OFFLINE_SIGNATURE) { if (!m_RemoteIdentity) @@ -510,7 +532,7 @@ namespace stream LogPrint (eLogInfo, "Streaming: offline signature without identity"); return false; } - if (sessionVerified) + if (verified) { // skip offline signature optionData += 4; // timestamp @@ -558,7 +580,6 @@ namespace stream LogPrint (eLogError, "Streaming: Signature too big, ", signatureLen, " bytes"); return false; } - bool verified = sessionVerified; if (!verified) // packet was not verified through session { // verify actual signature @@ -591,8 +612,13 @@ namespace stream { LogPrint (eLogError, "Streaming: Signature verification failed, sSID=", m_SendStreamID, ", rSID=", m_RecvStreamID); return false; - } + } } + if (!verified) + { + LogPrint (eLogError, "Streaming: Missing signature, sSID=", m_SendStreamID, ", rSID=", m_RecvStreamID); + return false; + } if (immediateAckRequested) SendQuickAck (); return true; From 20ba95ee52f7c5c7cc487b4ef656c628379d9cde Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 6 Aug 2025 13:44:46 -0400 Subject: [PATCH 1131/1171] don't add signature to ping message if i2p.streaming.dontSign --- libi2pd/Streaming.cpp | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 8fefb0f2..f9e2e60c 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -1218,7 +1218,8 @@ namespace stream size += 4; // sendStreamID memset (packet + size, 0, 14); size += 14; // all zeroes - uint16_t flags = PACKET_FLAG_ECHO | PACKET_FLAG_SIGNATURE_INCLUDED | PACKET_FLAG_FROM_INCLUDED; + uint16_t flags = PACKET_FLAG_ECHO | PACKET_FLAG_FROM_INCLUDED; + if (!m_DontSign) flags |= PACKET_FLAG_SIGNATURE_INCLUDED; bool isOfflineSignature = m_LocalDestination.GetOwner ()->GetPrivateKeys ().IsOfflineSignature (); if (isOfflineSignature) flags |= PACKET_FLAG_OFFLINE_SIGNATURE; htobe16buf (packet + size, flags); @@ -1229,17 +1230,22 @@ namespace stream size += 2; // options size m_LocalDestination.GetOwner ()->GetIdentity ()->ToBuffer (packet + size, identityLen); size += identityLen; // from - if (isOfflineSignature) - { - const auto& offlineSignature = m_LocalDestination.GetOwner ()->GetPrivateKeys ().GetOfflineSignature (); - memcpy (packet + size, offlineSignature.data (), offlineSignature.size ()); - size += offlineSignature.size (); // offline signature - } - uint8_t * signature = packet + size; // set it later - memset (signature, 0, signatureLen); // zeroes for now - size += signatureLen; // signature - htobe16buf (optionsSize, packet + size - 2 - optionsSize); // actual options size - m_LocalDestination.GetOwner ()->Sign (packet, size, signature); + if (m_DontSign) + htobe16buf (optionsSize, packet + size - 2 - optionsSize); // actual options size + else + { + if (isOfflineSignature) + { + const auto& offlineSignature = m_LocalDestination.GetOwner ()->GetPrivateKeys ().GetOfflineSignature (); + memcpy (packet + size, offlineSignature.data (), offlineSignature.size ()); + size += offlineSignature.size (); // offline signature + } + uint8_t * signature = packet + size; // set it later + memset (signature, 0, signatureLen); // zeroes for now + size += signatureLen; // signature + htobe16buf (optionsSize, packet + size - 2 - optionsSize); // actual options size + m_LocalDestination.GetOwner ()->Sign (packet, size, signature); + } p.len = size; SendPackets (std::vector { &p }); LogPrint (eLogDebug, "Streaming: Ping of ", p.len, " bytes sent"); From 9276042078249c9d60917518f95e26e5b831c0bd Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 6 Aug 2025 15:31:34 -0400 Subject: [PATCH 1132/1171] offline signature for close packet --- libi2pd/Streaming.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index f9e2e60c..b1e10ae6 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -1225,7 +1225,6 @@ namespace stream htobe16buf (packet + size, flags); size += 2; // flags size_t identityLen = m_LocalDestination.GetOwner ()->GetIdentity ()->GetFullLen (); - size_t signatureLen = m_LocalDestination.GetOwner ()->GetPrivateKeys ().GetSignatureLen (); uint8_t * optionsSize = packet + size; // set options size later size += 2; // options size m_LocalDestination.GetOwner ()->GetIdentity ()->ToBuffer (packet + size, identityLen); @@ -1240,6 +1239,7 @@ namespace stream memcpy (packet + size, offlineSignature.data (), offlineSignature.size ()); size += offlineSignature.size (); // offline signature } + size_t signatureLen = m_LocalDestination.GetOwner ()->GetPrivateKeys ().GetSignatureLen (); uint8_t * signature = packet + size; // set it later memset (signature, 0, signatureLen); // zeroes for now size += signatureLen; // signature @@ -1301,6 +1301,8 @@ namespace stream size++; // resend delay uint16_t flags = PACKET_FLAG_CLOSE; if (!m_DontSign) flags |= PACKET_FLAG_SIGNATURE_INCLUDED; + bool isOfflineSignature = m_LocalDestination.GetOwner ()->GetPrivateKeys ().IsOfflineSignature (); + if (isOfflineSignature) flags |= PACKET_FLAG_OFFLINE_SIGNATURE; htobe16buf (packet + size, flags); size += 2; // flags if (m_DontSign) @@ -1310,6 +1312,12 @@ namespace stream } else { + if (isOfflineSignature) + { + const auto& offlineSignature = m_LocalDestination.GetOwner ()->GetPrivateKeys ().GetOfflineSignature (); + memcpy (packet + size, offlineSignature.data (), offlineSignature.size ()); + size += offlineSignature.size (); // offline signature + } size_t signatureLen = m_LocalDestination.GetOwner ()->GetPrivateKeys ().GetSignatureLen (); htobe16buf (packet + size, signatureLen); // signature only size += 2; // options size From 2fb8ca9cc782d7113ee07b29f532b5541117337e Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 9 Aug 2025 19:35:55 -0400 Subject: [PATCH 1133/1171] send Datagram2 --- libi2pd/Datagram.cpp | 57 ++++++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 18 deletions(-) diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp index 1ccf67c3..eff2533a 100644 --- a/libi2pd/Datagram.cpp +++ b/libi2pd/Datagram.cpp @@ -60,28 +60,49 @@ namespace datagram { if (session) { - if (session->GetVersion () == eDatagramV3) + std::shared_ptr msg; + switch (session->GetVersion ()) { - constexpr uint8_t flags[] = { 0x00, 0x03 }; // datagram3, no options - auto msg = CreateDataMessage ({{m_Owner->GetIdentity ()->GetIdentHash (), 32}, - {flags, 2}, {payload, len}}, fromPort, toPort, i2p::client::PROTOCOL_TYPE_DATAGRAM3, false); // datagram3 - session->SendMsg(msg); - } - else - { - if (m_Owner->GetIdentity ()->GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1) + case eDatagramV3: { - uint8_t hash[32]; - SHA256(payload, len, hash); - m_Owner->Sign (hash, 32, m_Signature.data ()); + constexpr uint8_t flags[] = { 0x00, 0x03 }; // datagram3, no options + msg = CreateDataMessage ({{m_Owner->GetIdentity ()->GetIdentHash (), 32}, + {flags, 2}, {payload, len}}, fromPort, toPort, i2p::client::PROTOCOL_TYPE_DATAGRAM3, false); // datagram3 + break; } - else - m_Owner->Sign (payload, len, m_Signature.data ()); + case eDatagramV1: + { + if (m_Owner->GetIdentity ()->GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1) + { + uint8_t hash[32]; + SHA256(payload, len, hash); + m_Owner->Sign (hash, 32, m_Signature.data ()); + } + else + m_Owner->Sign (payload, len, m_Signature.data ()); + msg = CreateDataMessage ({{m_From.data (), m_From.size ()}, {m_Signature.data (), m_Signature.size ()}, {payload, len}}, + fromPort, toPort, i2p::client::PROTOCOL_TYPE_DATAGRAM, !session->IsRatchets ()); // datagram1 + break; + } + case eDatagramV2: + { + constexpr uint8_t flags[] = { 0x00, 0x02 }; // datagram2, no options + // signature + std::vector signedData (len + 32 + 2); + memcpy (signedData.data (), m_Owner->GetIdentity ()->GetIdentHash (), 32); + memcpy (signedData.data () + 32, flags, 2); + memcpy (signedData.data () + 34, payload, len); + m_Owner->Sign (signedData.data (), signedData.size (), m_Signature.data ()); + // TODO: offline signatures and options + msg = CreateDataMessage ({{m_From.data (), m_From.size ()}, {flags, 2}, {payload, len}, + {m_Signature.data (), m_Signature.size ()}}, fromPort, toPort, i2p::client::PROTOCOL_TYPE_DATAGRAM2, false); // datagram2 - auto msg = CreateDataMessage ({{m_From.data (), m_From.size ()}, {m_Signature.data (), m_Signature.size ()}, {payload, len}}, - fromPort, toPort, i2p::client::PROTOCOL_TYPE_DATAGRAM, !session->IsRatchets ()); // datagram1 - session->SendMsg(msg); - } + break; + } + default: + LogPrint (eLogError, "Datagram: datagram type ", (int)session->GetVersion (), " is not supported"); + } + if (msg) session->SendMsg(msg); } } From 91027168f9152c132bf687d2593e260a37566d53 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 11 Aug 2025 13:14:55 -0400 Subject: [PATCH 1134/1171] correct max UDP buffer size for openbsd --- libi2pd/SSU2.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index b7214480..3be9f2d1 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -34,7 +34,11 @@ namespace transport const int SSU2_RESEND_CHECK_MORE_TIMEOUT_VARIANCE = 9; // in milliseconds const size_t SSU2_MAX_RESEND_PACKETS = 128; // packets to resend at the time const uint64_t SSU2_SOCKET_MIN_BUFFER_SIZE = 128 * 1024; +#if defined(__OpenBSD__) + const uint64_t SSU2_SOCKET_MAX_BUFFER_SIZE = 2 * 1024 * 1024; +#else const uint64_t SSU2_SOCKET_MAX_BUFFER_SIZE = 4 * 1024 * 1024; +#endif const size_t SSU2_MAX_NUM_INTRODUCERS = 3; const size_t SSU2_MIN_RECEIVED_PACKET_SIZE = 40; // 16 byte short header + 8 byte minimum payload + 16 byte MAC const size_t SSU2_MAX_RECEIVED_QUEUE_SIZE = 2500; // in packets From d496b15249e782cb4e10b082022de47478be9dc5 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 13 Aug 2025 17:16:56 -0400 Subject: [PATCH 1135/1171] handle SESSION ADD without FROM_PORT --- libi2pd_client/SAM.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 09c2dfe9..1f5e313d 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -893,11 +893,17 @@ namespace client SendSessionI2PError("Unsupported STYLE"); return; } - auto fromPort = std::stoi(std::string (params[SAM_PARAM_FROM_PORT])); - if (fromPort == -1) + uint16_t fromPort = 0; + auto it = params.find (SAM_PARAM_FROM_PORT); + if (it != params.end ()) { - SendSessionI2PError("Invalid from port"); - return; + auto p = it->second; + auto res = std::from_chars(p.data(), p.data() + p.size(), fromPort); + if (res.ec != std::errc()) + { + SendSessionI2PError("Invalid from port"); + return; + } } auto subsession = std::make_shared(masterSession, id, type, fromPort); if (m_Owner.AddSession (subsession)) @@ -1364,9 +1370,10 @@ namespace client SAMSubSession::SAMSubSession (std::shared_ptr master, std::string_view name, SAMSessionType type, uint16_t port): SAMSession (master->m_Bridge, name, type), masterSession (master), inPort (port) - { - if (Type == SAMSessionType::eSAMSessionTypeStream) + { + if (Type == SAMSessionType::eSAMSessionTypeStream && port) { + // additional streaming destination, use default if port is 0 auto d = masterSession->GetLocalDestination ()->CreateStreamingDestination (inPort); if (d) d->Start (); } From 7dd174d32caf38f11e9a836fc169ec7ac3e255e6 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 14 Aug 2025 15:44:48 -0400 Subject: [PATCH 1136/1171] extract and check VERSION --- libi2pd_client/SAM.cpp | 140 ++++++++++++++++++++--------------------- libi2pd_client/SAM.h | 23 ++++--- 2 files changed, 83 insertions(+), 80 deletions(-) diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 1f5e313d..94bac10f 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -26,9 +26,9 @@ namespace client { SAMSocket::SAMSocket (SAMBridge& owner): m_Owner (owner), m_Socket(owner.GetService()), m_Timer (m_Owner.GetService ()), - m_BufferOffset (0), - m_SocketType (SAMSocketType::eSAMSocketTypeUnknown), m_IsSilent (false), - m_IsAccepting (false), m_IsReceiving (false) + m_BufferOffset (0), m_SocketType (SAMSocketType::eSAMSocketTypeUnknown), + m_IsSilent (false), m_IsAccepting (false), m_IsReceiving (false), + m_Version (MIN_SAM_VERSION) { } @@ -81,21 +81,26 @@ namespace client std::placeholders::_1, std::placeholders::_2)); } - static bool SAMVersionAcceptable(const std::string & ver) + static int ExtractVersion (std::string_view ver) { - return ver == "3.0" || ver == "3.1"; - } + int version = 0; + for (auto ch: ver) + { + if (ch >= '0' && ch <= '9') + { + version *= 10; + version += (ch - '0'); + } + } + return version; + } - static bool SAMVersionTooLow(const std::string & ver) + static std::string CreateVersion (int ver) { - return ver.size() && ver[0] < '3'; - } - - static bool SAMVersionTooHigh(const std::string & ver) - { - return ver.size() && ver > "3.1"; - } - + auto d = div (ver, 10); + return std::to_string (d.quot) + "." + std::to_string (d.rem); + } + void SAMSocket::HandleHandshakeReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred) { if (ecode) @@ -121,8 +126,7 @@ namespace client if (!strcmp (m_Buffer, SAM_HANDSHAKE)) { - std::string maxver("3.1"); - std::string minver("3.0"); + int minVer = 0, maxVer = 0; // try to find MIN and MAX, 3.0 if not found if (separator) { @@ -130,39 +134,33 @@ namespace client auto params = ExtractParams (separator); auto it = params.find (SAM_PARAM_MAX); if (it != params.end ()) - maxver = it->second; + maxVer = ExtractVersion (it->second); it = params.find(SAM_PARAM_MIN); if (it != params.end ()) - minver = it->second; + minVer = ExtractVersion (it->second); } // version negotiation - std::string version; - if (SAMVersionAcceptable(maxver)) - { - version = maxver; - } - else if (SAMVersionAcceptable(minver)) - { - version = minver; - } - else if (SAMVersionTooLow(minver) && SAMVersionTooHigh(maxver)) - { - version = "3.0"; - } - - if (SAMVersionAcceptable(version)) - { -#ifdef _MSC_VER - size_t l = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_HANDSHAKE_REPLY, version.c_str ()); -#else - size_t l = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_HANDSHAKE_REPLY, version.c_str ()); -#endif - boost::asio::async_write (m_Socket, boost::asio::buffer (m_Buffer, l), boost::asio::transfer_all (), - std::bind(&SAMSocket::HandleHandshakeReplySent, shared_from_this (), - std::placeholders::_1, std::placeholders::_2)); - } + if (maxVer && maxVer <= MAX_SAM_VERSION) + m_Version = maxVer; + else if (minVer && minVer >= MIN_SAM_VERSION && minVer <= MAX_SAM_VERSION) + m_Version = minVer; + else if (!maxVer && !minVer) + m_Version = MIN_SAM_VERSION; else - SendMessageReply (SAM_HANDSHAKE_NOVERSION, strlen (SAM_HANDSHAKE_NOVERSION), true); + { + LogPrint (eLogError, "SAM: Handshake version mismatch ", minVer, " ", maxVer); + SendMessageReply (SAM_HANDSHAKE_NOVERSION, true); + return; + } + // send reply +#ifdef _MSC_VER + size_t l = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_HANDSHAKE_REPLY, CreateVersion (m_Version).c_str ()); +#else + size_t l = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_HANDSHAKE_REPLY, CreateVersion (m_Version).c_str ()); +#endif + boost::asio::async_write (m_Socket, boost::asio::buffer (m_Buffer, l), boost::asio::transfer_all (), + std::bind(&SAMSocket::HandleHandshakeReplySent, shared_from_this (), + std::placeholders::_1, std::placeholders::_2)); } else { @@ -193,12 +191,12 @@ namespace client } } - void SAMSocket::SendMessageReply (const char * msg, size_t len, bool close) + void SAMSocket::SendMessageReply (std::string_view msg, bool close) { LogPrint (eLogDebug, "SAMSocket::SendMessageReply, close=",close?"true":"false", " reason: ", msg); if (!m_IsSilent || m_SocketType == SAMSocketType::eSAMSocketTypeForward) - boost::asio::async_write (m_Socket, boost::asio::buffer (msg, len), boost::asio::transfer_all (), + boost::asio::async_write (m_Socket, boost::asio::buffer (msg.data (), msg.size ()), boost::asio::transfer_all (), std::bind(&SAMSocket::HandleMessageReplySent, shared_from_this (), std::placeholders::_1, std::placeholders::_2, close)); else @@ -341,14 +339,14 @@ namespace client if(!IsAcceptableSessionName(id)) { // invalid session id - SendMessageReply (SAM_SESSION_CREATE_INVALID_ID, strlen(SAM_SESSION_CREATE_INVALID_ID), true); + SendMessageReply (SAM_SESSION_CREATE_INVALID_ID, true); return; } m_ID = id; if (m_Owner.FindSession (id)) { // session exists - SendMessageReply (SAM_SESSION_CREATE_DUPLICATED_ID, strlen(SAM_SESSION_CREATE_DUPLICATED_ID), true); + SendMessageReply (SAM_SESSION_CREATE_DUPLICATED_ID, true); return; } @@ -412,7 +410,7 @@ namespace client //ensure we actually received a destination if (destination.empty()) { - SendMessageReply (SAM_SESSION_STATUS_INVALID_KEY, strlen(SAM_SESSION_STATUS_INVALID_KEY), true); + SendMessageReply (SAM_SESSION_STATUS_INVALID_KEY, true); return; } @@ -422,7 +420,7 @@ namespace client i2p::data::PrivateKeys keys; if (!keys.FromBase64(destination)) { - SendMessageReply(SAM_SESSION_STATUS_INVALID_KEY, strlen(SAM_SESSION_STATUS_INVALID_KEY), true); + SendMessageReply(SAM_SESSION_STATUS_INVALID_KEY, true); return; } } @@ -465,7 +463,7 @@ namespace client } } else - SendMessageReply (SAM_SESSION_CREATE_DUPLICATED_DEST, strlen(SAM_SESSION_CREATE_DUPLICATED_DEST), true); + SendMessageReply (SAM_SESSION_CREATE_DUPLICATED_DEST, true); } void SAMSocket::HandleSessionReadinessCheckTimer (const boost::system::error_code& ecode) @@ -503,7 +501,7 @@ namespace client #else size_t l2 = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_CREATE_REPLY_OK, priv.c_str ()); #endif - SendMessageReply (m_Buffer, l2, false); + SendMessageReply ({m_Buffer, l2}, false); } } @@ -571,10 +569,10 @@ namespace client shared_from_this(), std::placeholders::_1)); } else - SendMessageReply (SAM_STREAM_STATUS_INVALID_KEY, strlen(SAM_STREAM_STATUS_INVALID_KEY), true); + SendMessageReply (SAM_STREAM_STATUS_INVALID_KEY, true); } else - SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); + SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, true); } void SAMSocket::Connect (std::shared_ptr remote, std::shared_ptr session) @@ -591,16 +589,16 @@ namespace client m_Stream->Send ((uint8_t *)m_Buffer, m_BufferOffset); // connect and send m_BufferOffset = 0; I2PReceive (); - SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); + SendMessageReply (SAM_STREAM_STATUS_OK, false); } else - SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); + SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, true); } else SendStreamCantReachPeer ("Incompatible crypto"); } else - SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); + SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, true); } void SAMSocket::HandleConnectLeaseSetRequestComplete (std::shared_ptr leaseSet) @@ -634,7 +632,7 @@ namespace client if (!session->GetLocalDestination ()->IsAcceptingStreams ()) { m_IsAccepting = true; - SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); + SendMessageReply (SAM_STREAM_STATUS_OK, false); session->GetLocalDestination ()->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, shared_from_this (), std::placeholders::_1)); } else @@ -650,7 +648,7 @@ namespace client if (session->acceptQueue.size () < SAM_SESSION_MAX_ACCEPT_QUEUE_SIZE) { // already accepting, queue up - SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); + SendMessageReply (SAM_STREAM_STATUS_OK, false); session->acceptQueue.push_back (std::make_pair(shared_from_this(), ts)); } else @@ -661,7 +659,7 @@ namespace client } } else - SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); + SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, true); } void SAMSocket::ProcessStreamForward (std::string_view buf) @@ -680,7 +678,7 @@ namespace client auto session = m_Owner.FindSession(id); if (!session) { - SendMessageReply(SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); + SendMessageReply(SAM_STREAM_STATUS_INVALID_ID, true); return; } if (session->GetLocalDestination()->IsAcceptingStreams()) @@ -748,7 +746,7 @@ namespace client session->GetLocalDestination()->AcceptStreams( std::bind(&SAMSocket::HandleI2PForward, shared_from_this(), std::placeholders::_1, ep)); - SendMessageReply(SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); + SendMessageReply(SAM_STREAM_STATUS_OK, false); } @@ -823,7 +821,7 @@ namespace client size_t l = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_DEST_REPLY, keys.GetPublic ()->ToBase64 ().c_str (), keys.ToBase64 ().c_str ()); #endif - SendMessageReply (m_Buffer, l, false); + SendMessageReply ({m_Buffer, l}, false); } void SAMSocket::ProcessNamingLookup (std::string_view buf) @@ -864,7 +862,7 @@ namespace client #else size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY, name.c_str()); #endif - SendMessageReply (m_Buffer, len, false); + SendMessageReply ({m_Buffer, len}, false); } } @@ -880,7 +878,7 @@ namespace client if (masterSession->subsessions.count (id) > 1) { // session exists - SendMessageReply (SAM_SESSION_CREATE_DUPLICATED_ID, strlen(SAM_SESSION_CREATE_DUPLICATED_ID), false); + SendMessageReply (SAM_SESSION_CREATE_DUPLICATED_ID, false); return; } std::string_view style = params[SAM_PARAM_STYLE]; @@ -912,7 +910,7 @@ namespace client SendSessionCreateReplyOk (); } else - SendMessageReply (SAM_SESSION_CREATE_DUPLICATED_ID, strlen(SAM_SESSION_CREATE_DUPLICATED_ID), false); + SendMessageReply (SAM_SESSION_CREATE_DUPLICATED_ID, false); } else SendSessionI2PError ("Wrong session type"); @@ -929,7 +927,7 @@ namespace client std::string id(params[SAM_PARAM_ID]); if (!masterSession->subsessions.erase (id)) { - SendMessageReply (SAM_SESSION_STATUS_INVALID_KEY, strlen(SAM_SESSION_STATUS_INVALID_KEY), false); + SendMessageReply (SAM_SESSION_STATUS_INVALID_KEY, false); return; } m_Owner.CloseSession (id); @@ -946,7 +944,7 @@ namespace client #else size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, reply, msg.c_str()); #endif - SendMessageReply (m_Buffer, len, true); + SendMessageReply ({m_Buffer, len}, true); } void SAMSocket::SendSessionI2PError(const std::string & msg) @@ -981,7 +979,7 @@ namespace client #else size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY, name.c_str()); #endif - SendMessageReply (m_Buffer, len, false); + SendMessageReply ({m_Buffer, len}, false); } } @@ -993,7 +991,7 @@ namespace client #else size_t l = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY, name.c_str (), base64.c_str ()); #endif - SendMessageReply (m_Buffer, l, false); + SendMessageReply ({m_Buffer, l}, false); } const std::map SAMSocket::ExtractParams (std::string_view buf) diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index a0ea924d..7ffafb61 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -39,21 +39,21 @@ namespace client const char SAM_HANDSHAKE[] = "HELLO VERSION"; const char SAM_HANDSHAKE_REPLY[] = "HELLO REPLY RESULT=OK VERSION=%s\n"; - const char SAM_HANDSHAKE_NOVERSION[] = "HELLO REPLY RESULT=NOVERSION\n"; + constexpr std::string_view SAM_HANDSHAKE_NOVERSION { "HELLO REPLY RESULT=NOVERSION\n" }; const char SAM_HANDSHAKE_I2P_ERROR[] = "HELLO REPLY RESULT=I2P_ERROR\n"; const char SAM_SESSION_CREATE[] = "SESSION CREATE"; const char SAM_SESSION_CREATE_REPLY_OK[] = "SESSION STATUS RESULT=OK DESTINATION=%s\n"; - const char SAM_SESSION_CREATE_DUPLICATED_ID[] = "SESSION STATUS RESULT=DUPLICATED_ID\n"; - const char SAM_SESSION_CREATE_DUPLICATED_DEST[] = "SESSION STATUS RESULT=DUPLICATED_DEST\n"; - const char SAM_SESSION_CREATE_INVALID_ID[] = "SESSION STATUS RESULT=INVALID_ID\n"; - const char SAM_SESSION_STATUS_INVALID_KEY[] = "SESSION STATUS RESULT=INVALID_KEY\n"; + constexpr std::string_view SAM_SESSION_CREATE_DUPLICATED_ID { "SESSION STATUS RESULT=DUPLICATED_ID\n" }; + constexpr std::string_view SAM_SESSION_CREATE_DUPLICATED_DEST { "SESSION STATUS RESULT=DUPLICATED_DEST\n" }; + constexpr std::string_view SAM_SESSION_CREATE_INVALID_ID { "SESSION STATUS RESULT=INVALID_ID\n" }; + constexpr std::string_view SAM_SESSION_STATUS_INVALID_KEY { "SESSION STATUS RESULT=INVALID_KEY\n" }; const char SAM_SESSION_STATUS_I2P_ERROR[] = "SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"%s\"\n"; const char SAM_SESSION_ADD[] = "SESSION ADD"; const char SAM_SESSION_REMOVE[] = "SESSION REMOVE"; const char SAM_STREAM_CONNECT[] = "STREAM CONNECT"; - const char SAM_STREAM_STATUS_OK[] = "STREAM STATUS RESULT=OK\n"; - const char SAM_STREAM_STATUS_INVALID_ID[] = "STREAM STATUS RESULT=INVALID_ID\n"; - const char SAM_STREAM_STATUS_INVALID_KEY[] = "STREAM STATUS RESULT=INVALID_KEY\n"; + constexpr std::string_view SAM_STREAM_STATUS_OK { "STREAM STATUS RESULT=OK\n" }; + constexpr std::string_view SAM_STREAM_STATUS_INVALID_ID { "STREAM STATUS RESULT=INVALID_ID\n" }; + constexpr std::string_view SAM_STREAM_STATUS_INVALID_KEY { "STREAM STATUS RESULT=INVALID_KEY\n" }; const char SAM_STREAM_STATUS_CANT_REACH_PEER[] = "STREAM STATUS RESULT=CANT_REACH_PEER MESSAGE=\"%s\"\n"; const char SAM_STREAM_STATUS_I2P_ERROR[] = "STREAM STATUS RESULT=I2P_ERROR MESSAGE=\"%s\"\n"; const char SAM_STREAM_ACCEPT[] = "STREAM ACCEPT"; @@ -90,6 +90,10 @@ namespace client constexpr std::string_view SAM_VALUE_DATAGRAM { "DATAGRAM" }; constexpr std::string_view SAM_VALUE_RAW { "RAW" }; constexpr std::string_view SAM_VALUE_MASTER { "MASTER" }; + + constexpr int MAKE_SAM_VERSION_NUMBER (int major, int minor) { return major*10 + minor; } + constexpr int MIN_SAM_VERSION = MAKE_SAM_VERSION_NUMBER (3, 0); + constexpr int MAX_SAM_VERSION = MAKE_SAM_VERSION_NUMBER (3, 3); enum class SAMSocketType { @@ -127,7 +131,7 @@ namespace client void HandleHandshakeReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred); void HandleHandshakeReplySent (const boost::system::error_code& ecode, std::size_t bytes_transferred); void HandleMessage (const boost::system::error_code& ecode, std::size_t bytes_transferred); - void SendMessageReply (const char * msg, size_t len, bool close); + void SendMessageReply (std::string_view msg, bool close); void HandleMessageReplySent (const boost::system::error_code& ecode, std::size_t bytes_transferred, bool close); void Receive (); void HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred); @@ -182,6 +186,7 @@ namespace client bool m_IsAccepting; // for eSAMSocketTypeAcceptor only bool m_IsReceiving; // for eSAMSocketTypeStream only std::shared_ptr m_Stream; + int m_Version; }; enum class SAMSessionType From 83f9e1098d66d9a01c61c67535ae70ca9b2a8151 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 14 Aug 2025 15:58:42 -0400 Subject: [PATCH 1137/1171] decline master session if SAM version is less than 3.3 --- libi2pd_client/SAM.cpp | 20 +++++++++++++++++++- libi2pd_client/SAM.h | 1 + 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 94bac10f..22279001 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -373,7 +373,15 @@ namespace client } } else if (style == SAM_VALUE_RAW) type = SAMSessionType::eSAMSessionTypeRaw; - else if (style == SAM_VALUE_MASTER) type = SAMSessionType::eSAMSessionTypeMaster; + else if (style == SAM_VALUE_MASTER) + { + if (m_Version < SAM_VERSION_33) // < SAM 3.3 + { + SendSessionI2PError("MASTER session is not supported"); + return; + } + type = SAMSessionType::eSAMSessionTypeMaster; + } if (type == SAMSessionType::eSAMSessionTypeUnknown) { // unknown style @@ -868,6 +876,11 @@ namespace client void SAMSocket::ProcessSessionAdd (std::string_view buf) { + if (m_Version < SAM_VERSION_33) // < SAM 3.3 + { + SendSessionI2PError("SESSION ADD is not supported"); + return; + } auto session = m_Owner.FindSession(m_ID); if (session && session->Type == SAMSessionType::eSAMSessionTypeMaster) { @@ -918,6 +931,11 @@ namespace client void SAMSocket::ProcessSessionRemove (std::string_view buf) { + if (m_Version < SAM_VERSION_33) // < SAM 3.3 + { + SendSessionI2PError("SESSION REMOVE is not supported"); + return; + } auto session = m_Owner.FindSession(m_ID); if (session && session->Type == SAMSessionType::eSAMSessionTypeMaster) { diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index 7ffafb61..00b7ed03 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -94,6 +94,7 @@ namespace client constexpr int MAKE_SAM_VERSION_NUMBER (int major, int minor) { return major*10 + minor; } constexpr int MIN_SAM_VERSION = MAKE_SAM_VERSION_NUMBER (3, 0); constexpr int MAX_SAM_VERSION = MAKE_SAM_VERSION_NUMBER (3, 3); + constexpr int SAM_VERSION_33 = MAKE_SAM_VERSION_NUMBER (3, 3); // SAM 3.3 enum class SAMSocketType { From 27f2c5285da9bec537caeba9f7df6920b9f21c87 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 14 Aug 2025 18:51:54 -0400 Subject: [PATCH 1138/1171] support boost 1.89 --- Makefile.bsd | 2 +- Makefile.homebrew | 2 +- Makefile.osx | 2 +- libi2pd/Timestamp.h | 3 ++- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Makefile.bsd b/Makefile.bsd index 1c911802..9c6de7f0 100644 --- a/Makefile.bsd +++ b/Makefile.bsd @@ -3,7 +3,7 @@ CXXFLAGS ?= ${CXX_DEBUG} -Wall -Wextra -Wno-unused-parameter -pedantic -Wno-misl DEFINES = -D_GLIBCXX_USE_NANOSLEEP=1 INCFLAGS = -I/usr/include/ -I/usr/local/include/ LDFLAGS = ${LD_DEBUG} -Wl,-rpath,/usr/local/lib -L/usr/local/lib -LDLIBS = -lssl -lcrypto -lz -lpthread -lboost_system -lboost_program_options +LDLIBS = -lssl -lcrypto -lz -lpthread -lboost_program_options ## NOTE: NEEDED_CXXFLAGS is here so that custom CXXFLAGS can be specified at build time ## **without** overwriting the CXXFLAGS which we need in order to build. diff --git a/Makefile.homebrew b/Makefile.homebrew index 706f9811..9d8d17cd 100644 --- a/Makefile.homebrew +++ b/Makefile.homebrew @@ -18,7 +18,7 @@ endif LDLIBS += -lpthread -ldl else LDFLAGS += -L${SSLROOT}/lib -L${BOOSTROOT}/lib - LDLIBS = -lz -lssl -lcrypto -lboost_system -lboost_filesystem -lboost_program_options -lpthread + LDLIBS = -lz -lssl -lcrypto -lboost_program_options -lpthread ifeq ($(USE_UPNP),yes) LDFLAGS += -L${UPNPROOT}/lib LDLIBS += -lminiupnpc diff --git a/Makefile.osx b/Makefile.osx index 52282307..a2ad515e 100644 --- a/Makefile.osx +++ b/Makefile.osx @@ -9,7 +9,7 @@ LDFLAGS += -Wl,-dead_strip_dylibs ifeq ($(USE_STATIC),yes) LDLIBS = -lz /usr/local/lib/libssl.a /usr/local/lib/libcrypto.a /usr/local/lib/libboost_system.a /usr/local/lib/libboost_filesystem.a /usr/local/lib/libboost_program_options.a -lpthread else - LDLIBS = -lz -lssl -lcrypto -lboost_system -lboost_filesystem -lboost_program_options -lpthread + LDLIBS = -lz -lssl -lcrypto -lboost_program_options -lpthread endif ifeq ($(USE_UPNP),yes) diff --git a/libi2pd/Timestamp.h b/libi2pd/Timestamp.h index 00c60433..6b224685 100644 --- a/libi2pd/Timestamp.h +++ b/libi2pd/Timestamp.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2024, The PurpleI2P Project +* Copyright (c) 2013-2025, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -14,6 +14,7 @@ #include #include #include +#include // for boost 1.89 namespace i2p { From d148dd0b5e2a58f59d994235919b89e1a91c0df2 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 15 Aug 2025 10:22:58 +0700 Subject: [PATCH 1139/1171] feat: http theme for webconsole --- daemon/HTTPServer.cpp | 16 ++++++++++++++++ libi2pd/Config.cpp | 1 + 2 files changed, 17 insertions(+) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index c9371ab6..61bd2229 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -167,6 +167,11 @@ namespace http { { std::string webroot; i2p::config::GetOption("http.webroot", webroot); + std::string theme; i2p::config::GetOption("http.theme", theme); + if(theme != "light" && theme != "black" ) theme = "light"; + + + // Page language std::string currLang = i2p::client::context.GetLanguage ()->GetLanguage(); // get current used language auto it = i2p::i18n::languages.find(currLang); @@ -184,6 +189,17 @@ namespace http { " \r\n" " " << tr(/* tr: Webconsole page title */ "Purple I2P Webconsole") << "\r\n"; GetStyles(s); + if (theme == "black") + { + s << + ""; + + } s << "\r\n" "\r\n" diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 50f4c8a5..70b30f6b 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -97,6 +97,7 @@ namespace config { ("http.webroot", value()->default_value("/"), "WebUI root path (default: / )") ("http.lang", value()->default_value("english"), "WebUI language (default: english )") ("http.showTotalTCSR", value()->default_value(false), "Show additional value with total TCSR since router's start (default: false)") + ("http.theme", value()->default_value("light"), "Theme for http web console") ; options_description httpproxy("HTTP Proxy options"); From 95ae5336d32655422f94f0a63defd794b73ee2d6 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 15 Aug 2025 19:19:31 +0700 Subject: [PATCH 1140/1171] feat: custom CSS themes --- contrib/webconsole/style.css | 2 +- daemon/HTTPServer.cpp | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/contrib/webconsole/style.css b/contrib/webconsole/style.css index 89021539..ea8ffd4f 100644 --- a/contrib/webconsole/style.css +++ b/contrib/webconsole/style.css @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2023, The PurpleI2P Project + * Copyright (c) 2021-2025, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 61bd2229..18fecce7 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -42,10 +42,10 @@ namespace i2p { namespace http { - static void LoadExtCSS () + static void LoadExtCSS (std::string fileName = "style.css") { std::stringstream s; - std::string styleFile = i2p::fs::DataDirPath ("webconsole/style.css"); + std::string styleFile = i2p::fs::DataDirPath ("webconsole/"+fileName+".css"); if (i2p::fs::Exists(styleFile)) { std::ifstream f(styleFile, std::ifstream::binary); s << f.rdbuf(); @@ -168,7 +168,15 @@ namespace http { std::string webroot; i2p::config::GetOption("http.webroot", webroot); std::string theme; i2p::config::GetOption("http.theme", theme); - if(theme != "light" && theme != "black" ) theme = "light"; + if(theme != "light" && theme != "black" ) + { + if (theme =="white") { + theme = "light"; + } else { + LoadExtCSS(theme); + } + + } From cf7134ad14d6c6376b849e317e991abfe28571ac Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 15 Aug 2025 19:22:04 +0700 Subject: [PATCH 1141/1171] feat: update README.md about custom CSS themes --- README.md | 18 ++++ contrib/webconsole/hacker.css | 160 ++++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+) create mode 100644 contrib/webconsole/hacker.css diff --git a/README.md b/README.md index 9ec24d63..4e613838 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,24 @@ New languages can be requested on project's [discussion page](https://crowdin.co Current status: [![Crowdin](https://badges.crowdin.net/i2pd/localized.svg)](https://crowdin.com/project/i2pd) +Custom CSS Theme +------------ + +You can use a custom theme for i2pd web console, e.g., `hacker.css`. + +Example: + +```bash +user@computer:~/i2pd$ mkdir -p ~/.i2pd/webconsole +user@computer:~/i2pd$ cp contrib/webconsole/hacker.css ~/.i2pd/webconsole/ +user@computer:~/i2pd$ ./i2pd --http.theme=hacker +``` +Or set it in i2pd.conf: +``` +[HTTP] +theme=hacker +``` + Donations --------- diff --git a/contrib/webconsole/hacker.css b/contrib/webconsole/hacker.css new file mode 100644 index 00000000..d5ca4011 --- /dev/null +++ b/contrib/webconsole/hacker.css @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2021-2025, The PurpleI2P Project + * + * This file is part of Purple i2pd project and licensed under BSD3 + * + * See full license text in LICENSE file at top of project tree + * + ****************************************************************** + * + * This is style sheet for webconsole, with @media selectors for adaptive + * view on desktop and mobile devices, respecting preferred user's color + * scheme used in system/browser. + * + * Minified copy of that style sheet is bundled inside i2pd sources. +*/ +:root { + --main-bg-color: #0a0a0a; + --main-text-color: #00ff99; + --main-link-color: #ff00ff; + --main-link-hover-color: #00ffff; +} + +body { + font: 100%/1.5em "Courier New", Courier, monospace; + margin: 0; + padding: 1.5em; + background: var(--main-bg-color); + color: var(--main-text-color); +} + +a, .slide label { + text-decoration: none; + color: var(--main-link-color); +} + +a:hover, a.button.selected, .slide label:hover, button[type=submit]:hover { + color: var(--main-link-hover-color); + background: var(--main-link-color); +} +.slidecontent { + display:none; +} +#slide-info { + display:none; +} +.enabled { + color: green; + text-shadow: 2px green; +} +.disabled { + color: red; +} +#slide-info:checked ~ .slidecontent { + display: block; +} +.header { + font-size: 2.5em; + text-align: center; + margin: 1em 0; + color: var(--main-link-color); + text-shadow: 0 0 5px #ff00ff, 0 0 10px #ff00ff; +} + +.wrapper { + margin: 0 auto; + padding: 1em; + max-width: 64em; +} + +.menu { + display: block; + float: left; + overflow: hidden; + padding: 4px; + max-width: 12em; + white-space: nowrap; + text-overflow: ellipsis; +} + +.listitem, .tableitem { + display: block; + font-family: monospace; + font-size: 1.2em; + white-space: nowrap; + color: #00ff99; +} + +.content { + float: left; + font-size: 1em; + margin-left: 2em; + padding: 4px; + max-width: 50em; + overflow: auto; +} + +.tunnel.established { + color: #0ff; +} + +.tunnel.expiring { + color: #ff0; +} + +.tunnel.failed { + color: #f00; +} + +.tunnel.building { + color: #888; +} + +caption { + font-size: 1.5em; + text-align: center; + color: var(--main-link-color); + text-shadow: 0 0 3px #ff00ff; +} + +table { + display: table; + border-collapse: collapse; + text-align: center; +} + +textarea, input, select { + background-color: #111; + color: var(--main-text-color); + border: 1px solid var(--main-link-color); + font-family: monospace; + font-size: 14px; + padding: 5px; + border-radius: 3px; +} + +button[type=submit], a.button { + background-color: transparent; + color: var(--main-link-color); + border: 1px solid var(--main-link-color); + padding: 5px 10px; + font-family: monospace; + border-radius: 4px; + cursor: pointer; + text-decoration: none; +} + +button[type=submit]:hover, a.button:hover { + color: var(--main-link-hover-color); + background-color: #222; + box-shadow: 0 0 5px var(--main-link-hover-color); +} + +@media screen and (max-width: 980px) { + .menu, .content, input, select, textarea, button[type=submit], a.button { + width: 90%; + margin: 0 auto 10px auto; + display: block; + text-align: center; + } +} From 1a958df8d3bed6219a42728d224201cb59f7e5e8 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 15 Aug 2025 19:28:27 +0700 Subject: [PATCH 1142/1171] del: del additional information to README.md --- README.md | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/README.md b/README.md index 4e613838..9ec24d63 100644 --- a/README.md +++ b/README.md @@ -96,24 +96,6 @@ New languages can be requested on project's [discussion page](https://crowdin.co Current status: [![Crowdin](https://badges.crowdin.net/i2pd/localized.svg)](https://crowdin.com/project/i2pd) -Custom CSS Theme ------------- - -You can use a custom theme for i2pd web console, e.g., `hacker.css`. - -Example: - -```bash -user@computer:~/i2pd$ mkdir -p ~/.i2pd/webconsole -user@computer:~/i2pd$ cp contrib/webconsole/hacker.css ~/.i2pd/webconsole/ -user@computer:~/i2pd$ ./i2pd --http.theme=hacker -``` -Or set it in i2pd.conf: -``` -[HTTP] -theme=hacker -``` - Donations --------- From be05fa0fe143e4a9315689a21e5848ff009365cc Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 15 Aug 2025 09:01:53 -0400 Subject: [PATCH 1143/1171] verify session for close packet onlly if ECIESx25519 --- libi2pd/Streaming.cpp | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index b1e10ae6..2651fd55 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -507,22 +507,25 @@ namespace stream if (flags & (PACKET_FLAG_CLOSE | PACKET_FLAG_RESET)) { verified = false; - if (packet->from && !m_RemoteLeaseSet && m_RemoteIdentity) - m_RemoteLeaseSet = m_LocalDestination.GetOwner ()->FindLeaseSet (m_RemoteIdentity->GetIdentHash ()); - if (m_RemoteLeaseSet) - { - uint8_t staticKey[32]; - m_RemoteLeaseSet->Encrypt (nullptr, staticKey); - if (memcmp (packet->from->GetRemoteStaticKey (), staticKey, 32)) + if (packet->from) + { + if (!m_RemoteLeaseSet && m_RemoteIdentity) + m_RemoteLeaseSet = m_LocalDestination.GetOwner ()->FindLeaseSet (m_RemoteIdentity->GetIdentHash ()); + if (m_RemoteLeaseSet) { - LogPrint (eLogError, "Streaming: Remote LeaseSet static key mismatch for stream from ", - m_RemoteIdentity->GetIdentHash ().ToBase32 ()); - return false; + uint8_t staticKey[32]; + m_RemoteLeaseSet->Encrypt (nullptr, staticKey); + if (memcmp (packet->from->GetRemoteStaticKey (), staticKey, 32)) + { + LogPrint (eLogError, "Streaming: Remote LeaseSet static key mismatch for stream from ", + m_RemoteIdentity->GetIdentHash ().ToBase32 ()); + return false; + } + verified = true; } - verified = true; - } - else // invalid stream, safe to close - verified = true; + else // invalid stream, safe to close + verified = true; + } } if (flags & PACKET_FLAG_OFFLINE_SIGNATURE) From c7ad247929cf98309345fcfa8d9b8e54920baec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=9C=83=20Ezor=20Kael?= <60944239+wipedlifepotato@users.noreply.github.com> Date: Sat, 16 Aug 2025 12:06:46 +0700 Subject: [PATCH 1144/1171] Update HTTPServer.cpp. fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Починка style.css если нет кастомных тем --- daemon/HTTPServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 18fecce7..4e5d815e 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -42,7 +42,7 @@ namespace i2p { namespace http { - static void LoadExtCSS (std::string fileName = "style.css") + static void LoadExtCSS (std::string fileName = "style") { std::stringstream s; std::string styleFile = i2p::fs::DataDirPath ("webconsole/"+fileName+".css"); From aeb6dddcb13f45aa5a558fe3508e8b67ad3c734b Mon Sep 17 00:00:00 2001 From: wipedlifepotato Date: Mon, 18 Aug 2025 19:43:52 +0700 Subject: [PATCH 1145/1171] feat: bandwidth with bytes/kbytes/gbytes seconds and fix for style.css --- daemon/Daemon.cpp | 34 ++++++++++++++++++++++++++++++++-- daemon/HTTPServer.cpp | 26 ++++++++++++++++---------- libi2pd/RouterContext.cpp | 3 +++ 3 files changed, 51 insertions(+), 12 deletions(-) diff --git a/daemon/Daemon.cpp b/daemon/Daemon.cpp index e2fdf2d4..5c4f9c97 100644 --- a/daemon/Daemon.cpp +++ b/daemon/Daemon.cpp @@ -8,6 +8,7 @@ #include #include +#include #include "Daemon.h" @@ -186,12 +187,41 @@ namespace util std::string bandwidth; i2p::config::GetOption("bandwidth", bandwidth); if (bandwidth.length () > 0) { + const auto NumBandwithRegex = std::regex(R"(^\d+$)"); + const auto BandwithRegex = std::regex(R"((\d+)(b|kb|mb|gb))"); + std::smatch bandWithMatch; + if (bandwidth.length () == 1 && ((bandwidth[0] >= 'K' && bandwidth[0] <= 'P') || bandwidth[0] == 'X' )) { i2p::context.SetBandwidth (bandwidth[0]); LogPrint(eLogInfo, "Daemon: Bandwidth set to ", i2p::context.GetBandwidthLimit (), "KBps"); } - else + else if (std::regex_match(bandwidth, bandWithMatch, BandwithRegex)) { + const auto number = bandWithMatch[1].str(); + const auto unit = bandWithMatch[2].str(); + int limit = std::atoi(number.c_str()); + std::cout << unit; + if (unit == "b") + { + limit /= 1000; + } + else if(unit == "mb") + { + limit *= 1000; + } else if(unit == "gb") + { + limit *= 1000000; + } + // if limit more than 32 bits then its will be negative + if (limit < 0) + { + LogPrint(eLogInfo, "Daemon: Unexpected bandwidth ", bandwidth, ". Set to 'low'"); + i2p::context.SetBandwidth (i2p::data::CAPS_FLAG_LOW_BANDWIDTH2); + } else { + i2p::context.SetBandwidth(limit); + } + } + else if(std::regex_search(bandwidth, NumBandwithRegex)) { auto value = std::atoi(bandwidth.c_str()); if (value > 0) @@ -204,7 +234,7 @@ namespace util LogPrint(eLogInfo, "Daemon: Unexpected bandwidth ", bandwidth, ". Set to 'low'"); i2p::context.SetBandwidth (i2p::data::CAPS_FLAG_LOW_BANDWIDTH2); } - } + } } else if (isFloodfill) { diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 18fecce7..e5c69a81 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -42,6 +43,7 @@ namespace i2p { namespace http { + static void LoadExtCSS (std::string fileName = "style.css") { std::stringstream s; @@ -166,19 +168,17 @@ namespace http { static void ShowPageHead (std::stringstream& s) { std::string webroot; i2p::config::GetOption("http.webroot", webroot); - std::string theme; i2p::config::GetOption("http.theme", theme); - if(theme != "light" && theme != "black" ) + + const auto isThemeRegex = std::regex("^(white|black|light)"); + if (!std::regex_search(theme, isThemeRegex)) { - if (theme =="white") { - theme = "light"; - } else { - LoadExtCSS(theme); - } - + LoadExtCSS(theme); } - - + else + { + LoadExtCSS(); + } // Page language std::string currLang = i2p::client::context.GetLanguage ()->GetLanguage(); // get current used language @@ -1482,6 +1482,12 @@ namespace http { } else if (cmd == HTTP_COMMAND_RELOAD_CSS) { + std::string theme; i2p::config::GetOption("http.theme", theme); + + if (theme != "light" && theme != "black" && theme !="white") + { + + } LoadExtCSS(); } else diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 9eb0f9a5..cfb92f00 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -683,6 +683,9 @@ namespace i2p else if (limit > (int)i2p::data::LOW_BANDWIDTH_LIMIT) { SetBandwidth('M'); } else if (limit > 12) { SetBandwidth('L'); } else { SetBandwidth('K'); } + + + LogPrint(eLogInfo, "RouterContext: Set bandwidth ", limit, ". kb/s"); m_BandwidthLimit = limit; // set precise limit } From 578844e3edc80da0214512cf12d25a59a71b6ad4 Mon Sep 17 00:00:00 2001 From: wipedlifepotato Date: Mon, 18 Aug 2025 19:46:15 +0700 Subject: [PATCH 1146/1171] fix: fix hacker.css --- contrib/webconsole/hacker.css | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/contrib/webconsole/hacker.css b/contrib/webconsole/hacker.css index d5ca4011..93baf564 100644 --- a/contrib/webconsole/hacker.css +++ b/contrib/webconsole/hacker.css @@ -14,7 +14,7 @@ * Minified copy of that style sheet is bundled inside i2pd sources. */ :root { - --main-bg-color: #0a0a0a; + --main-bg-color: #0b0b0b; --main-text-color: #00ff99; --main-link-color: #ff00ff; --main-link-hover-color: #00ffff; @@ -53,6 +53,18 @@ a:hover, a.button.selected, .slide label:hover, button[type=submit]:hover { #slide-info:checked ~ .slidecontent { display: block; } +#slide_ntcp2 { + display: none; +} +#slide_ssu2 { + display: none; +} +#slide_ssu2:checked ~ .slidecontent { + display: block; +} +#slide_ntcp2:checked ~ .slidecontent{ + display:block; +} .header { font-size: 2.5em; text-align: center; From 14ce620825aa6c138315369c13ea3b64eb94cb3d Mon Sep 17 00:00:00 2001 From: wipedlifepotato Date: Mon, 18 Aug 2025 19:52:43 +0700 Subject: [PATCH 1147/1171] fix logic --- daemon/HTTPServer.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 73b5a6e3..c4dedf61 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -1498,11 +1498,8 @@ namespace http { { std::string theme; i2p::config::GetOption("http.theme", theme); - if (theme != "light" && theme != "black" && theme !="white") - { - - } - LoadExtCSS(); + if (theme != "light" && theme != "black" && theme !="white") LoadExtCSS(theme); + else LoadExtCSS(); } else { From 39069e0bd6eac4ac87504d9415c4bdef55b68110 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 19 Aug 2025 15:21:44 -0400 Subject: [PATCH 1148/1171] BOB ping command --- libi2pd/ECIESX25519AEADRatchetSession.h | 1 + libi2pd/Streaming.cpp | 13 +++++ libi2pd/Streaming.h | 6 ++- libi2pd_client/BOB.cpp | 70 +++++++++++++++++++++++++ libi2pd_client/BOB.h | 7 +++ 5 files changed, 96 insertions(+), 1 deletion(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h index fd9cc45d..5fa947b7 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.h +++ b/libi2pd/ECIESX25519AEADRatchetSession.h @@ -181,6 +181,7 @@ namespace garlic { if (!m_Destination) m_Destination.reset (new i2p::data::IdentHash (dest)); } + const i2p::data::IdentHash * GetDestinationPtr () const { return m_Destination ? m_Destination.get () : nullptr; }; // for pongs bool CheckExpired (uint64_t ts); // true is expired bool CanBeRestarted (uint64_t ts) const { return ts > m_SessionCreatedTimestamp + ECIESX25519_RESTART_TIMEOUT; } bool IsInactive (uint64_t ts) const { return ts > m_LastActivityTimestamp + ECIESX25519_INACTIVITY_TIMEOUT && CanBeRestarted (ts); } diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 2651fd55..7e8747ad 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -1991,6 +1991,7 @@ namespace stream void StreamingDestination::Stop () { ResetAcceptor (); + ResetPongHandler (); m_PendingIncomingTimer.cancel (); m_PendingIncomingStreams.clear (); { @@ -2037,6 +2038,8 @@ namespace stream { // pong LogPrint (eLogInfo, "Streaming: Pong received rSID=", packet->GetReceiveStreamID ()); + if (m_PongHandler != nullptr) + m_PongHandler (packet->from ? packet->from->GetDestinationPtr () : nullptr); DeletePacket (packet); return; } @@ -2216,6 +2219,16 @@ namespace stream m_Acceptor = nullptr; } + void StreamingDestination::SetPongHandler (const PongHandler& handler) + { + m_PongHandler = handler; + } + + void StreamingDestination::ResetPongHandler () + { + m_PongHandler = nullptr; + } + void StreamingDestination::AcceptOnce (const Acceptor& acceptor) { boost::asio::post (m_Owner->GetService (), [acceptor, this](void) diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 5aeced26..d3bd314e 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -312,6 +312,7 @@ namespace stream public: typedef std::function)> Acceptor; + typedef std::function PongHandler; StreamingDestination (std::shared_ptr owner, uint16_t localPort = 0, bool gzip = false); ~StreamingDestination (); @@ -330,7 +331,9 @@ namespace stream void AcceptOnce (const Acceptor& acceptor); void AcceptOnceAcceptor (std::shared_ptr stream, Acceptor acceptor, Acceptor prev); std::shared_ptr AcceptStream (int timeout = 0); // sync - + void SetPongHandler (const PongHandler& handler); + void ResetPongHandler (); + std::shared_ptr GetOwner () const { return m_Owner; }; void SetOwner (std::shared_ptr owner) { m_Owner = owner; }; uint16_t GetLocalPort () const { return m_LocalPort; }; @@ -358,6 +361,7 @@ namespace stream std::unordered_map > m_IncomingStreams; // receiveStreamID->stream std::shared_ptr m_LastStream; Acceptor m_Acceptor; + PongHandler m_PongHandler; std::list > m_PendingIncomingStreams; boost::asio::deadline_timer m_PendingIncomingTimer; std::unordered_map > m_SavedPackets; // receiveStreamID->packets, arrived before SYN diff --git a/libi2pd_client/BOB.cpp b/libi2pd_client/BOB.cpp index 3f02f779..d8bf76a9 100644 --- a/libi2pd_client/BOB.cpp +++ b/libi2pd_client/BOB.cpp @@ -355,6 +355,17 @@ namespace client Send (); } + void BOBCommandSession::SendReplyOK (const std::vector& strings) + { + std::ostream os(&m_SendBuffer); + os << "OK"; + if (!strings.empty ()) os << " "; + for (auto& it: strings) + os << it; + os << std::endl; + Send (); + } + void BOBCommandSession::SendReplyError (const char * msg) { std::ostream os(&m_SendBuffer); @@ -802,6 +813,64 @@ namespace client SendReplyError ("empty lookup address"); } + void BOBCommandSession::PingCommandHandler (const char * operand, size_t len) + { + LogPrint (eLogDebug, "BOB: ping ", operand); + if (*operand) + { + auto addr = context.GetAddressBook ().GetAddress (operand); + if (!addr) + { + SendReplyError ("Address Not found"); + return; + } + auto localDestination = (m_CurrentDestination && m_CurrentDestination->IsRunning ()) ? + m_CurrentDestination->GetLocalDestination () : i2p::client::context.GetSharedLocalDestination (); + if (!localDestination) + { + SendReplyError ("No local destination"); + return; + } + auto streamingDestination = localDestination->GetStreamingDestination (); + if (!streamingDestination) + { + SendReplyError ("No streaming destination"); + return; + } + auto timer = std::make_shared(localDestination->GetService ()); + timer->expires_from_now (boost::posix_time::milliseconds(BOB_PING_TIMEOUT)); + timer->async_wait ([streamingDestination, s = shared_from_this ()](const boost::system::error_code& ecode) + { + if (ecode != boost::asio::error::operation_aborted) + { + LogPrint (eLogDebug, "BOB: Pong not received after ", BOB_PING_TIMEOUT, " millliseconds"); + streamingDestination->ResetPongHandler (); + s->SendReplyError ("timeout"); + } + }); + auto ts = i2p::util::GetMillisecondsSinceEpoch (); + streamingDestination->SetPongHandler ( + [streamingDestination, timer, ts, s = shared_from_this ()](const i2p::data::IdentHash * from) + { + int t = i2p::util::GetMillisecondsSinceEpoch () - ts; + if (t < 0) t = 0; + streamingDestination->ResetPongHandler (); + timer->cancel (); + if (from) + s->SendReplyOK ({"pong ", "from ", from->ToBase32(), ".b32.i2p: time=", std::to_string (t), " ms"}); + else + s->SendReplyOK ({"pong: time=", std::to_string (t), " ms"}); + }); + + if (addr->IsIdentHash ()) + localDestination->SendPing (addr->identHash); + else + localDestination->SendPing (addr->blindedPublicKey); + } + else + SendReplyError ("empty ping address"); + } + void BOBCommandSession::ClearCommandHandler (const char * operand, size_t len) { LogPrint (eLogDebug, "BOB: clear"); @@ -949,6 +1018,7 @@ namespace client m_CommandHandlers[BOB_COMMAND_QUIET] = &BOBCommandSession::QuietCommandHandler; m_CommandHandlers[BOB_COMMAND_LOOKUP] = &BOBCommandSession::LookupCommandHandler; m_CommandHandlers[BOB_COMMAND_LOOKUP_LOCAL] = &BOBCommandSession::LookupLocalCommandHandler; + m_CommandHandlers[BOB_COMMAND_PING] = &BOBCommandSession::PingCommandHandler; m_CommandHandlers[BOB_COMMAND_CLEAR] = &BOBCommandSession::ClearCommandHandler; m_CommandHandlers[BOB_COMMAND_LIST] = &BOBCommandSession::ListCommandHandler; m_CommandHandlers[BOB_COMMAND_OPTION] = &BOBCommandSession::OptionCommandHandler; diff --git a/libi2pd_client/BOB.h b/libi2pd_client/BOB.h index 7b92c85d..c0a5da14 100644 --- a/libi2pd_client/BOB.h +++ b/libi2pd_client/BOB.h @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include #include #include "util.h" @@ -29,6 +31,8 @@ namespace i2p namespace client { const size_t BOB_COMMAND_BUFFER_SIZE = 1024; + const int BOB_PING_TIMEOUT = 8000; // in milliseconds + const char BOB_COMMAND_ZAP[] = "zap"; const char BOB_COMMAND_QUIT[] = "quit"; const char BOB_COMMAND_START[] = "start"; @@ -46,6 +50,7 @@ namespace client const char BOB_COMMAND_QUIET[] = "quiet"; const char BOB_COMMAND_LOOKUP[] = "lookup"; const char BOB_COMMAND_LOOKUP_LOCAL[] = "lookuplocal"; + const char BOB_COMMAND_PING[] = "ping"; const char BOB_COMMAND_CLEAR[] = "clear"; const char BOB_COMMAND_LIST[] = "list"; const char BOB_COMMAND_OPTION[] = "option"; @@ -233,6 +238,7 @@ namespace client void QuietCommandHandler (const char * operand, size_t len); void LookupCommandHandler (const char * operand, size_t len); void LookupLocalCommandHandler (const char * operand, size_t len); + void PingCommandHandler (const char * operand, size_t len); void ClearCommandHandler (const char * operand, size_t len); void ListCommandHandler (const char * operand, size_t len); void OptionCommandHandler (const char * operand, size_t len); @@ -249,6 +255,7 @@ namespace client void Send (); void HandleSent (const boost::system::error_code& ecode, std::size_t bytes_transferred); void SendReplyOK (const char * msg = nullptr); + void SendReplyOK (const std::vector& strings); void SendReplyError (const char * msg); void SendRaw (const char * data); From dcafb62ab090b8dd1c4e289931f4d9dc3b7d8889 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 19 Aug 2025 16:47:06 -0400 Subject: [PATCH 1149/1171] set default number of descriptors to 4096 for Haiku --- libi2pd/Config.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 70b30f6b..22faa7c6 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -76,7 +76,12 @@ namespace config { options_description limits("Limits options"); limits.add_options() ("limits.coresize", value()->default_value(0), "Maximum size of corefile in Kb (0 - use system limit)") +#if defined(__HAIKU__) + // Haiku's system default is 512, so we set 4096 explicitly + ("limits.openfiles", value()->default_value(4096), "Maximum number of open files (4096 by default)") +#else ("limits.openfiles", value()->default_value(0), "Maximum number of open files (0 - use system default)") +#endif ("limits.transittunnels", value()->default_value(10000), "Maximum active transit tunnels (default:10000)") ("limits.zombies", value()->default_value(0), "Minimum percentage of successfully created tunnels under which tunnel cleanup is paused (default [%]: 0.00)") ("limits.ntcpsoft", value()->default_value(0), "Ignored") From d3ab6f61c27a429897b57f3238d471dca163f988 Mon Sep 17 00:00:00 2001 From: nonlin-lin-chaos-order-etc-etal <19966907+nonlin-lin-chaos-order-etc-etal@users.noreply.github.com> Date: Wed, 20 Aug 2025 21:03:39 +0800 Subject: [PATCH 1150/1171] Add github downloads count badge to README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 9ec24d63..3463ed3b 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ [![License](https://img.shields.io/github/license/PurpleI2P/i2pd.svg)](https://github.com/PurpleI2P/i2pd/blob/openssl/LICENSE) [![Packaging status](https://repology.org/badge/tiny-repos/i2pd.svg)](https://repology.org/project/i2pd/versions) [![Docker Pulls](https://img.shields.io/docker/pulls/purplei2p/i2pd)](https://hub.docker.com/r/purplei2p/i2pd) +[![Github Downloads](https://img.shields.io/github/downloads/PurpleI2P/i2pd/total.svg)]() [![Crowdin](https://badges.crowdin.net/i2pd/localized.svg)](https://crowdin.com/project/i2pd) *note: i2pd for Android can be found in [i2pd-android](https://github.com/PurpleI2P/i2pd-android) repository and with Qt GUI in [i2pd-qt](https://github.com/PurpleI2P/i2pd-qt) repository* From b00001752b35ba6f85ff4deffbf6768e08e80c9a Mon Sep 17 00:00:00 2001 From: Dimitris Apostolou Date: Wed, 20 Aug 2025 17:49:45 +0300 Subject: [PATCH 1151/1171] fix typos --- libi2pd/ECIESX25519AEADRatchetSession.cpp | 2 +- libi2pd_client/AddressBook.cpp | 2 +- libi2pd_client/I2PTunnel.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp index 08af4be3..fea10cd9 100644 --- a/libi2pd/ECIESX25519AEADRatchetSession.cpp +++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp @@ -843,7 +843,7 @@ namespace garlic if (m_State == eSessionStateNewSessionSent) { m_State = eSessionStateEstablished; - // don't delete m_EpehemralKey and m_PQKeys because delayd NSR's migth come + // don't delete m_EpehemralKey and m_PQKeys because delayed NSR's might come // done in CleanupReceiveNSRKeys called from NSR tagset destructor m_SessionCreatedTimestamp = i2p::util::GetSecondsSinceEpoch (); GetOwner ()->AddECIESx25519Session (m_RemoteStaticKey, shared_from_this ()); diff --git a/libi2pd_client/AddressBook.cpp b/libi2pd_client/AddressBook.cpp index 8333e87d..c7cd80c0 100644 --- a/libi2pd_client/AddressBook.cpp +++ b/libi2pd_client/AddressBook.cpp @@ -60,7 +60,7 @@ namespace client int LoadLocal (Addresses& addresses) override; int Save (const Addresses& addresses) override; - void SaveEtag (const i2p::data::IdentHash& subsciption, const std::string& etag, const std::string& lastModified) override; + void SaveEtag (const i2p::data::IdentHash& subscription, const std::string& etag, const std::string& lastModified) override; bool GetEtag (const i2p::data::IdentHash& subscription, std::string& etag, std::string& lastModified) override; void ResetEtags () override; diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index 6fc7d1bc..7c12ff82 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -880,7 +880,7 @@ namespace client Connect (stream); else if (!Resolve (stream)) { - LogPrint (eLogWarning, "I2PTunnel: Address ", m_Address, " cann't be resolved. Incoming connection dropped"); + LogPrint (eLogWarning, "I2PTunnel: Address ", m_Address, " can't be resolved. Incoming connection dropped"); stream->Close (); return; } From 51b58c952a11f945a5429f92ed87f450a0baafcc Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 20 Aug 2025 21:29:36 -0400 Subject: [PATCH 1152/1171] pass string_view instead const char *. EdDSA signature be default --- libi2pd_client/BOB.cpp | 61 +++++++++++++++++------------------------- libi2pd_client/BOB.h | 6 ++--- 2 files changed, 27 insertions(+), 40 deletions(-) diff --git a/libi2pd_client/BOB.cpp b/libi2pd_client/BOB.cpp index d8bf76a9..83630a17 100644 --- a/libi2pd_client/BOB.cpp +++ b/libi2pd_client/BOB.cpp @@ -343,18 +343,16 @@ namespace client } } - void BOBCommandSession::SendReplyOK (const char * msg) + void BOBCommandSession::SendReplyOK (std::string_view msg) { std::ostream os(&m_SendBuffer); os << "OK"; - if(msg) - { + if (!msg.empty ()) os << " " << msg; - } os << std::endl; Send (); - } - + } + void BOBCommandSession::SendReplyOK (const std::vector& strings) { std::ostream os(&m_SendBuffer); @@ -366,7 +364,7 @@ namespace client Send (); } - void BOBCommandSession::SendReplyError (const char * msg) + void BOBCommandSession::SendReplyError (std::string_view msg) { std::ostream os(&m_SendBuffer); os << "ERROR " << msg << std::endl; @@ -377,10 +375,10 @@ namespace client { std::ostream os(&m_SendBuffer); os << "BOB 00.00.10" << std::endl; - SendReplyOK(); + SendReplyOK(std::string_view()); // empty string } - void BOBCommandSession::SendRaw (const char * data) + void BOBCommandSession::SendRaw (std::string_view data) { std::ostream os(&m_SendBuffer); os << data << std::endl; @@ -575,9 +573,7 @@ namespace client if (!dest) { m_Nickname = operand; - std::string msg ("Nickname set to "); - msg += m_Nickname; - SendReplyOK (msg.c_str ()); + SendReplyOK ({ "Nickname set to ", m_Nickname }); } else SendReplyError ("tunnel is active"); @@ -602,11 +598,7 @@ namespace client m_Nickname = operand; } if (m_Nickname == operand) - { - std::string msg ("Nickname set to "); - msg += m_Nickname; - SendReplyOK (msg.c_str ()); - } + SendReplyOK ({"Nickname set to ", m_Nickname}); else SendReplyError ("no nickname has been set"); } @@ -617,7 +609,7 @@ namespace client void BOBCommandSession::NewkeysCommandHandler (const char * operand, size_t len) { LogPrint (eLogDebug, "BOB: newkeys"); - i2p::data::SigningKeyType signatureType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1; + i2p::data::SigningKeyType signatureType = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519; i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL; if (*operand) { @@ -639,14 +631,14 @@ namespace client m_Keys = i2p::data::PrivateKeys::CreateRandomKeys (signatureType, cryptoType, true); - SendReplyOK (m_Keys.GetPublic ()->ToBase64 ().c_str ()); + SendReplyOK (m_Keys.GetPublic ()->ToBase64 ()); } void BOBCommandSession::SetkeysCommandHandler (const char * operand, size_t len) { LogPrint (eLogDebug, "BOB: setkeys ", operand); if (*operand && m_Keys.FromBase64 (operand)) - SendReplyOK (m_Keys.GetPublic ()->ToBase64 ().c_str ()); + SendReplyOK (m_Keys.GetPublic ()->ToBase64 ()); else SendReplyError ("invalid keys"); } @@ -655,7 +647,7 @@ namespace client { LogPrint (eLogDebug, "BOB: getkeys"); if (m_Keys.GetPublic ()) // keys are set ? - SendReplyOK (m_Keys.ToBase64 ().c_str ()); + SendReplyOK (m_Keys.ToBase64 ()); else SendReplyError ("keys are not set"); } @@ -664,7 +656,7 @@ namespace client { LogPrint (eLogDebug, "BOB: getdest"); if (m_Keys.GetPublic ()) // keys are set ? - SendReplyOK (m_Keys.GetPublic ()->ToBase64 ().c_str ()); + SendReplyOK (m_Keys.GetPublic ()->ToBase64 ()); else SendReplyError ("keys are not set"); } @@ -770,7 +762,7 @@ namespace client auto leaseSet = localDestination->FindLeaseSet (addr->identHash); if (leaseSet) { - SendReplyOK (leaseSet->GetIdentity ()->ToBase64 ().c_str ()); + SendReplyOK (leaseSet->GetIdentity ()->ToBase64 ()); return; } } @@ -779,7 +771,7 @@ namespace client auto requstCallback = [s](std::shared_ptr ls) { if (ls) - s->SendReplyOK (ls->GetIdentity ()->ToBase64 ().c_str ()); + s->SendReplyOK (ls->GetIdentity ()->ToBase64 ()); else s->SendReplyError ("LeaseSet Not found"); }; @@ -805,7 +797,7 @@ namespace client } auto ls = i2p::data::netdb.FindLeaseSet (addr->identHash); if (ls) - SendReplyOK (ls->GetIdentity ()->ToBase64 ().c_str ()); + SendReplyOK (ls->GetIdentity ()->ToBase64 ()); else SendReplyError ("Local LeaseSet Not found"); } @@ -888,7 +880,7 @@ namespace client for (const auto& it: destinations) { BuildStatusLine(false, it.second, statusLine); - SendRaw(statusLine.c_str()); + SendRaw(statusLine); if(m_Nickname.compare(it.second->GetNickname()) == 0) sentCurrent = true; } @@ -897,7 +889,7 @@ namespace client // add the current tunnel to the list. // this is for the incomplete tunnel which has not been started yet. BuildStatusLine(true, m_CurrentDestination, statusLine); - SendRaw(statusLine.c_str()); + SendRaw(statusLine); } SendReplyOK ("Listing done"); } @@ -908,14 +900,10 @@ namespace client const char * value = strchr (operand, '='); if (value) { - std::string msg ("option "); *(const_cast(value)) = 0; m_Options[operand] = value + 1; - msg += operand; + SendReplyOK ({ "option ", operand, " set to ", value + 1 }); *(const_cast(value)) = '='; - msg += " set to "; - msg += value + 1; - SendReplyOK (msg.c_str ()); } else SendReplyError ("malformed"); @@ -933,7 +921,7 @@ namespace client { // tunnel destination exists BuildStatusLine(false, dest, statusLine); - SendReplyOK(statusLine.c_str()); + SendReplyOK(statusLine); } else { @@ -941,7 +929,7 @@ namespace client { // tunnel is incomplete / has not been started yet BuildStatusLine(true, nullptr, statusLine); - SendReplyOK(statusLine.c_str()); + SendReplyOK(statusLine); } else { @@ -960,15 +948,14 @@ namespace client { ss << " " << x.first; } - const std::string &str = ss.str(); - SendReplyOK(str.c_str()); + SendReplyOK(ss.str ()); } else { auto it = helpStrings.find(operand); if (it != helpStrings.end ()) { - SendReplyOK(it->second.c_str()); + SendReplyOK(it->second); return; } SendReplyError("No such command"); diff --git a/libi2pd_client/BOB.h b/libi2pd_client/BOB.h index c0a5da14..9ee7e0a0 100644 --- a/libi2pd_client/BOB.h +++ b/libi2pd_client/BOB.h @@ -254,10 +254,10 @@ namespace client void Send (); void HandleSent (const boost::system::error_code& ecode, std::size_t bytes_transferred); - void SendReplyOK (const char * msg = nullptr); + void SendReplyOK (std::string_view msg); void SendReplyOK (const std::vector& strings); - void SendReplyError (const char * msg); - void SendRaw (const char * data); + void SendReplyError (std::string_view msg); + void SendRaw (std::string_view data); void BuildStatusLine(bool currentTunnel, std::shared_ptr destination, std::string &out); From ad390f70b314ab004c31a800647c80f530cf67a3 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 21 Aug 2025 21:13:13 -0400 Subject: [PATCH 1153/1171] enable PQ encryption type by default if supported --- libi2pd/Config.cpp | 6 +++++- libi2pd/Destination.cpp | 5 ++++- libi2pd_client/ClientContext.cpp | 6 +++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 22faa7c6..8eebe7ac 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -168,7 +168,11 @@ namespace config { ("shareddest.inbound.quantity", value()->default_value("3"), "Shared local destination inbound tunnels quantity") ("shareddest.outbound.quantity", value()->default_value("3"), "Shared local destination outbound tunnels quantity") ("shareddest.i2cp.leaseSetType", value()->default_value("3"), "Shared local destination's LeaseSet type") - ("shareddest.i2cp.leaseSetEncType", value()->default_value("0,4"), "Shared local destination's LeaseSet encryption type") +#if OPENSSL_PQ + ("shareddest.i2cp.leaseSetEncType", value()->default_value("6,4,0"), "Shared local destination's LeaseSet encryption type") +#else + ("shareddest.i2cp.leaseSetEncType", value()->default_value("4,0"), "Shared local destination's LeaseSet encryption type") +#endif ("shareddest.i2p.streaming.profile", value()->default_value("2"), "Shared local destination bandwidth usage profile. 1 - bulk(high), 2- interactive(low)") ; diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index c24ef1db..ae6e46ef 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1069,7 +1069,10 @@ namespace client // if no param or valid crypto type use from identity if (encryptionKeyTypes.empty ()) encryptionKeyTypes.insert ( { GetIdentity ()->GetCryptoKeyType (), - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD }); // usually 0,4 +#if OPENSSL_PQ + i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM768_X25519_AEAD, +#endif + i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD }); // usually 0,4 or 0,6,4 if post quantum for (auto& it: encryptionKeyTypes) { diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index 8bee52ae..57ab0e48 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -480,7 +480,11 @@ namespace client options[I2CP_PARAM_STREAMING_PROFILE] = GetI2CPOption(section, I2CP_PARAM_STREAMING_PROFILE, DEFAULT_STREAMING_PROFILE); options[I2CP_PARAM_STREAMING_MAX_WINDOW_SIZE] = GetI2CPOption(section, I2CP_PARAM_STREAMING_MAX_WINDOW_SIZE, i2p::stream::MAX_WINDOW_SIZE); options[I2CP_PARAM_LEASESET_TYPE] = GetI2CPOption(section, I2CP_PARAM_LEASESET_TYPE, DEFAULT_LEASESET_TYPE); - std::string encType = GetI2CPStringOption(section, I2CP_PARAM_LEASESET_ENCRYPTION_TYPE, isServer ? "4" : "0,4"); +#if OPENSSL_PQ + std::string encType = GetI2CPStringOption(section, I2CP_PARAM_LEASESET_ENCRYPTION_TYPE, isServer ? "6,4" : "6,4,0"); +#else + std::string encType = GetI2CPStringOption(section, I2CP_PARAM_LEASESET_ENCRYPTION_TYPE, isServer ? "4" : "4,0"); +#endif if (encType.length () > 0) options[I2CP_PARAM_LEASESET_ENCRYPTION_TYPE] = encType; std::string privKey = GetI2CPStringOption(section, I2CP_PARAM_LEASESET_PRIV_KEY, ""); if (privKey.length () > 0) options[I2CP_PARAM_LEASESET_PRIV_KEY] = privKey; From 32bf9224f24adafa497b6d5d45288ba7f79d65d9 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 22 Aug 2025 12:05:37 -0400 Subject: [PATCH 1154/1171] don't show endpoint for terminated or closed SAM streams --- daemon/HTTPServer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index c4dedf61..a59ae5bd 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -1026,7 +1026,8 @@ namespace http { case i2p::client::SAMSocketType::eSAMSocketTypeForward : s << "forward"; break; default: s << "unknown"; break; } - s << " [" << it->GetSocket ().remote_endpoint() << "]"; + if (it->GetSocketType () != i2p::client::SAMSocketType::eSAMSocketTypeTerminated && it->GetSocket ().is_open ()) + s << " [" << it->GetSocket ().remote_endpoint() << "]"; s << "
\r\n"; } s << "
\r\n"; From 5dadecba034251ec9783d9ddef91a156ada64d19 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 22 Aug 2025 14:49:59 -0400 Subject: [PATCH 1155/1171] enable PQ encryption type by default for HTTP and SOCKS proxy if supported --- libi2pd/Config.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 8eebe7ac..822d9036 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -125,7 +125,11 @@ namespace config { ("httpproxy.addresshelper", value()->default_value(true), "Enable or disable addresshelper") ("httpproxy.senduseragent", value()->default_value(false), "Pass through user's User-Agent if enabled. Disabled by default") ("httpproxy.i2cp.leaseSetType", value()->default_value("3"), "Local destination's LeaseSet type") - ("httpproxy.i2cp.leaseSetEncType", value()->default_value("0,4"), "Local destination's LeaseSet encryption type") +#if OPENSSL_PQ + ("httpproxy.i2cp.leaseSetEncType", value()->default_value("6,4,0"), "Local destination's LeaseSet encryption type") +#else + ("httpproxy.i2cp.leaseSetEncType", value()->default_value("4,0"), "Local destination's LeaseSet encryption type") +#endif ("httpproxy.i2cp.leaseSetPrivKey", value()->default_value(""), "LeaseSet private key") ("httpproxy.i2p.streaming.maxOutboundSpeed", value()->default_value("1730000000"), "Max outbound speed of HTTP proxy stream in bytes/sec") ("httpproxy.i2p.streaming.maxInboundSpeed", value()->default_value("1730000000"), "Max inbound speed of HTTP proxy stream in bytes/sec") @@ -153,7 +157,11 @@ namespace config { ("socksproxy.outproxy", value()->default_value("127.0.0.1"), "Upstream outproxy address for SOCKS Proxy") ("socksproxy.outproxyport", value()->default_value(9050), "Upstream outproxy port for SOCKS Proxy") ("socksproxy.i2cp.leaseSetType", value()->default_value("3"), "Local destination's LeaseSet type") - ("socksproxy.i2cp.leaseSetEncType", value()->default_value("0,4"), "Local destination's LeaseSet encryption type") +#if OPENSSL_PQ + ("socksproxy.i2cp.leaseSetEncType", value()->default_value("6,4,0"), "Local destination's LeaseSet encryption type") +#else + ("socksproxy.i2cp.leaseSetEncType", value()->default_value("4,0"), "Local destination's LeaseSet encryption type") +#endif ("socksproxy.i2cp.leaseSetPrivKey", value()->default_value(""), "LeaseSet private key") ("socksproxy.i2p.streaming.maxOutboundSpeed", value()->default_value("1730000000"), "Max outbound speed of SOCKS proxy stream in bytes/sec") ("socksproxy.i2p.streaming.maxInboundSpeed", value()->default_value("1730000000"), "Max inbound speed of SOCKS proxy stream in bytes/sec") From a2073a8751b0cb7f7fc9dc222e3e9d91ae201efb Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 26 Aug 2025 14:50:34 -0400 Subject: [PATCH 1156/1171] lookup LeaseSet before sending ping --- libi2pd_client/BOB.cpp | 96 +++++++++++++++++++++++++++--------------- libi2pd_client/BOB.h | 2 + 2 files changed, 65 insertions(+), 33 deletions(-) diff --git a/libi2pd_client/BOB.cpp b/libi2pd_client/BOB.cpp index 83630a17..08d3c3f0 100644 --- a/libi2pd_client/BOB.cpp +++ b/libi2pd_client/BOB.cpp @@ -823,45 +823,75 @@ namespace client SendReplyError ("No local destination"); return; } - auto streamingDestination = localDestination->GetStreamingDestination (); - if (!streamingDestination) - { - SendReplyError ("No streaming destination"); - return; - } - auto timer = std::make_shared(localDestination->GetService ()); - timer->expires_from_now (boost::posix_time::milliseconds(BOB_PING_TIMEOUT)); - timer->async_wait ([streamingDestination, s = shared_from_this ()](const boost::system::error_code& ecode) - { - if (ecode != boost::asio::error::operation_aborted) - { - LogPrint (eLogDebug, "BOB: Pong not received after ", BOB_PING_TIMEOUT, " millliseconds"); - streamingDestination->ResetPongHandler (); - s->SendReplyError ("timeout"); - } - }); - auto ts = i2p::util::GetMillisecondsSinceEpoch (); - streamingDestination->SetPongHandler ( - [streamingDestination, timer, ts, s = shared_from_this ()](const i2p::data::IdentHash * from) - { - int t = i2p::util::GetMillisecondsSinceEpoch () - ts; - if (t < 0) t = 0; - streamingDestination->ResetPongHandler (); - timer->cancel (); - if (from) - s->SendReplyOK ({"pong ", "from ", from->ToBase32(), ".b32.i2p: time=", std::to_string (t), " ms"}); - else - s->SendReplyOK ({"pong: time=", std::to_string (t), " ms"}); - }); - if (addr->IsIdentHash ()) - localDestination->SendPing (addr->identHash); + { + // we might have leaseset already + auto leaseSet = localDestination->FindLeaseSet (addr->identHash); + if (leaseSet) + { + boost::asio::post (localDestination->GetService (), + std::bind (&BOBCommandSession::SendPing, shared_from_this (), leaseSet)); + return; + } + } + // request LeaseSet + if (addr->IsIdentHash ()) + localDestination->RequestDestination (addr->identHash, + std::bind (&BOBCommandSession::SendPing, shared_from_this (), std::placeholders::_1)); else - localDestination->SendPing (addr->blindedPublicKey); + localDestination->RequestDestinationWithEncryptedLeaseSet (addr->blindedPublicKey, + std::bind (&BOBCommandSession::SendPing, shared_from_this (), std::placeholders::_1)); } else SendReplyError ("empty ping address"); } + + void BOBCommandSession::SendPing (std::shared_ptr ls) + { + if (!ls) + { + SendReplyError ("LeaseSet Not found"); + return; + } + auto localDestination = (m_CurrentDestination && m_CurrentDestination->IsRunning ()) ? + m_CurrentDestination->GetLocalDestination () : i2p::client::context.GetSharedLocalDestination (); + if (!localDestination) + { + SendReplyError ("No local destination"); + return; + } + auto streamingDestination = localDestination->GetStreamingDestination (); + if (!streamingDestination) + { + SendReplyError ("No streaming destination"); + return; + } + auto timer = std::make_shared(localDestination->GetService ()); + timer->expires_from_now (boost::posix_time::milliseconds(BOB_PING_TIMEOUT)); + timer->async_wait ([streamingDestination, s = shared_from_this ()](const boost::system::error_code& ecode) + { + if (ecode != boost::asio::error::operation_aborted) + { + LogPrint (eLogDebug, "BOB: Pong not received after ", BOB_PING_TIMEOUT, " millliseconds"); + streamingDestination->ResetPongHandler (); + s->SendReplyError ("timeout"); + } + }); + auto ts = i2p::util::GetMillisecondsSinceEpoch (); + streamingDestination->SetPongHandler ( + [streamingDestination, timer, ts, s = shared_from_this ()](const i2p::data::IdentHash * from) + { + int t = i2p::util::GetMillisecondsSinceEpoch () - ts; + if (t < 0) t = 0; + streamingDestination->ResetPongHandler (); + timer->cancel (); + if (from) + s->SendReplyOK ({"pong ", "from ", from->ToBase32(), ".b32.i2p: time=", std::to_string (t), " ms"}); + else + s->SendReplyOK ({"pong: time=", std::to_string (t), " ms"}); + }); + streamingDestination->SendPing (ls); + } void BOBCommandSession::ClearCommandHandler (const char * operand, size_t len) { diff --git a/libi2pd_client/BOB.h b/libi2pd_client/BOB.h index 9ee7e0a0..a3f6754f 100644 --- a/libi2pd_client/BOB.h +++ b/libi2pd_client/BOB.h @@ -261,6 +261,8 @@ namespace client void BuildStatusLine(bool currentTunnel, std::shared_ptr destination, std::string &out); + void SendPing (std::shared_ptr ls); + private: BOBCommandChannel& m_Owner; From 310ee78d2452537b1085ddd886058265dbb63663 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 26 Aug 2025 21:16:15 -0400 Subject: [PATCH 1157/1171] create unique loopback address for ipv6 --- libi2pd_client/I2PTunnel.cpp | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index 7c12ff82..3fea7172 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -81,14 +81,26 @@ namespace client return ourIP; } + boost::asio::ip::address GetLoopbackAddress6For(const i2p::data::IdentHash & addr) + { + boost::asio::ip::address_v6::bytes_type bytes; + const uint8_t * ident = addr; + bytes[0] = 0xfd; + memcpy (bytes.data ()+1, ident, 15); + boost::asio::ip::address ourIP = boost::asio::ip::address_v6 (bytes); + return ourIP; + } + #ifdef __linux__ - static void MapToLoopback(std::shared_ptr sock, const i2p::data::IdentHash & addr) + static void MapToLoopback(std::shared_ptr sock, const i2p::data::IdentHash & addr, bool isV4) { if (sock) { - // bind to 127.x.x.x address + // bind to 127.x.x.x address for ipv4 // where x.x.x are first three bytes from ident - auto ourIP = GetLoopbackAddressFor(addr); + // bind to fdxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx address for ipv6 + // where xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx are first 15 bytes from ident + auto ourIP = isV4 ? GetLoopbackAddressFor(addr) : GetLoopbackAddress6For(addr); boost::system::error_code ec; sock->bind (boost::asio::ip::tcp::endpoint (ourIP, 0), ec); if (ec) @@ -103,12 +115,19 @@ namespace client { I2PTunnelSetSocketOptions (m_Socket); #ifdef __linux__ - if (isUniqueLocal && m_RemoteEndpoint.address ().is_v4 () && - m_RemoteEndpoint.address ().to_v4 ().to_bytes ()[0] == 127) - { - m_Socket->open (boost::asio::ip::tcp::v4 ()); + if (isUniqueLocal && m_RemoteEndpoint.address ().is_loopback ()) + { auto ident = m_Stream->GetRemoteIdentity()->GetIdentHash(); - MapToLoopback(m_Socket, ident); + if (m_RemoteEndpoint.address ().is_v4 ()) + { + m_Socket->open (boost::asio::ip::tcp::v4 ()); + MapToLoopback(m_Socket, ident, true); + } + else if (m_RemoteEndpoint.address ().is_v6 ()) + { + m_Socket->open (boost::asio::ip::tcp::v6 ()); + MapToLoopback(m_Socket, ident, false); + } } #endif m_Socket->async_connect (m_RemoteEndpoint, std::bind (&I2PTunnelConnection::HandleConnect, From 938a6989043b06b20fac0f9af2d4e7dfed9dc58f Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 27 Aug 2025 18:33:46 -0400 Subject: [PATCH 1158/1171] don't create unique loopback address for ::1 if not set explicitly --- libi2pd_client/ClientContext.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index 57ab0e48..b890fbc6 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -774,7 +774,7 @@ namespace client i2p::data::CryptoKeyType cryptoType = section.second.get (I2P_CLIENT_TUNNEL_CRYPTO_TYPE, i2p::data::CRYPTO_KEY_TYPE_ELGAMAL); std::string address = section.second.get (I2P_SERVER_TUNNEL_ADDRESS, ""); - bool isUniqueLocal = section.second.get (I2P_SERVER_TUNNEL_ENABLE_UNIQUE_LOCAL, true); + bool isUniqueLocal = section.second.get (I2P_SERVER_TUNNEL_ENABLE_UNIQUE_LOCAL, (host == "::1") ? false : true); bool ssl = section.second.get (I2P_SERVER_TUNNEL_SSL, false); // I2CP From 6dd2c6aaf9c34ea99beb24133a4dc265eeedd1d0 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 27 Aug 2025 21:15:13 -0400 Subject: [PATCH 1159/1171] don't include remote ident hash to SYN packet if no signature --- libi2pd/Streaming.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 7e8747ad..122a26d2 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -955,10 +955,18 @@ namespace stream if (m_Status == eStreamStatusNew && !m_SendStreamID && m_RemoteIdentity) { // first SYN packet - packet[size] = 8; - size++; // NACK count - memcpy (packet + size, m_RemoteIdentity->GetIdentHash (), 32); - size += 32; + if (m_DontSign) + { + // remote ident is useless without signature, don't include it + packet[size] = 0; size++; // NACK count + } + else + { + packet[size] = 8; + size++; // NACK count + memcpy (packet + size, m_RemoteIdentity->GetIdentHash (), 32); + size += 32; + } } else { From f46db7b8c75f83d24f71f9214587da6e06a93402 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 28 Aug 2025 17:46:43 -0400 Subject: [PATCH 1160/1171] don't show Network status: Unknown for ipv6 only --- daemon/HTTPServer.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index a59ae5bd..bb2f44db 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -288,9 +288,12 @@ namespace http { s << "" << tr("Uptime") << ": "; ShowUptime(s, i2p::context.GetUptime ()); s << "
\r\n"; - s << "" << tr("Network status") << ": "; - ShowNetworkStatus (s, i2p::context.GetStatus (), i2p::context.GetTesting(), i2p::context.GetError ()); - s << "
\r\n"; + if (i2p::context.SupportsV4 () || i2p::context.GetStatus () != eRouterStatusUnknown) // don't show Unknown for ipv6-only + { + s << "" << tr("Network status") << ": "; + ShowNetworkStatus (s, i2p::context.GetStatus (), i2p::context.GetTesting(), i2p::context.GetError ()); + s << "
\r\n"; + } if (i2p::context.SupportsV6 ()) { s << "" << tr("Network status v6") << ": "; From 1d7c7ac14898b0f8e956685a49b1382b0132d221 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 29 Aug 2025 11:16:54 -0400 Subject: [PATCH 1161/1171] fixed #2231. Close outgoing stream if LeaseSet not found --- libi2pd/Streaming.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 122a26d2..25fb7b5d 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -1817,19 +1817,29 @@ namespace stream auto remoteLeaseSet = m_LocalDestination.GetOwner ()->FindLeaseSet (m_RemoteIdentity->GetIdentHash ()); if (!remoteLeaseSet) { - LogPrint (eLogWarning, "Streaming: LeaseSet ", m_RemoteIdentity->GetIdentHash ().ToBase64 (), m_RemoteLeaseSet ? " expired" : " not found"); + LogPrint (eLogWarning, "Streaming: LeaseSet ", m_RemoteIdentity->GetIdentHash ().ToBase32 (), m_RemoteLeaseSet ? " expired" : " not found"); if (!m_IsIncoming) // outgoing { + auto requestCallback = [s = shared_from_this ()](std::shared_ptr ls) + { + if (!ls && s->m_Status == eStreamStatusOpen) // LeaseSet not found + { + // close the socket without sending FIN or RST + s->m_Status = eStreamStatusClosed; + s->AsyncClose (); + } + }; + if (m_RemoteLeaseSet && m_RemoteLeaseSet->IsPublishedEncrypted ()) { m_LocalDestination.GetOwner ()->RequestDestinationWithEncryptedLeaseSet ( - std::make_shared(m_RemoteIdentity)); + std::make_shared(m_RemoteIdentity), requestCallback); return; // we keep m_RemoteLeaseSet for possible next request } else { m_RemoteLeaseSet = nullptr; - m_LocalDestination.GetOwner ()->RequestDestination (m_RemoteIdentity->GetIdentHash ()); // try to request for a next attempt + m_LocalDestination.GetOwner ()->RequestDestination (m_RemoteIdentity->GetIdentHash (), requestCallback); // try to request for a next attempt } } else // incoming From 3522a3180b2b7d34b5ab68999efb3e3e16801bb9 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 31 Aug 2025 17:50:02 -0400 Subject: [PATCH 1162/1171] implement PING command --- libi2pd_client/SAM.cpp | 14 ++++++++++++++ libi2pd_client/SAM.h | 6 +++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 22279001..80987c78 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -248,6 +248,14 @@ namespace client char * separator = strchr (m_Buffer, ' '); if (separator) { + // one word command + if (std::string_view (m_Buffer, separator - m_Buffer) == SAM_PING) + { + ProcessPing ({ separator + 1, (size_t)(eol - separator - 1) }); + return; + } + + // two words command size_t l = 0; separator = strchr (separator + 1, ' '); if (separator) @@ -955,6 +963,12 @@ namespace client SendSessionI2PError ("Wrong session type"); } + void SAMSocket::ProcessPing (std::string_view text) + { + LogPrint (eLogDebug, "SAM: Ping ", text); + SendReplyWithMessage (SAM_PONG, std::string (text)); + } + void SAMSocket::SendReplyWithMessage (const char * reply, const std::string & msg) { #ifdef _MSC_VER diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index 00b7ed03..fd73003f 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -85,12 +85,15 @@ namespace client const char SAM_VALUE_TRANSIENT[] = "TRANSIENT"; const char SAM_VALUE_TRUE[] = "true"; const char SAM_VALUE_FALSE[] = "false"; - + constexpr std::string_view SAM_VALUE_STREAM { "STREAM" }; constexpr std::string_view SAM_VALUE_DATAGRAM { "DATAGRAM" }; constexpr std::string_view SAM_VALUE_RAW { "RAW" }; constexpr std::string_view SAM_VALUE_MASTER { "MASTER" }; + constexpr std::string_view SAM_PING { "PING" }; + const char SAM_PONG[] = "PONG %s\n"; + constexpr int MAKE_SAM_VERSION_NUMBER (int major, int minor) { return major*10 + minor; } constexpr int MIN_SAM_VERSION = MAKE_SAM_VERSION_NUMBER (3, 0); constexpr int MAX_SAM_VERSION = MAKE_SAM_VERSION_NUMBER (3, 3); @@ -153,6 +156,7 @@ namespace client void ProcessNamingLookup (std::string_view buf); void ProcessSessionAdd (std::string_view buf); void ProcessSessionRemove (std::string_view buf); + void ProcessPing (std::string_view text); void SendReplyWithMessage (const char * reply, const std::string & msg); void SendSessionI2PError(const std::string & msg); void SendStreamI2PError(const std::string & msg); From decf5a0376e16ff10f951b57490f460e29502b6b Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 5 Sep 2025 13:56:03 -0400 Subject: [PATCH 1163/1171] removed cubicchaos.net and i2p.ghativega.in for reseeds list --- .../reseed/arnavbhatt288_at_mail.i2p.crt | 34 ------------------- .../reseed/unixeno_at_cubicchaos.net.crt | 34 ------------------- libi2pd/Config.cpp | 4 +-- 3 files changed, 1 insertion(+), 71 deletions(-) delete mode 100644 contrib/certificates/reseed/arnavbhatt288_at_mail.i2p.crt delete mode 100644 contrib/certificates/reseed/unixeno_at_cubicchaos.net.crt diff --git a/contrib/certificates/reseed/arnavbhatt288_at_mail.i2p.crt b/contrib/certificates/reseed/arnavbhatt288_at_mail.i2p.crt deleted file mode 100644 index 9068afb9..00000000 --- a/contrib/certificates/reseed/arnavbhatt288_at_mail.i2p.crt +++ /dev/null @@ -1,34 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIF2TCCA8GgAwIBAgIQIHQPtSoFU+cUpYD8PZaWZjANBgkqhkiG9w0BAQsFADB2 -MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYDVQQK -ExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEfMB0GA1UEAwwW -YXJuYXZiaGF0dDI4OEBtYWlsLmkycDAeFw0yMzAxMjUxODUzNDFaFw0zMzAxMjUx -ODUzNDFaMHYxCzAJBgNVBAYTAlhYMQswCQYDVQQHEwJYWDELMAkGA1UECRMCWFgx -HjAcBgNVBAoTFUkyUCBBbm9ueW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMR8w -HQYDVQQDDBZhcm5hdmJoYXR0Mjg4QG1haWwuaTJwMIICIjANBgkqhkiG9w0BAQEF -AAOCAg8AMIICCgKCAgEAtwG73sC0jYd3fgEzZh0SveAdUd5yD35nINJRrdPSrSwY -n3i1qGe3fNLj877PvUDU+qiHH0fFZfyFkXTaq3TUp1u4YkmvaoPHy6FZlojB08lK -FBm+iJ1hifQ7MFmvIKUGv+cjlN6xSoQ0U6B2QOy6iZnBgFZ/7jbRY4iZOIj7VJtY -aodeHfy0bWe447VJovbkUi7NJPFZQS65LMcAIWcWTxrC0Gj8SmdxL3a5+hxpmmg0 -+KCQvWQDdxAQjsc16sgUCdUc6cWYO4yw9H6fgdq9GJX+LnXR9OB58GsAjjlLlFoI -CZxdARDpoqcIj6AoKIanALf8yfbIyrqqJE47cuaqV9bht5MWKnXbwHplEkT4ZNkh -PnRDia7B5HY3uwbt39CBm264PEWXvWG2sozTWKQqBjmMN2cj/NFDUEqKv6BggMY1 -HcqxWFKRcgKCtRvrmTmfp5l0/ou+OtUaFUg0a6Qhtb93Hj10vK6wZzidBqj0ggzB -eJDI95b89u8JgzRoOBriuMKTc91WTkOvBLkB3dgUbUpx2p8KHjvf/pppBH9u0oxp -qJFFK840DbnJydEvjKezeVe5Ax6YRSRxyEdKzRoWdvKVxb3qBBKMdCKTYEPxHPBu -JMEQVUCXJMti++1KEiQGhcfWvLyT7OewbcIZNk9XWNrxlKcGrTp9AOwaaNC5m1kC -AwEAAaNjMGEwDgYDVR0PAQH/BAQDAgKEMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggr -BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB8GA1UdDgQYBBZhcm5hdmJoYXR0Mjg4 -QG1haWwuaTJwMA0GCSqGSIb3DQEBCwUAA4ICAQAHiK0ld/1PF9DIhutD660/bzBg -mF2Z76hcBqDZ8tnQai/u/RXYrH9wso9BYyrVsvk3fr6tpGT49Ian0MVpPOxMoTU2 -oBEmQlYrfclQLFsOLmA0y2r1ggXzIrt69jB710Vhwdnz09oOE8rS4E2T5oDD8Wvy -Kony+AarRceqtkOlzyquc42KjzdrbHsosF7G2iGhNI6t+T3BfWJ+Q+d5sj3OIh6e -gSfvHL44E4vZt6dtofRN3MAZ60kNLF5YWyaUo3Snv9Lso1IwIz3AVr5ehv+8sFL/ -KxaXdkZ5Yn2YUX7p1t4VQd+eXVPYjf1befg4PvrwSkylu3Jpee3fllZSKXeSVx9x -jpJiq5vIakqk22pnWb1Vn7xzSW1vtEG7QLjobOr1WrcGiwdv+HKiWcXJXDzKoWXs -h3VEfr51Kap8cIJv+D6lJIG9IcIhiQ6CXWBmtjWJvbdVwFBy1/3Fhaou9liHi+gK -4Yh5a5OGCzc7xjtpGaTmoLEz7NzDNOdd/r840qRDOh70izzmFZd5Gwq4hoVcPJcS -EAySwtgqK0/4d0zDd2Wg9ASJV9DnDf8QuSmHZgZ9Efs47XcWz9TvkWUS1E66AJsN -mmI1NDQ3mv3dv5+WPq+dqqYFsnx3xWL1g5Z3buk0opeuXMzoHwM7UfN8h7Q1M5+t -+XBgkaYA4iEwYKqlCQ== ------END CERTIFICATE----- diff --git a/contrib/certificates/reseed/unixeno_at_cubicchaos.net.crt b/contrib/certificates/reseed/unixeno_at_cubicchaos.net.crt deleted file mode 100644 index c94d319e..00000000 --- a/contrib/certificates/reseed/unixeno_at_cubicchaos.net.crt +++ /dev/null @@ -1,34 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIF2TCCA8GgAwIBAgIQVpTNnJZlUTDqmZiHRU4wCjANBgkqhkiG9w0BAQsFADB2 -MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYDVQQK -ExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEfMB0GA1UEAwwW -dW5peGVub0BjdWJpY2NoYW9zLm5ldDAeFw0yNTAzMDQxODU5NDZaFw0zNTAzMDQx -ODU5NDZaMHYxCzAJBgNVBAYTAlhYMQswCQYDVQQHEwJYWDELMAkGA1UECRMCWFgx -HjAcBgNVBAoTFUkyUCBBbm9ueW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMR8w -HQYDVQQDDBZ1bml4ZW5vQGN1YmljY2hhb3MubmV0MIICIjANBgkqhkiG9w0BAQEF -AAOCAg8AMIICCgKCAgEAr/JoAzLDtHXoAc7QcP4IxO+xNTeiYs78Wlg/Sl/sa6qz -gJoGaKH/X++z4Xe9lBSZalXCamnO4QMTgsWOIeoMy6XVbGzNTXPl8JUcblTIXwkP -pv848b1nxLfgLHzPRz1mJMpMikBugJ3Iz1sQzDVlUdye2fgbGChWliz9P4ClEODv -A/4+7i6uvJgEZ7A+jx3vBCXhiJppE3wTuz5D9BQqG8NuEwwjwBTBByoCC4oxOe0h -Qu1k7kEr+n4qpSEg/1eJ/RYSm+I8BftK1RUfykTwxlfmyEmKsfLBQWczE8Ca9nUB -5V34UH2bRy1cvavJYcNW3EPsGNf4naRs+Gy8XIFrb315GgWC1Z6+tzk+QFli9YeF -0DgtYEZciqu/407o8ZEURTnPjB7GhLDDp1LAQ7CQRhzaraXjHj0hyO+6rFpFdD0D -mXhvI/Eph3QIldsgnQc7nPhU2csN8Vi6bNDgm0HZ8cdmIBpI2Uxn/acZX/9G40oj -czrhsCBEecu/BluLJsfaWCYg90rvONP8Fc4edHAMonzYZR4r0q4hbv7AM8GmDRDN -J9/DZFi+Qs9NAe06jJC3jSsj7IdIs8TMhw8FX3xWOlXwjmVETAgY/dta/MpLJ6tJ -i+E+TH/Ndntj/D6WUwdQq+LyCR6gqHUWR6rl6EDQz+08DWb7j/72JSLb/DaXrDUC -AwEAAaNjMGEwDgYDVR0PAQH/BAQDAgKEMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggr -BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB8GA1UdDgQYBBZ1bml4ZW5vQGN1Ymlj -Y2hhb3MubmV0MA0GCSqGSIb3DQEBCwUAA4ICAQBBVoPeuOkmJDUdzIrzmxTmjMyz -gpfrZnjirTQKWhbv53sAWNeJ3kZ9l9m+0YpqEtFDrZPL5LTBXcSci5gGuxPkp+i/ -f/axsdcFMKbI9B/M53fyXLLJY0EM4mdhNAWtph1kTowFPhhReefCdqxYIy9uk2pL -gfb6NYJf+w9//fKYFZXb9SsiRchfv81+lbN+PIprnCpV3cTZWmpLRi2hN86pMW20 -3rh7rqJ4dPnA/NoyM+JstL10IU/4StqInweEvoo4W44+cC0zYGvfkkrKL4LB8w5S -6DKebtk7NQDtzuw2QnA9Ms4bmqWQpbL6/7uGaauS0+nmF+2gkqi9hcv0W5ZoBb/D -IVRauySnCtp9PbYM7pIJP9a1U6naLj7L1VixqsJGfPQ8V9TCOOi5bDc3RTetI/DX -bXHhAqHYzboakptylCp+Ao5h2hu0+w4rqnG63HwsHDJWcETbdVFQfzlzUmbx53yV -GnBsUxDgMOiHTZdKLkEnH4Q/XI76uc0ntTRlK9ktKWZPSISUlHrFnFl6I5UdeBMy -6vpB9sJO5L5RPRi4945K5Xdennywdi508mNXtMMmNCqrk1SMYbwaY6ZtIvXEGam9 -uHQTiTEX9LED/VXzFGqzdyDbG43HgS0PksgzedelHWfVAEnc06U3JX2lqUyihYHa -N4jAXWQ7s5p4GYaf4Q== ------END CERTIFICATE----- diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 822d9036..d87b3ba1 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -259,10 +259,8 @@ namespace config { "https://coconut.incognet.io/," "https://reseed-pl.i2pd.xyz/," "https://www2.mk16.de/," - "https://i2p.ghativega.in/," "https://i2p.novg.net/," - "https://reseed.stormycloud.org/," - "https://cubicchaos.net:8443/" + "https://reseed.stormycloud.org/" ), "Reseed URLs, separated by comma") ("reseed.yggurls", value()->default_value( "http://[324:71e:281a:9ed3::ace]:7070/," From e8d59c83754a0809b753ea7f59021160f755abad Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 6 Sep 2025 15:33:26 -0400 Subject: [PATCH 1164/1171] 2.58.0 --- ChangeLog | 31 +++++++++++++++++++++++++++++++ contrib/rpm/i2pd-git.spec | 5 ++++- contrib/rpm/i2pd.spec | 5 ++++- debian/changelog | 6 ++++++ libi2pd/version.h | 4 ++-- 5 files changed, 47 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index e8d6daf7..6c4ef5b3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,37 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog +## [2.58.0] - 2025-09-08 +### Added +- Post-quantum end-to-end crypto(ML-KEM-512, ML-KEM-768, ML-KEM-1024) support if openssl >= 3.5.0 +- Datagram2 and Datagram3 +- SAM PING command +- Support boost 1.89 +- Specify light or dark theme for webconsole +- "ssu2.firewalled4" and "ssu2.firewalled6" params to force Firewalled even if network is OK +- Streaming ping through BOB +- Ability to specify bandwidth with "mb" and "gb" suffixes +- "i2p.streaming.maxWindowSize" and "i2p.streaming.dontSign" params +### Changed +- Don't verify streaming SYN packet signature if comes from an ECIESx25519 session +- Non-blocking mode for UDP sockets in UDP tunnels +- Accept "HELLO VERSION" without "MIN" and "MAX" in SAM +- Try to resolve host again in server tunnel if failed before +- Don't call deprecated functions for openssl 3 +- Enable post-quantum crypto by default if supported +- Create unique loopback address from fd00::/8 range for ::1 if explicitly set in server tunnels +- Limit number of outbound streaming packets if the peer can't handle them +- Don't show Network status if ipv6 only +- Reseeds list +### Fixed +- Version in I2CP SetDate message +- Crash when SAM session is getting closed +- Max UDP buffer size for OpenBSD +- Lack of file descriptors for Haiku +- Outgoing stream constantly re-requests LeaseSet if the remote peer has gone away +- Numeric value for "i2p.streaming.answerPings" param +- 'R' and 'U' router caps together if operating through a proxy + ## [2.57.0] - 2025-06-02 ### Added - Local domain sockets for I2PControl diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index d9393f47..23daddf6 100644 --- a/contrib/rpm/i2pd-git.spec +++ b/contrib/rpm/i2pd-git.spec @@ -1,7 +1,7 @@ %define git_hash %(git rev-parse HEAD | cut -c -7) Name: i2pd-git -Version: 2.57.0 +Version: 2.58.0 Release: git%{git_hash}%{?dist} Summary: I2P router written in C++ Conflicts: i2pd @@ -136,6 +136,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Mon Sep 08 2025 orignal - 2.58.0 +- update to 2.58.0 + * Mon Jun 02 2025 orignal - 2.57.0 - update to 2.57.0 diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index e094c3b7..c2b7c923 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,5 +1,5 @@ Name: i2pd -Version: 2.57.0 +Version: 2.58.0 Release: 1%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git @@ -134,6 +134,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Mon Sep 08 2025 orignal - 2.58.0 +- update to 2.58.0 + * Mon Jun 02 2025 orignal - 2.57.0 - update to 2.57.0 diff --git a/debian/changelog b/debian/changelog index 8b1e6237..2267246d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i2pd (2.58.0-1) unstable; urgency=medium + + * updated to version 2.58.0/0.9.67 + + -- orignal Mon, 08 Sep 2025 16:00:00 +0000 + i2pd (2.57.0-1) unstable; urgency=medium * updated to version 2.57.0/0.9.66 diff --git a/libi2pd/version.h b/libi2pd/version.h index 45f209ac..f88133e4 100644 --- a/libi2pd/version.h +++ b/libi2pd/version.h @@ -18,7 +18,7 @@ #define MAKE_VERSION_NUMBER(a,b,c) ((a*100+b)*100+c) #define I2PD_VERSION_MAJOR 2 -#define I2PD_VERSION_MINOR 57 +#define I2PD_VERSION_MINOR 58 #define I2PD_VERSION_MICRO 0 #define I2PD_VERSION_PATCH 0 #ifdef GITVER @@ -33,7 +33,7 @@ #define I2P_VERSION_MAJOR 0 #define I2P_VERSION_MINOR 9 -#define I2P_VERSION_MICRO 66 +#define I2P_VERSION_MICRO 67 #define I2P_VERSION_PATCH 0 #define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO) #define I2P_VERSION_NUMBER MAKE_VERSION_NUMBER(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO) From 227f397c06abcd722ea0d6e3d70b453f0da9e37c Mon Sep 17 00:00:00 2001 From: wipedlifepotato Date: Wed, 10 Sep 2025 22:20:36 +0700 Subject: [PATCH 1165/1171] patch: fix css for webconsole --- contrib/webconsole/hacker.css | 4 +++- contrib/webconsole/style.css | 4 +++- daemon/HTTPServerResources.h | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/contrib/webconsole/hacker.css b/contrib/webconsole/hacker.css index 93baf564..5d93be50 100644 --- a/contrib/webconsole/hacker.css +++ b/contrib/webconsole/hacker.css @@ -98,12 +98,14 @@ a:hover, a.button.selected, .slide label:hover, button[type=submit]:hover { } .content { - float: left; +/* float: left;*/ font-size: 1em; margin-left: 2em; padding: 4px; max-width: 50em; overflow: auto; + left: 35%; + position: absolute; } .tunnel.established { diff --git a/contrib/webconsole/style.css b/contrib/webconsole/style.css index ea8ffd4f..c3aa4e98 100644 --- a/contrib/webconsole/style.css +++ b/contrib/webconsole/style.css @@ -92,12 +92,14 @@ a.button { } .content { - float: left; +/* float: left;*/ font-size: 1em; margin-left: 2em; padding: 4px; max-width: 50em; overflow: auto; + left: 35%; + position: absolute; } .tunnel.established { diff --git a/daemon/HTTPServerResources.h b/daemon/HTTPServerResources.h index 1e5b6f75..011475a4 100644 --- a/daemon/HTTPServerResources.h +++ b/daemon/HTTPServerResources.h @@ -45,7 +45,7 @@ namespace http ".menu { display: block; float: left; overflow: hidden; padding: 4px; 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: 2em; padding: 4px; max-width: 50em; overflow: auto; }\r\n" + ".content { font-size: 1em; margin-left: 2em; padding: 4px; max-width: 50em; overflow: auto; position: absolute; left: 35%; }\r\n" ".tunnel.established { color: #56B734; }\r\n" ".tunnel.expiring { color: #D3AE3F; }\r\n" ".tunnel.failed { color: #D33F3F; }\r\n" From 0afce7304cec2b042dc380c86e366b78dcd24c53 Mon Sep 17 00:00:00 2001 From: wipedlifepotato Date: Wed, 10 Sep 2025 22:31:09 +0700 Subject: [PATCH 1166/1171] fix: fix css for small width size --- contrib/webconsole/style.css | 2 ++ daemon/HTTPServerResources.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/contrib/webconsole/style.css b/contrib/webconsole/style.css index c3aa4e98..2f399fea 100644 --- a/contrib/webconsole/style.css +++ b/contrib/webconsole/style.css @@ -232,6 +232,8 @@ input[type=number]::-webkit-inner-spin-button { max-width: 100%; width: 100%; text-align: center; + position: absolute; + left: 0; } a, .slide label { diff --git a/daemon/HTTPServerResources.h b/daemon/HTTPServerResources.h index 011475a4..2772fb69 100644 --- a/daemon/HTTPServerResources.h +++ b/daemon/HTTPServerResources.h @@ -73,7 +73,7 @@ namespace http "@media screen and (max-width: 980px) { body { font: 100%/1.2em sans-serif; padding: 1.2em 0 0 0; }\r\n" " .menu { width: 100%; max-width: unset; display: block; float: none; position: unset; font-size: 16px; text-align: center; }\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%; text-align: center; }\r\n" + " .content { float: none; margin-left: unset; margin-top: 16px; max-width: 100%; width: 100%; text-align: center; position: absolute; left: 0; }\r\n" " a, .slide label { display: block; }\r\n" " .header { margin: unset; font-size: 1.5em; }\r\n" " small { display: block; }\r\n" From 0f279017a22897ec1ed3e7d04d20686107c7f18d Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 11 Sep 2025 18:44:25 -0400 Subject: [PATCH 1167/1171] renamed DaemonLinux to DaemonUnix --- daemon/Daemon.h | 12 ++++++------ daemon/UnixDaemon.cpp | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/daemon/Daemon.h b/daemon/Daemon.h index 26d4a047..3f53b89f 100644 --- a/daemon/Daemon.h +++ b/daemon/Daemon.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2025, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -97,15 +97,15 @@ namespace util return instance; } }; -#else -#define Daemon i2p::util::DaemonLinux::Instance() - class DaemonLinux : public Daemon_Singleton +#else // Unix-like systems, including Linux +#define Daemon i2p::util::DaemonUnix::Instance() + class DaemonUnix : public Daemon_Singleton { public: - static DaemonLinux& Instance() + static DaemonUnix& Instance() { - static DaemonLinux instance; + static DaemonUnix instance; return instance; } diff --git a/daemon/UnixDaemon.cpp b/daemon/UnixDaemon.cpp index 66661e0f..0c182afe 100644 --- a/daemon/UnixDaemon.cpp +++ b/daemon/UnixDaemon.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2024, The PurpleI2P Project +* Copyright (c) 2013-2025, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -71,7 +71,7 @@ namespace i2p { namespace util { - bool DaemonLinux::start() + bool DaemonUnix::start() { if (isDaemon) { @@ -213,13 +213,13 @@ namespace i2p return Daemon_Singleton::start(); } - bool DaemonLinux::stop() + bool DaemonUnix::stop() { i2p::fs::Remove(pidfile); return Daemon_Singleton::stop(); } - void DaemonLinux::run () + void DaemonUnix::run () { i2p::util::SetThreadName ("i2pd-daemon"); while (running) From f20cc3f04b446436da51cb55ce75fcabf202a927 Mon Sep 17 00:00:00 2001 From: wipedlifepotato Date: Sun, 14 Sep 2025 23:56:14 +0700 Subject: [PATCH 1168/1171] fix: fix default value httpproxy.keys, socksproxy.keys --- contrib/i2pd.conf | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/contrib/i2pd.conf b/contrib/i2pd.conf index fa6b1f8b..f2652f38 100644 --- a/contrib/i2pd.conf +++ b/contrib/i2pd.conf @@ -142,7 +142,9 @@ ipv6 = false ## Address and port service will listen on (default: 127.0.0.1:4444) # address = 127.0.0.1 # port = 4444 -## Optional keys file for proxy local destination (default: http-proxy-keys.dat) +## Optional keys file for proxy local destination (default: transient-proxy) +## "Transient" means it changes on every new app launch ## +# If you want not change address then set like http-proxy-keys.dat # keys = http-proxy-keys.dat ## Enable address helper for adding .i2p domains with "jump URLs" (default: true) ## You should disable this feature if your i2pd HTTP Proxy is public, @@ -158,7 +160,9 @@ ipv6 = false ## Address and port service will listen on (default: 127.0.0.1:4447) # address = 127.0.0.1 # port = 4447 -## Optional keys file for proxy local destination (default: socks-proxy-keys.dat) +## Optional keys file for proxy local destination (default: transient-proxy) +# "Transient" means it changes on every new app launch ## +# If you don't want the address to change, set a file name like socks-proxy-keys.dat # keys = socks-proxy-keys.dat ## Socks outproxy. Example below is set to use Tor for all connections except i2p ## Enable using of SOCKS outproxy (works only with SOCKS4, default: false) From 842519ec8e7524deab1ff3af205cf903bdbbf6f5 Mon Sep 17 00:00:00 2001 From: wipedlifepotato Date: Sun, 14 Sep 2025 23:59:27 +0700 Subject: [PATCH 1169/1171] fix: fix default value httpproxy.keys, socksproxy.keys --- contrib/i2pd.conf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contrib/i2pd.conf b/contrib/i2pd.conf index f2652f38..1cc357e2 100644 --- a/contrib/i2pd.conf +++ b/contrib/i2pd.conf @@ -143,7 +143,7 @@ ipv6 = false # address = 127.0.0.1 # port = 4444 ## Optional keys file for proxy local destination (default: transient-proxy) -## "Transient" means it changes on every new app launch ## +## "Transient" means it changes on every new app launch # If you want not change address then set like http-proxy-keys.dat # keys = http-proxy-keys.dat ## Enable address helper for adding .i2p domains with "jump URLs" (default: true) @@ -161,11 +161,11 @@ ipv6 = false # address = 127.0.0.1 # port = 4447 ## Optional keys file for proxy local destination (default: transient-proxy) -# "Transient" means it changes on every new app launch ## +# "Transient" means it changes on every new app launch # If you don't want the address to change, set a file name like socks-proxy-keys.dat # keys = socks-proxy-keys.dat ## Socks outproxy. Example below is set to use Tor for all connections except i2p -## Enable using of SOCKS outproxy (works only with SOCKS4, default: false) +## Enable SOCKS outproxy (works only with SOCKS4, default: false) # outproxy.enabled = false ## Address and port of outproxy # outproxy = 127.0.0.1 From df794e6627d4ad86d05b20a6b558285b48038a3e Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 16 Sep 2025 13:45:49 -0400 Subject: [PATCH 1170/1171] Drop expired tunnel messages. Don't overwrite tunnel message timestamp --- libi2pd/TransitTunnel.cpp | 4 +++- libi2pd/Tunnel.cpp | 3 ++- libi2pd/Tunnel.h | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/libi2pd/TransitTunnel.cpp b/libi2pd/TransitTunnel.cpp index b24c8ac5..9e1924ac 100644 --- a/libi2pd/TransitTunnel.cpp +++ b/libi2pd/TransitTunnel.cpp @@ -68,7 +68,9 @@ namespace tunnel m_NumTransmittedBytes += tunnelMsg->GetLength (); htobe32buf (tunnelMsg->GetPayload (), GetNextTunnelID ()); - tunnelMsg->FillI2NPMessageHeader (eI2NPTunnelData); + // update header, expiration and size remain the same + tunnelMsg->SetMsgID (i2p::tunnel::tunnels.GetRng ()()); // assign new msgID + tunnelMsg->UpdateChks (); // new checksum TODO: remove later m_TunnelDataMsgs.push_back (tunnelMsg); } diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 1347b5b8..f4aa01ce 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -561,13 +561,14 @@ namespace tunnel if (m_Queue.Wait (1,0)) // 1 sec { m_Queue.GetWholeQueue (msgs); + auto mts = i2p::util::GetMillisecondsSinceEpoch (); int numMsgs = 0; uint32_t prevTunnelID = 0, tunnelID = 0; std::shared_ptr prevTunnel; while (!msgs.empty ()) { auto msg = msgs.front (); msgs.pop_front (); - if (!msg) continue; + if (!msg || msg->IsExpired (mts)) continue; std::shared_ptr tunnel; uint8_t typeID = msg->GetTypeID (); switch (typeID) diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index 78e2d124..e9d78083 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -248,6 +248,7 @@ namespace tunnel void SetMaxNumTransitTunnels (uint32_t maxNumTransitTunnels); uint32_t GetMaxNumTransitTunnels () const { return m_MaxNumTransitTunnels; }; int GetCongestionLevel() const { return m_MaxNumTransitTunnels ? CONGESTION_LEVEL_FULL * m_TransitTunnels.GetNumTransitTunnels () / m_MaxNumTransitTunnels : CONGESTION_LEVEL_FULL; } + std::mt19937& GetRng () { return m_Rng; } private: From 5494a6c96195059e6fe99d9af2a7cb8f1a5ab027 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 16 Sep 2025 21:51:49 -0400 Subject: [PATCH 1171/1171] remove route48's MTU --- libi2pd/util.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/libi2pd/util.cpp b/libi2pd/util.cpp index 925cf629..0bd19d23 100644 --- a/libi2pd/util.cpp +++ b/libi2pd/util.cpp @@ -513,12 +513,6 @@ namespace net // Hurricane Electric return 1480; break; - case 0x2a06a003: - case 0x2a06a004: - case 0x2a06a005: - // route48 - return 1420; - break; default: ; } return 1500; @@ -648,7 +642,7 @@ namespace net if (host.is_unspecified ()) return false; if (host.is_v4()) { - static const std::array, 14> reservedIPv4Ranges + static const std::array reservedIPv4Ranges { address_pair_v4("0.0.0.0", "0.255.255.255"), address_pair_v4("10.0.0.0", "10.255.255.255"), @@ -674,7 +668,7 @@ namespace net } if (host.is_v6()) { - static const std::array, 7> reservedIPv6Ranges + static std::array reservedIPv6Ranges { address_pair_v6("64:ff9b::", "64:ff9b:ffff:ffff:ffff:ffff:ffff:ffff"), // NAT64 address_pair_v6("2001:db8::", "2001:db8:ffff:ffff:ffff:ffff:ffff:ffff"),