From 7d93ac0f022c1128a156ec0ce6bcc4e79869e5c3 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 8 Sep 2026 20:53:22 -0400 Subject: [PATCH] maintain connections list per torrent --- libi2pd_client/Torrents.cpp | 31 +++++++++++++++++++++++++++++-- libi2pd_client/Torrents.h | 4 ++++ libi2pd_client/TorrentsRPC.cpp | 8 ++++---- libi2pd_client/TorrentsTunnel.cpp | 22 ++-------------------- libi2pd_client/TorrentsTunnel.h | 1 - 5 files changed, 39 insertions(+), 27 deletions(-) diff --git a/libi2pd_client/Torrents.cpp b/libi2pd_client/Torrents.cpp index e28dea7a..cd95c260 100644 --- a/libi2pd_client/Torrents.cpp +++ b/libi2pd_client/Torrents.cpp @@ -725,6 +725,7 @@ namespace torrents bool Torrent::UpdateStatus (uint64_t ts) { + GetConnections (); // cleanup expired connections if (!m_Length) return false; // non ready magnet bool complete = true; for (auto& it: m_Pieces) @@ -902,6 +903,29 @@ namespace torrents return eTorrentStatusDownloading; } + void Torrent::AddConnection (std::shared_ptr conn) + { + m_Connections.emplace_back (conn); + } + + std::list > Torrent::GetConnections () + { + std::list > ret; + auto it = m_Connections.begin (); + while (it != m_Connections.end ()) + { + auto conn = it->lock (); + if (conn) + { + ret.emplace_back (conn); + it++; + } + else + it = m_Connections.erase (it); + } + return ret; + } + PeerConnection::PeerConnection (std::shared_ptr owner, std::shared_ptr stream): i2p::client::I2PServiceHandler (owner), m_Stream (stream), m_ReceiveBufferOffset (0), m_NextMsgLength (0), m_MaxNumRequests (MIN_NUM_REQUESTS), @@ -1268,6 +1292,9 @@ namespace torrents // BEP6 if (m_ReceiveBuffer[20 + 7] & 0x04) // bit 61 of reserved m_IsFast = true; + // established + m_IsEstablished = true; + m_Torrent->AddConnection (shared_from_this ()); // send bitfield, have all or have none auto [bitfield, empty] = m_Torrent->CreateBitfield (); if (!empty) @@ -1279,7 +1306,7 @@ namespace torrents } else if (m_IsFast) SendHaveNoneMsg (); - m_IsEstablished = true; + return HANDSHAKE_MSG_LENGTH; } @@ -1444,7 +1471,7 @@ namespace torrents torrent->SaveTorrentResumeFile (resumeFilePath); }); // send have - auto conns = GetTorrentsTunnel ()->GetTorrentConnections (m_Torrent); + auto conns = m_Torrent->GetConnections (); for (auto it: conns) it->SendHaveMsg (index); } diff --git a/libi2pd_client/Torrents.h b/libi2pd_client/Torrents.h index 24e7ae66..e6f1b555 100644 --- a/libi2pd_client/Torrents.h +++ b/libi2pd_client/Torrents.h @@ -161,6 +161,7 @@ namespace torrents }; using RequestedBlock = std::tuple; // (index, offset, len) + class PeerConnection; class Torrent final { using TrackerStats = std::tuple, @@ -210,6 +211,8 @@ namespace torrents std::vector GetPieceFileFragments (int index) const; std::vector GetFilesCompleted () const; // completed size per file bool UpdateStatus (uint64_t ts); // return true if complete + void AddConnection (std::shared_ptr conn); + std::list > GetConnections (); uint64_t GetNextTrackerRequestTime (size_t trackerID) const; void SetNextTrackerRequestTime (size_t trackerID, uint64_t ts); @@ -259,6 +262,7 @@ namespace torrents InfoHash m_InfoHash; // SHA1 std::vector m_Pieces; std::vector m_TrackerStats; + std::list > m_Connections; bool m_IsComplete, m_IsStopped; std::list > m_Files; // list of (path, length) size_t m_Uploaded, m_Downloaded; diff --git a/libi2pd_client/TorrentsRPC.cpp b/libi2pd_client/TorrentsRPC.cpp index 0e5b59ab..ff745eaf 100644 --- a/libi2pd_client/TorrentsRPC.cpp +++ b/libi2pd_client/TorrentsRPC.cpp @@ -370,9 +370,9 @@ namespace torrents boost::json::array peers; std::list > conns; boost::asio::post (m_Tunnel->GetService (), - boost::asio::use_future ([tunnel = m_Tunnel, torrent, &conns]() + boost::asio::use_future ([torrent, &conns]() { - conns = tunnel->GetTorrentConnections (torrent); + conns = torrent->GetConnections (); })).wait (); for (const auto& it: conns) { @@ -410,9 +410,9 @@ namespace torrents { std::list > conns; boost::asio::post (m_Tunnel->GetService (), - boost::asio::use_future ([tunnel = m_Tunnel, torrent, &conns]() + boost::asio::use_future ([torrent, &conns]() { - conns = tunnel->GetTorrentConnections (torrent); + conns = torrent->GetConnections (); })).wait (); return boost::json::value(conns.size ()); } diff --git a/libi2pd_client/TorrentsTunnel.cpp b/libi2pd_client/TorrentsTunnel.cpp index 86ef115c..8d247d5e 100644 --- a/libi2pd_client/TorrentsTunnel.cpp +++ b/libi2pd_client/TorrentsTunnel.cpp @@ -277,7 +277,7 @@ namespace torrents // inform trackers that we are done RequestTorrentTrackers (torrent, eTrackerAnnounceEventCompleted); // close connections with seeds and reset stats for remaining - auto conns = GetTorrentConnections (torrent); + auto conns = torrent->GetConnections (); for (auto it: conns) { if (it->GetRemoteBitfield ().all ()) // seed @@ -508,7 +508,7 @@ namespace torrents // inform trackers that we stopped RequestTorrentTrackers (torrent, eTrackerAnnounceEventStopped); // close connections - auto connections = GetTorrentConnections (torrent); + auto connections = torrent->GetConnections (); for (auto it: connections) it->Close (); } @@ -827,24 +827,6 @@ namespace torrents } } - std::list > TorrentsTunnel::GetTorrentConnections (std::shared_ptr torrent) - { - std::list > ret; - if (torrent) - { - IterateHandlers ([&ret, torrent](std::shared_ptr handler) - { - if (handler) - { - auto conn = std::static_pointer_cast(handler); - if (conn->GetTorrent () == torrent && conn->GetStream ()) - ret.emplace_back (conn); - } - }); - } - return ret; - } - std::unordered_set TorrentsTunnel::GetNonConnectedPeers (std::shared_ptr torrent) { std::unordered_set ret; diff --git a/libi2pd_client/TorrentsTunnel.h b/libi2pd_client/TorrentsTunnel.h index 9a9a070f..155e5aa1 100644 --- a/libi2pd_client/TorrentsTunnel.h +++ b/libi2pd_client/TorrentsTunnel.h @@ -105,7 +105,6 @@ namespace torrents bool RemoveTorrent (int id, bool deleteFiles); bool StopTorrent (int id); bool StartTorrent (int id); - std::list > GetTorrentConnections (std::shared_ptr torrent); const char* GetName() const override { return m_Name.c_str (); }