stochastic-routing-extended 1.0.2

SRX (Stochastic Routing eXtended) — a next-generation VPN protocol with stochastic routing, DPI evasion, post-quantum cryptography, and multi-transport channel splitting
Documentation
//! Channel health monitoring: RTT, loss, and blockage detection.

use std::time::Duration;

/// Monitors the health of a transport channel.
pub struct HealthMonitor {
    /// Smoothed RTT estimate.
    pub srtt: Duration,
    /// Packet loss ratio (0.0 to 1.0).
    pub loss_ratio: f64,
    /// Number of consecutive failures.
    pub consecutive_failures: u32,
    /// Threshold for declaring the channel blocked.
    pub block_threshold: u32,
}

impl HealthMonitor {
    pub fn new(block_threshold: u32) -> Self {
        Self {
            srtt: Duration::from_millis(50),
            loss_ratio: 0.0,
            consecutive_failures: 0,
            block_threshold,
        }
    }

    /// Record a successful probe/packet.
    pub fn record_success(&mut self, rtt: Duration) {
        self.consecutive_failures = 0;
        // Exponential moving average
        self.srtt = Duration::from_micros(
            (self.srtt.as_micros() as f64 * 0.875 + rtt.as_micros() as f64 * 0.125) as u64,
        );
    }

    /// Record a failure.
    pub fn record_failure(&mut self) {
        self.consecutive_failures += 1;
    }

    /// Whether the channel appears to be blocked by DPI.
    pub fn is_blocked(&self) -> bool {
        self.consecutive_failures >= self.block_threshold
    }

    /// Health score from 0.0 (dead) to 1.0 (perfect).
    pub fn score(&self) -> f64 {
        if self.is_blocked() {
            return 0.0;
        }
        (1.0 - self.loss_ratio) * (1.0 / (1.0 + self.srtt.as_millis() as f64 / 1000.0))
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn blocked_after_threshold() {
        let mut h = HealthMonitor::new(3);
        h.record_failure();
        h.record_failure();
        assert!(!h.is_blocked());
        h.record_failure();
        assert!(h.is_blocked());
        assert_eq!(h.score(), 0.0);
    }

    #[test]
    fn success_resets_failures() {
        let mut h = HealthMonitor::new(2);
        h.record_failure();
        h.record_success(Duration::from_millis(10));
        h.record_failure();
        assert!(!h.is_blocked());
    }
}