diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 5e790290..eca0ddd1 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1167,6 +1167,23 @@ namespace client if (m_StreamingDestination) m_StreamingDestination->Start (); } + void ClientDestination::UpdateOfflineSignature (const i2p::data::PrivateKeys& keys) + { + // Adopt a newer offline transient of the same identity in place: swap keys and + // republish the LeaseSet, keeping tunnels and streams (unlike SetPrivateKeys). + if (!keys.IsOfflineSignature () || !m_Keys.IsOfflineSignature ()) return; + if (keys.GetPublic ()->GetIdentHash () != GetIdentHash ()) return; + const uint32_t expires = bufbe32toh (keys.GetOfflineSignature ().data ()); + if (expires <= bufbe32toh (m_Keys.GetOfflineSignature ().data ())) return; // only move forward + LogPrint (eLogInfo, "Destination: Refreshing offline signature for ", + GetIdentHash ().ToBase32 (), ", transient expires ", expires); + boost::asio::post (GetService (), [s = GetSharedFromThis (), keys]() + { + s->m_Keys = keys; + s->UpdateLeaseSet (); + }); + } + void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len, i2p::garlic::ECIESX25519AEADRatchetSession * from) { diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 579ba7d4..82cda560 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -186,10 +186,10 @@ namespace client // I2CP virtual void HandleDataMessage (const uint8_t * buf, size_t len, i2p::garlic::ECIESX25519AEADRatchetSession * from) = 0; virtual void CreateNewLeaseSet (const std::vector >& tunnels) = 0; + void UpdateLeaseSet (); private: - void UpdateLeaseSet (); std::shared_ptr GetLeaseSetMt (); void Publish (); void HandlePublishConfirmationTimer (const boost::system::error_code& ecode); @@ -252,6 +252,7 @@ namespace client const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; }; void SetPrivateKeys (const i2p::data::PrivateKeys& keys); + void UpdateOfflineSignature (const i2p::data::PrivateKeys& keys); void Sign (const uint8_t * buf, int len, uint8_t * signature) const { m_Keys.Sign (buf, len, signature); }; // ref counter diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index 9cabe30a..3f15e41a 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -410,6 +410,8 @@ namespace client if (it != m_Destinations.end ()) { LogPrint (eLogWarning, "Clients: Local destination ", m_AddressBook.ToAddress(keys.GetPublic ()->GetIdentHash ()), " exists"); + if (keys.IsOfflineSignature ()) + it->second->UpdateOfflineSignature (keys); it->second->Start (); // make sure to start return it->second; } @@ -425,6 +427,8 @@ namespace client if (it != m_Destinations.end ()) { LogPrint (eLogWarning, "Clients: Local destination ", m_AddressBook.ToAddress(keys.GetPublic ()->GetIdentHash ()), " exists"); + if (keys.IsOfflineSignature ()) + it->second->UpdateOfflineSignature (keys); it->second->Start (); // make sure to start return it->second; }