From d81ca5f919e1f0f7290c19e9fa379c2c1a3e7f2e Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 11 Feb 2016 14:45:33 -0500 Subject: [PATCH 1/5] local destination leaseset storage verification --- Destination.cpp | 54 +++++++++++++++++++++++++++++++++++++++++++------ Destination.h | 5 ++++- LeaseSet.h | 2 ++ 3 files changed, 54 insertions(+), 7 deletions(-) diff --git a/Destination.cpp b/Destination.cpp index e7e9b93c..b1866969 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -17,7 +17,8 @@ namespace client const std::map * params): m_IsRunning (false), m_Thread (nullptr), m_Work (m_Service), m_Keys (keys), m_IsPublic (isPublic), m_PublishReplyToken (0), - m_DatagramDestination (nullptr), m_PublishConfirmationTimer (m_Service), m_CleanupTimer (m_Service) + m_DatagramDestination (nullptr), m_PublishConfirmationTimer (m_Service), + m_PublishVerificationTimer (m_Service), m_CleanupTimer (m_Service) { if (m_IsPublic) PersistTemporaryKeys (); @@ -156,6 +157,8 @@ namespace client if (m_IsRunning) { m_CleanupTimer.cancel (); + m_PublishConfirmationTimer.cancel (); + m_PublishVerificationTimer.cancel (); m_IsRunning = false; m_StreamingDestination->Stop (); m_StreamingDestination = nullptr; @@ -298,8 +301,13 @@ namespace client leaseSet = std::make_shared (buf + offset, len - offset); if (leaseSet->IsValid ()) { - LogPrint (eLogDebug, "New remote LeaseSet added"); - m_RemoteLeaseSets[buf + DATABASE_STORE_KEY_OFFSET] = leaseSet; + if (leaseSet->GetIdentHash () != GetIdentHash ()) + { + LogPrint (eLogDebug, "New remote LeaseSet added"); + m_RemoteLeaseSets[buf + DATABASE_STORE_KEY_OFFSET] = leaseSet; + } + else + LogPrint (eLogDebug, "Own remote LeaseSet dropped"); } else { @@ -371,6 +379,10 @@ namespace client LogPrint (eLogDebug, "Destination: Publishing LeaseSet confirmed"); m_ExcludedFloodfills.clear (); m_PublishReplyToken = 0; + // schedule verification + m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT)); + m_PublishVerificationTimer.async_wait (std::bind (&ClientDestination::HandlePublishVerificationTimer, + shared_from_this (), std::placeholders::_1)); } else i2p::garlic::GarlicDestination::HandleDeliveryStatusMessage (msg); @@ -381,7 +393,10 @@ namespace client i2p::garlic::GarlicDestination::SetLeaseSetUpdated (); UpdateLeaseSet (); if (m_IsPublic) + { + m_PublishVerificationTimer.cancel (); Publish (); + } } void ClientDestination::Publish () @@ -402,7 +417,6 @@ namespace client LogPrint (eLogError, "Destination: Can't publish LeaseSet. No outbound tunnels"); return; } - std::set excluded; auto floodfill = i2p::data::netdb.GetClosestFloodfill (m_LeaseSet->GetIdentHash (), m_ExcludedFloodfills); if (!floodfill) { @@ -416,7 +430,7 @@ namespace client auto msg = WrapMessage (floodfill, i2p::CreateDatabaseStoreMsg (m_LeaseSet, m_PublishReplyToken)); m_PublishConfirmationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT)); m_PublishConfirmationTimer.async_wait (std::bind (&ClientDestination::HandlePublishConfirmationTimer, - this, std::placeholders::_1)); + shared_from_this (), std::placeholders::_1)); outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, msg); } @@ -433,6 +447,34 @@ namespace client } } + void ClientDestination::HandlePublishVerificationTimer (const boost::system::error_code& ecode) + { + if (ecode != boost::asio::error::operation_aborted) + { + auto s = shared_from_this (); + RequestLeaseSet (GetIdentHash (), + [s](std::shared_ptr leaseSet) + { + if (leaseSet) + { + if (s->m_LeaseSet && *s->m_LeaseSet == *leaseSet) + { + // we got latest LeasetSet + LogPrint (eLogDebug, "Destination: published LeaseSet verified"); + s->m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_REGULAR_VERIFICATION_INTERNAL)); + s->m_PublishVerificationTimer.async_wait (std::bind (&ClientDestination::HandlePublishVerificationTimer, + s, std::placeholders::_1)); + return; + } + } + else + LogPrint (eLogWarning, "Destination: couldn't find published LeaseSet"); + // we have to publish again + s->Publish (); + }); + } + } + void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len) { uint32_t length = bufbe32toh (buf); @@ -622,7 +664,7 @@ namespace client }); request->requestTimeoutTimer.expires_from_now (boost::posix_time::seconds(LEASESET_REQUEST_TIMEOUT)); request->requestTimeoutTimer.async_wait (std::bind (&ClientDestination::HandleRequestTimoutTimer, - this, std::placeholders::_1, dest)); + shared_from_this (), std::placeholders::_1, dest)); } else return false; diff --git a/Destination.h b/Destination.h index c45a20ec..34e7fa38 100644 --- a/Destination.h +++ b/Destination.h @@ -26,6 +26,8 @@ namespace client const uint8_t PROTOCOL_TYPE_DATAGRAM = 17; const uint8_t PROTOCOL_TYPE_RAW = 18; const int PUBLISH_CONFIRMATION_TIMEOUT = 5; // in seconds + const int PUBLISH_VERIFICATION_TIMEOUT = 10; // in seconds after successfull publish + const int PUBLISH_REGULAR_VERIFICATION_INTERNAL = 100; // in seconds periodically const int LEASESET_REQUEST_TIMEOUT = 5; // in seconds const int MAX_LEASESET_REQUEST_TIMEOUT = 40; // in seconds const int DESTINATION_CLEANUP_TIMEOUT = 3; // in minutes @@ -116,6 +118,7 @@ namespace client void UpdateLeaseSet (); void Publish (); void HandlePublishConfirmationTimer (const boost::system::error_code& ecode); + void HandlePublishVerificationTimer (const boost::system::error_code& ecode); void HandleDatabaseStoreMessage (const uint8_t * buf, size_t len); void HandleDatabaseSearchReplyMessage (const uint8_t * buf, size_t len); void HandleDeliveryStatusMessage (std::shared_ptr msg); @@ -148,7 +151,7 @@ namespace client std::map > m_StreamingDestinationsByPorts; i2p::datagram::DatagramDestination * m_DatagramDestination; - boost::asio::deadline_timer m_PublishConfirmationTimer, m_CleanupTimer; + boost::asio::deadline_timer m_PublishConfirmationTimer, m_PublishVerificationTimer, m_CleanupTimer; public: diff --git a/LeaseSet.h b/LeaseSet.h index aed27683..6a0da922 100644 --- a/LeaseSet.h +++ b/LeaseSet.h @@ -57,6 +57,8 @@ namespace data bool IsExpired () const; bool IsEmpty () const { return m_Leases.empty (); }; uint64_t GetExpirationTime () const { return m_ExpirationTime; }; + bool operator== (const LeaseSet& other) const + { return m_BufferLen == other.m_BufferLen && !memcmp (m_Buffer, other.m_Buffer, m_BufferLen); }; // implements RoutingDestination const IdentHash& GetIdentHash () const { return m_Identity->GetIdentHash (); }; From b967acda5856c93671c791020db9acc7443bf8a2 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 11 Feb 2016 15:05:46 -0500 Subject: [PATCH 2/5] flood to floodfills that are close than us only --- NetDb.cpp | 11 ++++++++--- NetDb.h | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/NetDb.cpp b/NetDb.cpp index fe1d6a45..6d019316 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -496,9 +496,11 @@ namespace data std::set excluded; for (int i = 0; i < 3; i++) { - auto floodfill = GetClosestFloodfill (ident, excluded); + auto floodfill = GetClosestFloodfill (ident, excluded, true); // we need a floodfill close than us only if (floodfill) transports.SendMessage (floodfill->GetIdentHash (), floodMsg); + else + break; } } else @@ -885,12 +887,15 @@ namespace data } std::shared_ptr NetDb::GetClosestFloodfill (const IdentHash& destination, - const std::set& excluded) const + const std::set& excluded, bool closeThanUsOnly) const { std::shared_ptr r; XORMetric minMetric; IdentHash destKey = CreateRoutingKey (destination); - minMetric.SetMax (); + if (closeThanUsOnly) + minMetric = destKey ^ i2p::context.GetIdentHash (); + else + minMetric.SetMax (); std::unique_lock l(m_FloodfillsMutex); for (auto it: m_Floodfills) { diff --git a/NetDb.h b/NetDb.h index 237e5be1..f1b97728 100644 --- a/NetDb.h +++ b/NetDb.h @@ -52,7 +52,7 @@ namespace data std::shared_ptr GetHighBandwidthRandomRouter (std::shared_ptr compatibleWith) const; std::shared_ptr GetRandomPeerTestRouter () const; std::shared_ptr GetRandomIntroducer () const; - std::shared_ptr GetClosestFloodfill (const IdentHash& destination, const std::set& excluded) const; + std::shared_ptr GetClosestFloodfill (const IdentHash& destination, const std::set& excluded, bool closeThanUsOnly = false) const; std::vector GetClosestFloodfills (const IdentHash& destination, size_t num, std::set& excluded) const; std::shared_ptr GetClosestNonFloodfill (const IdentHash& destination, const std::set& excluded) const; From ee8ab58d64ced0c83214866289fa9c25bd3850cd Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 11 Feb 2016 22:17:33 -0500 Subject: [PATCH 3/5] don't reply to lookup with expired LeaseSet --- NetDb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NetDb.cpp b/NetDb.cpp index 6d019316..6376f44e 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -690,7 +690,7 @@ namespace data lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP)) { auto leaseSet = FindLeaseSet (ident); - if (leaseSet) // we don't send back our LeaseSets + if (leaseSet && !leaseSet->IsExpired ()) // we don't send back our LeaseSets { LogPrint (eLogDebug, "NetDb: requested LeaseSet ", key, " found"); replyMsg = CreateDatabaseStoreMsg (leaseSet); From 517385fb63e0358690796544cc4416828fec60ff Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 11 Feb 2016 22:18:24 -0500 Subject: [PATCH 4/5] Lease enddate threshold --- LeaseSet.cpp | 10 ++++++++-- LeaseSet.h | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/LeaseSet.cpp b/LeaseSet.cpp index 677f19ca..561dc28c 100644 --- a/LeaseSet.cpp +++ b/LeaseSet.cpp @@ -130,7 +130,7 @@ namespace data leases += 4; // tunnel ID lease.endDate = bufbe64toh (leases); leases += 8; // end date - if (ts < lease.endDate) + if (ts < lease.endDate + LEASE_ENDDATE_THRESHOLD) { if (lease.endDate > m_ExpirationTime) m_ExpirationTime = lease.endDate; @@ -151,7 +151,7 @@ namespace data else LogPrint (eLogWarning, "LeaseSet: Lease is expired already "); } - if (!m_ExpirationTime) + if (!m_ExpirationTime && m_Leases.empty ()) { LogPrint (eLogWarning, "LeaseSet: all leases are expired. Dropped"); m_IsValid = false; @@ -192,6 +192,12 @@ namespace data if (ts < endDate) leases.push_back (it); } + if (leases.empty () && withThreshold) + { + for (auto it: m_Leases) + if (ts < it->endDate + LEASE_ENDDATE_THRESHOLD) + leases.push_back (it); + } return leases; } diff --git a/LeaseSet.h b/LeaseSet.h index 6a0da922..b9ec2d0b 100644 --- a/LeaseSet.h +++ b/LeaseSet.h @@ -17,6 +17,7 @@ namespace tunnel namespace data { + const int LEASE_ENDDATE_THRESHOLD = 9500; // in milliseconds struct Lease { IdentHash tunnelGateway; From 333103f50e44fee638a0058baa6af6ab478d547b Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 11 Feb 2016 22:18:44 -0500 Subject: [PATCH 5/5] shared RTT --- Destination.cpp | 3 +-- Garlic.h | 1 + Streaming.cpp | 7 +++++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Destination.cpp b/Destination.cpp index b1866969..5e76f770 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -462,8 +462,7 @@ namespace client // we got latest LeasetSet LogPrint (eLogDebug, "Destination: published LeaseSet verified"); s->m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_REGULAR_VERIFICATION_INTERNAL)); - s->m_PublishVerificationTimer.async_wait (std::bind (&ClientDestination::HandlePublishVerificationTimer, - s, std::placeholders::_1)); + s->m_PublishVerificationTimer.async_wait (std::bind (&ClientDestination::HandlePublishVerificationTimer, s, std::placeholders::_1)); return; } } diff --git a/Garlic.h b/Garlic.h index 95a59e72..1d8aa8cf 100644 --- a/Garlic.h +++ b/Garlic.h @@ -62,6 +62,7 @@ namespace garlic { std::shared_ptr outboundTunnel; std::shared_ptr remoteLease; + int rtt; // RTT uint32_t updateTime; // seconds since epoch }; diff --git a/Streaming.cpp b/Streaming.cpp index 1e9cdd84..7047c1fb 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -274,7 +274,7 @@ namespace stream if (!seqn && m_RoutingSession) // first message confirmed m_RoutingSession->SetSharedRoutingPath ( std::make_shared ( - i2p::garlic::GarlicRoutingPath{m_CurrentOutboundTunnel, m_CurrentRemoteLease, 0})); + i2p::garlic::GarlicRoutingPath{m_CurrentOutboundTunnel, m_CurrentRemoteLease, m_RTT, 0})); } else break; @@ -605,6 +605,8 @@ namespace stream { m_CurrentOutboundTunnel = routingPath->outboundTunnel; m_CurrentRemoteLease = routingPath->remoteLease; + m_RTT = routingPath->rtt; + m_RTO = m_RTT*1.5; // TODO: implement it better } } } @@ -727,7 +729,8 @@ namespace stream { if (!m_RemoteLeaseSet || m_RemoteLeaseSet->IsExpired ()) { - m_RemoteLeaseSet = m_LocalDestination.GetOwner ()->FindLeaseSet (m_RemoteIdentity->GetIdentHash ()); + auto remoteLeaseSet = m_LocalDestination.GetOwner ()->FindLeaseSet (m_RemoteIdentity->GetIdentHash ()); + if (remoteLeaseSet) m_RemoteLeaseSet = remoteLeaseSet; // renew if possible if (!m_RemoteLeaseSet) LogPrint (eLogWarning, "Streaming: LeaseSet ", m_RemoteIdentity->GetIdentHash ().ToBase64 (), " not found"); }