bitfold_protocol/command_codec/
decoder.rs1use std::io::{self, Cursor, Read};
8
9use bitfold_core::shared::SharedBytes;
10use byteorder::{BigEndian, ReadBytesExt};
11
12use super::super::command::{CommandPacket, ProtocolCommand};
13
14pub struct CommandDecoder;
16
17impl CommandDecoder {
18 pub fn decode_command(cursor: &mut Cursor<&[u8]>) -> io::Result<ProtocolCommand> {
20 let cmd_type = cursor.read_u8()?;
21
22 let command = match cmd_type {
23 1 => {
24 let channel_id = cursor.read_u8()?;
26 let sequence = cursor.read_u16::<BigEndian>()?;
27 let ordered = cursor.read_u8()? != 0;
28 let data_len = cursor.read_u16::<BigEndian>()? as usize;
29 let mut data_vec = vec![0u8; data_len];
30 cursor.read_exact(&mut data_vec)?;
31 let data = SharedBytes::from_vec(data_vec);
32 ProtocolCommand::SendReliable { channel_id, sequence, ordered, data }
33 }
34 2 => {
35 let channel_id = cursor.read_u8()?;
37 let data_len = cursor.read_u16::<BigEndian>()? as usize;
38 let mut data_vec = vec![0u8; data_len];
39 cursor.read_exact(&mut data_vec)?;
40 let data = SharedBytes::from_vec(data_vec);
41 ProtocolCommand::SendUnreliable { channel_id, data }
42 }
43 3 => {
44 let channel_id = cursor.read_u8()?;
46 let sequence = cursor.read_u16::<BigEndian>()?;
47 let data_len = cursor.read_u16::<BigEndian>()? as usize;
48 let mut data_vec = vec![0u8; data_len];
49 cursor.read_exact(&mut data_vec)?;
50 let data = SharedBytes::from_vec(data_vec);
51 ProtocolCommand::SendUnreliableSequenced { channel_id, sequence, data }
52 }
53 4 => {
54 let channel_id = cursor.read_u8()?;
56 let unsequenced_group = cursor.read_u16::<BigEndian>()?;
57 let data_len = cursor.read_u16::<BigEndian>()? as usize;
58 let mut data_vec = vec![0u8; data_len];
59 cursor.read_exact(&mut data_vec)?;
60 let data = SharedBytes::from_vec(data_vec);
61 ProtocolCommand::SendUnsequenced { channel_id, unsequenced_group, data }
62 }
63 5 => {
64 let channel_id = cursor.read_u8()?;
66 let sequence = cursor.read_u16::<BigEndian>()?;
67 let ordered = cursor.read_u8()? != 0;
68 let fragment_id = cursor.read_u8()?;
69 let fragment_count = cursor.read_u8()?;
70 let data_len = cursor.read_u16::<BigEndian>()? as usize;
71 let mut data_vec = vec![0u8; data_len];
72 cursor.read_exact(&mut data_vec)?;
73 let data = SharedBytes::from_vec(data_vec);
74 ProtocolCommand::SendFragment {
75 channel_id,
76 sequence,
77 ordered,
78 fragment_id,
79 fragment_count,
80 data,
81 }
82 }
83 6 => {
84 let channel_id = cursor.read_u8()?;
86 let sequence = cursor.read_u16::<BigEndian>()?;
87 let fragment_id = cursor.read_u8()?;
88 let fragment_count = cursor.read_u8()?;
89 let data_len = cursor.read_u16::<BigEndian>()? as usize;
90 let mut data_vec = vec![0u8; data_len];
91 cursor.read_exact(&mut data_vec)?;
92 let data = SharedBytes::from_vec(data_vec);
93 ProtocolCommand::SendUnreliableFragment {
94 channel_id,
95 sequence,
96 fragment_id,
97 fragment_count,
98 data,
99 }
100 }
101 7 => {
102 let sequence = cursor.read_u16::<BigEndian>()?;
104 let received_mask = cursor.read_u32::<BigEndian>()?;
105 let sent_time = if cursor.position() < cursor.get_ref().len() as u64 {
107 Some(cursor.read_u32::<BigEndian>()?)
108 } else {
109 None
110 };
111 ProtocolCommand::Acknowledge { sequence, received_mask, sent_time }
112 }
113 8 => {
114 let timestamp = cursor.read_u32::<BigEndian>()?;
116 ProtocolCommand::Ping { timestamp }
117 }
118 9 => {
119 let timestamp = cursor.read_u32::<BigEndian>()?;
121 ProtocolCommand::Pong { timestamp }
122 }
123 10 => {
124 let channels = cursor.read_u8()?;
126 let mtu = cursor.read_u16::<BigEndian>()?;
127 let protocol_version = cursor.read_u16::<BigEndian>()?;
128 let outgoing_session_id = cursor.read_u16::<BigEndian>()?;
129 let connect_id = cursor.read_u32::<BigEndian>()?;
130 ProtocolCommand::Connect {
131 channels,
132 mtu,
133 protocol_version,
134 outgoing_session_id,
135 connect_id,
136 }
137 }
138 11 => {
139 let peer_id = cursor.read_u16::<BigEndian>()?;
141 let channels = cursor.read_u8()?;
142 let mtu = cursor.read_u16::<BigEndian>()?;
143 let incoming_session_id = cursor.read_u16::<BigEndian>()?;
144 let outgoing_session_id = cursor.read_u16::<BigEndian>()?;
145 let window_size = cursor.read_u32::<BigEndian>()?;
146 ProtocolCommand::VerifyConnect {
147 peer_id,
148 channels,
149 mtu,
150 incoming_session_id,
151 outgoing_session_id,
152 window_size,
153 }
154 }
155 12 => {
156 let reason = cursor.read_u32::<BigEndian>()?;
158 ProtocolCommand::Disconnect { reason }
159 }
160 13 => {
161 let incoming = cursor.read_u32::<BigEndian>()?;
163 let outgoing = cursor.read_u32::<BigEndian>()?;
164 ProtocolCommand::BandwidthLimit { incoming, outgoing }
165 }
166 14 => {
167 let interval = cursor.read_u32::<BigEndian>()?;
169 let acceleration = cursor.read_u32::<BigEndian>()?;
170 let deceleration = cursor.read_u32::<BigEndian>()?;
171 ProtocolCommand::ThrottleConfigure { interval, acceleration, deceleration }
172 }
173 15 => {
174 let size = cursor.read_u16::<BigEndian>()?;
176 let token = cursor.read_u32::<BigEndian>()?;
177 let payload_len = cursor.read_u16::<BigEndian>()? as usize;
178 let mut payload = vec![0u8; payload_len];
179 cursor.read_exact(&mut payload)?;
180 ProtocolCommand::PMTUProbe { size, token, payload: SharedBytes::from_vec(payload) }
181 }
182 16 => {
183 let size = cursor.read_u16::<BigEndian>()?;
185 let token = cursor.read_u32::<BigEndian>()?;
186 ProtocolCommand::PMTUReply { size, token }
187 }
188 _ => {
189 return Err(io::Error::new(
190 io::ErrorKind::InvalidData,
191 format!("Unknown command type: {}", cmd_type),
192 ));
193 }
194 };
195
196 Ok(command)
197 }
198
199 pub fn decode_packet(data: &[u8]) -> io::Result<CommandPacket> {
201 let mut cursor = Cursor::new(data);
202 let mut packet = CommandPacket::new();
203
204 let cmd_count = cursor.read_u8()?;
206
207 for _ in 0..cmd_count {
209 let cmd_len = cursor.read_u16::<BigEndian>()? as usize;
210 let pos = cursor.position() as usize;
211
212 if pos + cmd_len > data.len() {
213 return Err(io::Error::new(
214 io::ErrorKind::UnexpectedEof,
215 "Command length exceeds buffer",
216 ));
217 }
218
219 let cmd_data = &data[pos..pos + cmd_len];
220 let mut cmd_cursor = Cursor::new(cmd_data);
221 let command = Self::decode_command(&mut cmd_cursor)?;
222
223 packet.add_command(command);
224 cursor.set_position((pos + cmd_len) as u64);
225 }
226
227 Ok(packet)
228 }
229
230 pub fn validate_and_strip_checksum(data: &[u8]) -> io::Result<&[u8]> {
235 super::checksum::validate_and_strip_checksum(data)
236 }
237
238 pub fn decompress(data: &[u8]) -> io::Result<Vec<u8>> {
246 super::compression::decompress(data)
247 }
248}