pub const PACKET_DATA: u8 = 0x01;
pub const PACKET_PARITY: u8 = 0x02;
pub const PACKET_PING: u8 = 0x03;
pub const PACKET_PONG: u8 = 0x04;
pub const PACKET_CONTROL: u8 = 0x05;
pub const HEADER_SIZE: usize = 11; pub const AUTH_TAG_SIZE: usize = 16;
pub const MAX_PAYLOAD: usize = 1400; pub const MAX_PACKET: usize = HEADER_SIZE + MAX_PAYLOAD + AUTH_TAG_SIZE;
pub fn encode_header(buf: &mut [u8], packet_type: u8, seq: u64, payload_len: u16) {
buf[0] = packet_type;
buf[1..9].copy_from_slice(&seq.to_le_bytes());
buf[9..11].copy_from_slice(&payload_len.to_le_bytes());
}
pub fn decode_header(buf: &[u8]) -> (u8, u64, u16) {
let packet_type = buf[0];
let seq = u64::from_le_bytes([
buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8],
]);
let payload_len = u16::from_le_bytes([buf[9], buf[10]]);
(packet_type, seq, payload_len)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn roundtrip_header() {
let mut buf = [0u8; HEADER_SIZE];
encode_header(&mut buf, PACKET_DATA, 1234u64, 500);
let (ptype, seq, len) = decode_header(&buf);
assert_eq!(ptype, PACKET_DATA);
assert_eq!(seq, 1234u64);
assert_eq!(len, 500);
}
#[test]
fn all_packet_types() {
for ptype in [
PACKET_DATA,
PACKET_PARITY,
PACKET_PING,
PACKET_PONG,
PACKET_CONTROL,
] {
let mut buf = [0u8; HEADER_SIZE];
encode_header(&mut buf, ptype, 0, 0);
let (decoded_type, _, _) = decode_header(&buf);
assert_eq!(decoded_type, ptype);
}
}
#[test]
fn max_seq_and_len() {
let mut buf = [0u8; HEADER_SIZE];
encode_header(&mut buf, PACKET_DATA, u64::MAX, u16::MAX);
let (ptype, seq, len) = decode_header(&buf);
assert_eq!(ptype, PACKET_DATA);
assert_eq!(seq, u64::MAX);
assert_eq!(len, u16::MAX);
}
#[test]
fn zero_values() {
let mut buf = [0u8; HEADER_SIZE];
encode_header(&mut buf, 0, 0, 0);
let (ptype, seq, len) = decode_header(&buf);
assert_eq!(ptype, 0);
assert_eq!(seq, 0);
assert_eq!(len, 0);
}
#[test]
fn payload_within_mtu() {
assert!(MAX_PACKET <= 1500);
assert_eq!(MAX_PACKET, HEADER_SIZE + MAX_PAYLOAD + AUTH_TAG_SIZE);
}
}