pub struct ChokingAlgorithm { /* private fields */ }Expand description
BitTorrent choking algorithm implementation (tit-for-tat strategy)
This implements the standard BT choking algorithm:
- Top K peers by score get unchoked (reciprocity-based)
- One additional slot for optimistic unchoke (random selection)
- Snubbed peers are penalized heavily
The algorithm minimizes churn by only changing state when necessary.
Implementations§
Source§impl ChokingAlgorithm
impl ChokingAlgorithm
Sourcepub fn new(config: ChokingConfig) -> Self
pub fn new(config: ChokingConfig) -> Self
Create a new choking algorithm with the given configuration
Sourcepub fn remove_peer(&mut self, idx: usize)
pub fn remove_peer(&mut self, idx: usize)
Remove a peer at the given index
Sourcepub fn rotate_choke(&mut self) -> Vec<ChokeAction>
pub fn rotate_choke(&mut self) -> Vec<ChokeAction>
Core algorithm: called every ~10 seconds (config.choke_rotation_interval_secs)
This performs the tit-for-tat choke rotation:
- Check and mark snubbed peers (timeout-based)
- Calculate score for each peer
- Sort by score descending
- Top K get Unchoke, rest get Choke BUT: keep currently unchoked peers unchoked if they’re still in top K (avoid churn - only change what’s necessary)
- Return only the actions that changed state
Sourcepub fn optimistically_unchoke(&mut self) -> Option<usize>
pub fn optimistically_unchoke(&mut self) -> Option<usize>
Called every ~30 seconds (config.optimistic_unchoke_interval_secs)
Selects ONE choked+interested peer for optimistic unchoke. This gives new/unknown peers a chance to prove themselves.
Uses round-robin rotation among eligible non-snubbed peers to ensure fair distribution of the optimistic unchoke slot.
Returns Some(index) if found, None if no eligible peer
Sourcepub fn rotate_optimistic_unchoked(&mut self, eligible_peers: &[usize]) -> usize
pub fn rotate_optimistic_unchoked(&mut self, eligible_peers: &[usize]) -> usize
Rotate which peer gets the optimistic unchoke slot using round-robin.
Picks a different peer than the current one when possible, cycling through eligible peers in order.
§Arguments
eligible_peers- Indices of peers that are eligible for optimistic unchoke
§Returns
The index of the selected peer from the eligible set
Sourcepub fn on_data_received(&mut self, peer_idx: usize, bytes: u64)
pub fn on_data_received(&mut self, peer_idx: usize, bytes: u64)
Called whenever we receive data from a peer. Automatically unsnubs the peer if it was in the explicit snubbed set.
Sourcepub fn mark_peer_snubbed(&mut self, peer_id: usize)
pub fn mark_peer_snubbed(&mut self, peer_id: usize)
Explicitly mark a peer as snubbed (algorithm-level).
This adds the peer to the snubbed_peers set, which causes
calculate_peer_score to return -1000 for this peer, ensuring
they always get choked on the next rotation.
Sourcepub fn unsnub_peer(&mut self, peer_id: usize) -> bool
pub fn unsnub_peer(&mut self, peer_id: usize) -> bool
Remove a peer from the explicit snubbed set (they sent data again).
Returns true if the peer was actually in the snubbed set (newly un-snubbed),
false if they were not snubbed.
Sourcepub fn is_explicitly_snubbed(&self, peer_id: usize) -> bool
pub fn is_explicitly_snubbed(&self, peer_id: usize) -> bool
Check if a peer is in the explicit snubbed set.
Sourcepub fn snubbed_count(&self) -> usize
pub fn snubbed_count(&self) -> usize
Get the number of explicitly snubbed peers.
Sourcepub fn check_snubbed_peers(&mut self) -> Vec<usize>
pub fn check_snubbed_peers(&mut self) -> Vec<usize>
Check all peers for snubbed status Returns indices of newly snubbed peers
Sourcepub fn get_peer_mut(&mut self, idx: usize) -> Option<&mut PeerStats>
pub fn get_peer_mut(&mut self, idx: usize) -> Option<&mut PeerStats>
Get mutable reference to peer stats
Sourcepub fn config(&self) -> &ChokingConfig
pub fn config(&self) -> &ChokingConfig
Get reference to configuration