diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index a86153b9..6f25c2e8 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2021, The PurpleI2P Project +* Copyright (c) 2013-2022, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -519,21 +519,26 @@ namespace client void I2CPSession::CreateSessionMessageHandler (const uint8_t * buf, size_t len) { RAND_bytes ((uint8_t *)&m_SessionID, 2); - m_Owner.InsertSession (shared_from_this ()); auto identity = std::make_shared(); size_t offset = identity->FromBuffer (buf, len); if (!offset) { LogPrint (eLogError, "I2CP: Create session malformed identity"); - SendSessionStatusMessage (3); // invalid + SendSessionStatusMessage (eI2CPSessionStatusInvalid); // invalid return; } + if (m_Owner.FindSessionByIdentHash (identity->GetIdentHash ())) + { + LogPrint (eLogError, "I2CP: Create session duplicate address ", identity->GetIdentHash ().ToBase32 ()); + SendSessionStatusMessage (eI2CPSessionStatusInvalid); // invalid + return; + } uint16_t optionsSize = bufbe16toh (buf + offset); offset += 2; if (optionsSize > len - offset) { LogPrint (eLogError, "I2CP: Options size ", optionsSize, "exceeds message size"); - SendSessionStatusMessage (3); // invalid + SendSessionStatusMessage (eI2CPSessionStatusInvalid); // invalid return; } std::map params; @@ -549,33 +554,41 @@ namespace client m_Destination = m_Owner.IsSingleThread () ? std::make_shared(m_Owner.GetService (), shared_from_this (), identity, true, params): std::make_shared(shared_from_this (), identity, true, params); - SendSessionStatusMessage (1); // created - LogPrint (eLogDebug, "I2CP: Session ", m_SessionID, " created"); - m_Destination->Start (); + if (m_Owner.InsertSession (shared_from_this ())) + { + SendSessionStatusMessage (eI2CPSessionStatusCreated); // created + LogPrint (eLogDebug, "I2CP: Session ", m_SessionID, " created"); + m_Destination->Start (); + } + else + { + LogPrint (eLogError, "I2CP: Session already exists"); + SendSessionStatusMessage (eI2CPSessionStatusRefused); + } } else { LogPrint (eLogError, "I2CP: Session already exists"); - SendSessionStatusMessage (4); // refused + SendSessionStatusMessage (eI2CPSessionStatusRefused); // refused } } else { LogPrint (eLogError, "I2CP: Create session signature verification failed"); - SendSessionStatusMessage (3); // invalid + SendSessionStatusMessage (eI2CPSessionStatusInvalid); // invalid } } void I2CPSession::DestroySessionMessageHandler (const uint8_t * buf, size_t len) { - SendSessionStatusMessage (0); // destroy + SendSessionStatusMessage (eI2CPSessionStatusDestroyed); // destroy LogPrint (eLogDebug, "I2CP: Session ", m_SessionID, " destroyed"); Terminate (); } void I2CPSession::ReconfigureSessionMessageHandler (const uint8_t * buf, size_t len) { - uint8_t status = 3; // rejected + I2CPSessionStatus status = eI2CPSessionStatusInvalid; // rejected if(len > sizeof(uint16_t)) { uint16_t sessionID = bufbe16toh(buf); @@ -605,7 +618,7 @@ namespace client if(m_Destination->Reconfigure(opts)) { LogPrint(eLogInfo, "I2CP: Reconfigured destination"); - status = 2; // updated + status = eI2CPSessionStatusUpdated; // updated } else LogPrint(eLogWarning, "I2CP: Failed to reconfigure destination"); @@ -630,11 +643,11 @@ namespace client SendSessionStatusMessage (status); } - void I2CPSession::SendSessionStatusMessage (uint8_t status) + void I2CPSession::SendSessionStatusMessage (I2CPSessionStatus status) { uint8_t buf[3]; htobe16buf (buf, m_SessionID); - buf[2] = status; + buf[2] = (uint8_t)status; SendI2CPMessage (I2CP_SESSION_STATUS_MESSAGE, buf, 3); } @@ -1009,5 +1022,19 @@ namespace client { m_Sessions.erase (sessionID); } + + std::shared_ptr I2CPServer::FindSessionByIdentHash (const i2p::data::IdentHash& ident) const + { + for (const auto& it: m_Sessions) + { + if (it.second) + { + auto dest = it.second->GetDestination (); + if (dest && dest->GetIdentHash () == ident) + return it.second; + } + } + return nullptr; + } } } diff --git a/libi2pd_client/I2CP.h b/libi2pd_client/I2CP.h index b2e1d15f..5495be7a 100644 --- a/libi2pd_client/I2CP.h +++ b/libi2pd_client/I2CP.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013-2020, The PurpleI2P Project +* Copyright (c) 2013-2022, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * @@ -61,6 +61,15 @@ namespace client eI2CPMessageStatusNoLeaseSet = 21 }; + enum I2CPSessionStatus + { + eI2CPSessionStatusDestroyed = 0, + eI2CPSessionStatusCreated = 1, + eI2CPSessionStatusUpdated = 2, + eI2CPSessionStatusInvalid = 3, + eI2CPSessionStatusRefused = 4 + }; + // params const char I2CP_PARAM_MESSAGE_RELIABILITY[] = "i2cp.messageReliability"; @@ -180,7 +189,7 @@ namespace client std::string ExtractString (const uint8_t * buf, size_t len); size_t PutString (uint8_t * buf, size_t len, const std::string& str); void ExtractMapping (const uint8_t * buf, size_t len, std::map& mapping); - void SendSessionStatusMessage (uint8_t status); + void SendSessionStatusMessage (I2CPSessionStatus status); void SendHostReplyMessage (uint32_t requestID, std::shared_ptr identity); private: @@ -216,6 +225,7 @@ namespace client bool InsertSession (std::shared_ptr session); void RemoveSession (uint16_t sessionID); + std::shared_ptr FindSessionByIdentHash (const i2p::data::IdentHash& ident) const; private: