bitfold_protocol/command_codec/
encoder.rs1use std::io::{self, Write};
7
8use byteorder::{BigEndian, WriteBytesExt};
9
10use super::super::command::{CommandPacket, ProtocolCommand};
11
12pub struct CommandEncoder;
14
15impl CommandEncoder {
16 pub fn encode_command_into(buffer: &mut Vec<u8>, command: &ProtocolCommand) -> io::Result<()> {
18 buffer.write_u8(command.command_type())?;
20
21 match command {
22 ProtocolCommand::SendReliable { channel_id, sequence, ordered, data } => {
23 buffer.write_u8(*channel_id)?;
24 buffer.write_u16::<BigEndian>(*sequence)?;
25 buffer.write_u8(if *ordered { 1 } else { 0 })?;
26 buffer.write_u16::<BigEndian>(data.len() as u16)?;
27 buffer.write_all(data.as_slice())?;
28 }
29 ProtocolCommand::SendUnreliable { channel_id, data } => {
30 buffer.write_u8(*channel_id)?;
31 buffer.write_u16::<BigEndian>(data.len() as u16)?;
32 buffer.write_all(data.as_slice())?;
33 }
34 ProtocolCommand::SendUnreliableSequenced { channel_id, sequence, data } => {
35 buffer.write_u8(*channel_id)?;
36 buffer.write_u16::<BigEndian>(*sequence)?;
37 buffer.write_u16::<BigEndian>(data.len() as u16)?;
38 buffer.write_all(data.as_slice())?;
39 }
40 ProtocolCommand::SendUnsequenced { channel_id, unsequenced_group, data } => {
41 buffer.write_u8(*channel_id)?;
42 buffer.write_u16::<BigEndian>(*unsequenced_group)?;
43 buffer.write_u16::<BigEndian>(data.len() as u16)?;
44 buffer.write_all(data.as_slice())?;
45 }
46 ProtocolCommand::SendFragment {
47 channel_id,
48 sequence,
49 ordered,
50 fragment_id,
51 fragment_count,
52 data,
53 } => {
54 buffer.write_u8(*channel_id)?;
55 buffer.write_u16::<BigEndian>(*sequence)?;
56 buffer.write_u8(if *ordered { 1 } else { 0 })?;
57 buffer.write_u8(*fragment_id)?;
58 buffer.write_u8(*fragment_count)?;
59 buffer.write_u16::<BigEndian>(data.len() as u16)?;
60 buffer.write_all(data.as_slice())?;
61 }
62 ProtocolCommand::SendUnreliableFragment {
63 channel_id,
64 sequence,
65 fragment_id,
66 fragment_count,
67 data,
68 } => {
69 buffer.write_u8(*channel_id)?;
70 buffer.write_u16::<BigEndian>(*sequence)?;
71 buffer.write_u8(*fragment_id)?;
72 buffer.write_u8(*fragment_count)?;
73 buffer.write_u16::<BigEndian>(data.len() as u16)?;
74 buffer.write_all(data.as_slice())?;
75 }
76 ProtocolCommand::Acknowledge { sequence, received_mask, sent_time } => {
77 buffer.write_u16::<BigEndian>(*sequence)?;
78 buffer.write_u32::<BigEndian>(*received_mask)?;
79 if let Some(time) = sent_time {
80 buffer.write_u32::<BigEndian>(*time)?;
81 }
82 }
83 ProtocolCommand::Ping { timestamp } => {
84 buffer.write_u32::<BigEndian>(*timestamp)?;
85 }
86 ProtocolCommand::Pong { timestamp } => {
87 buffer.write_u32::<BigEndian>(*timestamp)?;
88 }
89 ProtocolCommand::Connect {
90 channels,
91 mtu,
92 protocol_version,
93 outgoing_session_id,
94 connect_id,
95 } => {
96 buffer.write_u8(*channels)?;
97 buffer.write_u16::<BigEndian>(*mtu)?;
98 buffer.write_u16::<BigEndian>(*protocol_version)?;
99 buffer.write_u16::<BigEndian>(*outgoing_session_id)?;
100 buffer.write_u32::<BigEndian>(*connect_id)?;
101 }
102 ProtocolCommand::VerifyConnect {
103 peer_id,
104 channels,
105 mtu,
106 incoming_session_id,
107 outgoing_session_id,
108 window_size,
109 } => {
110 buffer.write_u16::<BigEndian>(*peer_id)?;
111 buffer.write_u8(*channels)?;
112 buffer.write_u16::<BigEndian>(*mtu)?;
113 buffer.write_u16::<BigEndian>(*incoming_session_id)?;
114 buffer.write_u16::<BigEndian>(*outgoing_session_id)?;
115 buffer.write_u32::<BigEndian>(*window_size)?;
116 }
117 ProtocolCommand::Disconnect { reason } => {
118 buffer.write_u32::<BigEndian>(*reason)?;
119 }
120 ProtocolCommand::BandwidthLimit { incoming, outgoing } => {
121 buffer.write_u32::<BigEndian>(*incoming)?;
122 buffer.write_u32::<BigEndian>(*outgoing)?;
123 }
124 ProtocolCommand::ThrottleConfigure { interval, acceleration, deceleration } => {
125 buffer.write_u32::<BigEndian>(*interval)?;
126 buffer.write_u32::<BigEndian>(*acceleration)?;
127 buffer.write_u32::<BigEndian>(*deceleration)?;
128 }
129 ProtocolCommand::PMTUProbe { size, token, payload } => {
130 buffer.write_u16::<BigEndian>(*size)?;
131 buffer.write_u32::<BigEndian>(*token)?;
132 buffer.write_u16::<BigEndian>(payload.len() as u16)?;
133 buffer.write_all(payload.as_slice())?;
134 }
135 ProtocolCommand::PMTUReply { size, token } => {
136 buffer.write_u16::<BigEndian>(*size)?;
137 buffer.write_u32::<BigEndian>(*token)?;
138 }
139 }
140
141 Ok(())
142 }
143
144 pub fn encode_packet_into(buffer: &mut Vec<u8>, packet: &CommandPacket) -> io::Result<()> {
146 buffer.write_u8(packet.commands.len() as u8)?;
148
149 for command in &packet.commands {
152 let len_pos = buffer.len();
153 buffer.write_u16::<BigEndian>(0)?; let start = buffer.len();
155 Self::encode_command_into(buffer, command)?;
156 let cmd_len = buffer.len() - start;
157 buffer[len_pos] = ((cmd_len >> 8) & 0xFF) as u8;
159 buffer[len_pos + 1] = (cmd_len & 0xFF) as u8;
160 }
161
162 Ok(())
163 }
164
165 pub fn encode_command(command: &ProtocolCommand) -> io::Result<Vec<u8>> {
167 let mut buffer = Vec::new();
168
169 buffer.write_u8(command.command_type())?;
171
172 match command {
173 ProtocolCommand::SendReliable { channel_id, sequence, ordered, data } => {
174 buffer.write_u8(*channel_id)?;
175 buffer.write_u16::<BigEndian>(*sequence)?;
176 buffer.write_u8(if *ordered { 1 } else { 0 })?;
177 buffer.write_u16::<BigEndian>(data.len() as u16)?;
178 buffer.write_all(data.as_slice())?;
179 }
180 ProtocolCommand::SendUnreliable { channel_id, data } => {
181 buffer.write_u8(*channel_id)?;
182 buffer.write_u16::<BigEndian>(data.len() as u16)?;
183 buffer.write_all(data.as_slice())?;
184 }
185 ProtocolCommand::SendUnreliableSequenced { channel_id, sequence, data } => {
186 buffer.write_u8(*channel_id)?;
187 buffer.write_u16::<BigEndian>(*sequence)?;
188 buffer.write_u16::<BigEndian>(data.len() as u16)?;
189 buffer.write_all(data.as_slice())?;
190 }
191 ProtocolCommand::SendUnsequenced { channel_id, unsequenced_group, data } => {
192 buffer.write_u8(*channel_id)?;
193 buffer.write_u16::<BigEndian>(*unsequenced_group)?;
194 buffer.write_u16::<BigEndian>(data.len() as u16)?;
195 buffer.write_all(data.as_slice())?;
196 }
197 ProtocolCommand::SendFragment {
198 channel_id,
199 sequence,
200 ordered,
201 fragment_id,
202 fragment_count,
203 data,
204 } => {
205 buffer.write_u8(*channel_id)?;
206 buffer.write_u16::<BigEndian>(*sequence)?;
207 buffer.write_u8(if *ordered { 1 } else { 0 })?;
208 buffer.write_u8(*fragment_id)?;
209 buffer.write_u8(*fragment_count)?;
210 buffer.write_u16::<BigEndian>(data.len() as u16)?;
211 buffer.write_all(data.as_slice())?;
212 }
213 ProtocolCommand::SendUnreliableFragment {
214 channel_id,
215 sequence,
216 fragment_id,
217 fragment_count,
218 data,
219 } => {
220 buffer.write_u8(*channel_id)?;
221 buffer.write_u16::<BigEndian>(*sequence)?;
222 buffer.write_u8(*fragment_id)?;
223 buffer.write_u8(*fragment_count)?;
224 buffer.write_u16::<BigEndian>(data.len() as u16)?;
225 buffer.write_all(data.as_slice())?;
226 }
227 ProtocolCommand::Acknowledge { sequence, received_mask, sent_time } => {
228 buffer.write_u16::<BigEndian>(*sequence)?;
229 buffer.write_u32::<BigEndian>(*received_mask)?;
230 if let Some(time) = sent_time {
231 buffer.write_u32::<BigEndian>(*time)?;
232 }
233 }
234 ProtocolCommand::Ping { timestamp } => {
235 buffer.write_u32::<BigEndian>(*timestamp)?;
236 }
237 ProtocolCommand::Pong { timestamp } => {
238 buffer.write_u32::<BigEndian>(*timestamp)?;
239 }
240 ProtocolCommand::Connect {
241 channels,
242 mtu,
243 protocol_version,
244 outgoing_session_id,
245 connect_id,
246 } => {
247 buffer.write_u8(*channels)?;
248 buffer.write_u16::<BigEndian>(*mtu)?;
249 buffer.write_u16::<BigEndian>(*protocol_version)?;
250 buffer.write_u16::<BigEndian>(*outgoing_session_id)?;
251 buffer.write_u32::<BigEndian>(*connect_id)?;
252 }
253 ProtocolCommand::VerifyConnect {
254 peer_id,
255 channels,
256 mtu,
257 incoming_session_id,
258 outgoing_session_id,
259 window_size,
260 } => {
261 buffer.write_u16::<BigEndian>(*peer_id)?;
262 buffer.write_u8(*channels)?;
263 buffer.write_u16::<BigEndian>(*mtu)?;
264 buffer.write_u16::<BigEndian>(*incoming_session_id)?;
265 buffer.write_u16::<BigEndian>(*outgoing_session_id)?;
266 buffer.write_u32::<BigEndian>(*window_size)?;
267 }
268 ProtocolCommand::Disconnect { reason } => {
269 buffer.write_u32::<BigEndian>(*reason)?;
270 }
271 ProtocolCommand::BandwidthLimit { incoming, outgoing } => {
272 buffer.write_u32::<BigEndian>(*incoming)?;
273 buffer.write_u32::<BigEndian>(*outgoing)?;
274 }
275 ProtocolCommand::ThrottleConfigure { interval, acceleration, deceleration } => {
276 buffer.write_u32::<BigEndian>(*interval)?;
277 buffer.write_u32::<BigEndian>(*acceleration)?;
278 buffer.write_u32::<BigEndian>(*deceleration)?;
279 }
280 ProtocolCommand::PMTUProbe { size, token, payload } => {
281 buffer.write_u16::<BigEndian>(*size)?;
282 buffer.write_u32::<BigEndian>(*token)?;
283 buffer.write_u16::<BigEndian>(payload.len() as u16)?;
284 buffer.write_all(payload.as_slice())?;
285 }
286 ProtocolCommand::PMTUReply { size, token } => {
287 buffer.write_u16::<BigEndian>(*size)?;
288 buffer.write_u32::<BigEndian>(*token)?;
289 }
290 }
291
292 Ok(buffer)
293 }
294
295 pub fn encode_packet(packet: &CommandPacket) -> io::Result<Vec<u8>> {
297 let mut buffer = Vec::new();
298
299 buffer.write_u8(packet.commands.len() as u8)?;
301
302 for command in &packet.commands {
304 let cmd_bytes = Self::encode_command(command)?;
305 buffer.write_u16::<BigEndian>(cmd_bytes.len() as u16)?;
306 buffer.write_all(&cmd_bytes)?;
307 }
308
309 Ok(buffer)
310 }
311}