From 8c833634caec4a94453090fcf77b1d76353575c4 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 15 Sep 2026 19:19:00 -0400 Subject: [PATCH] add tracker from torrent's announce --- libi2pd_client/TorrentsRPC.cpp | 90 ++++++++++++++++--------------- libi2pd_client/TorrentsTunnel.cpp | 53 +++++++++--------- libi2pd_client/TorrentsTunnel.h | 6 +-- 3 files changed, 80 insertions(+), 69 deletions(-) diff --git a/libi2pd_client/TorrentsRPC.cpp b/libi2pd_client/TorrentsRPC.cpp index e1476d41..4de0aec9 100644 --- a/libi2pd_client/TorrentsRPC.cpp +++ b/libi2pd_client/TorrentsRPC.cpp @@ -410,11 +410,14 @@ namespace torrents boost::json::array trackers; for (size_t i = 0; i < m_Tunnel->GetNumTrackers (); i++) { - boost::json::object tracker; - tracker["id"] = i; - tracker["announce"] = m_Tunnel->GetTrackerAnnounce (i); - tracker["tier"] = 0; - trackers.push_back (tracker); + if (torrent->GetNextTrackerRequestTime (i)) + { + boost::json::object tracker; + tracker["id"] = i; + tracker["announce"] = m_Tunnel->GetTrackerAnnounce (i); + tracker["tier"] = 0; + trackers.push_back (tracker); + } } return trackers; } @@ -426,45 +429,48 @@ namespace torrents auto tsSinceEpoch = i2p::util::GetMillisecondsSinceEpoch (); for (size_t i = 0; i < m_Tunnel->GetNumTrackers (); i++) { - boost::json::object tracker; - tracker["id"] = i; - tracker["announce"] = m_Tunnel->GetTrackerAnnounce (i); - i2p::http::URL announceURL; - announceURL.parse (m_Tunnel->GetTrackerAnnounce (i)); - tracker["host"]= announceURL.host; - tracker["announceState"] = 1; - tracker["scrapeState"] = 0; - tracker["hasAnnounced"] = true; // TODO: - tracker["hasScraped"] = false; - tracker["isBackup"] = false; - tracker["downloadCount"] = -1; - tracker["tier"] = 0; - tracker["seederCount"] = torrent->GetNumSeeders (i); - tracker["leecherCount"] = torrent->GetNumLeechers (i); - tracker["lastAnnouncePeerCount"] = torrent->GetNumPeers (i); - auto trackerError = torrent->GetTrackerError (i); - if (trackerError.empty ()) + if (torrent->GetNextTrackerRequestTime (i)) { - tracker["lastAnnounceResult"] = "Success"; - tracker["lastAnnounceSucceeded"] = true; + boost::json::object tracker; + tracker["id"] = i; + tracker["announce"] = m_Tunnel->GetTrackerAnnounce (i); + i2p::http::URL announceURL; + announceURL.parse (m_Tunnel->GetTrackerAnnounce (i)); + tracker["host"]= announceURL.host; + tracker["announceState"] = 1; + tracker["scrapeState"] = 0; + tracker["hasAnnounced"] = true; // TODO: + tracker["hasScraped"] = false; + tracker["isBackup"] = false; + tracker["downloadCount"] = -1; + tracker["tier"] = 0; + tracker["seederCount"] = torrent->GetNumSeeders (i); + tracker["leecherCount"] = torrent->GetNumLeechers (i); + tracker["lastAnnouncePeerCount"] = torrent->GetNumPeers (i); + auto trackerError = torrent->GetTrackerError (i); + if (trackerError.empty ()) + { + tracker["lastAnnounceResult"] = "Success"; + tracker["lastAnnounceSucceeded"] = true; + } + else + { + tracker["lastAnnounceResult"] = trackerError; + tracker["lastAnnounceSucceeded"] = false; + } + tracker["lastAnnounceTimedOut"] = false; // TODO: + auto nextRequestTime = torrent->GetNextTrackerRequestTime (i); + tracker["nextAnnounceTime"] = ((nextRequestTime && nextRequestTime > ts ? nextRequestTime - ts : 0) + tsSinceEpoch)/1000; + tracker["lastAnnounceTime"] = torrent->GetLastTrackerUpdateTime (i); + tracker["lastAnnounceStartTime"] = torrent->GetLastTrackerUpdateTime (i); // TODO: + tracker["lastScrapeTime"] = 0; + tracker["lastScrapeStartTime"] = 0; + tracker["nextScrapeTime"] = 0; + tracker["lastScrapeResult"]= ""; + tracker["lastScrapeTimedOut"]= false; + tracker["lastScrapeSucceeded"]= true; + trackers.push_back (tracker); } - else - { - tracker["lastAnnounceResult"] = trackerError; - tracker["lastAnnounceSucceeded"] = false; - } - tracker["lastAnnounceTimedOut"] = false; // TODO: - auto nextRequestTime = torrent->GetNextTrackerRequestTime (i); - tracker["nextAnnounceTime"] = ((nextRequestTime && nextRequestTime > ts ? nextRequestTime - ts : 0) + tsSinceEpoch)/1000; - tracker["lastAnnounceTime"] = torrent->GetLastTrackerUpdateTime (i); - tracker["lastAnnounceStartTime"] = torrent->GetLastTrackerUpdateTime (i); // TODO: - tracker["lastScrapeTime"] = 0; - tracker["lastScrapeStartTime"] = 0; - tracker["nextScrapeTime"] = 0; - tracker["lastScrapeResult"]= ""; - tracker["lastScrapeTimedOut"]= false; - tracker["lastScrapeSucceeded"]= true; - trackers.push_back (tracker); } return trackers; } diff --git a/libi2pd_client/TorrentsTunnel.cpp b/libi2pd_client/TorrentsTunnel.cpp index 0695f442..2724157f 100644 --- a/libi2pd_client/TorrentsTunnel.cpp +++ b/libi2pd_client/TorrentsTunnel.cpp @@ -40,7 +40,7 @@ namespace torrents std::vector trackersList; boost::split(trackersList, trackers, boost::is_any_of(","), boost::token_compress_on); for (const auto& it: trackersList) - m_Trackers.emplace_back (TrackerInfo{ it, 0, 0, 0 }); + m_Trackers.emplace_back (TrackerInfo{ it, true, 0, 0, 0 }); } } @@ -390,6 +390,17 @@ namespace torrents if (!m_TorrentsByID.empty ()) id = m_TorrentsByID.rbegin ()->first + 1; m_TorrentsByID.emplace (id, torrent); + if (!torrent->GetAnnounce ().empty ()) + { + // add announce to trackers + auto it = std::find_if (m_Trackers.begin (), m_Trackers.end (), + [announce = torrent->GetAnnounce ()](const TrackerInfo& tracker) + { + return std::get<0>(tracker) == announce; + }); + if (it == m_Trackers.end()) + m_Trackers.emplace_back (TrackerInfo{ torrent->GetAnnounce (), false, 0, 0, 0 }); + } return id; } return 0; @@ -533,35 +544,26 @@ namespace torrents void TorrentsTunnel::RequestTorrentTrackers (std::shared_ptr torrent, TrackerAnnounceEvent event) { - if (!m_Trackers.empty ()) - for (size_t i = 0; i < m_Trackers.size (); i++) - RequestTracker (i, torrent, event); - else - RequestTracker (0, torrent, event); // from announce + for (size_t i = 0; i < m_Trackers.size (); i++) + RequestTracker (i, torrent, event); } - void TorrentsTunnel::RequestTracker (size_t trackerID, std::shared_ptr torrent, TrackerAnnounceEvent event) + bool TorrentsTunnel::RequestTracker (size_t trackerID, std::shared_ptr torrent, TrackerAnnounceEvent event) { - if (!torrent) return; + if (!torrent || trackerID >= m_Trackers.size() || + (!std::get<1>(m_Trackers[trackerID]) && std::get<0>(m_Trackers[trackerID]) != torrent->GetAnnounce ())) // not common tracker or with torrent's aanpunce + return false; i2p::http::URL reqURL; - if (trackerID < m_Trackers.size()) - reqURL.parse (std::get<0>(m_Trackers[trackerID])); - else - reqURL.parse (torrent->GetAnnounce ()); -#if __cplusplus >= 202002L // C++20 + reqURL.parse (std::get<0>(m_Trackers[trackerID])); if (!reqURL.host.ends_with (".i2p")) -#else - if (reqURL.host.find(".i2p") == reqURL.host.npos) -#endif { LogPrint (eLogWarning, "TorrentsTunnel: Non-I2P address ", reqURL.host, " for torrent ", torrent->GetName ()); - return; + return false; } if (reqURL.schema == "udp") { - if (trackerID >= m_Trackers.size()) return; auto ts = i2p::util::GetMonotonicMilliseconds (); - auto& [announce, connectionID, expiration, fromPort] = m_Trackers[trackerID]; + auto& [announce, common, connectionID, expiration, fromPort] = m_Trackers[trackerID]; if (connectionID && ts <= expiration) SendAnnounceToDatagramTracker (trackerID, connectionID, torrent, reqURL.host, reqURL.port, fromPort, event); else @@ -573,7 +575,7 @@ namespace torrents ConnectToDatagramTracker (trackerID, reqURL.host, reqURL.port); } } - return; + return true; } std::map params; params.emplace ("info_hash", torrent->GetHexStringInfoHash ()); @@ -606,6 +608,7 @@ namespace torrents std::placeholders::_2, httpStream, torrent, req, trackerID)); } }, reqURL.host, reqURL.port); + return true; } void TorrentsTunnel::TrackerRequestSent (const boost::beast::error_code& ecode, size_t bytes_transferred, @@ -731,9 +734,11 @@ namespace torrents } if (ts >= it.second->GetNextTrackerRequestTime (i)) { - auto nextInterval = it.second->GetInterval (i) + GetLocalDestination ()->GetRng()() % TRACKER_REQUESTS_INTERVAL_VARIANCE; - it.second->SetNextTrackerRequestTime (i, ts + nextInterval); - RequestTracker (i, it.second, eTrackerAnnounceEventNone); + if (RequestTracker (i, it.second, eTrackerAnnounceEventNone)) + { + auto nextInterval = it.second->GetInterval (i) + GetLocalDestination ()->GetRng()() % TRACKER_REQUESTS_INTERVAL_VARIANCE; + it.second->SetNextTrackerRequestTime (i, ts + nextInterval); + } } } } @@ -944,7 +949,7 @@ namespace torrents auto [trackerID, fromPort, torrent, ts] = it->second; if (trackerID < m_Trackers.size ()) { - auto& [announce, connID, connExpiration, connFromPort] = m_Trackers[trackerID]; + auto& [announce, common, connID, connExpiration, connFromPort] = m_Trackers[trackerID]; connID = connectionID; connExpiration = i2p::util::GetMonotonicMilliseconds () + lifetime; connFromPort = fromPort; diff --git a/libi2pd_client/TorrentsTunnel.h b/libi2pd_client/TorrentsTunnel.h index 5e9c6b4a..5eab93e3 100644 --- a/libi2pd_client/TorrentsTunnel.h +++ b/libi2pd_client/TorrentsTunnel.h @@ -83,8 +83,8 @@ namespace torrents void Stop () { StopWorkAndFinishTasks (); } }; - using TrackerInfo = std::tuple; - // (announce, connection_id, connection expiration time in monotonic milliseconds, connction from_port) + using TrackerInfo = std::tuple; + // (announce, common, connection_id, connection expiration time in monotonic milliseconds, connection from_port) public: @@ -125,7 +125,7 @@ namespace torrents bool CreateAndReserveFile (const std::filesystem::path& filePath, size_t reserve); void CompleteTorrent (std::shared_ptr torrent); void StopTorrent (std::shared_ptr torrent); - void RequestTracker (size_t trackerID, std::shared_ptr torrent, TrackerAnnounceEvent event); + bool RequestTracker (size_t trackerID, std::shared_ptr torrent, TrackerAnnounceEvent event); void RequestTorrentTrackers (std::shared_ptr torrent, TrackerAnnounceEvent event); void TrackerRequestSent (const boost::beast::error_code& ecode, size_t bytes_transferred, std::shared_ptr httpStream, std::shared_ptr torrent,