use crate::config::ipc_security::{RateLimitConfig, RequestSizeLimitConfig};
use crate::dashboard::error::DashboardError;
use std::time::Instant;
pub fn check_request_size(
actual_bytes: usize,
config: &RequestSizeLimitConfig,
) -> Result<(), DashboardError> {
if !config.enabled {
return Ok(());
}
if actual_bytes > config.max_bytes {
return Err(DashboardError::request_too_large(
actual_bytes,
config.max_bytes,
));
}
Ok(())
}
pub struct TokenBucket {
tokens: f64,
max_tokens: f64,
refill_rate: f64,
last_refill: Instant,
}
impl TokenBucket {
pub fn new(refill_rate: f64, burst_capacity: u32) -> Self {
let max_tokens = burst_capacity as f64;
Self {
tokens: max_tokens,
max_tokens,
refill_rate,
last_refill: Instant::now(),
}
}
pub fn from_config(config: &RateLimitConfig) -> Self {
Self::new(config.refill_rate, config.burst_capacity)
}
fn refill(&mut self) {
let now = Instant::now();
let elapsed = now.duration_since(self.last_refill).as_secs_f64();
self.tokens = (self.tokens + elapsed * self.refill_rate).min(self.max_tokens);
self.last_refill = now;
}
pub fn try_consume(&mut self) -> bool {
self.refill();
if self.tokens >= 1.0 {
self.tokens -= 1.0;
true
} else {
false
}
}
pub fn check_rate_limit(&mut self, config: &RateLimitConfig) -> Result<(), DashboardError> {
if !config.enabled {
return Ok(());
}
if !self.try_consume() {
return Err(DashboardError::rate_limit_exceeded());
}
Ok(())
}
}