From 519c0fe81d8f922b73139bd762067661691cb24a Mon Sep 17 00:00:00 2001 From: Jigen <111368404+jiigen@users.noreply.github.com> Date: Fri, 2 Dec 2022 16:09:23 +0000 Subject: [PATCH 01/20] Remove "X-Requested-With" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When any app uses Android’s WebView to load a web page, WebView attaches an extra header, named X-Requested-With, with the value set to the application ID. That include Lightning-I2P browser by R4SAS. Google doesn’t want to make it easy to get rid of the X-Requested-With header. However, there is a mechanism for replacing header information. This doesn’t allow a program to stop sending the X-Requested-With header. More info on: https://www.stoutner.com/the-x-requested-with-header/ --- libi2pd_client/HTTPProxy.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index eb6d29b5..451c9c74 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -252,6 +252,7 @@ namespace proxy { req.RemoveHeader("From"); req.RemoveHeader("Forwarded"); req.RemoveHeader("DNT"); // Useless DoNotTrack flag + req.RemoveHeader("X-Requested-With"); // Android Webview send this with the value set to the application ID req.RemoveHeader("Accept", "Accept-Encoding"); // Accept*, but Accept-Encoding /* drop proxy-disclosing headers */ req.RemoveHeader("X-Forwarded"); From 629c7185277a9c9082e8ec224030a00fa3c00130 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 3 Dec 2022 14:18:40 -0500 Subject: [PATCH 02/20] fixed races condition with pending outgoing sessions --- libi2pd/SSU2.cpp | 7 +++++++ libi2pd/SSU2.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 4636762d..e1f75746 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -368,6 +368,7 @@ namespace transport bool SSU2Server::AddPendingOutgoingSession (std::shared_ptr session) { if (!session) return false; + std::unique_lock l(m_PendingOutgoingSessionsMutex); return m_PendingOutgoingSessions.emplace (session->GetRemoteEndpoint (), session).second; } @@ -381,6 +382,7 @@ namespace transport std::shared_ptr SSU2Server::FindPendingOutgoingSession (const boost::asio::ip::udp::endpoint& ep) const { + std::unique_lock l(m_PendingOutgoingSessionsMutex); auto it = m_PendingOutgoingSessions.find (ep); if (it != m_PendingOutgoingSessions.end ()) return it->second; @@ -389,6 +391,7 @@ namespace transport void SSU2Server::RemovePendingOutgoingSession (const boost::asio::ip::udp::endpoint& ep) { + std::unique_lock l(m_PendingOutgoingSessionsMutex); m_PendingOutgoingSessions.erase (ep); } @@ -510,7 +513,10 @@ namespace transport { if (it1->second->GetState () == eSSU2SessionStateSessionRequestSent && it1->second->ProcessSessionCreated (buf, len)) + { + std::unique_lock l(m_PendingOutgoingSessionsMutex); m_PendingOutgoingSessions.erase (it1); // we are done with that endpoint + } else it1->second->ProcessRetry (buf, len); } @@ -754,6 +760,7 @@ namespace transport if (it->second->IsTerminationTimeoutExpired (ts)) { //it->second->Terminate (); + std::unique_lock l(m_PendingOutgoingSessionsMutex); it = m_PendingOutgoingSessions.erase (it); } else diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index c5c2c140..ac4495db 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -10,6 +10,7 @@ #define SSU2_H__ #include +#include #include "util.h" #include "SSU2Session.h" @@ -140,6 +141,7 @@ namespace transport std::unordered_map > m_Sessions; std::unordered_map > m_SessionsByRouterHash; std::map > m_PendingOutgoingSessions; + mutable std::mutex m_PendingOutgoingSessionsMutex; std::map > m_IncomingTokens, m_OutgoingTokens; // remote endpoint -> (token, expires in seconds) std::map > m_Relays; // we are introducer, relay tag -> session std::list m_Introducers, m_IntroducersV6; // introducers we are connected to From 1ac171152a7981f4781d961802043d0a70b97ee0 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 3 Dec 2022 14:27:52 -0500 Subject: [PATCH 03/20] don't print error message if incomplete --- libi2pd/Gzip.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/libi2pd/Gzip.cpp b/libi2pd/Gzip.cpp index 07c6a96e..35676f5c 100644 --- a/libi2pd/Gzip.cpp +++ b/libi2pd/Gzip.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2022, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -57,7 +57,8 @@ namespace data if ((err = inflate (&m_Inflator, Z_NO_FLUSH)) == Z_STREAM_END) return outLen - m_Inflator.avail_out; // else - LogPrint (eLogError, "Gzip: Inflate error ", err); + if (err) + LogPrint (eLogError, "Gzip: Inflate error ", err); return 0; } } @@ -128,7 +129,8 @@ namespace data return outLen - m_Deflator.avail_out; } // else - LogPrint (eLogError, "Gzip: Deflate error ", err); + if (err) + LogPrint (eLogError, "Gzip: Deflate error ", err); return 0; } @@ -158,7 +160,8 @@ namespace data offset = outLen - m_Deflator.avail_out; } // else - LogPrint (eLogError, "Gzip: Deflate error ", err); + if (err) + LogPrint (eLogError, "Gzip: Deflate error ", err); return 0; } From 6589bdf6b59f1328c460ed15cb2b0d382250e7a7 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 3 Dec 2022 15:05:27 -0500 Subject: [PATCH 04/20] delete expired token right away --- libi2pd/SSU2.cpp | 18 ++++++++++++++---- libi2pd/SSU2.h | 2 +- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index e1f75746..adb27847 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -851,13 +851,17 @@ namespace transport m_OutgoingTokens[ep] = {token, exp}; } - uint64_t SSU2Server::FindOutgoingToken (const boost::asio::ip::udp::endpoint& ep) const + uint64_t SSU2Server::FindOutgoingToken (const boost::asio::ip::udp::endpoint& ep) { auto it = m_OutgoingTokens.find (ep); if (it != m_OutgoingTokens.end ()) { if (i2p::util::GetSecondsSinceEpoch () + SSU2_TOKEN_EXPIRATION_THRESHOLD > it->second.second) - return 0; // token expired + { + // token expired + m_OutgoingTokens.erase (it); + return 0; + } return it->second.first; } return 0; @@ -865,12 +869,18 @@ namespace transport uint64_t SSU2Server::GetIncomingToken (const boost::asio::ip::udp::endpoint& ep) { + auto ts = i2p::util::GetSecondsSinceEpoch (); auto it = m_IncomingTokens.find (ep); if (it != m_IncomingTokens.end ()) - return it->second.first; + { + if (ts + SSU2_TOKEN_EXPIRATION_THRESHOLD <= it->second.second) + return it->second.first; + else // token expired + m_IncomingTokens.erase (it); + } uint64_t token; RAND_bytes ((uint8_t *)&token, 8); - m_IncomingTokens.emplace (ep, std::make_pair (token, i2p::util::GetSecondsSinceEpoch () + SSU2_TOKEN_EXPIRATION_TIMEOUT)); + m_IncomingTokens.emplace (ep, std::make_pair (token, ts + SSU2_TOKEN_EXPIRATION_TIMEOUT)); return token; } diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index ac4495db..13607c29 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -89,7 +89,7 @@ namespace transport bool StartPeerTest (std::shared_ptr router, bool v4); void UpdateOutgoingToken (const boost::asio::ip::udp::endpoint& ep, uint64_t token, uint32_t exp); - uint64_t FindOutgoingToken (const boost::asio::ip::udp::endpoint& ep) const; + uint64_t FindOutgoingToken (const boost::asio::ip::udp::endpoint& ep); uint64_t GetIncomingToken (const boost::asio::ip::udp::endpoint& ep); std::pair NewIncomingToken (const boost::asio::ip::udp::endpoint& ep); From 8db352b4d08af6b0a92b27edc76d69f28db0a588 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 4 Dec 2022 16:30:45 -0500 Subject: [PATCH 05/20] recognize symmetric NAT from peer test msg 7 --- libi2pd/SSU2Session.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 315d39b6..7b92a93c 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1656,13 +1656,23 @@ namespace transport { if (isV4) { - if (i2p::context.GetStatus () == eRouterStatusTesting) + if (i2p::context.GetStatus () == eRouterStatusTesting || + m_State == eSSU2SessionStatePeerTest) + { i2p::context.SetError (eRouterErrorSymmetricNAT); + i2p::context.SetStatus (eRouterStatusFirewalled); + m_Server.RescheduleIntroducersUpdateTimer (); + } } else { - if (i2p::context.GetStatusV6 () == eRouterStatusTesting) + if (i2p::context.GetStatusV6 () == eRouterStatusTesting || + m_State == eSSU2SessionStatePeerTest) + { i2p::context.SetErrorV6 (eRouterErrorSymmetricNAT); + i2p::context.SetStatusV6 (eRouterStatusFirewalled); + m_Server.RescheduleIntroducersUpdateTimerV6 (); + } } } else From 50abeea82a9f19b61bd9b91cf926c539c4a7cea1 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 4 Dec 2022 17:08:38 -0500 Subject: [PATCH 06/20] print endpoint if more than two fragments of SessionConfirmed --- libi2pd/SSU2Session.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 7b92a93c..71d4dd81 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -878,7 +878,7 @@ namespace transport // fragmented if (numFragments > 2) { - LogPrint (eLogError, "SSU2: Too many fragments ", numFragments, " in SessionConfirmed"); + LogPrint (eLogError, "SSU2: Too many fragments ", (int)numFragments, " in SessionConfirmed from ", m_RemoteEndpoint); return false; } if (len < 32) From cb73c7c72e6f955c98f01d79dadb4c4bc54fcecf Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 4 Dec 2022 17:43:29 -0500 Subject: [PATCH 07/20] make sure that only *Mt method can be called for MemoryPoolMt --- libi2pd/util.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/util.h b/libi2pd/util.h index 9420060b..248c2bad 100644 --- a/libi2pd/util.h +++ b/libi2pd/util.h @@ -112,7 +112,7 @@ namespace util }; template - class MemoryPoolMt: public MemoryPool + class MemoryPoolMt: private MemoryPool { public: From 709c4514008091491bc7de7d24333874a8cb6b1f Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 4 Dec 2022 17:49:59 -0500 Subject: [PATCH 08/20] disable MemoryPool for RouterInfo's address --- libi2pd/NetDb.cpp | 2 +- libi2pd/NetDb.hpp | 4 ++-- libi2pd/RouterInfo.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 7dd32e30..e69de0d5 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -649,7 +649,7 @@ namespace data } // m_RouterInfos iteration m_RouterInfoBuffersPool.CleanUpMt (); - m_RouterInfoAddressesPool.CleanUpMt (); + // m_RouterInfoAddressesPool.CleanUpMt (); if (updatedCount > 0) LogPrint (eLogInfo, "NetDb: Saved ", updatedCount, " new/updated routers"); diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index 8edf8af2..312792e5 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -123,7 +123,7 @@ namespace data void ClearRouterInfos () { m_RouterInfos.clear (); }; std::shared_ptr NewRouterInfoBuffer () { return m_RouterInfoBuffersPool.AcquireSharedMt (); }; void PopulateRouterInfoBuffer (std::shared_ptr r); - std::shared_ptr NewRouterInfoAddress () { return m_RouterInfoAddressesPool.AcquireSharedMt (); }; + //std::shared_ptr NewRouterInfoAddress () { return m_RouterInfoAddressesPool.AcquireSharedMt (); }; std::shared_ptr NewLease (const Lease& lease) { return m_LeasesPool.AcquireSharedMt (lease); }; uint32_t GetPublishReplyToken () const { return m_PublishReplyToken; }; @@ -181,7 +181,7 @@ namespace data uint32_t m_PublishReplyToken = 0; i2p::util::MemoryPoolMt m_RouterInfoBuffersPool; - i2p::util::MemoryPoolMt m_RouterInfoAddressesPool; + //i2p::util::MemoryPoolMt m_RouterInfoAddressesPool; i2p::util::MemoryPoolMt m_LeasesPool; }; diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 580d1f74..270e86c2 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -212,7 +212,7 @@ namespace data for (int i = 0; i < numAddresses; i++) { uint8_t supportedTransports = 0; - auto address = netdb.NewRouterInfoAddress (); + auto address = std::make_shared
(); // netdb.NewRouterInfoAddress (); uint8_t cost; // ignore s.read ((char *)&cost, sizeof (cost)); s.read ((char *)&address->date, sizeof (address->date)); From 6a743f66e89fa58d242ba5e2585cc7dd20d37b1e Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 4 Dec 2022 17:52:44 -0500 Subject: [PATCH 09/20] eliminate RTT self-reduction --- libi2pd/Streaming.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 9ba236d7..5b4468fd 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -435,7 +435,7 @@ namespace stream LogPrint(eLogError, "Streaming: Packet ", seqn, "sent from the future, sendTime=", sentPacket->sendTime); rtt = 1; } - m_RTT = (m_RTT*seqn + rtt)/(seqn + 1); + m_RTT = std::round ((m_RTT*seqn + rtt)/(seqn + 1.0)); m_RTO = m_RTT*1.5; // TODO: implement it better LogPrint (eLogDebug, "Streaming: Packet ", seqn, " acknowledged rtt=", rtt, " sentTime=", sentPacket->sendTime); m_SentPackets.erase (it++); From 410d2c2fa95a921921ad0e8886c52d4144116df7 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 4 Dec 2022 19:21:51 -0500 Subject: [PATCH 10/20] use shared pointer for RouterInfo's addreses list --- daemon/HTTPServer.cpp | 63 ++++++++------- libi2pd/NTCP2.cpp | 5 +- libi2pd/RouterContext.cpp | 162 ++++++++++++++++++++++---------------- libi2pd/RouterInfo.cpp | 26 ++++-- libi2pd/RouterInfo.h | 3 +- libi2pd/SSU2.cpp | 5 +- 6 files changed, 156 insertions(+), 108 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 77254e61..374b1d29 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -299,44 +299,49 @@ namespace http { if ((outputFormat == OutputFormatEnum::forWebConsole) || !includeHiddenContent) { s << "\r\n\r\n
\r\n"; } - if (includeHiddenContent) { + if (includeHiddenContent) + { s << "" << tr("Router Ident") << ": " << i2p::context.GetRouterInfo().GetIdentHashBase64() << "
\r\n"; if (!i2p::context.GetRouterInfo().GetProperty("family").empty()) s << "" << tr("Router Family") << ": " << i2p::context.GetRouterInfo().GetProperty("family") << "
\r\n"; s << "" << tr("Router Caps") << ": " << i2p::context.GetRouterInfo().GetProperty("caps") << "
\r\n"; s << "" << tr("Version") << ": " VERSION "
\r\n"; s << ""<< tr("Our external address") << ":" << "
\r\n\r\n"; - for (const auto& address : i2p::context.GetRouterInfo().GetAddresses()) - { - s << "\r\n\r\n"; - if (address->published) - s << "\r\n"; - else - { - s << "\r\n\r\n"; + if (address->published) + s << "\r\n"; + else + { + s << "\r\n"; + } + s << "\r\n"; } - s << "\r\n"; - } + } s << "
"; - switch (address->transportStyle) + auto addresses = i2p::context.GetRouterInfo().GetAddresses (); + if (addresses) + { + for (const auto& address : *addresses) { - case i2p::data::RouterInfo::eTransportNTCP2: - s << "NTCP2"; - break; - case i2p::data::RouterInfo::eTransportSSU2: - s << "SSU2"; - break; - default: - s << tr("Unknown"); - } - if (address->IsV6 ()) - { - if (address->IsV4 ()) s << "v4"; - s << "v6"; - } - s << "" << address->host.to_string() << ":" << address->port << "" << tr("supported"); - if (address->port) - s << " :" << address->port; + s << "
"; + switch (address->transportStyle) + { + case i2p::data::RouterInfo::eTransportNTCP2: + s << "NTCP2"; + break; + case i2p::data::RouterInfo::eTransportSSU2: + s << "SSU2"; + break; + default: + s << tr("Unknown"); + } + if (address->IsV6 ()) + { + if (address->IsV4 ()) s << "v4"; + s << "v6"; + } s << "" << address->host.to_string() << ":" << address->port << "" << tr("supported"); + if (address->port) + s << " :" << address->port; + s << "
\r\n"; } s << "
\r\n\r\n"; diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 37553ceb..953fe333 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1210,8 +1210,9 @@ namespace transport else LogPrint(eLogInfo, "NTCP2: Proxy is not used"); // start acceptors - auto& addresses = context.GetRouterInfo ().GetAddresses (); - for (const auto& address: addresses) + auto addresses = context.GetRouterInfo ().GetAddresses (); + if (!addresses) return; + for (const auto& address: *addresses) { if (!address) continue; if (address->IsPublishedNTCP2 () && address->port) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index c8000e2e..8928fc7f 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -267,8 +267,10 @@ namespace i2p void RouterContext::UpdatePort (int port) { + auto addresses = m_RouterInfo.GetAddresses (); + if (!addresses) return; bool updated = false; - for (auto& address : m_RouterInfo.GetAddresses ()) + for (auto& address : *addresses) { if (address->port != port && address->transportStyle == i2p::data::RouterInfo::eTransportSSU2) { @@ -283,8 +285,10 @@ namespace i2p void RouterContext::PublishNTCP2Address (int port, bool publish, bool v4, bool v6, bool ygg) { if (!m_NTCP2Keys) return; + auto addresses = m_RouterInfo.GetAddresses (); + if (!addresses) return; bool updated = false; - for (auto& address : m_RouterInfo.GetAddresses ()) + for (auto& address : *addresses) { if (address->IsNTCP2 () && (address->port != port || address->published != publish)) { @@ -312,9 +316,10 @@ namespace i2p void RouterContext::UpdateNTCP2Address (bool enable) { - auto& addresses = m_RouterInfo.GetAddresses (); + auto addresses = m_RouterInfo.GetAddresses (); + if (!addresses) return; bool found = false, updated = false; - for (auto it = addresses.begin (); it != addresses.end ();) + for (auto it = addresses->begin (); it != addresses->end ();) { if ((*it)->IsNTCP2 ()) { @@ -326,7 +331,7 @@ namespace i2p it++; } else - it = addresses.erase (it); + it = addresses->erase (it); updated = true; } else @@ -344,10 +349,12 @@ namespace i2p void RouterContext::PublishSSU2Address (int port, bool publish, bool v4, bool v6) { if (!m_SSU2Keys) return; + auto addresses = m_RouterInfo.GetAddresses (); + if (!addresses) return; int newPort = 0; if (!port) { - for (const auto& address : m_RouterInfo.GetAddresses ()) + for (const auto& address : *addresses) if (address->port) { newPort = address->port; @@ -356,7 +363,7 @@ namespace i2p if (!newPort) newPort = SelectRandomPort (); } bool updated = false; - for (auto& address : m_RouterInfo.GetAddresses ()) + for (auto& address : *addresses) { if (address->IsSSU2 () && (!address->port || address->port != port || address->published != publish) && ((v4 && address->IsV4 ()) || (v6 && address->IsV6 ()))) @@ -377,9 +384,10 @@ namespace i2p void RouterContext::UpdateSSU2Address (bool enable) { - auto& addresses = m_RouterInfo.GetAddresses (); + auto addresses = m_RouterInfo.GetAddresses (); + if (!addresses) return; bool found = false, updated = false; - for (auto it = addresses.begin (); it != addresses.end ();) + for (auto it = addresses->begin (); it != addresses->end ();) { if ((*it)->IsSSU2 ()) { @@ -391,7 +399,7 @@ namespace i2p it++; } else - it = addresses.erase (it); + it = addresses->erase (it); updated = true; } else @@ -422,8 +430,10 @@ namespace i2p void RouterContext::UpdateAddress (const boost::asio::ip::address& host) { + auto addresses = m_RouterInfo.GetAddresses (); + if (!addresses) return; bool updated = false; - for (auto& address : m_RouterInfo.GetAddresses ()) + for (auto& address : *addresses) { if (address->host != host && address->IsCompatible (host) && !i2p::util::net::IsYggdrasilAddress (address->host)) @@ -472,9 +482,10 @@ namespace i2p void RouterContext::ClearSSU2Introducers (bool v4) { + auto addresses = m_RouterInfo.GetAddresses (); + if (!addresses) return; bool updated = false; - auto& addresses = m_RouterInfo.GetAddresses (); - for (auto& addr : addresses) + for (auto& addr : *addresses) if (addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())) && addr->ssu && !addr->ssu->introducers.empty ()) { @@ -597,15 +608,18 @@ namespace i2p } uint16_t port = 0; // delete previous introducers - auto& addresses = m_RouterInfo.GetAddresses (); - for (auto& addr : addresses) - if (addr->ssu && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ()))) - { - addr->published = false; - addr->caps &= ~i2p::data::RouterInfo::eSSUIntroducer; // can't be introducer - addr->ssu->introducers.clear (); - port = addr->port; - } + auto addresses = m_RouterInfo.GetAddresses (); + if (addresses) + { + for (auto& addr : *addresses) + if (addr->ssu && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ()))) + { + addr->published = false; + addr->caps &= ~i2p::data::RouterInfo::eSSUIntroducer; // can't be introducer + addr->ssu->introducers.clear (); + port = addr->port; + } + } // unpublish NTCP2 addreeses bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); if (ntcp2) @@ -630,15 +644,18 @@ namespace i2p uint16_t port = 0; // delete previous introducers bool isSSU2Published; i2p::config::GetOption ("ssu2.published", isSSU2Published); - auto& addresses = m_RouterInfo.GetAddresses (); - for (auto& addr : addresses) - if (addr->ssu && isSSU2Published && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ()))) - { - addr->published = true; - addr->caps |= i2p::data::RouterInfo::eSSUIntroducer; - addr->ssu->introducers.clear (); - if (addr->port) port = addr->port; - } + auto addresses = m_RouterInfo.GetAddresses (); + if (addresses) + { + for (auto& addr : *addresses) + if (addr->ssu && isSSU2Published && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ()))) + { + addr->published = true; + addr->caps |= i2p::data::RouterInfo::eSSUIntroducer; + addr->ssu->introducers.clear (); + if (addr->port) port = addr->port; + } + } // publish NTCP2 bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); if (ntcp2) @@ -663,23 +680,26 @@ namespace i2p // insert v6 addresses if necessary bool foundNTCP2 = false, foundSSU2 = false; uint16_t port = 0; - auto& addresses = m_RouterInfo.GetAddresses (); - for (auto& addr: addresses) + auto addresses = m_RouterInfo.GetAddresses (); + if (addresses) { - if (addr->IsV6 () && !i2p::util::net::IsYggdrasilAddress (addr->host)) + for (auto& addr: *addresses) { - switch (addr->transportStyle) + if (addr->IsV6 () && !i2p::util::net::IsYggdrasilAddress (addr->host)) { - case i2p::data::RouterInfo::eTransportNTCP2: - foundNTCP2 = true; - break; - case i2p::data::RouterInfo::eTransportSSU2: - foundSSU2 = true; - break; - default: ; + switch (addr->transportStyle) + { + case i2p::data::RouterInfo::eTransportNTCP2: + foundNTCP2 = true; + break; + case i2p::data::RouterInfo::eTransportSSU2: + foundSSU2 = true; + break; + default: ; + } } + port = addr->port; } - port = addr->port; } if (!port) { @@ -743,24 +763,27 @@ namespace i2p bool foundNTCP2 = false, foundSSU2 = false; std::string host = "127.0.0.1"; uint16_t port = 0; - auto& addresses = m_RouterInfo.GetAddresses (); - for (auto& addr: addresses) + auto addresses = m_RouterInfo.GetAddresses (); + if (addresses) { - if (addr->IsV4 ()) + for (auto& addr: *addresses) { - switch (addr->transportStyle) + if (addr->IsV4 ()) { - case i2p::data::RouterInfo::eTransportNTCP2: - foundNTCP2 = true; - break; - case i2p::data::RouterInfo::eTransportSSU2: - foundSSU2 = true; - break; - default: ; + switch (addr->transportStyle) + { + case i2p::data::RouterInfo::eTransportNTCP2: + foundNTCP2 = true; + break; + case i2p::data::RouterInfo::eTransportSSU2: + foundSSU2 = true; + break; + default: ; + } } + if (addr->port) port = addr->port; } - if (addr->port) port = addr->port; - } + } if (!port) { i2p::config::GetOption("port", port); @@ -816,16 +839,19 @@ namespace i2p i2p::config::GetOption ("ntcp2.port", port); if (!port) i2p::config::GetOption("port", port); bool foundMesh = false; - auto& addresses = m_RouterInfo.GetAddresses (); - for (auto& addr: addresses) + auto addresses = m_RouterInfo.GetAddresses (); + if (addresses) { - if (!port) port = addr->port; - if (i2p::util::net::IsYggdrasilAddress (addr->host)) + for (auto& addr: *addresses) { - foundMesh = true; - break; + if (!port) port = addr->port; + if (i2p::util::net::IsYggdrasilAddress (addr->host)) + { + foundMesh = true; + break; + } } - } + } if (!foundMesh) m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, host, port); } @@ -837,8 +863,9 @@ namespace i2p void RouterContext::SetMTU (int mtu, bool v4) { if (mtu < 1280 || mtu > 1500) return; - auto& addresses = m_RouterInfo.GetAddresses (); - for (auto& addr: addresses) + auto addresses = m_RouterInfo.GetAddresses (); + if (!addresses) return; + for (auto& addr: *addresses) { if (addr->ssu && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ()))) { @@ -852,8 +879,9 @@ namespace i2p { bool isYgg = i2p::util::net::IsYggdrasilAddress (host); bool updated = false; - auto& addresses = m_RouterInfo.GetAddresses (); - for (auto& addr: addresses) + auto addresses = m_RouterInfo.GetAddresses (); + if (!addresses) return; + for (auto& addr: *addresses) { if (addr->IsPublishedNTCP2 ()) { diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 270e86c2..7ca72a63 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -826,6 +826,15 @@ namespace data return nullptr; } + boost::shared_ptr RouterInfo::GetAddresses () const + { +#if (BOOST_VERSION >= 105300) + return boost::atomic_load (&m_Addresses); +#else + return m_Addresses; +#endif + } + template std::shared_ptr RouterInfo::GetAddress (Filter filter) const { @@ -1048,14 +1057,15 @@ namespace data void LocalRouterInfo::WriteToStream (std::ostream& s) const { + auto addresses = GetAddresses (); + if (!addresses) return; + uint64_t ts = htobe64 (GetTimestamp ()); s.write ((const char *)&ts, sizeof (ts)); - // addresses - const Addresses& addresses = GetAddresses (); - uint8_t numAddresses = addresses.size (); + uint8_t numAddresses = addresses->size (); s.write ((char *)&numAddresses, sizeof (numAddresses)); - for (const auto& addr_ptr : addresses) + for (const auto& addr_ptr : *addresses) { const Address& address = *addr_ptr; // calculate cost @@ -1257,7 +1267,9 @@ namespace data bool LocalRouterInfo::AddSSU2Introducer (const Introducer& introducer, bool v4) { - for (auto& addr : GetAddresses ()) + auto addresses = GetAddresses (); + if (!addresses) return false; + for (auto& addr : *addresses) { if (addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ()))) { @@ -1273,7 +1285,9 @@ namespace data bool LocalRouterInfo::RemoveSSU2Introducer (const IdentHash& h, bool v4) { - for (auto& addr: GetAddresses ()) + auto addresses = GetAddresses (); + if (!addresses) return false; + for (auto& addr: *addresses) { if (addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ()))) { diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 6e122d95..18e2b336 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -176,7 +176,7 @@ namespace data int GetVersion () const { return m_Version; }; virtual void SetProperty (const std::string& key, const std::string& value) {}; virtual void ClearProperties () {}; - Addresses& GetAddresses () { return *m_Addresses; }; // should be called for local RI only, otherwise must return shared_ptr + boost::shared_ptr GetAddresses () const; // should be called for local RI only, otherwise must return shared_ptr std::shared_ptr GetNTCP2AddressWithStaticKey (const uint8_t * key) const; std::shared_ptr GetSSU2AddressWithStaticKey (const uint8_t * key, bool isV6) const; std::shared_ptr GetPublishedNTCP2V4Address () const; @@ -258,7 +258,6 @@ namespace data void UpdateBuffer (const uint8_t * buf, size_t len); void SetBufferLen (size_t len) { m_BufferLen = len; }; void RefreshTimestamp (); - const Addresses& GetAddresses () const { return *m_Addresses; }; CompatibleTransports GetReachableTransports () const { return m_ReachableTransports; }; void SetReachableTransports (CompatibleTransports transports) { m_ReachableTransports = transports; }; diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index adb27847..dba29fff 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -36,8 +36,9 @@ namespace transport i2p::config::GetOption ("ssu2.published", m_IsPublished); i2p::config::GetOption("nettime.frompeers", m_IsSyncClockFromPeers); bool found = false; - auto& addresses = i2p::context.GetRouterInfo ().GetAddresses (); - for (const auto& address: addresses) + auto addresses = i2p::context.GetRouterInfo ().GetAddresses (); + if (!addresses) return; + for (const auto& address: *addresses) { if (!address) continue; if (address->transportStyle == i2p::data::RouterInfo::eTransportSSU2) From d0d0cd8445f2b805df763605a15f4b45148ff22c Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 4 Dec 2022 20:04:06 -0500 Subject: [PATCH 11/20] use shared pointer for RouterInfo's addreses list --- daemon/UPnP.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/daemon/UPnP.cpp b/daemon/UPnP.cpp index e48532b0..9230aeb2 100644 --- a/daemon/UPnP.cpp +++ b/daemon/UPnP.cpp @@ -159,8 +159,9 @@ namespace transport void UPnP::PortMapping () { - const auto& a = context.GetRouterInfo().GetAddresses(); - for (const auto& address : a) + auto a = context.GetRouterInfo().GetAddresses(); + if (!a) return; + for (const auto& address : *a) { if (!address->host.is_v6 () && address->port) TryPortMapping (address); @@ -210,8 +211,9 @@ namespace transport void UPnP::CloseMapping () { - const auto& a = context.GetRouterInfo().GetAddresses(); - for (const auto& address : a) + const a = context.GetRouterInfo().GetAddresses(); + if (!a) return; + for (const auto& address : *a) { if (!address->host.is_v6 () && address->port) CloseMapping (address); From 753c7efde8c44b4d3cc601c865191aae8efd5bae Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 4 Dec 2022 21:12:48 -0500 Subject: [PATCH 12/20] fixed build error --- daemon/UPnP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemon/UPnP.cpp b/daemon/UPnP.cpp index 9230aeb2..b7182055 100644 --- a/daemon/UPnP.cpp +++ b/daemon/UPnP.cpp @@ -211,7 +211,7 @@ namespace transport void UPnP::CloseMapping () { - const a = context.GetRouterInfo().GetAddresses(); + auto a = context.GetRouterInfo().GetAddresses(); if (!a) return; for (const auto& address : *a) { From 2bb5ff7184892051d3cf21bfdddb2ff3461fa6ba Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 5 Dec 2022 15:48:11 -0500 Subject: [PATCH 13/20] eliminate RTT self-reduction --- libi2pd/SSU2Session.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 71d4dd81..faf4e08a 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1623,7 +1623,7 @@ namespace transport if (ts > it1->second->sendTime) { auto rtt = ts - it1->second->sendTime; - m_RTT = (m_RTT*m_SendPacketNum + rtt)/(m_SendPacketNum + 1); + m_RTT = std::round ((m_RTT*m_SendPacketNum + rtt)/(m_SendPacketNum + 1.0)); m_RTO = m_RTT*SSU2_kAPPA; if (m_RTO < SSU2_MIN_RTO) m_RTO = SSU2_MIN_RTO; if (m_RTO > SSU2_MAX_RTO) m_RTO = SSU2_MAX_RTO; From 8ad5696e50e4851097235dd08b46a608ed80c115 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 6 Dec 2022 21:40:33 -0500 Subject: [PATCH 14/20] don't send termination again if termination received block received --- libi2pd/SSU2.cpp | 3 ++- libi2pd/SSU2Session.cpp | 15 +++++++++++---- libi2pd/SSU2Session.h | 1 + 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index dba29fff..f4fdfa04 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -496,9 +496,10 @@ namespace transport break; case eSSU2SessionStateClosing: m_LastSession->ProcessData (buf, len, senderEndpoint); // we might receive termintaion block - if (m_LastSession && m_LastSession->GetState () != eSSU2SessionStateTerminated) + if (m_LastSession && m_LastSession->GetState () == eSSU2SessionStateClosing) m_LastSession->RequestTermination (eSSU2TerminationReasonIdleTimeout); // send termination again break; + case eSSU2SessionStateClosingConfirmed: case eSSU2SessionStateTerminated: m_LastSession = nullptr; break; diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index faf4e08a..ac184506 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -1462,12 +1462,19 @@ namespace transport m_IsDataReceived = true; break; case eSSU2BlkTermination: - LogPrint (eLogDebug, "SSU2: Termination reason=", (int)buf[11]); - if (IsEstablished () && buf[11] != eSSU2TerminationReasonTerminationReceived) + { + uint8_t rsn = buf[11]; // reason + LogPrint (eLogDebug, "SSU2: Termination reason=", (int)rsn); + if (IsEstablished () && rsn != eSSU2TerminationReasonTerminationReceived) RequestTermination (eSSU2TerminationReasonTerminationReceived); - else + else if (m_State != eSSU2SessionStateTerminated) + { + if (m_State == eSSU2SessionStateClosing && rsn == eSSU2TerminationReasonTerminationReceived) + m_State = eSSU2SessionStateClosingConfirmed; Done (); - break; + } + break; + } case eSSU2BlkRelayRequest: LogPrint (eLogDebug, "SSU2: RelayRequest"); HandleRelayRequest (buf + offset, size); diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index a8c473a2..d12395d6 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -100,6 +100,7 @@ namespace transport eSSU2SessionStateSessionConfirmedSent, eSSU2SessionStateEstablished, eSSU2SessionStateClosing, + eSSU2SessionStateClosingConfirmed, eSSU2SessionStateTerminated, eSSU2SessionStateFailed, eSSU2SessionStateIntroduced, From 53ca5dc67a92ae0e334f23b084e55533245a3354 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 7 Dec 2022 14:08:27 -0500 Subject: [PATCH 15/20] memory pool for address vectors --- libi2pd/NetDb.cpp | 3 ++- libi2pd/NetDb.hpp | 12 ++++++++++-- libi2pd/RouterInfo.cpp | 14 ++++++-------- libi2pd/RouterInfo.h | 2 +- 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index e69de0d5..bf9d60de 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -649,7 +649,8 @@ namespace data } // m_RouterInfos iteration m_RouterInfoBuffersPool.CleanUpMt (); - // m_RouterInfoAddressesPool.CleanUpMt (); + m_RouterInfoAddressesPool.CleanUpMt (); + m_RouterInfoAddressVectorsPool.CleanUpMt (); if (updatedCount > 0) LogPrint (eLogInfo, "NetDb: Saved ", updatedCount, " new/updated routers"); diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index 312792e5..98b5fd86 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -123,7 +123,14 @@ namespace data void ClearRouterInfos () { m_RouterInfos.clear (); }; std::shared_ptr NewRouterInfoBuffer () { return m_RouterInfoBuffersPool.AcquireSharedMt (); }; void PopulateRouterInfoBuffer (std::shared_ptr r); - //std::shared_ptr NewRouterInfoAddress () { return m_RouterInfoAddressesPool.AcquireSharedMt (); }; + std::shared_ptr NewRouterInfoAddress () { return m_RouterInfoAddressesPool.AcquireSharedMt (); }; + boost::shared_ptr NewRouterInfoAddresses () + { + return boost::shared_ptr(m_RouterInfoAddressVectorsPool.AcquireMt (), + std::bind ::*)(RouterInfo::Addresses *)> + (&i2p::util::MemoryPoolMt::ReleaseMt, + &m_RouterInfoAddressVectorsPool, std::placeholders::_1)); + }; std::shared_ptr NewLease (const Lease& lease) { return m_LeasesPool.AcquireSharedMt (lease); }; uint32_t GetPublishReplyToken () const { return m_PublishReplyToken; }; @@ -181,7 +188,8 @@ namespace data uint32_t m_PublishReplyToken = 0; i2p::util::MemoryPoolMt m_RouterInfoBuffersPool; - //i2p::util::MemoryPoolMt m_RouterInfoAddressesPool; + i2p::util::MemoryPoolMt m_RouterInfoAddressesPool; + i2p::util::MemoryPoolMt m_RouterInfoAddressVectorsPool; i2p::util::MemoryPoolMt m_LeasesPool; }; diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 7ca72a63..13a0731e 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -206,13 +206,14 @@ namespace data s.read ((char *)&m_Timestamp, sizeof (m_Timestamp)); m_Timestamp = be64toh (m_Timestamp); // read addresses - if (!m_NewAddresses) m_NewAddresses = boost::make_shared(); + auto addresses = netdb.NewRouterInfoAddresses (); uint8_t numAddresses; s.read ((char *)&numAddresses, sizeof (numAddresses)); + addresses->reserve (numAddresses); for (int i = 0; i < numAddresses; i++) { uint8_t supportedTransports = 0; - auto address = std::make_shared
(); // netdb.NewRouterInfoAddress (); + auto address = netdb.NewRouterInfoAddress (); uint8_t cost; // ignore s.read ((char *)&cost, sizeof (cost)); s.read ((char *)&address->date, sizeof (address->date)); @@ -417,19 +418,16 @@ namespace data if (supportedTransports) { if (!(m_SupportedTransports & supportedTransports)) // avoid duplicates - m_NewAddresses->push_back(address); + addresses->push_back(address); m_SupportedTransports |= supportedTransports; } } // update addresses - auto prev = m_Addresses; #if (BOOST_VERSION >= 105300) - boost::atomic_store (&m_Addresses, m_NewAddresses); + boost::atomic_store (&m_Addresses, addresses); #else - m_Addresses = m_NewAddresses; // race condition + m_Addresses = addresses; // race condition #endif - if (prev) prev->clear (); - m_NewAddresses = prev; // read peers uint8_t numPeers; s.read ((char *)&numPeers, sizeof (numPeers)); if (!s) return; diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 18e2b336..9e98769f 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -281,7 +281,7 @@ namespace data std::shared_ptr m_Buffer; size_t m_BufferLen; uint64_t m_Timestamp; - boost::shared_ptr m_Addresses, m_NewAddresses; // TODO: use std::shared_ptr and std::atomic_store for gcc >= 4.9 + 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; uint8_t m_Caps; From 737603e81b9b33b1b25fb4a501930dcfffb50016 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 10 Dec 2022 13:22:37 -0500 Subject: [PATCH 16/20] No descriptors error --- daemon/HTTPServer.cpp | 3 +++ libi2pd/NTCP2.cpp | 22 ++++++++++++++++++++-- libi2pd/RouterContext.h | 3 ++- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 374b1d29..27cbcd78 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -248,6 +248,9 @@ namespace http { case eRouterErrorSymmetricNAT: s << " - " << tr("Symmetric NAT"); break; + case eRouterErrorNoDescriptors: + s << " - " << tr("No Descriptors"); + break; default: ; } } diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 953fe333..109f8b88 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1425,10 +1425,18 @@ namespace transport LogPrint (eLogError, "NTCP2: Connected from error ", ec.message ()); } else + { LogPrint (eLogError, "NTCP2: Accept error ", error.message ()); - + if (error == boost::asio::error::no_descriptors) + { + i2p::context.SetError (eRouterErrorNoDescriptors); + // TODO + return; + } + } + if (error != boost::asio::error::operation_aborted) - { + { if (!conn) // connection is used, create new one conn = std::make_shared (*this); else // reuse failed @@ -1457,6 +1465,16 @@ namespace transport else LogPrint (eLogError, "NTCP2: Connected from error ", ec.message ()); } + else + { + LogPrint (eLogError, "NTCP2: Accept ipv6 error ", error.message ()); + if (error == boost::asio::error::no_descriptors) + { + i2p::context.SetErrorV6 (eRouterErrorNoDescriptors); + // TODO + return; + } + } if (error != boost::asio::error::operation_aborted) { diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index f115f026..dd7f0272 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -47,7 +47,8 @@ namespace garlic eRouterErrorNone = 0, eRouterErrorClockSkew = 1, eRouterErrorOffline = 2, - eRouterErrorSymmetricNAT = 3 + eRouterErrorSymmetricNAT = 3, + eRouterErrorNoDescriptors = 4 }; class RouterContext: public i2p::garlic::GarlicDestination From 857df5c7341353e8b18af812829797c4da3ccb84 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sat, 10 Dec 2022 21:57:23 +0300 Subject: [PATCH 17/20] prevent log spamming with no_descriptors error Signed-off-by: R4SAS --- daemon/HTTPServer.cpp | 2 +- libi2pd/NTCP2.cpp | 53 +++++++++++++++++++++++-------------------- libi2pd/NTCP2.h | 4 ++++ 3 files changed, 34 insertions(+), 25 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 27cbcd78..7a6c5c12 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -250,7 +250,7 @@ namespace http { break; case eRouterErrorNoDescriptors: s << " - " << tr("No Descriptors"); - break; + break; default: ; } } diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 109f8b88..555a5622 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1424,19 +1424,20 @@ namespace transport else LogPrint (eLogError, "NTCP2: Connected from error ", ec.message ()); } - else - { - LogPrint (eLogError, "NTCP2: Accept error ", error.message ()); - if (error == boost::asio::error::no_descriptors) + else if (error == boost::asio::error::no_descriptors) + { + i2p::context.SetError (eRouterErrorNoDescriptors); + if (m_NoFileExhaustTimestamp < i2p::util::GetSecondsSinceEpoch () - NTCP2_DESCRIPTORS_EXHAUST_TIMEOUT) { - i2p::context.SetError (eRouterErrorNoDescriptors); - // TODO - return; - } - } - + m_NoFileExhaustTimestamp = i2p::util::GetSecondsSinceEpoch (); + LogPrint (eLogWarning, "NTCP2: WARNING! i2pd met file descriptors exhaustion! Please check your nofile limits!"); + } + } + else + LogPrint (eLogError, "NTCP2: Accept error ", error.message ()); + if (error != boost::asio::error::operation_aborted) - { + { if (!conn) // connection is used, create new one conn = std::make_shared (*this); else // reuse failed @@ -1463,22 +1464,26 @@ namespace transport } } else - LogPrint (eLogError, "NTCP2: Connected from error ", ec.message ()); + LogPrint (eLogError, "NTCP2: Connected from ipv6 error: ", ec.message ()); + } + else if (error == boost::asio::error::no_descriptors) + { + i2p::context.SetErrorV6 (eRouterErrorNoDescriptors); + if (m_NoFileExhaustTimestamp < i2p::util::GetSecondsSinceEpoch () - NTCP2_DESCRIPTORS_EXHAUST_TIMEOUT) + { + m_NoFileExhaustTimestamp = i2p::util::GetSecondsSinceEpoch (); + LogPrint (eLogWarning, "NTCP2: WARNING! i2pd met file descriptors exhaustion! Please check your nofile limits!"); + } } else - { - LogPrint (eLogError, "NTCP2: Accept ipv6 error ", error.message ()); - if (error == boost::asio::error::no_descriptors) - { - i2p::context.SetErrorV6 (eRouterErrorNoDescriptors); - // TODO - return; - } - } + LogPrint (eLogError, "NTCP2: Accept ipv6 error: ", error.message ()); if (error != boost::asio::error::operation_aborted) { - conn = std::make_shared (*this); + if (!conn) // connection is used, create new one + conn = std::make_shared (*this); + else // reuse failed + conn->Close (); m_NTCP2V6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAcceptV6, this, conn, std::placeholders::_1)); } @@ -1728,7 +1733,7 @@ namespace transport }); 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(), + boost::asio::transfer_all(), [timer, conn, sz, readbuff](const boost::system::error_code & e, std::size_t transferred) { if (e) @@ -1736,7 +1741,7 @@ namespace transport else if (!(*readbuff)[1]) // succeeded { boost::system::error_code ec; - size_t moreBytes = conn->GetSocket ().available(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(); diff --git a/libi2pd/NTCP2.h b/libi2pd/NTCP2.h index 754f5a6d..c8c86e5d 100644 --- a/libi2pd/NTCP2.h +++ b/libi2pd/NTCP2.h @@ -43,6 +43,8 @@ namespace transport const int NTCP2_CLOCK_SKEW = 60; // in seconds const int NTCP2_MAX_OUTGOING_QUEUE_SIZE = 500; // how many messages we can queue up + const int NTCP2_DESCRIPTORS_EXHAUST_TIMEOUT = 60; // 1 minute + enum NTCP2BlockType { eNTCP2BlkDateTime = 0, @@ -286,6 +288,8 @@ namespace transport std::unique_ptr m_ProxyEndpoint; std::shared_ptr m_Address4, m_Address6, m_YggdrasilAddress; + uint64_t m_NoFileExhaustTimestamp; + public: // for HTTP/I2PControl From 648b09d45f3283c3524e6f0918c713fd48edf387 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 10 Dec 2022 15:44:37 -0500 Subject: [PATCH 18/20] try to restart acceptors after termination of expired NTCP2 if no descriptors --- libi2pd/NTCP2.cpp | 67 +++++++++++++++++++++++++++-------------------- libi2pd/NTCP2.h | 4 --- 2 files changed, 38 insertions(+), 33 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 555a5622..f78999be 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1424,20 +1424,18 @@ namespace transport else LogPrint (eLogError, "NTCP2: Connected from error ", ec.message ()); } - else if (error == boost::asio::error::no_descriptors) - { - i2p::context.SetError (eRouterErrorNoDescriptors); - if (m_NoFileExhaustTimestamp < i2p::util::GetSecondsSinceEpoch () - NTCP2_DESCRIPTORS_EXHAUST_TIMEOUT) - { - m_NoFileExhaustTimestamp = i2p::util::GetSecondsSinceEpoch (); - LogPrint (eLogWarning, "NTCP2: WARNING! i2pd met file descriptors exhaustion! Please check your nofile limits!"); - } - } else + { LogPrint (eLogError, "NTCP2: Accept error ", error.message ()); - + if (error == boost::asio::error::no_descriptors) + { + i2p::context.SetError (eRouterErrorNoDescriptors); + return; + } + } + if (error != boost::asio::error::operation_aborted) - { + { if (!conn) // connection is used, create new one conn = std::make_shared (*this); else // reuse failed @@ -1464,26 +1462,21 @@ namespace transport } } else - LogPrint (eLogError, "NTCP2: Connected from ipv6 error: ", ec.message ()); - } - else if (error == boost::asio::error::no_descriptors) - { - i2p::context.SetErrorV6 (eRouterErrorNoDescriptors); - if (m_NoFileExhaustTimestamp < i2p::util::GetSecondsSinceEpoch () - NTCP2_DESCRIPTORS_EXHAUST_TIMEOUT) - { - m_NoFileExhaustTimestamp = i2p::util::GetSecondsSinceEpoch (); - LogPrint (eLogWarning, "NTCP2: WARNING! i2pd met file descriptors exhaustion! Please check your nofile limits!"); - } + LogPrint (eLogError, "NTCP2: Connected from error ", ec.message ()); } else - LogPrint (eLogError, "NTCP2: Accept ipv6 error: ", error.message ()); + { + LogPrint (eLogError, "NTCP2: Accept ipv6 error ", error.message ()); + if (error == boost::asio::error::no_descriptors) + { + i2p::context.SetErrorV6 (eRouterErrorNoDescriptors); + return; + } + } if (error != boost::asio::error::operation_aborted) { - if (!conn) // connection is used, create new one - conn = std::make_shared (*this); - else // reuse failed - conn->Close (); + conn = std::make_shared (*this); m_NTCP2V6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAcceptV6, this, conn, std::placeholders::_1)); } @@ -1524,8 +1517,24 @@ namespace transport else it++; } - ScheduleTermination (); + + // try to restart acceptors if no description + // we do it after timer to let timer take descriptor first + if (i2p::context.GetError () == eRouterErrorNoDescriptors) + { + i2p::context.SetError (eRouterErrorNone); + auto conn = std::make_shared (*this); + m_NTCP2Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAccept, this, + conn, std::placeholders::_1)); + } + if (i2p::context.GetErrorV6 () == eRouterErrorNoDescriptors) + { + i2p::context.SetErrorV6 (eRouterErrorNone); + auto conn = std::make_shared (*this); + m_NTCP2V6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAcceptV6, this, + conn, std::placeholders::_1)); + } } } @@ -1733,7 +1742,7 @@ namespace transport }); 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(), + boost::asio::transfer_all(), [timer, conn, sz, readbuff](const boost::system::error_code & e, std::size_t transferred) { if (e) @@ -1741,7 +1750,7 @@ namespace transport else if (!(*readbuff)[1]) // succeeded { boost::system::error_code ec; - size_t moreBytes = conn->GetSocket ().available(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(); diff --git a/libi2pd/NTCP2.h b/libi2pd/NTCP2.h index c8c86e5d..754f5a6d 100644 --- a/libi2pd/NTCP2.h +++ b/libi2pd/NTCP2.h @@ -43,8 +43,6 @@ namespace transport const int NTCP2_CLOCK_SKEW = 60; // in seconds const int NTCP2_MAX_OUTGOING_QUEUE_SIZE = 500; // how many messages we can queue up - const int NTCP2_DESCRIPTORS_EXHAUST_TIMEOUT = 60; // 1 minute - enum NTCP2BlockType { eNTCP2BlkDateTime = 0, @@ -288,8 +286,6 @@ namespace transport std::unique_ptr m_ProxyEndpoint; std::shared_ptr m_Address4, m_Address6, m_YggdrasilAddress; - uint64_t m_NoFileExhaustTimestamp; - public: // for HTTP/I2PControl From 832098712444af847f2d312169c3b02eb0c4a83e Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 10 Dec 2022 19:09:37 -0500 Subject: [PATCH 19/20] delete invalid sessions from peers --- libi2pd/TransportSession.h | 3 ++- libi2pd/Transports.cpp | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/libi2pd/TransportSession.h b/libi2pd/TransportSession.h index 3ad146cb..87c730f4 100644 --- a/libi2pd/TransportSession.h +++ b/libi2pd/TransportSession.h @@ -113,7 +113,8 @@ namespace transport 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; + protected: std::shared_ptr m_RemoteIdentity; diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 0256e3d9..34fcc065 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -743,7 +743,12 @@ namespace transport auto ts = i2p::util::GetSecondsSinceEpoch (); for (auto it = m_Peers.begin (); it != m_Peers.end (); ) { - if (it->second.sessions.empty () && ts > it->second.creationTime + SESSION_CREATION_TIMEOUT) + it->second.sessions.remove_if ( + [](std::shared_ptr session)->bool + { + return !session || !session->IsEstablished (); + }); + 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); From 3458665df8c784a2c58873549dd56bac918f87e6 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 11 Dec 2022 17:03:53 -0500 Subject: [PATCH 20/20] don't delete unreachable routers if tunnel creation success rate is too low --- libi2pd/NetDb.cpp | 3 ++- libi2pd/NetDb.hpp | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index bf9d60de..d588b809 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -603,6 +603,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; // 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 @@ -624,7 +625,7 @@ namespace data continue; } // make router reachable back if too few routers or floodfills - if (it.second->IsUnreachable () && (total - deletedCount < NETDB_MIN_ROUTERS || + 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 diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index 98b5fd86..95f6c692 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_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