DhtStorage
In-memory DHT data store. This is a pure-Kotlin port of libtorrent's dht_default_storage (src/kademlia/dht_storage.cpp). It holds the three things a DHT node serves:
announced peers per info-hash (BEP-5
announce_peer/get_peers), bucketed by address family and aged out after PEER_LIFETIME_SECONDS,immutable items keyed by SHA-1(value) (BEP-44), and
mutable items keyed by SHA-1(public key ‖ salt) (BEP-44), where a higher sequence number supersedes a lower one.
Time. libtorrent calls aux::time_now() internally; per this module's contract that ambient clock is replaced by an explicit now parameter (epoch seconds as a Long) threaded through announcePeer, getPeers, putImmutableItem, putMutableItem and tick. This keeps the structure pure and deterministically testable.
Scope. This is the data structure only. The transport-side machinery in node::incoming_request lives in the node layer and is not duplicated here. That covers write-token generation and verification, BEP-42 id checks, the infohashes_sample for BEP-51, the popularity-based eviction (pick_least_important_item) and the dht_max_* capacity caps. maxPeersPerTorrent and maxItems provide the same drop-when-full behaviour the settings drive upstream.
Types
One announced peer: the port of the anonymous peer_entry in dht_storage.cpp.
Result of getPeers: the selected peer endpoints plus the torrent name (if any).
Properties
Number of stored immutable items.
Cap on stored peers per torrent (dht_max_peers, default 2000).
Cap on the number of distinct torrents tracked (dht_max_torrents, default 2000).
Number of stored mutable items.
Number of distinct torrents currently tracked.
Functions
Record an announce_peer, the port of dht_default_storage::announce_peer. The peer is keyed by address family; re-announcing the same endpoint refreshes its timestamp/seed flag in place. A new torrent is created unless maxTorrents is reached, and a new peer is added unless maxPeersPerTorrent is reached.
Fetch a stored immutable item by target, the port of get_immutable_item. Returns null if absent.
Fetch a stored mutable item by target, the port of get_mutable_item. Returns null if absent.
The stored sequence number for target, or null if absent. This is the port of get_mutable_item_seq. The node layer uses this for the BEP-44 cas / old-sequence checks before a put.
Fetch the announced peers for infoHash in the requester's address family. This is the data half of dht_default_storage::get_peers. noseed excludes seeds (for a seeding requester); wantV4 picks peers4 vs peers6. At most maxReply peers are returned, taken in stored order rather than sampled, because sampling is a transport concern. The optional torrent name is returned alongside.
Store an immutable item, the port of put_immutable_item. The key is DhtItem.target (= SHA-1 of the bencoded value). Re-putting the same target just refreshes its last-seen stamp. When the table is full a put of a new target is dropped (libtorrent instead evicts the least-important item; that popularity heuristic is a node-layer concern, so here a full table simply refuses new targets).
Store or update a mutable item, the port of put_mutable_item. The key is MutableItem.target (= SHA-1(public key ‖ salt)). If a slot already exists, the new item replaces it only when its sequence number is strictly greater (if (item.seq < seq)), so older writes can never clobber newer ones; either way the last-seen stamp is refreshed. A new slot is dropped when the table is full (see putImmutableItem on eviction).
Remove expired peers and items, the port of dht_default_storage::tick. Peers older than PEER_LIFETIME_SECONDS are purged and torrents left with no peers are removed; immutable/mutable items not heard about within itemLifetimeSeconds are dropped.