use crate::network::{NetworkConfig, NetworkError};
use std::collections::BTreeMap;
use std::sync::{Arc, Mutex};
use std::collections::HashMap;
pub type Http3Handler = fn(&str, &[u8]) -> Result<Vec<u8>, NetworkError>;
#[derive(Debug, Clone)]
pub struct Http3Route {
pub path: String,
pub handler: Http3Handler,
}
#[derive(Debug, Clone)]
pub struct Http3ServerStats {
pub total_requests: u64,
pub active_connections: usize,
pub total_connections: usize,
pub zero_rtt_connections: u64,
}
pub struct Http3Server {
config: NetworkConfig,
enabled: bool,
routes: HashMap<String, Http3Handler>,
stats: std::sync::Arc<std::sync::Mutex<Http3ServerStats>>,
}
impl Http3Server {
pub fn new(config: NetworkConfig) -> Result<Self, NetworkError> {
Ok(Self {
enabled: config.enable_http3,
config,
routes: HashMap::new(),
stats: std::sync::Arc::new(Mutex::new(Http3ServerStats {
total_requests: 0,
active_connections: 0,
total_connections: 0,
zero_rtt_connections: 0,
})),
})
}
pub fn add_route(&mut self, path: &str, handler: Http3Handler) -> Result<(), NetworkError> {
self.routes.insert(path.to_string(), handler);
Ok(())
}
pub fn is_enabled(&self) -> bool {
self.enabled
}
pub fn start(&mut self, addr: &str) -> Result<UdpSocket, NetworkError> {
if !self.enabled {
return Err(NetworkError::Connection("HTTP/3 is not enabled".to_string()));
}
let socket: _ = UdpSocket::bind(addr)
.map_err(|e| NetworkError::Connection(e.to_string()))?;
{
let mut stats = self.stats.lock().unwrap();
stats.total_connections += 1;
}
Ok(socket)
}
pub fn handle_request(&self, path: &str, body: &[u8]) -> Result<Vec<u8>, NetworkError> {
let mut stats = self.stats.lock().unwrap();
stats.total_requests += 1;
if let Some(handler) = self.routes.get(path) {
handler(path, body)
} else {
Ok(b"HTTP/3 404 Not Found".to_vec())
}
}
pub fn get_stats(&self) -> Http3ServerStats {
self.stats.lock().unwrap().clone()
}
pub fn enable_zero_rtt(&mut self) {
let mut stats = self.stats.lock().unwrap();
stats.zero_rtt_connections += 1;
}
}
impl Default for Http3Server {
fn default() -> Self {
Http3Server::new(NetworkConfig::default()).unwrap()
}
}