Skip to main content

PeerStats

Struct PeerStats 

Source
pub struct PeerStats {
Show 22 fields pub peer_id: [u8; 20], pub addr: SocketAddr, pub uploaded_bytes: u64, pub downloaded_bytes: u64, pub upload_speed: f64, pub download_speed: f64, pub avg_upload_speed: u64, pub avg_download_speed: u64, pub am_choking: bool, pub am_interested: bool, pub peer_choking: bool, pub peer_interested: bool, pub is_snubbed: bool, pub bad_data_count: u32, pub snub_count: u32, pub is_banned: bool, pub ban_reason: Option<String>, pub last_message_received_at: Instant, pub last_data_time: Option<Instant>, pub last_upload_time: Option<Instant>, pub last_unchoke_at: Instant, pub last_optimistic_unchoke_at: Instant, /* private fields */
}
Expand description

Per-peer statistics for BitTorrent choking algorithm decisions.

Tracks cumulative byte counts, real-time speeds via EMA, choke/interested states, timestamps for snubbed detection and unchoke rotation eligibility, and bad data detection for peer banning system.

Fields§

§peer_id: [u8; 20]

20-byte peer identifier from the BitTorrent handshake.

§addr: SocketAddr

Network address of this peer.

§uploaded_bytes: u64

Total bytes uploaded to this peer (cumulative).

§downloaded_bytes: u64

Total bytes downloaded from this peer (cumulative).

§upload_speed: f64

Current upload speed estimate in bytes/second.

§download_speed: f64

Current download speed estimate in bytes/second.

§avg_upload_speed: u64

Average upload speed over the entire connection (bytes/sec).

§avg_download_speed: u64

Average download speed over the entire connection (bytes/sec).

§am_choking: bool

Whether we are choking this peer.

Starts as true (we choke all peers by default).

§am_interested: bool

Whether we are interested in data from this peer.

§peer_choking: bool

Whether this peer is choking us.

§peer_interested: bool

Whether this peer is interested in data from us.

§is_snubbed: bool

Whether this peer has been marked as snubbed (not sending data).

§bad_data_count: u32

Number of times this peer sent invalid piece data (hash verification failed).

When this reaches BAD_DATA_THRESHOLD, the peer is permanently banned.

§snub_count: u32

Number of times this peer has been marked as snubbed.

§is_banned: bool

Whether this peer has been banned for sending too much invalid data.

Banned peers are disconnected, excluded from selection, and not reconnected for the remainder of the session.

§ban_reason: Option<String>

Reason why this peer was banned (if is_banned == true).

§last_message_received_at: Instant

Instant of the most recent message received from this peer.

§last_data_time: Option<Instant>

Instant of the most recent data received FROM this peer.

§last_upload_time: Option<Instant>

Instant of the most recent data sent TO this peer.

§last_unchoke_at: Instant

Instant when we last unchoked this peer (for rotation round-robin).

§last_optimistic_unchoke_at: Instant

Instant when we last optimistically unchoked this peer.

Implementations§

Source§

impl PeerStats

Source

pub fn new(peer_id: [u8; 20], addr: SocketAddr) -> Self

Create a new PeerStats for the given peer.

§Default state
  • Byte counters start at 0.
  • Speeds start at 0.0.
  • am_choking = true (we choke by default).
  • All other boolean flags are false.
  • All timestamps are set to Instant::now().
  • Bad data count starts at 0.
§Example
use std::net::SocketAddr;
let addr: SocketAddr = "192.168.1.5:6881".parse().unwrap();
let stats = PeerStats::new([0u8; 20], addr);
assert!(stats.am_choking);
assert_eq!(stats.uploaded_bytes, 0);
assert!(!stats.is_banned);
Source

pub fn on_data_sent(&mut self, bytes: u64)

Record that we sent bytes to this peer.

Increments uploaded_bytes and updates upload_speed using an Exponential Moving Average:

new_speed = alpha * instant_rate + (1 - alpha) * old_speed

where alpha = 0.5. On the first call the raw instant rate is used directly. Also updates last_upload_time.

Source

pub fn on_data_received(&mut self, bytes: u64)

Record that we received bytes from this peer.

Increments downloaded_bytes, resets is_snubbed to false, updates last_message_received_at, updates last_data_time, and refreshes download_speed via EMA.

Source

pub fn check_snubbed(&mut self, timeout_secs: u64) -> bool

Check whether this peer should be marked as snubbed due to inactivity.

Returns true if the peer has just transitioned into the snubbed state (i.e., no data for at least timeout_secs seconds and was not already snubbed).

Returns false if the peer is still active or was already snubbed. Also increments snub_count when transitioning to snubbed state.

Source

pub fn reset_snubbed(&mut self)

Explicitly reset the snubbed flag (e.g. after an unchoke).

Source

pub fn record_unchoke(&mut self)

Record that we have unchoked this peer.

Sets am_choking to false and refreshes last_unchoke_at.

Source

pub fn record_choke(&mut self)

Record that we have choked this peer.

Sets am_choking to true.

Source

pub fn record_optimistic_unchoke(&mut self)

Record that we performed an optimistic unchoke on this peer.

Sets am_choking to false and refreshes last_optimistic_unchoke_at.

Source

pub fn time_since_last_unchoke(&self) -> Duration

Elapsed time since we last unchoked this peer (regular unchoke).

Used by the choking algorithm to determine rotation eligibility (peers that have been unchoked longest are candidates for choking).

Source

pub fn time_since_last_optimistic_unchoke(&self) -> Duration

Elapsed time since we last optimistically unchoked this peer.

Used to avoid re-selecting the same peer for optimistic unchoke too frequently.

Source

pub fn age(&self) -> Duration

Elapsed time since this PeerStats was created.

Source

pub fn connection_duration_secs(&self) -> u64

Get the total duration of this peer connection in seconds.

Returns the number of seconds since this peer was first connected.

Source

pub fn increment_bad_data(&mut self) -> bool

Increment the bad data counter for this peer.

Called when a piece received from this peer fails hash verification.

§Returns
  • true if the peer should now be banned (count >= BAD_DATA_THRESHOLD)
  • false if the peer is still under the threshold
Source

pub fn decrement_bad_data(&mut self)

Decrement the bad data counter for this peer (gradual recovery).

Called when a valid, verified piece is successfully received from this peer. This allows peers who occasionally send bad data to recover their reputation. The count is floored at 0 (never goes negative).

Source

pub fn ban_peer(&mut self, reason: String)

Ban this peer with a reason.

Sets is_banned to true, stores the reason, and logs the ban event. Banned peers are:

  • Disconnected immediately
  • Not reconnected for the rest of the session
  • Excluded from all selection algorithms
§Arguments
  • reason - Human-readable explanation for why the peer was banned
Source

pub fn is_eligible_for_selection(&self) -> bool

Check if this peer is eligible for selection in algorithms.

Returns false if the peer is banned, regardless of other metrics. This should be called before including a peer in any selection logic.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more