porta-rs 0.1.1

Zero-trust CGNAT bypass via WireGuard tunnel
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use parking_lot::RwLock;

/// Metrics snapshot
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MetricsSnapshot {
    pub timestamp: DateTime<Utc>,
    pub bytes_sent: u64,
    pub bytes_received: u64,
    pub packets_sent: u64,
    pub packets_received: u64,
    pub active_connections: u64,
    pub latency_ms: Option<f64>,
}

/// Metrics collector
pub struct MetricsCollector {
    snapshot: Arc<RwLock<MetricsSnapshot>>,
}

impl MetricsCollector {
    pub fn new() -> Self {
        Self {
            snapshot: Arc::new(RwLock::new(MetricsSnapshot {
                timestamp: Utc::now(),
                bytes_sent: 0,
                bytes_received: 0,
                packets_sent: 0,
                packets_received: 0,
                active_connections: 0,
                latency_ms: None,
            })),
        }
    }

    /// Update metrics
    pub fn update(&self, snapshot: MetricsSnapshot) {
        let mut current = self.snapshot.write();
        *current = snapshot;
    }

    /// Get current snapshot
    pub fn snapshot(&self) -> MetricsSnapshot {
        self.snapshot.read().clone()
    }

    /// Record bytes sent
    pub fn record_bytes_sent(&self, bytes: u64) {
        let mut s = self.snapshot.write();
        s.bytes_sent += bytes;
    }

    /// Record bytes received
    pub fn record_bytes_received(&self, bytes: u64) {
        let mut s = self.snapshot.write();
        s.bytes_received += bytes;
    }

    /// Record a new connection
    pub fn record_connection(&self) {
        let mut s = self.snapshot.write();
        s.active_connections += 1;
    }

    /// Record a closed connection
    pub fn record_disconnection(&self) {
        let mut s = self.snapshot.write();
        s.active_connections = s.active_connections.saturating_sub(1);
    }

    /// Record latency
    pub fn record_latency(&self, ms: f64) {
        let mut s = self.snapshot.write();
        s.latency_ms = Some(ms);
    }
}

impl Default for MetricsCollector {
    fn default() -> Self {
        Self::new()
    }
}