diff --git a/libi2pd_client/Torrents.cpp b/libi2pd_client/Torrents.cpp index 02914bfd..44b9e0d6 100644 --- a/libi2pd_client/Torrents.cpp +++ b/libi2pd_client/Torrents.cpp @@ -474,9 +474,8 @@ namespace torrents Torrent::Torrent (): m_AnnounceTrackerID (-1), m_Length (0), m_PieceLength (0), m_IsComplete (false), m_IsStopped (false), m_IsSingleFile (true), m_Uploaded (0), m_Downloaded (0), - m_NextUpdateStatusTime (0), m_NextReconnectTime (0), - m_NextDHTUpdateTime (i2p::util::GetMonotonicSeconds () + DHT_TORRENT_INITIAL_UPDATE_INTERVAL), - m_Error (eTorrentErrorNoError) + m_NextUpdateStatusTime (0), m_NextReconnectTime (0), m_NextDHTUpdateTime (0), + m_LastDHTAnnounceTime (0), m_Error (eTorrentErrorNoError) { } diff --git a/libi2pd_client/Torrents.h b/libi2pd_client/Torrents.h index f625549f..b2140281 100644 --- a/libi2pd_client/Torrents.h +++ b/libi2pd_client/Torrents.h @@ -72,6 +72,7 @@ namespace torrents constexpr int DHT_TORRENT_UPDATE_INTERVAL = 880; // in seconds constexpr int DHT_TORRENT_UPDATE_INTERVAL_VARIANCE = 130; // in seconds constexpr int DHT_TORRENT_INITIAL_UPDATE_INTERVAL = 100; // in seconds + constexpr int DHT_TORRENT_INITIAL_UPDATE_INTERVAL_VARIANCE = 40; // in seconds constexpr size_t PEER_CONNECTION_RECEIVE_BUFFER_SIZE = 65535; constexpr int PEER_CONNECTION_MAX_IDLE = 3600; // in seconds constexpr int PEER_KEEP_ALIVE_TIMEOUT = 120; // in seconds @@ -314,6 +315,8 @@ namespace torrents void SetNextReconnectTime (uint64_t nextReconnectTime) { m_NextReconnectTime = nextReconnectTime; } uint64_t GetNextDHTUpdateTime () { return m_NextDHTUpdateTime; } void SetNextDHTUpdateTime (uint64_t nextDHTUpdateTime) { m_NextDHTUpdateTime = nextDHTUpdateTime; } + uint64_t GetLastDHTAnnounceTime () const { return m_LastDHTAnnounceTime; } + void SetLastDHTAnnounceTime (uint64_t lastDHTAnnounceTime) { m_LastDHTAnnounceTime = lastDHTAnnounceTime; } bool AddConnection (std::shared_ptr conn); void RemoveConnection (std::shared_ptr conn); std::list > GetConnections (); @@ -367,7 +370,7 @@ namespace torrents bool m_IsComplete, m_IsStopped, m_IsSingleFile; std::list > m_Files; size_t m_Uploaded, m_Downloaded; - uint64_t m_NextUpdateStatusTime, m_NextReconnectTime, m_NextDHTUpdateTime; // in monotonic seconds + uint64_t m_NextUpdateStatusTime, m_NextReconnectTime, m_NextDHTUpdateTime, m_LastDHTAnnounceTime; // in monotonic seconds TorrentError m_Error; }; diff --git a/libi2pd_client/TorrentsDHT.cpp b/libi2pd_client/TorrentsDHT.cpp index 372bc5df..94bc4212 100644 --- a/libi2pd_client/TorrentsDHT.cpp +++ b/libi2pd_client/TorrentsDHT.cpp @@ -796,7 +796,8 @@ namespace torrents break; } case eKRPCQueryAnnouncePeer: - LogPrint (eLogDebug, "TorrentsDHT: Announce peer response received"); + LogPrint (eLogDebug, "TorrentsDHT: Announce peer response received from ", ident.ToBase64 ()); + HandleAnnouncePeerResponse (info); break; default: LogPrint (eLogInfo, "TorrentsDHT: Response to unknown KRPC query ", (int)query); @@ -844,7 +845,7 @@ namespace torrents } } LogPrint (eLogDebug, "TorrentsDHT: Send announce to ", toIdent.ToBase64 ()); - SendAnnouncePeerQuery (info->torrent->GetInfoHash (), token, toIdent, toPort); + SendAnnouncePeerQuery (info, token, toIdent, toPort); } void TorrentsDHT::HandleFindNodeResponse (std::shared_ptr info, std::string_view nodes) @@ -867,6 +868,14 @@ namespace torrents SendNextFindNodeQuery (info); } + void TorrentsDHT::HandleAnnouncePeerResponse (std::shared_ptr info) + { + if (info && info->torrent) + info->torrent->SetLastDHTAnnounceTime (i2p::util::GetMonotonicSeconds ()); + else + LogPrint (eLogError, "TorrentsDHT: Announced torrent not found"); + } + void TorrentsDHT::SendDatagram (std::string_view msg, const i2p::data::IdentHash& toIdent, uint16_t toPort) { auto dest = m_Tunnel.GetLocalDestination (); @@ -970,7 +979,7 @@ namespace torrents int numAnnounces = 0; for (const auto& [distance, node, token]: info->tokens) { - SendAnnouncePeerQuery (info->torrent->GetInfoHash (), token, node->peer, node->port + 1); // to rport + SendAnnouncePeerQuery (info, token, node->peer, node->port + 1); // to rport numAnnounces++; if (numAnnounces >= DHT_MAX_NUM_CLOSEST_NODES_TO_ANNOUNCE) break; } @@ -1037,15 +1046,17 @@ namespace torrents transactionID, toIdent, toPort); } - void TorrentsDHT::SendAnnouncePeerQuery (const Torrent::InfoHash& infoHash, uint64_t token, - const i2p::data::IdentHash& toIdent, uint16_t toPort) + void TorrentsDHT::SendAnnouncePeerQuery (std::shared_ptr info, + uint64_t token, const i2p::data::IdentHash& toIdent, uint16_t toPort) { + if (!info || !info->torrent) return; + auto infoHash = info->torrent->GetInfoHash (); SendQueryMsg (eKRPCQueryAnnouncePeer, CreateDictionary ({ { "id", CreateByteString (std::string_view ((const char *)m_NodeID.data (), m_NodeID.size ())) }, { "info_hash", CreateByteString (std::string_view ((const char *)infoHash.data (), infoHash.size ())) }, { "token", CreateByteString (std::string_view ((const char *)&token, 8)) } }), - toIdent, toPort, true); // raw + toIdent, toPort, true, info); // raw } void TorrentsDHT::Explore () diff --git a/libi2pd_client/TorrentsDHT.h b/libi2pd_client/TorrentsDHT.h index 22321a52..43d7c4af 100644 --- a/libi2pd_client/TorrentsDHT.h +++ b/libi2pd_client/TorrentsDHT.h @@ -256,6 +256,7 @@ namespace torrents void HandleGetPeersResponsePeersAndAnnounce (std::shared_ptr info, const std::vector& peers, uint64_t token, const i2p::data::IdentHash& toIdent, uint16_t toPort); void HandleFindNodeResponse (std::shared_ptr info, std::string_view nodes); + void HandleAnnouncePeerResponse (std::shared_ptr info); void HandleAnnouncePeer (std::string_view transactionID, const NodeID& nodeID, const Torrent::InfoHash& infoHash, uint64_t token); void SendDatagram (std::string_view msg, const i2p::data::IdentHash& toIdent, uint16_t toPort); @@ -274,7 +275,8 @@ namespace torrents uint64_t token, const i2p::data::IdentHash& toIdent, uint16_t toPort); void SendFindNodeResponse (std::string_view transactionID, std::string_view nodes, const i2p::data::IdentHash& toIdent, uint16_t toPort); - void SendAnnouncePeerQuery (const Torrent::InfoHash& infoHash, uint64_t token, const i2p::data::IdentHash& toIdent, uint16_t toPort); + void SendAnnouncePeerQuery (std::shared_ptr info, + uint64_t token, const i2p::data::IdentHash& toIdent, uint16_t toPort); std::filesystem::path GetDHTFilePath (std::string_view filename) const; void Save (const std::filesystem::path& file); diff --git a/libi2pd_client/TorrentsTunnel.cpp b/libi2pd_client/TorrentsTunnel.cpp index 465ed0c2..e35bdd8c 100644 --- a/libi2pd_client/TorrentsTunnel.cpp +++ b/libi2pd_client/TorrentsTunnel.cpp @@ -825,11 +825,26 @@ namespace torrents it.second->SetNextTrackerRequestTime (i, ts + nextInterval); } } - if (SupportsDHT () && ts >= it.second->GetNextDHTUpdateTime ()*1000) + } + if (SupportsDHT ()) + { + uint64_t nextUpdateTime = it.second->GetNextDHTUpdateTime ()*1000; + if (nextUpdateTime) { - if (m_DHT) m_DHT->GetPeersAndAnnounce (it.second); - it.second->SetNextDHTUpdateTime (ts/1000 + DHT_TORRENT_UPDATE_INTERVAL + GetLocalDestination ()->GetRng()() % DHT_TORRENT_UPDATE_INTERVAL_VARIANCE); + if (ts >= nextUpdateTime) + { + if (m_DHT) m_DHT->GetPeersAndAnnounce (it.second); + if (it.second->GetLastDHTAnnounceTime ()) + it.second->SetNextDHTUpdateTime (ts/1000 + DHT_TORRENT_UPDATE_INTERVAL + + GetLocalDestination ()->GetRng()() % DHT_TORRENT_UPDATE_INTERVAL_VARIANCE); + else + it.second->SetNextDHTUpdateTime (ts/1000 + DHT_TORRENT_INITIAL_UPDATE_INTERVAL + + GetLocalDestination ()->GetRng()() % DHT_TORRENT_INITIAL_UPDATE_INTERVAL_VARIANCE); + } } + else + it.second->SetNextDHTUpdateTime (ts/1000 + DHT_TORRENT_INITIAL_UPDATE_INTERVAL + + GetLocalDestination ()->GetRng()() % DHT_TORRENT_INITIAL_UPDATE_INTERVAL_VARIANCE); } } }