diff --git a/libi2pd_client/TorrentsDHT.cpp b/libi2pd_client/TorrentsDHT.cpp index 04609c41..ae4cad66 100644 --- a/libi2pd_client/TorrentsDHT.cpp +++ b/libi2pd_client/TorrentsDHT.cpp @@ -361,10 +361,13 @@ namespace torrents return false; } - bool RequestInfo::AddNode (std::shared_ptr node) + bool RequestInfo::AddNode (std::shared_ptr node, uint64_t token) { if (!node || tried.contains (node->id)) return false; - return nodesToRequest.emplace (torrent ? node->id ^ torrent->GetInfoHash () : node->id ^ target, node).second; + auto distance = torrent ? node->id ^ torrent->GetInfoHash () : node->id ^ target; + if (token && torrent) + tokens.emplace (distance, node, token); + return nodesToRequest.emplace (distance, node).second; } std::shared_ptr RequestInfo::GetNextNode () @@ -494,11 +497,6 @@ namespace torrents return; m_RoutingTable = std::make_unique (m_NodeID); - std::set, std::function&, const std::shared_ptr&)> > - sortedNodes ([](const std::shared_ptr& n1, const std::shared_ptr& n2)->bool - { - return n1->id > n2->id; - }); while (f.read ((char *)nodeInfo.data (), nodeInfo.size ())) { auto bytesRead = f.gcount(); @@ -506,16 +504,11 @@ namespace torrents { auto node = std::make_shared(nodeInfo); if (node->VerifyID ()) - sortedNodes.emplace (node); + m_RoutingTable->AddNode (node); } } - if (!sortedNodes.empty ()) - { - for (auto it: sortedNodes) - m_RoutingTable->AddNode (it); - LogPrint (eLogInfo, "TorrentsDHT: DHT nodes loaded ", - m_RoutingTable->GetNumNodes (), " to ", m_RoutingTable->GetNumBuckets (), " buckets"); - } + LogPrint (eLogInfo, "TorrentsDHT: ", m_RoutingTable->GetNumNodes (), + " DHT nodes loaded to ", m_RoutingTable->GetNumBuckets (), " buckets"); } } @@ -842,14 +835,11 @@ namespace torrents memcpy (nodeInfo.data (), nodes.data (), nodeInfo.size ()); auto node = UpdateNode (std::make_shared(nodeInfo)); if (info && node) - info->AddNode (node); + info->AddNode (node, token); nodes = nodes.substr (nodeInfo.size ()); } if (info) - { - info->token = token; SendNextGetPeersQuery (info); - } } } @@ -971,16 +961,33 @@ namespace torrents void TorrentsDHT::SendNextGetPeersQuery (std::shared_ptr info) { if (!info) return; + bool sent = false; if (!info->IsDone () && m_RoutingTable) { auto nextNode = info->GetNextNode (); if (nextNode) + { + sent = true; SendGetPeersQuery (info, nextNode->peer, nextNode->port); + } else LogPrint (eLogDebug, "TorrentsDHT: No more nodes to send get_peers"); } else LogPrint (eLogDebug, "TorrentsDHT: Closest node not found after ", DHT_MAX_NUM_GET_PEERS_ATTEMPTS, " get_peers attempts"); + if (!sent && !info->tokens.empty () && info->torrent) + { + // announce + int numAnnounces = 0; + for (const auto& [distance, node, token]: info->tokens) + { + SendAnnouncePeerQuery (info->torrent->GetInfoHash (), token, node->peer, node->port + 1); // to rport + numAnnounces++; + if (numAnnounces >= DHT_MAX_NUM_CLOSEST_NODES_TO_ANNOUNCE) break; + } + if (numAnnounces > 0) + LogPrint (eLogDebug, "TorrentsDHT: Announce sent to ", numAnnounces, " closest nodes"); + } } void TorrentsDHT::SendGetPeersResponse (std::string_view transactionID, std::shared_ptr torrent, @@ -1124,7 +1131,7 @@ namespace torrents if (m_RoutingTable) { m_RoutingTable->DeleteExpiredNodes (ts); - LogPrint (eLogDebug, "TorrentsDHT: Stats buckets ", m_RoutingTable->GetNumBuckets (), " nodes ", m_RoutingTable->GetNumNodes ()); + LogPrint (eLogDebug, "TorrentsDHT: Stats ", m_RoutingTable->GetNumNodes (), " nodes in ", m_RoutingTable->GetNumBuckets (), " buckets "); } { auto it = m_Torrents.begin (); diff --git a/libi2pd_client/TorrentsDHT.h b/libi2pd_client/TorrentsDHT.h index 8c6880be..1740f39c 100644 --- a/libi2pd_client/TorrentsDHT.h +++ b/libi2pd_client/TorrentsDHT.h @@ -42,7 +42,7 @@ namespace torrents constexpr int DHT_EXPIRATION_CHECK_INTERVAL = 73; // in seconds constexpr int DHT_SEND_PING_CHECK_INTERVAL = 38; // in seconds constexpr int DHT_QUERY_EXPIRATION_CHECK_INTERVAL = 8; // in seconds - constexpr int DHT_EXPLORATORY_INTERVAL = 430; // in seconds + constexpr int DHT_EXPLORATORY_INTERVAL = 230; // in seconds constexpr int DHT_EXPLORATORY_INTERVAL_VARIANCE = 40; // in seconds constexpr int DHT_INITIAL_EXPLORATORY_INTERVAL = 90; // in seconds constexpr int DHT_NODE_SEND_PING_TIME = 740; // in seconds @@ -51,9 +51,10 @@ namespace torrents constexpr int DHT_TORRENT_PEER_EXPIRATION_TIME = 3*3600; // in seconds constexpr int DHT_INCOMING_GET_PEERS_TOKEN_EXPIRATION_TIME = 600; // in seconds constexpr int DHT_EMPTY_TORRENT_EXPIRATION_TIME = 30; // in seconds - constexpr int DHT_QUERY_EXPIRATION_TIME = 20; // in seconds + constexpr int DHT_QUERY_EXPIRATION_TIME = 25; // in seconds constexpr int DHT_MAX_NUM_GET_PEERS_ATTEMPTS = 22; constexpr int DHT_MAX_NUM_FIND_NODE_ATTEMPTS = 8; + constexpr int DHT_MAX_NUM_CLOSEST_NODES_TO_ANNOUNCE = 4; using Distance = Torrent::InfoHash; struct NodeID: public Torrent::InfoHash @@ -185,15 +186,15 @@ namespace torrents { std::shared_ptr torrent; // for get_peers NodeID target; // for find_node - std::map > nodesToRequest; + std::set > > nodesToRequest; + std::set, uint64_t > > tokens; // token received from nodes for get_peers std::set tried; - uint64_t token; int numAttempts, maxNumAttempts; RequestInfo (std::shared_ptr t, int maxNumAttempts1): torrent (t), - token (0), numAttempts (0), maxNumAttempts (maxNumAttempts1) { } + numAttempts (0), maxNumAttempts (maxNumAttempts1) { } bool IsDone () const { return numAttempts >= maxNumAttempts; } - bool AddNode (std::shared_ptr node); + bool AddNode (std::shared_ptr node, uint64_t token = 0); std::shared_ptr GetNextNode (); };