From 6fb5fa1c52b1316f9ededb04be2dcc5f593b8188 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 26 Dec 2014 19:09:44 -0500 Subject: [PATCH] LeaseSet request complete callback --- AddressBook.cpp | 18 +++++++++++++----- Destination.cpp | 46 ++++++++++++++++++++++++++++------------------ Destination.h | 9 ++++++--- 3 files changed, 47 insertions(+), 26 deletions(-) diff --git a/AddressBook.cpp b/AddressBook.cpp index 6290aa8c..23a12180 100644 --- a/AddressBook.cpp +++ b/AddressBook.cpp @@ -430,12 +430,22 @@ namespace client i2p::data::IdentHash ident; if (m_Book.GetIdentHash (u.host_, ident)) { + std::condition_variable newDataReceived; + std::mutex newDataReceivedMutex; const i2p::data::LeaseSet * leaseSet = i2p::data::netdb.FindLeaseSet (ident); if (!leaseSet) { - i2p::client::context.GetSharedLocalDestination ()->RequestDestination (ident); - std::this_thread::sleep_for (std::chrono::seconds (5)); // wait for 5 seconds - leaseSet = i2p::client::context.GetSharedLocalDestination ()->FindLeaseSet (ident); + bool found = false; + std::unique_lock l(newDataReceivedMutex); + i2p::client::context.GetSharedLocalDestination ()->RequestDestination (ident, + [&newDataReceived, &found](bool success) + { + found = success; + newDataReceived.notify_all (); + }); + newDataReceived.wait (l); + if (found) + leaseSet = i2p::client::context.GetSharedLocalDestination ()->FindLeaseSet (ident); } if (leaseSet) { @@ -455,8 +465,6 @@ namespace client bool end = false; while (!end) { - std::condition_variable newDataReceived; - std::mutex newDataReceivedMutex; stream->AsyncReceive (boost::asio::buffer (buf, 4096), [&](const boost::system::error_code& ecode, std::size_t bytes_transferred) { diff --git a/Destination.cpp b/Destination.cpp index 85f7b426..752ad5b0 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -211,8 +211,9 @@ namespace client auto it1 = m_LeaseSetRequests.find (msg->key); if (it1 != m_LeaseSetRequests.end ()) { + if (it1->second->requestComplete) it1->second->requestComplete (true); delete it1->second; - m_LeaseSetRequests.erase (it1); + m_LeaseSetRequests.erase (it1); } size_t offset = sizeof (I2NPDatabaseStoreMsg); if (msg->replyToken) // TODO: @@ -242,10 +243,11 @@ namespace client int num = buf[32]; // num LogPrint ("DatabaseSearchReply for ", key.ToBase64 (), " num=", num); auto it = m_LeaseSetRequests.find (key); - if (it != m_LeaseSetRequests.end ()) + if (it != m_LeaseSetRequests.end ()) { + LeaseSetRequest * request = it->second; bool found = false; - if (it->second->excluded.size () < MAX_NUM_FLOODFILLS_PER_REQUEST) + if (request->excluded.size () < MAX_NUM_FLOODFILLS_PER_REQUEST) { for (int i = 0; i < num; i++) { @@ -253,8 +255,9 @@ namespace client auto floodfill = i2p::data::netdb.FindRouter (peerHash); if (floodfill) { - found = true; - SendLeaseSetRequest (key, floodfill, it->second); + LogPrint (eLogInfo, "Requesting ", key.ToBase64 (), " at ", peerHash.ToBase64 ()); + if (SendLeaseSetRequest (key, floodfill, request)) + found = true; } else { @@ -262,14 +265,16 @@ namespace client i2p::data::netdb.RequestDestination (peerHash); } } + if (!found) + LogPrint (eLogError, "Suggested floodfills are not presented in netDb"); } else LogPrint (eLogInfo, key.ToBase64 (), " was not found on ", MAX_NUM_FLOODFILLS_PER_REQUEST," floodfills"); if (!found) { - LogPrint (eLogError, "Suggested floodfills are not presented in netDb"); - delete it->second; - m_LeaseSetRequests.erase (it); + if (request->requestComplete) request->requestComplete (false); + delete request; + m_LeaseSetRequests.erase (key); } } else @@ -407,28 +412,35 @@ namespace client return m_DatagramDestination; } - bool ClientDestination::RequestDestination (const i2p::data::IdentHash& dest) + bool ClientDestination::RequestDestination (const i2p::data::IdentHash& dest, RequestComplete requestComplete) { if (!m_Pool || !IsReady ()) return false; - m_Service.post (std::bind (&ClientDestination::RequestLeaseSet, this, dest)); + m_Service.post (std::bind (&ClientDestination::RequestLeaseSet, this, dest, requestComplete)); return true; } - void ClientDestination::RequestLeaseSet (const i2p::data::IdentHash& dest) + void ClientDestination::RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete) { std::set excluded; auto floodfill = i2p::data::netdb.GetClosestFloodfill (dest, excluded); if (floodfill) { LeaseSetRequest * request = new LeaseSetRequest (m_Service); + request->requestComplete = requestComplete; m_LeaseSetRequests[dest] = request; - SendLeaseSetRequest (dest, floodfill, request); + if (!SendLeaseSetRequest (dest, floodfill, request)) + { + // request failed + if (request->requestComplete) request->requestComplete (false); + delete request; + m_LeaseSetRequests.erase (dest); + } } else LogPrint (eLogError, "No floodfills found"); } - void ClientDestination::SendLeaseSetRequest (const i2p::data::IdentHash& dest, + bool ClientDestination::SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr nextFloodfill, LeaseSetRequest * request) { auto replyTunnel = m_Pool->GetNextInboundTunnel (); @@ -459,11 +471,8 @@ namespace client this, std::placeholders::_1, dest)); } else - { - // request failed - delete request; - m_LeaseSetRequests.erase (dest); - } + return false; + return true; } void ClientDestination::HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest) @@ -491,6 +500,7 @@ namespace client if (done) { + if (it->second->requestComplete) it->second->requestComplete (false); delete it->second; m_LeaseSetRequests.erase (it); } diff --git a/Destination.h b/Destination.h index fe665db5..66836725 100644 --- a/Destination.h +++ b/Destination.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "Identity.h" #include "TunnelPool.h" @@ -37,12 +38,14 @@ namespace client class ClientDestination: public i2p::garlic::GarlicDestination { + typedef std::function RequestComplete; struct LeaseSetRequest { LeaseSetRequest (boost::asio::io_service& service): requestTime (0), requestTimeoutTimer (service) {}; std::set excluded; uint64_t requestTime; boost::asio::deadline_timer requestTimeoutTimer; + RequestComplete requestComplete; }; public: @@ -57,7 +60,7 @@ namespace client i2p::tunnel::TunnelPool * GetTunnelPool () { return m_Pool; }; bool IsReady () const { return m_LeaseSet && m_LeaseSet->HasNonExpiredLeases (); }; const i2p::data::LeaseSet * FindLeaseSet (const i2p::data::IdentHash& ident); - bool RequestDestination (const i2p::data::IdentHash& dest); + bool RequestDestination (const i2p::data::IdentHash& dest, RequestComplete requestComplete = nullptr); // streaming i2p::stream::StreamingDestination * GetStreamingDestination () const { return m_StreamingDestination; }; @@ -98,8 +101,8 @@ namespace client void HandleDatabaseSearchReplyMessage (const uint8_t * buf, size_t len); void HandleDeliveryStatusMessage (I2NPMessage * msg); - void RequestLeaseSet (const i2p::data::IdentHash& dest); - void SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr nextFloodfill, LeaseSetRequest * request); + void RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete); + bool SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr nextFloodfill, LeaseSetRequest * request); void HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest); private: