diff --git a/Garlic.cpp b/Garlic.cpp index 88e255ff..b26077eb 100644 --- a/Garlic.cpp +++ b/Garlic.cpp @@ -42,7 +42,27 @@ namespace garlic delete it.second; m_UnconfirmedTagsMsgs.clear (); } - + + std::shared_ptr GarlicRoutingSession::GetSharedRoutingPath () + { + if (!m_SharedRoutingPath) return nullptr; + uint32_t ts = i2p::util::GetSecondsSinceEpoch (); + if (!m_SharedRoutingPath->outboundTunnel->IsEstablished () || + ts*1000LL > m_SharedRoutingPath->remoteLease->endDate || + ts > m_SharedRoutingPath->updateTime + ROUTING_PATH_EXPIRATION_TIMEOUT) + m_SharedRoutingPath = nullptr; + return m_SharedRoutingPath; + } + + void GarlicRoutingSession::SetSharedRoutingPath (std::shared_ptr path) + { + if (path && path->outboundTunnel && path->remoteLease) + path->updateTime = i2p::util::GetSecondsSinceEpoch (); + else + path = nullptr; + m_SharedRoutingPath = path; + } + GarlicRoutingSession::UnconfirmedTags * GarlicRoutingSession::GenerateSessionTags () { auto tags = new UnconfirmedTags (m_NumTags); @@ -570,6 +590,7 @@ namespace garlic std::unique_lock l(m_SessionsMutex); for (auto it = m_Sessions.begin (); it != m_Sessions.end ();) { + it->second->GetSharedRoutingPath (); // delete shared path if necessary if (!it->second->CleanupExpiredTags ()) { LogPrint (eLogInfo, "Routing session to ", it->first.ToBase32 (), " deleted"); diff --git a/Garlic.h b/Garlic.h index b42f92cf..95a59e72 100644 --- a/Garlic.h +++ b/Garlic.h @@ -15,7 +15,12 @@ #include "Identity.h" namespace i2p -{ +{ +namespace tunnel +{ + class OutboundTunnel; +} + namespace garlic { @@ -27,19 +32,18 @@ namespace garlic eGarlicDeliveryTypeTunnel = 3 }; -#pragma pack(1) struct ElGamalBlock { uint8_t sessionKey[32]; uint8_t preIV[32]; uint8_t padding[158]; }; -#pragma pack() const int INCOMING_TAGS_EXPIRATION_TIMEOUT = 960; // 16 minutes const int OUTGOING_TAGS_EXPIRATION_TIMEOUT = 720; // 12 minutes const int OUTGOING_TAGS_CONFIRMATION_TIMEOUT = 10; // 10 seconds const int LEASET_CONFIRMATION_TIMEOUT = 4000; // in milliseconds + const int ROUTING_PATH_EXPIRATION_TIMEOUT = 30; // 30 seconds struct SessionTag: public i2p::data::Tag<32> { @@ -53,7 +57,14 @@ namespace garlic #endif uint32_t creationTime; // seconds since epoch }; - + + struct GarlicRoutingPath + { + std::shared_ptr outboundTunnel; + std::shared_ptr remoteLease; + uint32_t updateTime; // seconds since epoch + }; + class GarlicDestination; class GarlicRoutingSession: public std::enable_shared_from_this { @@ -88,6 +99,9 @@ namespace garlic { if (m_LeaseSetUpdateStatus != eLeaseSetDoNotSend) m_LeaseSetUpdateStatus = eLeaseSetUpdated; }; + + std::shared_ptr GetSharedRoutingPath (); + void SetSharedRoutingPath (std::shared_ptr path); private: @@ -115,6 +129,8 @@ namespace garlic i2p::crypto::CBCEncryption m_Encryption; std::unique_ptr m_ElGamalEncryption; + std::shared_ptr m_SharedRoutingPath; + public: // for HTTP only size_t GetNumOutgoingTags () const { return m_SessionTags.size (); }; diff --git a/LeaseSet.cpp b/LeaseSet.cpp index ebbdbd97..677f19ca 100644 --- a/LeaseSet.cpp +++ b/LeaseSet.cpp @@ -180,10 +180,10 @@ namespace data } } - const std::vector > LeaseSet::GetNonExpiredLeases (bool withThreshold) const + const std::vector > LeaseSet::GetNonExpiredLeases (bool withThreshold) const { auto ts = i2p::util::GetMillisecondsSinceEpoch (); - std::vector > leases; + std::vector > leases; for (auto it: m_Leases) { auto endDate = it->endDate; diff --git a/LeaseSet.h b/LeaseSet.h index dd94bfaf..aed27683 100644 --- a/LeaseSet.h +++ b/LeaseSet.h @@ -52,7 +52,7 @@ namespace data const uint8_t * GetBuffer () const { return m_Buffer; }; size_t GetBufferLen () const { return m_BufferLen; }; bool IsValid () const { return m_IsValid; }; - const std::vector > GetNonExpiredLeases (bool withThreshold = true) const; + const std::vector > GetNonExpiredLeases (bool withThreshold = true) const; bool HasExpiredLeases () const; bool IsExpired () const; bool IsEmpty () const { return m_Leases.empty (); }; diff --git a/Streaming.cpp b/Streaming.cpp index 0c1a5e5d..1e9cdd84 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -271,6 +271,10 @@ namespace stream m_LastWindowSizeIncreaseTime = ts; } } + if (!seqn && m_RoutingSession) // first message confirmed + m_RoutingSession->SetSharedRoutingPath ( + std::make_shared ( + i2p::garlic::GarlicRoutingPath{m_CurrentOutboundTunnel, m_CurrentRemoteLease, 0})); } else break; @@ -589,6 +593,21 @@ namespace stream return; } } + if (!m_CurrentOutboundTunnel) // first message to send + { + // try to get shared path first + if (!m_RoutingSession) + m_RoutingSession = m_LocalDestination.GetOwner ()->GetRoutingSession (m_RemoteLeaseSet, true); + if (m_RoutingSession) + { + auto routingPath = m_RoutingSession->GetSharedRoutingPath (); + if (routingPath) + { + m_CurrentOutboundTunnel = routingPath->outboundTunnel; + m_CurrentRemoteLease = routingPath->remoteLease; + } + } + } if (!m_CurrentOutboundTunnel || !m_CurrentOutboundTunnel->IsEstablished ()) m_CurrentOutboundTunnel = m_LocalDestination.GetOwner ()->GetTunnelPool ()->GetNewOutboundTunnel (m_CurrentOutboundTunnel); if (!m_CurrentOutboundTunnel) @@ -668,12 +687,14 @@ namespace stream case 2: m_RTO = INITIAL_RTO; // drop RTO to initial upon tunnels pair change first time // no break here - case 4: + case 4: + if (m_RoutingSession) m_RoutingSession->SetSharedRoutingPath (nullptr); UpdateCurrentRemoteLease (); // pick another lease LogPrint (eLogWarning, "Streaming: Another remote lease has been selected for stream"); break; case 3: // pick another outbound tunnel + if (m_RoutingSession) m_RoutingSession->SetSharedRoutingPath (nullptr); m_CurrentOutboundTunnel = m_LocalDestination.GetOwner ()->GetTunnelPool ()->GetNextOutboundTunnel (m_CurrentOutboundTunnel); LogPrint (eLogWarning, "Streaming: Another outbound tunnel has been selected for stream"); break; diff --git a/Streaming.h b/Streaming.h index 2f85397a..c908c6ec 100644 --- a/Streaming.h +++ b/Streaming.h @@ -172,7 +172,7 @@ namespace stream std::shared_ptr m_RemoteIdentity; std::shared_ptr m_RemoteLeaseSet; std::shared_ptr m_RoutingSession; - std::shared_ptr m_CurrentRemoteLease; + std::shared_ptr m_CurrentRemoteLease; std::shared_ptr m_CurrentOutboundTunnel; std::queue m_ReceiveQueue; std::set m_SavedPackets;