PeerList

class PeerList

The set of known peers for one torrent. This is the pure-Kotlin port of libtorrent's struct peer_list (include/libtorrent/peer_list.hpp, src/peer_list.cpp).

This is a pure data structure: it owns no sockets and performs no I/O. Its job is to remember every endpoint we have heard about (TorrentPeer), keep the collection deduplicated and bounded, track how many of them are worth trying to connect to right now ("connect candidates"), and hand back the next best peer to dial via connectOnePeer. The actual dialing, handshaking and transfer live in higher layers that v0 does not include.

What is ported faithfully

What is intentionally omitted

Anything that requires a live connection or session pointer: the duplicate- connection resolution dance in new_connection (which decides which of two live sockets to drop), ip/port-filter application (needs a filter + live disconnects), and i2p peers. The connection-lifecycle hooks are reduced to setConnected / onConnectionClosed, which maintain exactly the same candidate bookkeeping the upstream functions do.

Threading

libtorrent's peer_list is single_threaded; so is this. It is not safe for concurrent use and assumes a single owning torrent task.

Constructors

Link copied to clipboard
constructor(random: Random = Random.Default)

Functions

Link copied to clipboard
fun addPeer(host: String, port: Int, source: Int, pexFlags: Int = PexFlags.NONE, state: TorrentState = TorrentState()): TorrentPeer?

Add (or merge) a peer learned for (host, port) from source. This is the port of the IP path of peer_list::add_peer. Returns the stored TorrentPeer (existing or freshly created), or null if the endpoint is rejected.

Link copied to clipboard

Ban p, the port of peer_list::ban_peer. A banned peer is removed from the connect-candidate count and can never become a candidate again. Returns true (upstream always reports the ban as applied).

Link copied to clipboard
fun clear()

Drop all peers and reset all counters (peer_list::clear).

Link copied to clipboard

Clear every cached peer rank, the port of peer_list::clear_peer_prio.

Link copied to clipboard
fun comparePeer(lhs: TorrentPeer, rhs: TorrentPeer, external: ExternalIp, externalPort: Int, finished: Boolean): Boolean

True if lhs is a better connect candidate than rhs. This is the port of the file-local compare_peer in src/peer_list.cpp. The ordering, in priority order:

Link copied to clipboard

True if lhs is a better erase candidate than rhs (i.e. should be dropped first). This is the port of the file-local compare_peer_erase. Priority:

Link copied to clipboard
fun connectOnePeer(sessionTime: Int, state: TorrentState): TorrentPeer?

Return the single best peer to try to connect to next, or null if there is none. This is the port of peer_list::connect_one_peer. It maintains a cache of pre-ranked candidates: stale entries (no longer candidates) are dropped, the cache is refilled via findConnectCandidates when empty, and the front (best) peer is popped and returned. The returned peer is guaranteed to be a current connect candidate (not banned, not connected, connectable).

Link copied to clipboard

Remove p from the list, correcting every counter and cursor. This is the port of peer_list::erase_peer(torrent_peer*). The removed peer is appended to TorrentState.erased. No-op if p is not present.

Link copied to clipboard

True if p is in this list (peer_list::has_peer).

Link copied to clipboard

Increment p's failcount (saturating at 31). This is the port of peer_list::inc_failcount. Updates the candidate count if this pushes the peer past maxFailcount.

Link copied to clipboard

Whether p is a connect candidate. This is the port of peer_list::is_connect_candidate. A peer is not a candidate if it is already connected, banned, a web seed, not connectable, a seed while we are finished, or has failed too many times. Everything else is a candidate.

Link copied to clipboard

Number of current connect candidates (peer_list::num_connect_candidates).

Link copied to clipboard
fun numPeers(): Int

Number of peers in the list (peer_list::num_peers).

Link copied to clipboard
fun numSeeds(): Int

Number of known seeds (peer_list::num_seeds).

Link copied to clipboard
fun onConnectionClosed(p: TorrentPeer, sessionTime: Int, failed: Boolean, state: TorrentState, fastReconnect: Boolean = false)

Record that a connection to p just closed. This is the port of the bookkeeping in peer_list::connection_closed. Clears the connected flag and optimistic unchoke, optionally stamps lastConnected with sessionTime, bumps the failcount when failed, and re-counts the peer as a candidate if it now is one. If multiple-connections-per-IP is on and this was a non-connectable incoming peer, the entry is erased (we can't reliably identify it again).

Link copied to clipboard

Read-only snapshot of the peers, in stored (address-sorted) order.

Link copied to clipboard

Recompute the connect-candidate count from scratch and snapshot the finished and max-failcount state. This is the port of peer_list::recalculate_connect_candidates. Called whenever the finished state flips or the failcount threshold changes, since both alter which peers count.

Link copied to clipboard
fun setConnected(p: TorrentPeer, connected: Boolean)

Mark p as connected or not. This is the candidate-bookkeeping core of peer_list::set_connection (when connecting) and connection_closed's pointer clearing. Setting connected clears the TorrentPeer.maybeUploadOnly hint (we will soon learn the truth) and removes the peer from the candidate count; clearing it may make the peer a candidate again.

Link copied to clipboard

Set p's failcount to f, the port of peer_list::set_failcount. It adjusts the candidate count in whichever direction the change implies.

Link copied to clipboard

Re-evaluate the candidate count if TorrentState.maxFailcount changed.

Link copied to clipboard

Set p's seed flag, the port of peer_list::set_seed. It maintains both the connect-candidate count (a seed is not a candidate when we're finished) and the numSeeds tally.

Link copied to clipboard
fun updatePeerPort(p: TorrentPeer, port: Int, src: Int, state: TorrentState): Boolean

Update a connected peer's advertised listen port. This is the simplified port of peer_list::update_peer_port (the single-connection-per-IP path). Returns false on a duplicate-endpoint collision (caller should drop the connection), true otherwise. Marks the peer connectable and folds in src.