use crate::protocol::codec::Decode; use nom::number; use nom::IResult; /****************************************************************************** * Struct ******************************************************************************/ /* * User Datagram Header Format * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Source Port | Destination Port | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Length | Checksum | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Data | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ #[derive(Clone, Debug, PartialEq, Eq)] pub struct UdpHeader { pub source_port: u16, pub dest_port: u16, pub length: u16, pub checksum: u16, } /****************************************************************************** * API ******************************************************************************/ impl Decode for UdpHeader { type Iterm = UdpHeader; fn decode(input: &[u8]) -> IResult<&[u8], UdpHeader> { let (input, source_port) = number::streaming::be_u16(input)?; let (input, dest_port) = number::streaming::be_u16(input)?; let (input, length) = number::streaming::be_u16(input)?; let (input, checksum) = number::streaming::be_u16(input)?; Ok(( input, UdpHeader { source_port, dest_port, length, checksum, }, )) } } /****************************************************************************** * TEST ******************************************************************************/ #[cfg(test)] mod tests { use super::UdpHeader; use crate::protocol::codec::Decode; const LAST_SLICE: &'static [u8] = &[0xff]; #[test] fn udp_header_decode() { /* * User Datagram Protocol, Src Port: 9993, Dst Port: 9993 * Source Port: 9993 * Destination Port: 9993 * Length: 145 * Checksum: 0x57d3 [correct] * [Calculated Checksum: 0x57d3] * [Checksum Status: Good] * [Stream index: 3] * [Timestamps] * [Time since first frame: 0.000000000 seconds] * [Time since previous frame: 0.000000000 seconds] * UDP payload (137 bytes) * Data (137 bytes) */ let bytes = [ 0x27, 0x09, /* Source Port */ 0x27, 0x09, /* Destination Port */ 0x00, 0x91, /* Length */ 0x57, 0xd3, /* Checksum */ 0xff, /* Payload */ ]; let expectation = UdpHeader { source_port: 9993, dest_port: 9993, length: 145, checksum: 0x57d3, }; assert_eq!(UdpHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); // example let result = UdpHeader::decode(&bytes); if let Ok((payload, header)) = result { println!("return: {:?}, payload: {}", header, payload.len()); } else { println!("return: Incomplete data"); } } }