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 (); };