diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index cb618b5d..c9db4a82 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -26,7 +26,8 @@ namespace client I2CPDestination::I2CPDestination (boost::asio::io_service& service, std::shared_ptr owner, std::shared_ptr identity, bool isPublic, const std::map& params): LeaseSetDestination (service, isPublic, ¶ms), - m_Owner (owner), m_Identity (identity), m_EncryptionKeyType (m_Identity->GetCryptoKeyType ()) + m_Owner (owner), m_Identity (identity), m_EncryptionKeyType (m_Identity->GetCryptoKeyType ()), + m_IsCreatingLeaseSet (false), m_LeaseSetCreationTimer (service) { } @@ -34,6 +35,7 @@ namespace client { LeaseSetDestination::Stop (); m_Owner = nullptr; + m_LeaseSetCreationTimer.cancel (); } void I2CPDestination::SetEncryptionPrivateKey (const uint8_t * key) @@ -84,6 +86,11 @@ namespace client void I2CPDestination::CreateNewLeaseSet (std::vector > tunnels) { + if (m_IsCreatingLeaseSet) + { + LogPrint (eLogInfo, "I2CP: LeaseSet is being created"); + return; + } uint8_t priv[256] = {0}; i2p::data::LocalLeaseSet ls (m_Identity, priv, tunnels); // we don't care about encryption key, we need leases only m_LeaseSetExpirationTime = ls.GetExpirationTime (); @@ -94,15 +101,28 @@ namespace client uint16_t sessionID = m_Owner->GetSessionID (); if (sessionID != 0xFFFF) { + m_IsCreatingLeaseSet = true; htobe16buf (leases - 3, sessionID); size_t l = 2/*sessionID*/ + 1/*num leases*/ + i2p::data::LEASE_SIZE*tunnels.size (); m_Owner->SendI2CPMessage (I2CP_REQUEST_VARIABLE_LEASESET_MESSAGE, leases - 3, l); + m_LeaseSetCreationTimer.expires_from_now (boost::posix_time::seconds (I2CP_LEASESET_CREATION_TIMEOUT)); + auto s = GetSharedFromThis (); + m_LeaseSetCreationTimer.async_wait ([s](const boost::system::error_code& ecode) + { + if (ecode != boost::asio::error::operation_aborted) + { + LogPrint (eLogInfo, "I2CP: LeaseSet creation timeout expired. Terminate"); + if (s->m_Owner) s->m_Owner->Stop (); + } + }); } } } void I2CPDestination::LeaseSetCreated (const uint8_t * buf, size_t len) { + m_IsCreatingLeaseSet = false; + m_LeaseSetCreationTimer.cancel (); auto ls = std::make_shared (m_Identity, buf, len); ls->SetExpirationTime (m_LeaseSetExpirationTime); SetLeaseSet (ls); @@ -110,6 +130,8 @@ namespace client void I2CPDestination::LeaseSet2Created (uint8_t storeType, const uint8_t * buf, size_t len) { + m_IsCreatingLeaseSet = false; + m_LeaseSetCreationTimer.cancel (); auto ls = (storeType == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) ? std::make_shared (m_Identity, buf, len): std::make_shared (storeType, m_Identity, buf, len); diff --git a/libi2pd_client/I2CP.h b/libi2pd_client/I2CP.h index 32f32221..da7d8ffa 100644 --- a/libi2pd_client/I2CP.h +++ b/libi2pd_client/I2CP.h @@ -27,7 +27,8 @@ namespace client const size_t I2CP_SESSION_BUFFER_SIZE = 4096; const size_t I2CP_MAX_MESSAGE_LENGTH = 65535; const size_t I2CP_MAX_SEND_QUEUE_SIZE = 1024*1024; // in bytes, 1M - + const int I2CP_LEASESET_CREATION_TIMEOUT = 10; // in seconds + const size_t I2CP_HEADER_LENGTH_OFFSET = 0; const size_t I2CP_HEADER_TYPE_OFFSET = I2CP_HEADER_LENGTH_OFFSET + 4; const size_t I2CP_HEADER_SIZE = I2CP_HEADER_TYPE_OFFSET + 1; @@ -109,6 +110,8 @@ namespace client std::shared_ptr m_ECIESx25519Decryptor; uint8_t m_ECIESx25519PrivateKey[32]; uint64_t m_LeaseSetExpirationTime; + bool m_IsCreatingLeaseSet; + boost::asio::deadline_timer m_LeaseSetCreationTimer; }; class RunnableI2CPDestination: private i2p::util::RunnableService, public I2CPDestination