use std::sync::Arc;
use std::time::Duration;
use bytes::BytesMut;
pub trait CoverGenerator: Send + Sync {
fn cover(&self, config: &ShapeConfig) -> BytesMut;
fn finalize_real(&self, config: &ShapeConfig, frame: BytesMut) -> BytesMut {
let _ = config;
frame
}
}
impl<F> CoverGenerator for F
where
F: Fn(&ShapeConfig) -> BytesMut + Send + Sync,
{
fn cover(&self, config: &ShapeConfig) -> BytesMut {
self(config)
}
}
#[derive(Clone)]
pub struct ShapeConfig {
pub name: Option<String>,
pub listener_addr: Option<std::net::SocketAddr>,
pub strategy: ShapingStrategy,
pub scope: ShapingScope,
pub fanout: usize,
pub frame_size: usize,
pub high_lane_capacity: usize,
pub low_lane_capacity: usize,
pub max_frame_size: usize,
pub max_connections: u16,
pub max_connections_per_ip: u16,
pub reuse_listener_port: bool,
pub cover_generator: Option<Arc<dyn CoverGenerator>>,
}
impl Default for ShapeConfig {
fn default() -> Self {
Self {
name: None,
listener_addr: None,
strategy: ShapingStrategy::Constant {
interval: Duration::from_secs(1),
},
scope: ShapingScope::Global,
fanout: 3,
frame_size: 256,
high_lane_capacity: 256,
low_lane_capacity: 1024,
max_frame_size: 1024 * 1024,
max_connections: 64,
max_connections_per_ip: 8,
reuse_listener_port: false,
cover_generator: None,
}
}
}
impl std::fmt::Debug for ShapeConfig {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ShapeConfig")
.field("name", &self.name)
.field("listener_addr", &self.listener_addr)
.field("strategy", &self.strategy)
.field("scope", &self.scope)
.field("fanout", &self.fanout)
.field("frame_size", &self.frame_size)
.field("high_lane_capacity", &self.high_lane_capacity)
.field("low_lane_capacity", &self.low_lane_capacity)
.field("max_frame_size", &self.max_frame_size)
.field("max_connections", &self.max_connections)
.field("max_connections_per_ip", &self.max_connections_per_ip)
.field("reuse_listener_port", &self.reuse_listener_port)
.field(
"cover_generator",
&self.cover_generator.as_ref().map(|_| "<custom>"),
)
.finish()
}
}
#[derive(Clone, Copy, Debug)]
#[non_exhaustive]
pub enum ShapingStrategy {
Constant {
interval: Duration,
},
Poisson {
rate: f64,
},
None,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum ShapingScope {
Global,
PerConnection {
randomize: bool,
},
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum Lane {
High,
Low,
}