diff --git a/libi2pd_client/Torrents.cpp b/libi2pd_client/Torrents.cpp index 1dba96b6..3a288b69 100644 --- a/libi2pd_client/Torrents.cpp +++ b/libi2pd_client/Torrents.cpp @@ -490,9 +490,8 @@ namespace torrents void Torrent::ParseTrackerResponse (size_t trackerID, std::string_view buf) { - if (trackerID >= m_TrackerStats.size ()) - m_TrackerStats.resize (trackerID + 1, TrackerStats{{}, MIN_TRACKER_REQUESTS_INTERVAL, - 0, 0, 0, i2p::util::GetSecondsSinceEpoch ()}); + CheckTrackerStatsSize (trackerID); + std::get<6>(m_TrackerStats[trackerID]) = ""; // clear error ParseDictionary (buf, [this, trackerID](std::string_view key, std::string_view buf)->size_t { if (key == "interval") @@ -524,6 +523,7 @@ namespace torrents { auto [reason, l] = ExtractByteString (buf); LogPrint (eLogError, "Torrents: Tracker error: ", reason); + std::get<6>(m_TrackerStats[trackerID]) = reason; // double interval if tracker failure int interval = std::max (MIN_TRACKER_REQUESTS_INTERVAL, std::get<1>(m_TrackerStats[trackerID])*2); std::get<1>(m_TrackerStats[trackerID]) = interval; @@ -551,10 +551,9 @@ namespace torrents void Torrent::HandleDatagramTrackerResponse (size_t trackerID, uint32_t interval, const uint8_t * hashes, size_t hashesLen, int numSeeders, int numLeechers) { - if (trackerID >= m_TrackerStats.size ()) - m_TrackerStats.resize (trackerID + 1, TrackerStats{{}, MIN_TRACKER_REQUESTS_INTERVAL, - 0, 0, 0, i2p::util::GetSecondsSinceEpoch () }); - auto& [peers, trackerRequestInterval, nextRequestTime, seeders, leechers, lastUpdateTime] = m_TrackerStats[trackerID]; + CheckTrackerStatsSize (trackerID); + auto& [peers, trackerRequestInterval, nextRequestTime, seeders, leechers, + lastUpdateTime, error] = m_TrackerStats[trackerID]; trackerRequestInterval = interval*1000; // milliseconds nextRequestTime = i2p::util::GetMonotonicMilliseconds () + trackerRequestInterval; seeders = numSeeders; @@ -571,6 +570,19 @@ namespace torrents } } + void Torrent::SetTrackerError (size_t trackerID, std::string_view error) + { + CheckTrackerStatsSize (trackerID); + std::get<6>(m_TrackerStats[trackerID]) = error; + } + + void Torrent::CheckTrackerStatsSize (size_t trackerID) + { + if (trackerID >= m_TrackerStats.size ()) + m_TrackerStats.resize (trackerID + 1, TrackerStats{{}, MIN_TRACKER_REQUESTS_INTERVAL, + 0, 0, 0, i2p::util::GetSecondsSinceEpoch (), ""}); + } + std::pair, bool> Torrent::CreateBitfield () const { size_t numPieces = m_Pieces.size (); @@ -816,7 +828,7 @@ namespace torrents { if (trackerID >= m_TrackerStats.size ()) m_TrackerStats.resize (trackerID + 1, TrackerStats{{}, MIN_TRACKER_REQUESTS_INTERVAL, - 0, 0, 0, i2p::util::GetSecondsSinceEpoch ()}); + 0, 0, 0, i2p::util::GetSecondsSinceEpoch (), ""}); std::get<2>(m_TrackerStats[trackerID]) = ts; } diff --git a/libi2pd_client/Torrents.h b/libi2pd_client/Torrents.h index 9ccabdbb..a8d3cc75 100644 --- a/libi2pd_client/Torrents.h +++ b/libi2pd_client/Torrents.h @@ -146,9 +146,10 @@ namespace torrents using RequestedBlock = std::tuple; // (index, offset, len) class Torrent final { - using TrackerStats = std::tuple, int, uint64_t, int, int, uint64_t>; + using TrackerStats = std::tuple, + int, uint64_t, int, int, uint64_t, std::string>; // (peers, interval, next tracker request time in monotonic milliseconds, - // seeders, leechers, last update time in seconds since epoch) + // seeders, leechers, last update time in seconds since epoch, error) public: using InfoHash = std::array; @@ -214,6 +215,8 @@ namespace torrents int GetNumLeechers (size_t trackerID) const { return (trackerID < m_TrackerStats.size ()) ? std::get<4>(m_TrackerStats[trackerID]) : 0; } int GetNumPeers (size_t trackerID) const { return (trackerID < m_TrackerStats.size ()) ? std::get<0>(m_TrackerStats[trackerID]).size () : 0; } uint64_t GetLastTrackerUpdateTime (size_t trackerID) const { return (trackerID < m_TrackerStats.size ()) ? std::get<5>(m_TrackerStats[trackerID]) : 0; } + std::string GetTrackerError (size_t trackerID) const { return (trackerID < m_TrackerStats.size ()) ? std::get<6>(m_TrackerStats[trackerID]) : ""; } + void SetTrackerError (size_t trackerID, std::string_view error); private: @@ -222,6 +225,7 @@ namespace torrents size_t ParsePeers (size_t trackerID, std::string_view buf); size_t ParseFiles (std::string_view buf); static bool IsSafeName (std::string_view name); // a name from a torrent file before it becomes a path + void CheckTrackerStatsSize (size_t trackerID); private: diff --git a/libi2pd_client/TorrentsRPC.cpp b/libi2pd_client/TorrentsRPC.cpp index 873c8a96..ca4b5158 100644 --- a/libi2pd_client/TorrentsRPC.cpp +++ b/libi2pd_client/TorrentsRPC.cpp @@ -443,8 +443,17 @@ namespace torrents tracker["seederCount"] = torrent->GetNumSeeders (i); tracker["leecherCount"] = torrent->GetNumLeechers (i); tracker["lastAnnouncePeerCount"] = torrent->GetNumPeers (i); - tracker["lastAnnounceResult"] = "Success"; // TODO: - tracker["lastAnnounceSucceeded"] = true; // TODO: + 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: tracker["nextAnnounceTime"] = (torrent->GetNextTrackerRequestTime (i) - i2p::util::GetMonotonicMilliseconds () + i2p::util::GetMillisecondsSinceEpoch ())/1000; diff --git a/libi2pd_client/TorrentsTunnel.cpp b/libi2pd_client/TorrentsTunnel.cpp index 682819b3..72ad7cb7 100644 --- a/libi2pd_client/TorrentsTunnel.cpp +++ b/libi2pd_client/TorrentsTunnel.cpp @@ -834,8 +834,18 @@ namespace torrents { uint32_t transactionID = bufbe32toh (buf); LogPrint (eLogDebug, "TorrentsTunnel: Datagram tracker action error response ", transactionID); - m_DatragramTrackerTransactions.erase (transactionID); - LogPrint (eLogInfo, "TorrentsTunnel: Datagram tracker error response: ", std::string_view ((const char *)(buf + 4), len - 4)); + auto it = m_DatragramTrackerTransactions.find (transactionID); + if (it == m_DatragramTrackerTransactions.end ()) + { + LogPrint (eLogInfo, "TorrentsTunnel: Datagram tracker transaction ", transactionID, " not found"); + return; + } + std::string_view error ((const char *)(buf + 4), len - 4); + LogPrint (eLogInfo, "TorrentsTunnel: Datagram tracker error response: ", error); + auto [trackerID, fromPort, torrent, ts] = it->second; + if (!torrent.expired ()) // response to announce + torrent.lock ()->SetTrackerError (trackerID, error); + m_DatragramTrackerTransactions.erase (it); } void TorrentsTunnel::ConnectToDatagramTracker (size_t trackerID, std::string_view dest, uint16_t port)