arcly_stream/protocol/srt/
packet.rs1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8#[non_exhaustive]
9pub enum ControlType {
10 Handshake,
12 Keepalive,
14 Ack,
16 Nak,
18 Shutdown,
20 AckAck,
22 Other(u16),
24}
25
26impl ControlType {
27 fn from_u16(v: u16) -> ControlType {
28 match v {
29 0x0000 => ControlType::Handshake,
30 0x0001 => ControlType::Keepalive,
31 0x0002 => ControlType::Ack,
32 0x0003 => ControlType::Nak,
33 0x0005 => ControlType::Shutdown,
34 0x0006 => ControlType::AckAck,
35 other => ControlType::Other(other),
36 }
37 }
38}
39
40#[derive(Debug, Clone, PartialEq, Eq)]
43pub enum SrtPacket {
44 Control {
46 control_type: ControlType,
48 dest_socket_id: u32,
50 },
51 Data {
53 sequence: u32,
55 dest_socket_id: u32,
57 payload_offset: usize,
59 },
60}
61
62impl SrtPacket {
63 pub fn parse(buf: &[u8]) -> Option<SrtPacket> {
66 use crate::protocol::byteops::ByteReader;
67 let mut r = ByteReader::new(buf);
68 let word0 = r.u32_be()?;
69 r.skip(8)?; let dest_socket_id = r.u32_be()?;
71
72 if word0 & 0x8000_0000 == 0 {
73 Some(SrtPacket::Data {
75 sequence: word0 & 0x7FFF_FFFF,
76 dest_socket_id,
77 payload_offset: 16,
78 })
79 } else {
80 let control_type = ((word0 >> 16) & 0x7FFF) as u16;
82 Some(SrtPacket::Control {
83 control_type: ControlType::from_u16(control_type),
84 dest_socket_id,
85 })
86 }
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93
94 fn header(word0: u32, dest: u32) -> Vec<u8> {
95 let mut b = word0.to_be_bytes().to_vec();
96 b.extend_from_slice(&[0; 8]); b.extend_from_slice(&dest.to_be_bytes());
98 b
99 }
100
101 #[test]
102 fn parses_data_packet() {
103 let pkt = SrtPacket::parse(&header(0x0000_002A, 99)).unwrap();
104 assert_eq!(
105 pkt,
106 SrtPacket::Data {
107 sequence: 42,
108 dest_socket_id: 99,
109 payload_offset: 16,
110 }
111 );
112 }
113
114 #[test]
115 fn parses_control_handshake() {
116 let pkt = SrtPacket::parse(&header(0x8000_0000, 7)).unwrap();
118 assert_eq!(
119 pkt,
120 SrtPacket::Control {
121 control_type: ControlType::Handshake,
122 dest_socket_id: 7,
123 }
124 );
125 }
126
127 #[test]
128 fn parses_control_nak() {
129 let pkt = SrtPacket::parse(&header(0x8003_0000, 1)).unwrap();
130 match pkt {
131 SrtPacket::Control { control_type, .. } => assert_eq!(control_type, ControlType::Nak),
132 _ => panic!("expected control"),
133 }
134 }
135
136 #[test]
137 fn rejects_short_buffer() {
138 assert!(SrtPacket::parse(&[0u8; 8]).is_none());
139 }
140}