1use byteorder::{BigEndian, ByteOrder};
2use thiserror::Error;
3
4#[derive(Error, Debug)]
5pub enum DdpError {
6 #[error("invalid size - expected {expected:?} bytes but found {found:?}")]
7 InvalidSize { expected: usize, found: usize },
8 #[error("unknown header type - expected 1 or 2, but found {header:?}")]
9 UnknownHeader { header: u8 },
10 #[error("unknown protocol type {found:?}")]
11 UnknownProtocol { found: u8 },
12}
13
14const RTMP_RESPONSE: u8 = 1;
15const NBP: u8 = 2;
16const ATP: u8 = 3;
17const AEP: u8 = 4;
18const RTMP_REQUEST: u8 = 5;
19const ZIP: u8 = 6;
20const ADSP: u8 = 7;
21
22#[repr(u8)]
23#[derive(Debug, Copy, Clone, PartialEq, Eq)]
24pub enum DdpProtocolType {
25 RtmpResponse = RTMP_RESPONSE,
26 Nbp = NBP,
27 Atp = ATP,
28 Aep = AEP,
29 RtmpRequest = RTMP_REQUEST,
30 Zip = ZIP,
31 Adsp = ADSP,
32}
33
34impl TryFrom<u8> for DdpProtocolType {
35 type Error = DdpError;
36
37 fn try_from(data: u8) -> Result<Self, Self::Error> {
38 match data {
39 RTMP_RESPONSE => Ok(DdpProtocolType::RtmpResponse),
40 NBP => Ok(DdpProtocolType::Nbp),
41 ATP => Ok(DdpProtocolType::Atp),
42 AEP => Ok(DdpProtocolType::Aep),
43 RTMP_REQUEST => Ok(DdpProtocolType::RtmpRequest),
44 ZIP => Ok(DdpProtocolType::Zip),
45 ADSP => Ok(DdpProtocolType::Adsp),
46 _ => Err(DdpError::UnknownProtocol { found: data }),
47 }
48 }
49}
50
51#[derive(Debug, Clone)]
52pub struct DdpPacket {
53 pub hop_count: u8,
54 pub len: usize,
55 pub chksum: u16,
56 pub dest_network_num: u16,
57 pub src_network_num: u16,
58 pub dest_node_id: u8,
59 pub dest_sock_num: u8,
60 pub src_sock_num: u8,
61 pub src_node_id: u8,
62 pub protocol_typ: DdpProtocolType,
63}
64
65impl DdpPacket {
66 pub const LEN: usize = 13;
67
68 pub const fn calc_len(buf: &[u8]) -> usize {
69 Self::LEN + buf.len() - 1
70 }
71
72 pub fn compute_checksum(buf: &[u8]) -> u16 {
73 let mut csum: u16 = 0;
74
75 for &byte in buf {
76 csum = csum.wrapping_add(byte as u16);
77 csum = csum.rotate_left(1);
78 }
79 if csum == 0 { 0xFFFF } else { csum }
80 }
81
82 pub fn parse(bytes: &[u8]) -> Result<Self, DdpError> {
83 if bytes.len() < 13 {
84 return Err(DdpError::InvalidSize {
85 expected: 13,
86 found: bytes.len(),
87 });
88 }
89
90 let hop_count = (bytes[0] & 0x3C) >> 2;
91 let data_len = (BigEndian::read_u16(bytes) & 0x3FF) as usize;
92 let chksum = BigEndian::read_u16(&bytes[2..]);
93 let dest_network_num = BigEndian::read_u16(&bytes[4..]);
94 let src_network_num = BigEndian::read_u16(&bytes[6..]);
95 let dest_node_id = bytes[8];
96 let src_node_id = bytes[9];
97 let dest_sock_num = bytes[10];
98 let src_sock_num = bytes[11];
99 let protocol_typ = bytes[12].try_into()?;
100
101 Ok(Self {
102 dest_node_id,
103 hop_count,
104 len: data_len,
105 chksum,
106 dest_network_num,
107 src_network_num,
108 src_node_id,
109 dest_sock_num,
110 src_sock_num,
111 protocol_typ,
112 })
113 }
114
115 pub fn parse_short(bytes: &[u8], dst_node: u8, src_node: u8) -> Result<Self, DdpError> {
116 if bytes.len() < 5 {
117 return Err(DdpError::InvalidSize {
118 expected: 5,
119 found: bytes.len(),
120 });
121 }
122
123 let len = (BigEndian::read_u16(bytes) & 0x3FF) as usize;
124 let dest_sock_num = bytes[2];
125 let src_sock_num = bytes[3];
126 let protocol_typ = bytes[4].try_into()?;
127
128 Ok(Self {
129 dest_node_id: dst_node,
130 hop_count: 0,
131 len,
132 chksum: 0,
133 dest_network_num: 0,
134 src_network_num: 0,
135 src_node_id: src_node,
136 dest_sock_num,
137 src_sock_num,
138 protocol_typ,
139 })
140 }
141
142 pub fn to_bytes(&self, buf: &mut [u8]) -> Result<usize, DdpError> {
143 if buf.len() < 13 {
144 return Err(DdpError::InvalidSize {
145 expected: 13,
146 found: buf.len(),
147 });
148 }
149
150 BigEndian::write_u16(buf, ((self.hop_count as u16 & 0xF) << 2) | self.len as u16);
151 BigEndian::write_u16(&mut buf[2..], self.chksum);
152 BigEndian::write_u16(&mut buf[4..], self.dest_network_num);
153 BigEndian::write_u16(&mut buf[6..], self.src_network_num);
154 buf[8] = self.dest_node_id;
155 buf[9] = self.src_node_id;
156 buf[10] = self.dest_sock_num;
157 buf[11] = self.src_sock_num;
158 buf[12] = self.protocol_typ as u8;
159
160 Ok(13)
161 }
162
163 pub fn to_bytes_short(&self, buf: &mut [u8]) -> Result<usize, DdpError> {
164 if buf.len() < 5 {
165 return Err(DdpError::InvalidSize {
166 expected: 5,
167 found: buf.len(),
168 });
169 }
170
171 BigEndian::write_u16(buf, self.len as u16 & 0x3FF);
172 buf[2] = self.dest_sock_num;
173 buf[3] = self.src_sock_num;
174 buf[4] = self.protocol_typ as u8;
175
176 Ok(5)
177 }
178}
179
180#[cfg(test)]
181mod tests {
182 use super::*;
183
184 #[test]
185 fn test_parse_ddp() {
186 let test_data: &[u8] = &[
187 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0xff, 0x54, 0xff, 0x44, 0x06, 0x06, 0x06, 0x05,
188 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
189 ];
190
191 let packet: DdpPacket = DdpPacket::parse(test_data).expect("failed to parse");
192
193 assert_eq!(packet.hop_count, 0);
194 assert_eq!(packet.len, 20);
195 assert_eq!(packet.chksum, 0);
196 assert_eq!(packet.src_network_num, 65364);
197 assert_eq!(packet.dest_network_num, 0);
198 assert_eq!(packet.src_node_id, 68);
199 assert_eq!(packet.dest_node_id, 255);
200 assert_eq!(packet.src_sock_num, 6);
201 assert_eq!(packet.dest_sock_num, 6);
202 assert_eq!(packet.protocol_typ, DdpProtocolType::Zip);
203 }
204
205 #[test]
206 fn test_generate_ddp() {
207 let test_data: &[u8] = &[
208 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0xff, 0x54, 0xff, 0x44, 0x06, 0x06, 0x06,
209 ];
210
211 let packet = DdpPacket {
212 hop_count: 0,
213 len: 20,
214 chksum: 0,
215 src_network_num: 65364,
216 dest_network_num: 0,
217 src_node_id: 68,
218 dest_node_id: 255,
219 src_sock_num: 6,
220 dest_sock_num: 6,
221 protocol_typ: DdpProtocolType::Zip,
222 };
223
224 let mut buffer: [u8; 13] = [0u8; 13];
225
226 packet
227 .to_bytes(&mut buffer)
228 .expect("failed to generate packet");
229
230 assert_eq!(test_data, &buffer);
231 }
232
233 #[test]
234 fn test_parse_ddp_short() {
235 let test_data: &[u8] = &[0x00, 0x05, 0x01, 0x02, 0x06];
237
238 let dst_node = 10;
239 let src_node = 20;
240
241 let packet =
242 DdpPacket::parse_short(test_data, dst_node, src_node).expect("failed to parse");
243
244 assert_eq!(packet.len, 5);
245 assert_eq!(packet.dest_node_id, dst_node);
246 assert_eq!(packet.src_node_id, src_node);
247 assert_eq!(packet.dest_sock_num, 1);
248 assert_eq!(packet.src_sock_num, 2);
249 assert_eq!(packet.protocol_typ, DdpProtocolType::Zip);
250 }
251}