diff --git a/Config.cpp b/Config.cpp index ed22c561..fb587e61 100644 --- a/Config.cpp +++ b/Config.cpp @@ -87,8 +87,8 @@ namespace config { ("httpproxy.outbound.length", value()->default_value("3"), "HTTP proxy outbound tunnel length") ("httpproxy.inbound.quantity", value()->default_value("5"), "HTTP proxy inbound tunnels quantity") ("httpproxy.outbound.quantity", value()->default_value("5"), "HTTP proxy outbound tunnels quantity") - ("httpproxy.latency.min", value()->default_value(0), "HTTP proxy min latency for tunnels") - ("httpproxy.latency.max", value()->default_value(0), "HTTP proxy max latency for tunnels") + ("httpproxy.latency.min", value()->default_value("0"), "HTTP proxy min latency for tunnels") + ("httpproxy.latency.max", value()->default_value("0"), "HTTP proxy max latency for tunnels") ; options_description socksproxy("SOCKS Proxy options"); @@ -101,8 +101,8 @@ namespace config { ("socksproxy.outbound.length", value()->default_value("3"), "SOCKS proxy outbound tunnel length") ("socksproxy.inbound.quantity", value()->default_value("5"), "SOCKS proxy inbound tunnels quantity") ("socksproxy.outbound.quantity", value()->default_value("5"), "SOCKS proxy outbound tunnels quantity") - ("socksproxy.latency.min", value()->default_value(0), "SOCKS proxy min latency for tunnels") - ("socksproxy.latency.max", value()->default_value(0), "SOCKS proxy max latency for tunnels") + ("socksproxy.latency.min", value()->default_value("0"), "SOCKS proxy min latency for tunnels") + ("socksproxy.latency.max", value()->default_value("0"), "SOCKS proxy max latency for tunnels") ("socksproxy.outproxy", value()->default_value("127.0.0.1"), "Upstream outproxy address for SOCKS Proxy") ("socksproxy.outproxyport", value()->default_value(9050), "Upstream outproxy port for SOCKS Proxy") ; diff --git a/Destination.cpp b/Destination.cpp index f0bc52cb..9cf49336 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -86,7 +86,7 @@ namespace client if (m_IsRunning) Stop (); for (auto& it: m_LeaseSetRequests) - if (it.second->requestComplete) it.second->requestComplete (nullptr); + it.second->Complete (nullptr); m_LeaseSetRequests.clear (); if (m_Pool) i2p::tunnel::tunnels.DeleteTunnelPool (m_Pool); @@ -345,7 +345,7 @@ namespace client if (it1 != m_LeaseSetRequests.end ()) { it1->second->requestTimeoutTimer.cancel (); - if (it1->second->requestComplete) it1->second->requestComplete (leaseSet); + if (it1->second) it1->second->Complete (leaseSet); m_LeaseSetRequests.erase (it1); } } @@ -383,7 +383,7 @@ namespace client if (!found) { LogPrint (eLogInfo, "Destination: ", key.ToBase64 (), " was not found on ", MAX_NUM_FLOODFILLS_PER_REQUEST, " floodfills"); - if (request->requestComplete) request->requestComplete (nullptr); + request->Complete (nullptr); m_LeaseSetRequests.erase (key); } } @@ -512,9 +512,9 @@ namespace client auto it = s->m_LeaseSetRequests.find (dest); if (it != s->m_LeaseSetRequests.end ()) { - auto requestComplete = it->second->requestComplete; + auto requestComplete = it->second; s->m_LeaseSetRequests.erase (it); - if (notify && requestComplete) requestComplete (nullptr); + if (notify && requestComplete) requestComplete->Complete (nullptr); } }); } @@ -526,7 +526,7 @@ namespace client if (floodfill) { auto request = std::make_shared (m_Service); - request->requestComplete = requestComplete; + request->requestComplete.push_back (requestComplete); auto ret = m_LeaseSetRequests.insert (std::pair >(dest,request)); if (ret.second) // inserted { @@ -534,20 +534,19 @@ namespace client { // request failed m_LeaseSetRequests.erase (dest); - if (request->requestComplete) request->requestComplete (nullptr); + requestComplete (nullptr); } } else // duplicate { - LogPrint (eLogWarning, "Destination: Request of LeaseSet ", dest.ToBase64 (), " is pending already"); - // TODO: queue up requests - if (request->requestComplete) request->requestComplete (nullptr); + LogPrint (eLogInfo, "Destination: Request of LeaseSet ", dest.ToBase64 (), " is pending already"); + ret.first->second->requestComplete.push_back (requestComplete); } } else { LogPrint (eLogError, "Destination: Can't request LeaseSet, no floodfills found"); - if (requestComplete) requestComplete (nullptr); + requestComplete (nullptr); } } @@ -622,9 +621,9 @@ namespace client if (done) { - auto requestComplete = it->second->requestComplete; + auto requestComplete = it->second; m_LeaseSetRequests.erase (it); - if (requestComplete) requestComplete (nullptr); + if (requestComplete) requestComplete->Complete (nullptr); } } } diff --git a/Destination.h b/Destination.h index 0d3b3b4a..5b3ee655 100644 --- a/Destination.h +++ b/Destination.h @@ -69,9 +69,15 @@ namespace client std::set excluded; uint64_t requestTime; boost::asio::deadline_timer requestTimeoutTimer; - RequestComplete requestComplete; + std::list requestComplete; std::shared_ptr outboundTunnel; std::shared_ptr replyTunnel; + + void Complete (std::shared_ptr ls) + { + for (auto& it: requestComplete) it (ls); + requestComplete.clear (); + } }; diff --git a/Garlic.cpp b/Garlic.cpp index 1cd1676e..35c8bc15 100644 --- a/Garlic.cpp +++ b/Garlic.cpp @@ -20,6 +20,7 @@ namespace garlic std::shared_ptr destination, int numTags, bool attachLeaseSet): m_Owner (owner), m_Destination (destination), m_NumTags (numTags), m_LeaseSetUpdateStatus (attachLeaseSet ? eLeaseSetUpdated : eLeaseSetDoNotSend), + m_LeaseSetUpdateMsgID (0), m_ElGamalEncryption (new i2p::crypto::ElGamalEncryption (destination->GetEncryptionPublicKey ())) { // create new session tags and session key @@ -28,7 +29,7 @@ namespace garlic } GarlicRoutingSession::GarlicRoutingSession (const uint8_t * sessionKey, const SessionTag& sessionTag): - m_Owner (nullptr), m_Destination (nullptr), m_NumTags (1), m_LeaseSetUpdateStatus (eLeaseSetDoNotSend) + m_Owner (nullptr), m_Destination (nullptr), m_NumTags (1), m_LeaseSetUpdateStatus (eLeaseSetDoNotSend), m_LeaseSetUpdateMsgID (0) { memcpy (m_SessionKey, sessionKey, 32); m_Encryption.SetKey (m_SessionKey); @@ -83,6 +84,7 @@ namespace garlic if (msgID == m_LeaseSetUpdateMsgID) { m_LeaseSetUpdateStatus = eLeaseSetUpToDate; + m_LeaseSetUpdateMsgID = 0; LogPrint (eLogInfo, "Garlic: LeaseSet update confirmed"); } else @@ -117,7 +119,7 @@ namespace garlic bool GarlicRoutingSession::CleanupExpiredTags () { - uint32_t ts = i2p::util::GetSecondsSinceEpoch (); + auto ts = i2p::util::GetSecondsSinceEpoch (); for (auto it = m_SessionTags.begin (); it != m_SessionTags.end ();) { if (ts >= it->creationTime + OUTGOING_TAGS_EXPIRATION_TIMEOUT) @@ -126,6 +128,12 @@ namespace garlic ++it; } CleanupUnconfirmedTags (); + if (m_LeaseSetUpdateMsgID && ts*1000LL > m_LeaseSetSubmissionTime + LEASET_CONFIRMATION_TIMEOUT) + { + if (m_Owner) + m_Owner->RemoveDeliveryStatusSession (m_LeaseSetUpdateMsgID); + m_LeaseSetUpdateMsgID = 0; + } return !m_SessionTags.empty () || !m_UnconfirmedTagsMsgs.empty (); } @@ -277,6 +285,7 @@ namespace garlic { newTags->msgID = msgID; m_UnconfirmedTagsMsgs.emplace_back (newTags); + newTags = nullptr; // got acquired } m_Owner->DeliveryStatusSent (shared_from_this (), msgID); } @@ -286,6 +295,7 @@ namespace garlic // attach LeaseSet if (m_LeaseSetUpdateStatus == eLeaseSetUpdated) { + if (m_LeaseSetUpdateMsgID) m_Owner->RemoveDeliveryStatusSession (m_LeaseSetUpdateMsgID); // remove previous m_LeaseSetUpdateStatus = eLeaseSetSubmitted; m_LeaseSetUpdateMsgID = msgID; m_LeaseSetSubmissionTime = ts; @@ -300,13 +310,14 @@ namespace garlic size += CreateGarlicClove (payload + size, msg, m_Destination ? m_Destination->IsDestination () : false); (*numCloves)++; } - memset (payload + size, 0, 3); // certificate of message size += 3; htobe32buf (payload + size, msgID); // MessageID size += 4; htobe64buf (payload + size, ts + 8000); // Expiration of message, 8 sec size += 8; + + if (newTags) delete newTags; // not acquired, delete return size; } @@ -623,18 +634,29 @@ namespace garlic LogPrint (eLogDebug, "Garlic: ", numExpiredTags, " tags expired for ", GetIdentHash().ToBase64 ()); // outgoing - std::unique_lock l(m_SessionsMutex); - for (auto it = m_Sessions.begin (); it != m_Sessions.end ();) { - it->second->GetSharedRoutingPath (); // delete shared path if necessary - if (!it->second->CleanupExpiredTags ()) + std::unique_lock l(m_SessionsMutex); + for (auto it = m_Sessions.begin (); it != m_Sessions.end ();) { - LogPrint (eLogInfo, "Routing session to ", it->first.ToBase32 (), " deleted"); - it = m_Sessions.erase (it); + it->second->GetSharedRoutingPath (); // delete shared path if necessary + if (!it->second->CleanupExpiredTags ()) + { + LogPrint (eLogInfo, "Routing session to ", it->first.ToBase32 (), " deleted"); + it->second->SetOwner (nullptr); + it = m_Sessions.erase (it); + } + else + ++it; } + } + // delivery status sessions + for (auto it = m_DeliveryStatusSessions.begin (); it != m_DeliveryStatusSessions.end (); ) + { + if (it->second->GetOwner () != this) + it = m_DeliveryStatusSessions.erase (it); else ++it; - } + } } void GarlicDestination::RemoveDeliveryStatusSession (uint32_t msgID) diff --git a/Garlic.h b/Garlic.h index a3ab7d92..e0e65111 100644 --- a/Garlic.h +++ b/Garlic.h @@ -111,6 +111,9 @@ namespace garlic std::shared_ptr GetSharedRoutingPath (); void SetSharedRoutingPath (std::shared_ptr path); + const GarlicDestination * GetOwner () const { return m_Owner; } + void SetOwner (GarlicDestination * owner) { m_Owner = owner; } + private: size_t CreateAESBlock (uint8_t * buf, std::shared_ptr msg); diff --git a/HTTPProxy.cpp b/HTTPProxy.cpp index 60b6bc33..c40989d1 100644 --- a/HTTPProxy.cpp +++ b/HTTPProxy.cpp @@ -29,7 +29,7 @@ namespace proxy { static const char *pageHead = "\r\n" - " I2P HTTP proxy: error\r\n" + " I2Pd HTTP proxy\r\n" "