1use crate::error::{EnigmaPacketError, Result};
2
3pub const MAGIC: [u8; 4] = *b"ENP1";
4pub const VERSION: u8 = 1;
5pub const HEADER_LEN: usize = 12;
6pub const MIN_PACKET_SIZE: usize = HEADER_LEN;
7pub const MAX_PACKET_SIZE: usize = 16 * 1024 * 1024;
8pub const MAX_BODY_SIZE: usize = MAX_PACKET_SIZE - HEADER_LEN;
9
10#[derive(Debug, Clone, Copy)]
11pub struct PacketView<'a> {
12 pub version: u8,
13 pub flags: u8,
14 pub reserved: u16,
15 pub body_len: u32,
16 pub body: &'a [u8],
17}
18
19pub fn peek_packet(packet: &[u8]) -> Result<PacketView<'_>> {
20 parse_frame(packet)
21}
22
23pub(crate) fn encode_frame(body: &[u8], flags: u8) -> Result<Vec<u8>> {
24 if body.len() > MAX_BODY_SIZE || body.len() > u32::MAX as usize {
25 return Err(EnigmaPacketError::SizeLimitExceeded);
26 }
27 let total = HEADER_LEN
28 .checked_add(body.len())
29 .ok_or(EnigmaPacketError::SizeLimitExceeded)?;
30 if total > MAX_PACKET_SIZE {
31 return Err(EnigmaPacketError::SizeLimitExceeded);
32 }
33 let mut buf = Vec::with_capacity(total);
34 buf.extend_from_slice(&MAGIC);
35 buf.push(VERSION);
36 buf.push(flags);
37 buf.extend_from_slice(&0u16.to_be_bytes());
38 buf.extend_from_slice(&(body.len() as u32).to_be_bytes());
39 buf.extend_from_slice(body);
40 Ok(buf)
41}
42
43pub(crate) fn parse_frame(packet: &[u8]) -> Result<PacketView<'_>> {
44 if packet.len() < HEADER_LEN {
45 return Err(EnigmaPacketError::InvalidPacket("packet too small".into()));
46 }
47 if packet.len() > MAX_PACKET_SIZE {
48 return Err(EnigmaPacketError::SizeLimitExceeded);
49 }
50 if packet[..4] != MAGIC {
51 return Err(EnigmaPacketError::InvalidPacket("invalid magic".into()));
52 }
53 let version = packet[4];
54 if version != VERSION {
55 return Err(EnigmaPacketError::UnsupportedVersion(version));
56 }
57 let flags = packet[5];
58 let reserved = u16::from_be_bytes([packet[6], packet[7]]);
59 let body_len = u32::from_be_bytes([packet[8], packet[9], packet[10], packet[11]]) as usize;
60 let total = HEADER_LEN
61 .checked_add(body_len)
62 .ok_or(EnigmaPacketError::SizeLimitExceeded)?;
63 if total > MAX_PACKET_SIZE {
64 return Err(EnigmaPacketError::SizeLimitExceeded);
65 }
66 if packet.len() != total {
67 return Err(EnigmaPacketError::InvalidPacket(
68 "body length mismatch".into(),
69 ));
70 }
71 let body = &packet[HEADER_LEN..];
72 Ok(PacketView {
73 version,
74 flags,
75 reserved,
76 body_len: body_len as u32,
77 body,
78 })
79}