From 8ec12a1b6519552ebb3dd2b1129cf52a74a56360 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 10 Mar 2019 09:22:42 -0400 Subject: [PATCH] fixed race condition for publishing --- libi2pd/Destination.cpp | 27 +++++++++++++++++---------- libi2pd/Destination.h | 5 +++-- libi2pd_client/I2CP.cpp | 4 ++-- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 60e9bbb0..dab62712 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -272,15 +272,20 @@ namespace client if (!m_Pool) return nullptr; if (!m_LeaseSet) UpdateLeaseSet (); + return GetLeaseSetMt (); + } + + std::shared_ptr LeaseSetDestination::GetLeaseSetMt () + { std::lock_guard l(m_LeaseSetMutex); return m_LeaseSet; } - - void LeaseSetDestination::SetLeaseSet (i2p::data::LocalLeaseSet * newLeaseSet) + + void LeaseSetDestination::SetLeaseSet (std::shared_ptr newLeaseSet) { { std::lock_guard l(m_LeaseSetMutex); - m_LeaseSet.reset (newLeaseSet); + m_LeaseSet = newLeaseSet; } i2p::garlic::GarlicDestination::SetLeaseSetUpdated (); if (m_IsPublic) @@ -505,7 +510,8 @@ namespace client void LeaseSetDestination::Publish () { - if (!m_LeaseSet || !m_Pool) + auto leaseSet = GetLeaseSetMt (); + if (!leaseSet || !m_Pool) { LogPrint (eLogError, "Destination: Can't publish non-existing LeaseSet"); return; @@ -537,7 +543,7 @@ namespace client LogPrint (eLogError, "Destination: Can't publish LeaseSet. No inbound tunnels"); return; } - auto floodfill = i2p::data::netdb.GetClosestFloodfill (m_LeaseSet->GetIdentHash (), m_ExcludedFloodfills); + auto floodfill = i2p::data::netdb.GetClosestFloodfill (leaseSet->GetIdentHash (), m_ExcludedFloodfills); if (!floodfill) { LogPrint (eLogError, "Destination: Can't publish LeaseSet, no more floodfills found"); @@ -547,7 +553,7 @@ namespace client m_ExcludedFloodfills.insert (floodfill->GetIdentHash ()); LogPrint (eLogDebug, "Destination: Publish LeaseSet of ", GetIdentHash ().ToBase32 ()); RAND_bytes ((uint8_t *)&m_PublishReplyToken, 4); - auto msg = WrapMessage (floodfill, i2p::CreateDatabaseStoreMsg (m_LeaseSet, m_PublishReplyToken, inbound)); + auto msg = WrapMessage (floodfill, i2p::CreateDatabaseStoreMsg (leaseSet, m_PublishReplyToken, inbound)); 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)); @@ -592,7 +598,8 @@ namespace client { if (leaseSet) { - if (s->m_LeaseSet && *s->m_LeaseSet == *leaseSet) + auto ls = s->GetLeaseSetMt (); + if (ls && *ls == *leaseSet) { // we got latest LeasetSet LogPrint (eLogDebug, "Destination: published LeaseSet verified for ", GetIdentHash().ToBase32()); @@ -1081,10 +1088,10 @@ namespace client void ClientDestination::CreateNewLeaseSet (std::vector > tunnels) { - i2p::data::LocalLeaseSet * leaseSet = nullptr; + std::shared_ptr leaseSet; if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET) { - leaseSet = new i2p::data::LocalLeaseSet (GetIdentity (), m_EncryptionPublicKey, tunnels); + leaseSet = std::make_shared (GetIdentity (), m_EncryptionPublicKey, tunnels); // sign Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ()); } @@ -1092,7 +1099,7 @@ namespace client { // standard LS2 (type 3) assumed for now. TODO: implement others auto keyLen = m_Decryptor ? m_Decryptor->GetPublicKeyLen () : 256; - leaseSet = new i2p::data::LocalLeaseSet2 (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2, + leaseSet = std::make_shared (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2, m_Keys, m_EncryptionKeyType, keyLen, m_EncryptionPublicKey, tunnels); } SetLeaseSet (leaseSet); diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 432a8101..57b6e114 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -127,7 +127,7 @@ namespace client protected: - void SetLeaseSet (i2p::data::LocalLeaseSet * newLeaseSet); + void SetLeaseSet (std::shared_ptr newLeaseSet); int GetLeaseSetType () const { return m_LeaseSetType; }; void SetLeaseSetType (int leaseSetType) { m_LeaseSetType = leaseSetType; }; virtual void CleanupDestination () {}; // additional clean up in derived classes @@ -139,6 +139,7 @@ namespace client void Run (); void UpdateLeaseSet (); + std::shared_ptr GetLeaseSetMt (); void Publish (); void HandlePublishConfirmationTimer (const boost::system::error_code& ecode); void HandlePublishVerificationTimer (const boost::system::error_code& ecode); @@ -164,7 +165,7 @@ namespace client std::shared_ptr m_Pool; std::mutex m_LeaseSetMutex; - std::shared_ptr m_LeaseSet; + std::shared_ptr m_LeaseSet; bool m_IsPublic; uint32_t m_PublishReplyToken; uint64_t m_LastSubmissionTime; // in seconds diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index 252332cd..e507b066 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -63,14 +63,14 @@ namespace client void I2CPDestination::LeaseSetCreated (const uint8_t * buf, size_t len) { - auto ls = new i2p::data::LocalLeaseSet (m_Identity, buf, len); + auto ls = std::make_shared (m_Identity, buf, len); ls->SetExpirationTime (m_LeaseSetExpirationTime); SetLeaseSet (ls); } void I2CPDestination::LeaseSet2Created (uint8_t storeType, const uint8_t * buf, size_t len) { - auto ls = new i2p::data::LocalLeaseSet2 (storeType, m_Identity, buf, len); + auto ls = std::make_shared (storeType, m_Identity, buf, len); ls->SetExpirationTime (m_LeaseSetExpirationTime); SetLeaseSet (ls); }