ferrotunnel_protocol/
validation.rs1use crate::frame::Frame;
4
5#[derive(Debug, thiserror::Error)]
7pub enum ValidationError {
8 #[error("Frame too large: {size} bytes exceeds limit of {limit} bytes")]
9 FrameTooLarge { size: u64, limit: u64 },
10
11 #[error("Token too long: {len} bytes exceeds limit of {limit} bytes")]
12 TokenTooLong { len: usize, limit: usize },
13
14 #[error("Too many capabilities: {count} exceeds limit of {limit}")]
15 TooManyCapabilities { count: usize, limit: usize },
16
17 #[error("Capability too long: {len} bytes exceeds limit of {limit} bytes")]
18 CapabilityTooLong { len: usize, limit: usize },
19
20 #[error("Payload too large: {size} bytes exceeds limit of {limit} bytes")]
21 PayloadTooLarge { size: usize, limit: usize },
22}
23
24#[derive(Debug, Clone)]
26pub struct ValidationLimits {
27 pub max_frame_bytes: u64,
28 pub max_token_len: usize,
29 pub max_capabilities: usize,
30 pub max_capability_len: usize,
31 pub max_payload_bytes: usize,
32}
33
34impl Default for ValidationLimits {
35 fn default() -> Self {
36 Self {
37 max_frame_bytes: 16 * 1024 * 1024,
38 max_token_len: 256,
39 max_capabilities: 32,
40 max_capability_len: 64,
41 max_payload_bytes: 16 * 1024 * 1024,
42 }
43 }
44}
45
46pub fn validate_frame(frame: &Frame, limits: &ValidationLimits) -> Result<(), ValidationError> {
48 match frame {
49 Frame::Handshake(handshake) => {
50 if handshake.token.len() > limits.max_token_len {
51 return Err(ValidationError::TokenTooLong {
52 len: handshake.token.len(),
53 limit: limits.max_token_len,
54 });
55 }
56 if handshake.capabilities.len() > limits.max_capabilities {
57 return Err(ValidationError::TooManyCapabilities {
58 count: handshake.capabilities.len(),
59 limit: limits.max_capabilities,
60 });
61 }
62 for cap in &handshake.capabilities {
63 if cap.len() > limits.max_capability_len {
64 return Err(ValidationError::CapabilityTooLong {
65 len: cap.len(),
66 limit: limits.max_capability_len,
67 });
68 }
69 }
70 }
71 Frame::HandshakeAck {
72 server_capabilities,
73 ..
74 } => {
75 if server_capabilities.len() > limits.max_capabilities {
76 return Err(ValidationError::TooManyCapabilities {
77 count: server_capabilities.len(),
78 limit: limits.max_capabilities,
79 });
80 }
81 for cap in server_capabilities {
82 if cap.len() > limits.max_capability_len {
83 return Err(ValidationError::CapabilityTooLong {
84 len: cap.len(),
85 limit: limits.max_capability_len,
86 });
87 }
88 }
89 }
90 Frame::Data { data, .. } => {
91 if data.len() > limits.max_payload_bytes {
92 return Err(ValidationError::PayloadTooLarge {
93 size: data.len(),
94 limit: limits.max_payload_bytes,
95 });
96 }
97 }
98 _ => {}
99 }
100 Ok(())
101}