diff --git a/Destination.cpp b/Destination.cpp index f2dac631..c07718cb 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -187,16 +187,17 @@ namespace client auto it = m_RemoteLeaseSets.find (ident); if (it != m_RemoteLeaseSets.end ()) { - if (it->second->HasNonExpiredLeases ()) + if (!it->second->IsExpired ()) return it->second; else - LogPrint (eLogWarning, "Destination: All leases of remote LeaseSet expired"); + LogPrint (eLogWarning, "Destination: remote LeaseSet expired"); } else { auto ls = i2p::data::netdb.FindLeaseSet (ident); if (ls) { + ls->PopulateLeases (); // since we don't store them in netdb m_RemoteLeaseSets[ident] = ls; return ls; } @@ -674,9 +675,10 @@ namespace client void ClientDestination::CleanupRemoteLeaseSets () { + auto ts = i2p::util::GetMillisecondsSinceEpoch (); for (auto it = m_RemoteLeaseSets.begin (); it != m_RemoteLeaseSets.end ();) { - if (!it->second->HasNonExpiredLeases ()) // all leases expired + if (ts > it->second->GetExpirationTime ()) // leaseset expired { LogPrint (eLogWarning, "Destination: Remote LeaseSet ", it->second->GetIdentHash ().ToBase64 (), " expired"); it = m_RemoteLeaseSets.erase (it); diff --git a/Destination.h b/Destination.h index ece125e3..c45a20ec 100644 --- a/Destination.h +++ b/Destination.h @@ -72,7 +72,7 @@ namespace client bool IsRunning () const { return m_IsRunning; }; boost::asio::io_service& GetService () { return m_Service; }; std::shared_ptr GetTunnelPool () { return m_Pool; }; - bool IsReady () const { return m_LeaseSet && m_LeaseSet->HasNonExpiredLeases () && m_Pool->GetOutboundTunnels ().size () > 0; }; + bool IsReady () const { return m_LeaseSet && !m_LeaseSet->IsExpired () && m_Pool->GetOutboundTunnels ().size () > 0; }; std::shared_ptr FindLeaseSet (const i2p::data::IdentHash& ident); bool RequestDestination (const i2p::data::IdentHash& dest, RequestComplete requestComplete = nullptr); void CancelDestinationRequest (const i2p::data::IdentHash& dest); diff --git a/HTTPServer.cpp b/HTTPServer.cpp index 2fef6e66..f04b0b1c 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -793,7 +793,7 @@ namespace util } auto leaseSet = i2p::client::context.GetSharedLocalDestination ()->FindLeaseSet (destination); - if (leaseSet && leaseSet->HasNonExpiredLeases ()) + if (leaseSet && !leaseSet->IsExpired ()) SendToDestination (leaseSet, port, buf, len); else { @@ -812,7 +812,7 @@ namespace util if (ecode != boost::asio::error::operation_aborted) { auto leaseSet = i2p::client::context.GetSharedLocalDestination ()->FindLeaseSet (destination); - if (leaseSet && leaseSet->HasNonExpiredLeases ()) + if (leaseSet && !leaseSet->IsExpired ()) SendToDestination (leaseSet, port, buf, len); else // still no LeaseSet diff --git a/LeaseSet.cpp b/LeaseSet.cpp index 716ee6d2..adcbc388 100644 --- a/LeaseSet.cpp +++ b/LeaseSet.cpp @@ -12,8 +12,8 @@ namespace i2p namespace data { - LeaseSet::LeaseSet (const uint8_t * buf, size_t len): - m_IsValid (true) + LeaseSet::LeaseSet (const uint8_t * buf, size_t len, bool storeLeases): + m_IsValid (true), m_StoreLeases (storeLeases), m_ExpirationTime (0) { m_Buffer = new uint8_t[len]; memcpy (m_Buffer, buf, len); @@ -22,7 +22,7 @@ namespace data } LeaseSet::LeaseSet (std::shared_ptr pool): - m_IsValid (true) + m_IsValid (true), m_StoreLeases (true), m_ExpirationTime (0) { if (!pool) return; // header @@ -55,6 +55,7 @@ namespace data uint64_t ts = it->GetCreationTime () + i2p::tunnel::TUNNEL_EXPIRATION_TIMEOUT - i2p::tunnel::TUNNEL_EXPIRATION_THRESHOLD; // 1 minute before expiration ts *= 1000; // in milliseconds ts += rand () % 6; // + random milliseconds 0-5 + if (ts > m_ExpirationTime) m_ExpirationTime = ts; htobe64buf (m_Buffer + m_BufferLen, ts); m_BufferLen += 8; // end date } @@ -79,7 +80,14 @@ namespace data m_BufferLen = len; ReadFromBuffer (false); } - + + void LeaseSet::PopulateLeases () + { + m_StoreLeases = true; + m_Leases.clear (); + ReadFromBuffer (false); + } + void LeaseSet::ReadFromBuffer (bool readIdentity) { if (readIdentity || !m_Identity) @@ -105,6 +113,7 @@ namespace data } // process leases + m_ExpirationTime = 0; const uint8_t * leases = m_Buffer + size; for (int i = 0; i < num; i++) { @@ -113,16 +122,20 @@ namespace data leases += 32; // gateway lease.tunnelID = bufbe32toh (leases); leases += 4; // tunnel ID - lease.endDate = bufbe64toh (leases); + lease.endDate = bufbe64toh (leases); leases += 8; // end date - m_Leases.push_back (lease); - - // check if lease's gateway is in our netDb - if (!netdb.FindRouter (lease.tunnelGateway)) - { - // if not found request it - LogPrint (eLogInfo, "LeaseSet: Lease's tunnel gateway not found, requesting"); - netdb.RequestDestination (lease.tunnelGateway); + if (lease.endDate > m_ExpirationTime) + m_ExpirationTime = lease.endDate; + if (m_StoreLeases) + { + m_Leases.push_back (lease); + // check if lease's gateway is in our netDb + if (!netdb.FindRouter (lease.tunnelGateway)) + { + // if not found request it + LogPrint (eLogInfo, "LeaseSet: Lease's tunnel gateway not found, requesting"); + netdb.RequestDestination (lease.tunnelGateway); + } } } @@ -150,19 +163,17 @@ namespace data } bool LeaseSet::HasExpiredLeases () const - { + { auto ts = i2p::util::GetMillisecondsSinceEpoch (); for (auto& it: m_Leases) if (ts >= it.endDate) return true; return false; - } + } - bool LeaseSet::HasNonExpiredLeases () const + bool LeaseSet::IsExpired () const { auto ts = i2p::util::GetMillisecondsSinceEpoch (); - for (auto& it: m_Leases) - if (ts < it.endDate) return true; - return false; + return ts > m_ExpirationTime; } } } diff --git a/LeaseSet.h b/LeaseSet.h index aa9b73ad..0f437170 100644 --- a/LeaseSet.h +++ b/LeaseSet.h @@ -37,10 +37,11 @@ namespace data { public: - LeaseSet (const uint8_t * buf, size_t len); + LeaseSet (const uint8_t * buf, size_t len, bool storeLeases = true); LeaseSet (std::shared_ptr pool); ~LeaseSet () { delete[] m_Buffer; }; void Update (const uint8_t * buf, size_t len); + void PopulateLeases (); /// from buffer std::shared_ptr GetIdentity () const { return m_Identity; }; const uint8_t * GetBuffer () const { return m_Buffer; }; @@ -52,7 +53,8 @@ namespace data const std::vector& GetLeases () const { return m_Leases; }; const std::vector GetNonExpiredLeases (bool withThreshold = true) const; bool HasExpiredLeases () const; - bool HasNonExpiredLeases () const; + bool IsExpired () const; + uint64_t GetExpirationTime () const { return m_ExpirationTime; }; const uint8_t * GetEncryptionPublicKey () const { return m_EncryptionKey; }; bool IsDestination () const { return true; }; @@ -62,8 +64,9 @@ namespace data private: - bool m_IsValid; + bool m_IsValid, m_StoreLeases; // we don't need to store leases for floodfill std::vector m_Leases; + uint64_t m_ExpirationTime; // in milliseconds std::shared_ptr m_Identity; uint8_t m_EncryptionKey[256]; uint8_t * m_Buffer; diff --git a/NetDb.cpp b/NetDb.cpp index 70b33f7f..fe1d6a45 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -206,7 +206,7 @@ namespace data } else { - auto leaseSet = std::make_shared (buf, len); + auto leaseSet = std::make_shared (buf, len, false); // we don't need leases in netdb if (leaseSet->IsValid ()) { LogPrint (eLogInfo, "NetDb: LeaseSet added: ", ident.ToBase64()); @@ -981,9 +981,10 @@ namespace data void NetDb::ManageLeaseSets () { + auto ts = i2p::util::GetMillisecondsSinceEpoch (); for (auto it = m_LeaseSets.begin (); it != m_LeaseSets.end ();) { - if (!it->second->HasNonExpiredLeases ()) // all leases expired + if (ts > it->second->GetExpirationTime ()) { LogPrint (eLogWarning, "NetDb: LeaseSet ", it->second->GetIdentHash ().ToBase64 (), " expired"); it = m_LeaseSets.erase (it);