#![expect(
clippy::unwrap_used,
reason = "ratchet MOIRAI-UNWRAP-1: pre-existing debt"
)]
use std::collections::HashMap;
use std::sync::Mutex;
use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering};
use std::time::{Duration, Instant};
#[derive(Debug, Clone)]
pub struct TcpServerConfig {
pub max_connections: Option<usize>,
pub nodelay: bool,
pub keep_alive: Option<Duration>,
pub timeout: Option<Duration>,
}
impl Default for TcpServerConfig {
fn default() -> Self {
Self {
max_connections: Some(1000),
nodelay: true,
keep_alive: Some(Duration::from_secs(300)),
timeout: Some(Duration::from_secs(30)),
}
}
}
#[derive(Debug, Default)]
pub struct ServerStats {
pub total_connections: AtomicU64,
pub active_connections: AtomicU64,
pub bytes_received: AtomicU64,
pub bytes_sent: AtomicU64,
}
pub type ConnectionId = u64;
#[derive(Debug, Clone)]
pub struct ConnectionInfo {
pub peer_addr: std::net::SocketAddr,
pub connected_at: Instant,
pub bytes_received: u64,
pub bytes_sent: u64,
pub last_activity: Instant,
}
#[derive(Debug)]
pub struct ConnectionPool {
active_connections: Mutex<HashMap<ConnectionId, ConnectionInfo>>,
reserved_connections: AtomicUsize,
next_connection_id: AtomicU64,
max_connections: Option<usize>,
}
impl ConnectionPool {
#[must_use]
pub fn new(max_connections: Option<usize>) -> Self {
Self {
active_connections: Mutex::new(HashMap::new()),
reserved_connections: AtomicUsize::new(0),
next_connection_id: AtomicU64::new(0),
max_connections,
}
}
pub fn try_reserve(&self) -> bool {
let max = match self.max_connections {
Some(m) => m,
None => return true,
};
let connections = self.active_connections.lock().unwrap();
let current = connections.len();
let reserved = self.reserved_connections.load(Ordering::Relaxed);
if current + reserved < max {
self.reserved_connections.fetch_add(1, Ordering::Relaxed);
true
} else {
false
}
}
pub fn cancel_reservation(&self) {
if self.max_connections.is_some() {
self.reserved_connections.fetch_sub(1, Ordering::Relaxed);
}
}
pub fn add_connection(&self, addr: std::net::SocketAddr) -> ConnectionId {
let id = self.next_connection_id.fetch_add(1, Ordering::Relaxed);
let now = Instant::now();
self.active_connections.lock().unwrap().insert(
id,
ConnectionInfo {
peer_addr: addr,
connected_at: now,
bytes_received: 0,
bytes_sent: 0,
last_activity: now,
},
);
id
}
pub fn add_connection_reserved(&self, addr: std::net::SocketAddr) -> ConnectionId {
let id = self.add_connection(addr);
if self.max_connections.is_some() {
self.reserved_connections.fetch_sub(1, Ordering::Relaxed);
}
id
}
pub fn record_io(&self, id: ConnectionId, bytes_received: u64, bytes_sent: u64) {
let mut connections = self.active_connections.lock().unwrap();
if let Some(info) = connections.get_mut(&id) {
info.bytes_received += bytes_received;
info.bytes_sent += bytes_sent;
info.last_activity = Instant::now();
}
}
pub fn remove_connection(&self, id: ConnectionId) -> bool {
self.active_connections
.lock()
.unwrap()
.remove(&id)
.is_some()
}
pub fn has_capacity(&self) -> bool {
match self.max_connections {
Some(max) => {
let current = self.connection_count();
let reserved = self.reserved_connections.load(Ordering::Relaxed);
current + reserved < max
}
None => true,
}
}
pub fn get_active_connections(&self) -> HashMap<ConnectionId, ConnectionInfo> {
self.active_connections.lock().unwrap().clone()
}
pub fn connection_count(&self) -> usize {
self.active_connections.lock().unwrap().len()
}
}
#[derive(Debug, Clone)]
pub struct ConnectionStats {
pub bytes_read: u64,
pub bytes_written: u64,
pub read_ops: u64,
pub write_ops: u64,
}
#[derive(Debug, Clone)]
pub struct UdpConfig {
pub buffer_size: usize,
pub broadcast: bool,
pub multicast: bool,
}
impl Default for UdpConfig {
fn default() -> Self {
Self {
buffer_size: 65536,
broadcast: false,
multicast: false,
}
}
}
#[derive(Debug, Default)]
pub struct UdpStats {
pub packets_sent: AtomicU64,
pub packets_received: AtomicU64,
pub bytes_sent: AtomicU64,
pub bytes_received: AtomicU64,
}
#[derive(Debug, Clone)]
pub struct TcpServerStats {
pub total_connections: u64,
pub active_connections: u64,
pub bytes_received: u64,
pub bytes_sent: u64,
}
#[derive(Debug, Clone)]
pub struct UdpSocketStats {
pub packets_sent: u64,
pub packets_received: u64,
pub bytes_sent: u64,
pub bytes_received: u64,
}