From e1c25fedb0b3f16fb9c935f4e638b79924c85855 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 28 Nov 2014 13:01:35 -0500 Subject: [PATCH] wait for confirmantion of publishing --- Destination.cpp | 92 ++++++++++++++++++++++++++++++++++++++++++++----- Destination.h | 11 ++++-- NetDb.cpp | 21 ----------- NetDb.h | 3 +- 4 files changed, 94 insertions(+), 33 deletions(-) diff --git a/Destination.cpp b/Destination.cpp index 12d6c84d..5f59667e 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -12,7 +12,8 @@ namespace client { ClientDestination::ClientDestination (bool isPublic, i2p::data::SigningKeyType sigType): m_IsRunning (false), m_Thread (nullptr), m_Service (nullptr), m_Work (nullptr), - m_LeaseSet (nullptr), m_IsPublic (isPublic), m_DatagramDestination (nullptr) + m_LeaseSet (nullptr), m_IsPublic (isPublic), m_PublishReplyToken (0), + m_DatagramDestination (nullptr), m_PublishConfirmationTimer (nullptr) { m_Keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType); CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg); @@ -25,7 +26,8 @@ namespace client ClientDestination::ClientDestination (const std::string& fullPath, bool isPublic): m_IsRunning (false), m_Thread (nullptr), m_Service (nullptr), m_Work (nullptr), - m_LeaseSet (nullptr), m_IsPublic (isPublic), m_DatagramDestination (nullptr) + m_LeaseSet (nullptr), m_IsPublic (isPublic), m_PublishReplyToken (0), + m_DatagramDestination (nullptr), m_PublishConfirmationTimer (nullptr) { std::ifstream s(fullPath.c_str (), std::ifstream::binary); if (s.is_open ()) @@ -61,7 +63,8 @@ namespace client ClientDestination::ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic): m_IsRunning (false), m_Thread (nullptr), m_Service (nullptr), m_Work (nullptr), - m_Keys (keys), m_LeaseSet (nullptr), m_IsPublic (isPublic), m_DatagramDestination (nullptr) + m_Keys (keys), m_LeaseSet (nullptr), m_IsPublic (isPublic), m_PublishReplyToken (0), + m_DatagramDestination (nullptr), m_PublishConfirmationTimer (nullptr) { CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg); dh.GenerateKeyPair(i2p::context.GetRandomNumberGenerator (), m_EncryptionPrivateKey, m_EncryptionPublicKey); @@ -80,6 +83,7 @@ namespace client i2p::tunnel::tunnels.DeleteTunnelPool (m_Pool); delete m_LeaseSet; delete m_Work; + delete m_PublishConfirmationTimer; delete m_Service; delete m_StreamingDestination; delete m_DatagramDestination; @@ -94,6 +98,7 @@ namespace client void ClientDestination::Start () { m_Service = new boost::asio::io_service; + m_PublishConfirmationTimer = new boost::asio::deadline_timer (*m_Service); m_Work = new boost::asio::io_service::work (*m_Service); m_Pool->SetActive (true); m_IsRunning = true; @@ -113,6 +118,8 @@ namespace client if (m_Pool) i2p::tunnel::tunnels.StopTunnelPool (m_Pool); m_IsRunning = false; + delete m_PublishConfirmationTimer; + m_PublishConfirmationTimer = nullptr; if (m_Service) m_Service->stop (); if (m_Thread) @@ -209,21 +216,35 @@ namespace client offset += 36; if (msg->type == 1) // LeaseSet { - LogPrint ("Remote LeaseSet"); + LogPrint (eLogDebug, "Remote LeaseSet"); auto it = m_RemoteLeaseSets.find (msg->key); if (it != m_RemoteLeaseSets.end ()) { it->second->Update (buf + offset, len - offset); - LogPrint ("Remote LeaseSet updated"); + LogPrint (eLogDebug, "Remote LeaseSet updated"); } else { - LogPrint ("New remote LeaseSet added"); + LogPrint (eLogDebug, "New remote LeaseSet added"); m_RemoteLeaseSets[msg->key] = new i2p::data::LeaseSet (buf + offset, len - offset); } } else - LogPrint ("Unexpected client's DatabaseStore type ", msg->type, ". Dropped"); + LogPrint (eLogError, "Unexpected client's DatabaseStore type ", msg->type, ". Dropped"); + } + + void ClientDestination::HandleDeliveryStatusMessage (I2NPMessage * msg) + { + I2NPDeliveryStatusMsg * deliveryStatus = (I2NPDeliveryStatusMsg *)msg->GetPayload (); + uint32_t msgID = be32toh (deliveryStatus->msgID); + if (msgID == m_PublishReplyToken) + { + LogPrint (eLogDebug, "Publishing confirmed"); + m_PublishReplyToken = 0; + i2p::DeleteI2NPMessage (msg); + } + else + i2p::garlic::GarlicDestination::HandleDeliveryStatusMessage (msg); } void ClientDestination::SetLeaseSetUpdated () @@ -231,7 +252,62 @@ namespace client i2p::garlic::GarlicDestination::SetLeaseSetUpdated (); UpdateLeaseSet (); if (m_IsPublic) - i2p::data::netdb.PublishLeaseSet (m_LeaseSet, m_Pool); + Publish (); + } + + void ClientDestination::Publish () + { + if (!m_LeaseSet || !m_Pool) + { + LogPrint (eLogError, "Can't publish non-existing LeaseSet"); + return; + } + if (m_PublishReplyToken) + { + LogPrint (eLogInfo, "Publishing is pending"); + return; + } + auto outbound = m_Pool->GetNextOutboundTunnel (); + if (!outbound) + { + LogPrint ("Can't publish LeaseSet. No outbound tunnels"); + return; + } + std::set excluded; + auto floodfill = i2p::data::netdb.GetClosestFloodfill (m_LeaseSet->GetIdentHash (), excluded); + if (!floodfill) + { + LogPrint ("Can't publish LeaseSet. No floodfills found"); + return; + } + LogPrint (eLogDebug, "Publish LeaseSet of ", GetIdentHash ().ToBase32 ()); + m_PublishReplyToken = i2p::context.GetRandomNumberGenerator ().GenerateWord32 (); + auto msg = WrapMessage (*floodfill, i2p::CreateDatabaseStoreMsg (m_LeaseSet, m_PublishReplyToken)); + if (m_PublishConfirmationTimer) + { + m_PublishConfirmationTimer->expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT)); + m_PublishConfirmationTimer->async_wait (std::bind (&ClientDestination::HandlePublishConfirmationTimer, + this, std::placeholders::_1)); + } + else + { + LogPrint (eLogWarning, "Destination's thread is not running"); + m_PublishReplyToken = 0; + } + outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, msg); + } + + void ClientDestination::HandlePublishConfirmationTimer (const boost::system::error_code& ecode) + { + if (ecode != boost::asio::error::operation_aborted) + { + if (m_PublishReplyToken) + { + LogPrint (eLogWarning, "Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, "seconds. Try again"); + m_PublishReplyToken = 0; + Publish (); + } + } } void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len) diff --git a/Destination.h b/Destination.h index ec70865e..404528e6 100644 --- a/Destination.h +++ b/Destination.h @@ -19,6 +19,7 @@ namespace client const uint8_t PROTOCOL_TYPE_STREAMING = 6; const uint8_t PROTOCOL_TYPE_DATAGRAM = 17; const uint8_t PROTOCOL_TYPE_RAW = 18; + const int PUBLISH_CONFIRMATION_TIMEOUT = 5; // in seconds class ClientDestination: public i2p::garlic::GarlicDestination { @@ -69,7 +70,10 @@ namespace client void Run (); void UpdateLeaseSet (); - void HandleDatabaseStoreMessage (const uint8_t * buf, size_t len); + void Publish (); + void HandlePublishConfirmationTimer (const boost::system::error_code& ecode); + void HandleDatabaseStoreMessage (const uint8_t * buf, size_t len); + void HandleDeliveryStatusMessage (I2NPMessage * msg); private: @@ -84,10 +88,13 @@ namespace client i2p::tunnel::TunnelPool * m_Pool; i2p::data::LeaseSet * m_LeaseSet; bool m_IsPublic; - + uint32_t m_PublishReplyToken; + i2p::stream::StreamingDestination * m_StreamingDestination; i2p::datagram::DatagramDestination * m_DatagramDestination; + boost::asio::deadline_timer * m_PublishConfirmationTimer; + public: // for HTTP only diff --git a/NetDb.cpp b/NetDb.cpp index ee225b00..3c4fb221 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -896,26 +896,5 @@ namespace data it++; } } - - void NetDb::PublishLeaseSet (const LeaseSet * leaseSet, i2p::tunnel::TunnelPool * pool) - { - if (!leaseSet || !pool) return; - auto outbound = pool->GetNextOutboundTunnel (); - if (!outbound) - { - LogPrint ("Can't publish LeaseSet. No outbound tunnels"); - return; - } - std::set excluded; - auto floodfill = GetClosestFloodfill (leaseSet->GetIdentHash (), excluded); - if (!floodfill) - { - LogPrint ("Can't publish LeaseSet. No floodfills found"); - return; - } - uint32_t replyToken = i2p::context.GetRandomNumberGenerator ().GenerateWord32 (); - auto msg = pool->GetGarlicDestination ().WrapMessage (*floodfill, i2p::CreateDatabaseStoreMsg (leaseSet, replyToken)); - outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, msg); - } } } diff --git a/NetDb.h b/NetDb.h index 8a8ef848..042347dc 100644 --- a/NetDb.h +++ b/NetDb.h @@ -67,7 +67,6 @@ namespace data std::shared_ptr FindRouter (const IdentHash& ident) const; LeaseSet * FindLeaseSet (const IdentHash& destination) const; - void PublishLeaseSet (const LeaseSet * leaseSet, i2p::tunnel::TunnelPool * pool); void RequestDestination (const IdentHash& destination, bool isLeaseSet = false, i2p::tunnel::TunnelPool * pool = nullptr); @@ -78,6 +77,7 @@ namespace data std::shared_ptr GetRandomRouter () const; std::shared_ptr GetRandomRouter (std::shared_ptr compatibleWith) const; std::shared_ptr GetHighBandwidthRandomRouter (std::shared_ptr compatibleWith) const; + std::shared_ptr GetClosestFloodfill (const IdentHash& destination, const std::set& excluded) const; void SetUnreachable (const IdentHash& ident, bool unreachable); void PostI2NPMsg (I2NPMessage * msg); @@ -95,7 +95,6 @@ namespace data void Run (); // exploratory thread void Explore (int numDestinations); void Publish (); - std::shared_ptr GetClosestFloodfill (const IdentHash& destination, const std::set& excluded) const; void ManageLeaseSets (); RequestedDestination * CreateRequestedDestination (const IdentHash& dest,