diff --git a/Destination.cpp b/Destination.cpp index f64fe208..a7d33454 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -192,7 +192,7 @@ namespace client return nullptr; } - std::shared_ptr LeaseSetDestination::GetLeaseSet () + std::shared_ptr LeaseSetDestination::GetLeaseSet () { if (!m_Pool) return nullptr; if (!m_LeaseSet) @@ -202,7 +202,12 @@ namespace client void LeaseSetDestination::UpdateLeaseSet () { - m_LeaseSet.reset (new i2p::data::LeaseSet (m_Pool)); + int numTunnels = m_Pool->GetNumInboundTunnels () + 2; // 2 backup tunnels + if (numTunnels > i2p::data::MAX_NUM_LEASES) numTunnels = i2p::data::MAX_NUM_LEASES; // 16 tunnels maximum + auto leaseSet = new i2p::data::LocalLeaseSet (GetIdentity (), GetEncryptionPublicKey (), + m_Pool->GetInboundTunnels (numTunnels)); + Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ()); // TODO + m_LeaseSet.reset (leaseSet); } bool LeaseSetDestination::SubmitSessionKey (const uint8_t * key, const uint8_t * tag) diff --git a/Destination.h b/Destination.h index c2292cfe..85b4b5ab 100644 --- a/Destination.h +++ b/Destination.h @@ -82,7 +82,7 @@ namespace client void CancelDestinationRequest (const i2p::data::IdentHash& dest); // implements GarlicDestination - std::shared_ptr GetLeaseSet (); + std::shared_ptr GetLeaseSet (); std::shared_ptr GetTunnelPool () const { return m_Pool; } void HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr from); @@ -124,7 +124,7 @@ namespace client std::map > m_LeaseSetRequests; std::shared_ptr m_Pool; - std::shared_ptr m_LeaseSet; + std::shared_ptr m_LeaseSet; bool m_IsPublic; uint32_t m_PublishReplyToken; std::set m_ExcludedFloodfills; // for publishing diff --git a/Garlic.h b/Garlic.h index ea53dd03..6d25fd39 100644 --- a/Garlic.h +++ b/Garlic.h @@ -163,7 +163,7 @@ namespace garlic virtual void ProcessDeliveryStatusMessage (std::shared_ptr msg); virtual void SetLeaseSetUpdated (); - virtual std::shared_ptr GetLeaseSet () = 0; // TODO + virtual std::shared_ptr GetLeaseSet () = 0; // TODO virtual std::shared_ptr GetTunnelPool () const = 0; virtual void HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr from) = 0; diff --git a/I2NPProtocol.cpp b/I2NPProtocol.cpp index 1f1caab7..c47a1657 100644 --- a/I2NPProtocol.cpp +++ b/I2NPProtocol.cpp @@ -249,7 +249,23 @@ namespace i2p return m; } - std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr leaseSet, uint32_t replyToken, std::shared_ptr replyTunnel) + std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr leaseSet) + { + if (!leaseSet) return nullptr; + auto m = NewI2NPShortMessage (); + uint8_t * payload = m->GetPayload (); + memcpy (payload + DATABASE_STORE_KEY_OFFSET, leaseSet->GetIdentHash (), 32); + payload[DATABASE_STORE_TYPE_OFFSET] = 1; // LeaseSet + htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0); + size_t size = DATABASE_STORE_HEADER_SIZE; + memcpy (payload + size, leaseSet->GetBuffer (), leaseSet->GetBufferLen ()); + size += leaseSet->GetBufferLen (); + m->len += size; + m->FillI2NPMessageHeader (eI2NPDatabaseStore); + return m; + } + + std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr leaseSet, uint32_t replyToken, std::shared_ptr replyTunnel) { if (!leaseSet) return nullptr; auto m = NewI2NPShortMessage (); diff --git a/I2NPProtocol.h b/I2NPProtocol.h index 1eff8c16..1ade55ed 100644 --- a/I2NPProtocol.h +++ b/I2NPProtocol.h @@ -224,7 +224,8 @@ namespace tunnel std::shared_ptr CreateDatabaseSearchReply (const i2p::data::IdentHash& ident, std::vector routers); std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr router = nullptr, uint32_t replyToken = 0); - std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr leaseSet, uint32_t replyToken = 0, std::shared_ptr replyTunnel = nullptr); + std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr leaseSet); // for floodfill only + std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr leaseSet, uint32_t replyToken = 0, std::shared_ptr replyTunnel = nullptr); bool IsRouterInfoMsg (std::shared_ptr msg); bool HandleBuildRequestRecords (int num, uint8_t * records, uint8_t * clearText); diff --git a/LeaseSet.cpp b/LeaseSet.cpp index 0bc380f6..e78cc9ce 100644 --- a/LeaseSet.cpp +++ b/LeaseSet.cpp @@ -247,7 +247,7 @@ namespace data } LocalLeaseSet::LocalLeaseSet (std::shared_ptr identity, const uint8_t * encryptionPublicKey, std::vector > tunnels): - m_Identity (identity) + m_ExpirationTime (0), m_Identity (identity) { int num = tunnels.size (); if (num > MAX_NUM_LEASES) num = MAX_NUM_LEASES; @@ -273,18 +273,19 @@ namespace data offset += 4; // tunnel id uint64_t ts = tunnels[i]->GetCreationTime () + i2p::tunnel::TUNNEL_EXPIRATION_TIMEOUT - i2p::tunnel::TUNNEL_EXPIRATION_THRESHOLD; // 1 minute before expiration ts *= 1000; // in milliseconds + if (ts > m_ExpirationTime) m_ExpirationTime = ts; // make sure leaseset is newer than previous, but adding some time to expiration date ts += (currentTime - tunnels[i]->GetCreationTime ()*1000LL)*2/i2p::tunnel::TUNNEL_EXPIRATION_TIMEOUT; // up to 2 secs htobe64buf (m_Buffer + offset, ts); offset += 8; // end date } // we don't sign it yet. must be signed later on - } + } - void LocalLeaseSet::SetSignature (const uint8_t * signature) + bool LocalLeaseSet::IsExpired () const { - auto signatureLen = GetSignatureLen (); - memcpy (m_Buffer + m_BufferLen - signatureLen, signature, signatureLen); - } + auto ts = i2p::util::GetMillisecondsSinceEpoch (); + return ts > m_ExpirationTime; + } } } diff --git a/LeaseSet.h b/LeaseSet.h index 644e0ef4..faeda67f 100644 --- a/LeaseSet.h +++ b/LeaseSet.h @@ -92,15 +92,19 @@ namespace data LocalLeaseSet (std::shared_ptr identity, const uint8_t * encryptionPublicKey, std::vector > tunnels); ~LocalLeaseSet () { delete[] m_Buffer; }; - void SetSignature (const uint8_t * signature); - const uint8_t * GetBuffer () const { return m_Buffer; }; + uint8_t * GetSignature () { return m_Buffer + m_BufferLen - GetSignatureLen (); }; size_t GetBufferLen () const { return m_BufferLen; }; size_t GetSignatureLen () const { return m_Identity->GetSignatureLen (); }; const IdentHash& GetIdentHash () const { return m_Identity->GetIdentHash (); }; + bool IsExpired () const; + bool operator== (const LeaseSet& other) const + { return m_BufferLen == other.GetBufferLen () && !memcmp (other.GetBuffer (), other.GetBuffer (), m_BufferLen); }; + private: + uint64_t m_ExpirationTime; // in milliseconds std::shared_ptr m_Identity; uint8_t * m_Buffer; size_t m_BufferLen; diff --git a/RouterContext.h b/RouterContext.h index 5a72ad58..29164f4b 100644 --- a/RouterContext.h +++ b/RouterContext.h @@ -79,7 +79,7 @@ namespace i2p void SetLeaseSetUpdated () {}; // implements GarlicDestination - std::shared_ptr GetLeaseSet () { return nullptr; }; + std::shared_ptr GetLeaseSet () { return nullptr; }; std::shared_ptr GetTunnelPool () const; void HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr from);