remove expired nodes from routing table

This commit is contained in:
orignal
2026-09-27 21:09:16 -04:00
parent 1078c347f1
commit 8510dce429
2 changed files with 69 additions and 5 deletions
+60 -4
View File
@@ -153,6 +153,34 @@ namespace torrents
}
}
std::list<NodeID> RoutingTable::DeleteExpiredNodes ()
{
auto ts = i2p::util::GetMonotonicSeconds ();
auto bucket = m_Buckets;
std::list<NodeID> deleted;
while (bucket)
{
if (ts > bucket->lastUpdateTime + DHT_BUCKET_EXPIRATION_THRESHOLD)
{
auto it = bucket->nodes.begin ();
while (it != bucket->nodes.end ())
{
if (ts > it->second + DHT_NODE_EXPIRATION_TIME)
{
deleted.push_back (it->first);
it = bucket->nodes.erase (it);
}
else
it++;
}
}
bucket = bucket->next;
}
if (!deleted.empty ())
RemoveEmptyBuckets ();
return deleted;
}
bool RoutingTable::AddNode (const NodeID& id)
{
if (id == m_OurNode) return false;
@@ -174,7 +202,11 @@ namespace torrents
while (bucket->IsFull ());
}
if (bucket)
bucket->nodes.emplace (id, i2p::util::GetMonotonicSeconds ());
{
auto ts = i2p::util::GetMonotonicSeconds ();
bucket->nodes.emplace (id, ts);
bucket->lastUpdateTime = ts;
}
RemoveEmptyBuckets ();
return true;
}
@@ -268,7 +300,8 @@ namespace torrents
}
TorrentsDHT::TorrentsDHT (TorrentsTunnel& tunnel, uint16_t port):
m_Tunnel (tunnel), m_DHTUpdateCheckTimer (tunnel.GetService ()), m_Port (port),
m_Tunnel (tunnel), m_DHTUpdateCheckTimer (tunnel.GetService ()),
m_DHTExpirationCheckTimer (tunnel.GetService ()), m_Port (port),
m_NextDHTExploratoryTime (i2p::util::GetMonotonicSeconds () + DHT_INITIAL_EXPLORATORY_INTERVAL)
{
auto dest = tunnel.GetLocalDestination ();
@@ -297,11 +330,13 @@ namespace torrents
}
Load (GetDHTFilePath (filename));
ScheduleDHTUpdateCheck ();
ScheduleDHTExpirationCheck ();
}
void TorrentsDHT::Stop ()
{
m_DHTUpdateCheckTimer.cancel ();
m_DHTExpirationCheckTimer.cancel ();
std::string filename ("nodest");
auto dest = m_Tunnel.GetLocalDestination ();
if (dest)
@@ -698,8 +733,8 @@ namespace torrents
{
auto node = std::make_shared<Node>(nodeInfo);
LogPrint (eLogDebug, "TorrentsDHT: find_node response received ", node->peer.ToBase64 ());
if (m_Nodes.emplace (node->id, node).second && m_RoutingTable)
m_RoutingTable->AddNode (node->id);
m_Nodes.emplace (node->id, node);
if (m_RoutingTable) m_RoutingTable->AddNode (node->id);
}
else
LogPrint (eLogInfo, "TorrentsDHT: Response to unknown query ", query);
@@ -868,6 +903,27 @@ namespace torrents
ScheduleDHTUpdateCheck ();
}
}
void TorrentsDHT::ScheduleDHTExpirationCheck ()
{
m_DHTExpirationCheckTimer.cancel ();
m_DHTExpirationCheckTimer.expires_after (std::chrono::seconds (DHT_EXPIRATION_CHECK_INTERVAL));
m_DHTExpirationCheckTimer.async_wait (std::bind_front(&TorrentsDHT::HandleDHTExpirationCheckTimer, this));
}
void TorrentsDHT::HandleDHTExpirationCheckTimer (const boost::system::error_code& ecode)
{
if (ecode != boost::asio::error::operation_aborted)
{
if (m_RoutingTable)
{
auto deleted = m_RoutingTable->DeleteExpiredNodes ();
for (auto it: deleted)
m_Nodes.erase (it);
}
ScheduleDHTExpirationCheck ();
}
}
}
}
+9 -1
View File
@@ -36,9 +36,12 @@ namespace i2p
namespace torrents
{
constexpr int DHT_UPDATE_CHECK_INTERVAL = 24; // in seconds
constexpr int DHT_EXPIRATION_CHECK_INTERVAL = 73; // in seconds
constexpr int DHT_EXPLORATORY_INTERVAL = 4*60; // in seconds
constexpr int DHT_EXPLORATORY_INTERVAL_VARIANCE = 40; // in seconds
constexpr int DHT_INITIAL_EXPLORATORY_INTERVAL = 90; // in seconds
constexpr int DHT_NODE_EXPIRATION_TIME = 855; // in seconds
constexpr int DHT_BUCKET_EXPIRATION_THRESHOLD = 290; // in seconds
using Distance = Torrent::InfoHash;
struct NodeID: public Torrent::InfoHash
@@ -87,6 +90,7 @@ namespace torrents
Bucket * next;
std::map<NodeID, uint64_t> nodes; // nodeID->update time in monotonic seconds
NodeID start;
uint64_t lastUpdateTime = 0; // monotonic seconds
Bucket (): next (nullptr), start{} {}
Bucket (const NodeID& start1): next (nullptr), start (start1) {}
@@ -112,6 +116,7 @@ namespace torrents
std::optional<NodeID> FindClosestNode (const Torrent::InfoHash& infoHash) const;
std::list<std::pair<NodeID, NodeID> > GetExploratoryTargets () const; // (target, node to send find_node to)
NodeID FindClosestNodeInBucket (const NodeID& target) const;
std::list<NodeID> DeleteExpiredNodes ();
private:
@@ -197,10 +202,13 @@ namespace torrents
void ScheduleDHTUpdateCheck ();
void HandleDHTUpdateCheckTimer (const boost::system::error_code& ecode);
void ScheduleDHTExpirationCheck ();
void HandleDHTExpirationCheckTimer (const boost::system::error_code& ecode);
private:
TorrentsTunnel& m_Tunnel;
boost::asio::steady_timer m_DHTUpdateCheckTimer;
boost::asio::steady_timer m_DHTUpdateCheckTimer, m_DHTExpirationCheckTimer;
uint16_t m_Port;
NodeID m_NodeID;
std::unique_ptr<RoutingTable> m_RoutingTable;