use mkit_rpc::mkit::rpc::v1::ssh::{SshFrame, ssh_frame};
use crate::upload::UploadLimits;
pub const MAX_FRAMES_PER_CONN: u32 = 10_000;
pub const MAX_BYTES_PER_CONN: u64 = 1024 * 1024 * 1024;
#[must_use]
pub const fn upload_limits() -> UploadLimits {
UploadLimits {
max_total_bytes: MAX_BYTES_PER_CONN,
max_chunks: MAX_FRAMES_PER_CONN,
}
}
#[must_use]
pub fn frame_byte_estimate(f: &SshFrame) -> u64 {
use ssh_frame::Body;
match &f.body {
Some(Body::PackChunk(c)) => c.data.as_ref().map_or(0, Vec::len) as u64,
Some(Body::UploadPack(h)) => h.total_bytes.unwrap_or(0),
Some(Body::DownloadPackHeader(h)) => h.total_bytes.unwrap_or(0),
_ => 64,
}
}
#[derive(Debug, Default)]
pub(super) struct Budget {
frames: u32,
bytes: u64,
}
impl Budget {
pub(super) fn charge(&mut self, frame: &SshFrame) -> Result<(), &'static str> {
self.frames = self.frames.saturating_add(1);
if self.frames > MAX_FRAMES_PER_CONN {
return Err("per-connection frame budget exceeded");
}
self.bytes = self.bytes.saturating_add(frame_byte_estimate(frame));
if self.bytes > MAX_BYTES_PER_CONN {
return Err("per-connection byte budget exceeded");
}
Ok(())
}
}