1use bitfield::bitfield;
6use packet_encoding::{decodable_enum, Decodable, Encodable};
7
8mod dlc_parameter_negotiation;
10pub use dlc_parameter_negotiation::{
11 CreditBasedFlowHandshake, ParameterNegotiationParams, DEFAULT_INITIAL_CREDITS,
12};
13
14mod flow_control;
16pub use flow_control::FlowControlParams;
17
18mod modem_status;
20pub use modem_status::ModemStatusParams;
21
22mod non_supported;
24pub use non_supported::NonSupportedCommandParams;
25
26mod remote_line_status;
28pub use remote_line_status::{RemoteLineStatusParams, RlsError};
29
30mod remote_port_negotiation;
32pub use remote_port_negotiation::RemotePortNegotiationParams;
33
34mod test_command;
36pub use test_command::TestCommandParams;
37
38use crate::frame::{CommandResponse, FrameParseError};
39use crate::DLCI;
40
41decodable_enum! {
42 pub enum MuxCommandMarker<u8, FrameParseError, OutOfRange> {
46 ParameterNegotiation = 0b100000,
47 Test = 0b001000,
48 FlowControlOn = 0b101000,
49 FlowControlOff = 0b011000,
50 ModemStatus = 0b111000,
51 NonSupportedCommand = 0b000100,
52 RemotePortNegotiation = 0b100100,
53 RemoteLineStatus = 0b010100,
54 }
55}
56
57const MIN_MUX_COMMAND_SIZE: usize = 2;
60
61const MUX_COMMAND_TYPE_IDX: usize = 0;
64bitfield! {
65 struct TypeField(u8);
66 impl Debug;
67 pub bool, ea_bit, set_ea_bit: 0;
68 pub bool, cr_bit, set_cr_bit: 1;
69 pub u8, command_type_raw, set_command_type: 7, 2;
70}
71
72impl TypeField {
73 fn command_type(&self) -> Result<MuxCommandMarker, FrameParseError> {
74 MuxCommandMarker::try_from(self.command_type_raw())
75 .or(Err(FrameParseError::UnsupportedMuxCommandType(self.command_type_raw())))
76 }
77
78 fn command_response(&self) -> CommandResponse {
79 if self.cr_bit() {
81 CommandResponse::Command
82 } else {
83 CommandResponse::Response
84 }
85 }
86}
87
88const MUX_COMMAND_LENGTH_IDX: usize = 1;
91
92const MUX_COMMAND_LENGTH_SHIFT: usize = 7;
95
96bitfield! {
97 pub struct LengthField(u8);
98 impl Debug;
99 pub bool, ea_bit, set_ea_bit: 0;
100 pub u8, length, set_length: 7, 1;
101}
102
103#[derive(Clone, Debug, PartialEq)]
105pub enum MuxCommandParams {
106 ParameterNegotiation(ParameterNegotiationParams),
107 FlowControlOn(FlowControlParams),
108 FlowControlOff(FlowControlParams),
109 ModemStatus(ModemStatusParams),
110 NonSupported(NonSupportedCommandParams),
111 RemoteLineStatus(RemoteLineStatusParams),
112 RemotePortNegotiation(RemotePortNegotiationParams),
113 Test(TestCommandParams),
114}
115
116impl MuxCommandParams {
117 pub fn marker(&self) -> MuxCommandMarker {
118 match self {
119 Self::ParameterNegotiation(_) => MuxCommandMarker::ParameterNegotiation,
120 Self::FlowControlOn(_) => MuxCommandMarker::FlowControlOn,
121 Self::FlowControlOff(_) => MuxCommandMarker::FlowControlOff,
122 Self::ModemStatus(_) => MuxCommandMarker::ModemStatus,
123 Self::NonSupported(_) => MuxCommandMarker::NonSupportedCommand,
124 Self::RemoteLineStatus(_) => MuxCommandMarker::RemoteLineStatus,
125 Self::RemotePortNegotiation(_) => MuxCommandMarker::RemotePortNegotiation,
126 Self::Test(_) => MuxCommandMarker::Test,
127 }
128 }
129
130 fn decode(command_type: &MuxCommandMarker, buf: &[u8]) -> Result<Self, FrameParseError> {
131 let params = match command_type {
132 MuxCommandMarker::ParameterNegotiation => {
133 Self::ParameterNegotiation(ParameterNegotiationParams::decode(buf)?)
134 }
135 MuxCommandMarker::FlowControlOn => Self::FlowControlOn(FlowControlParams::decode(buf)?),
136 MuxCommandMarker::FlowControlOff => {
137 Self::FlowControlOff(FlowControlParams::decode(buf)?)
138 }
139 MuxCommandMarker::ModemStatus => Self::ModemStatus(ModemStatusParams::decode(buf)?),
140 MuxCommandMarker::NonSupportedCommand => {
141 Self::NonSupported(NonSupportedCommandParams::decode(buf)?)
142 }
143 MuxCommandMarker::RemoteLineStatus => {
144 Self::RemoteLineStatus(RemoteLineStatusParams::decode(buf)?)
145 }
146 MuxCommandMarker::RemotePortNegotiation => {
147 Self::RemotePortNegotiation(RemotePortNegotiationParams::decode(buf)?)
148 }
149 MuxCommandMarker::Test => Self::Test(TestCommandParams::decode(buf)?),
150 };
151 Ok(params)
152 }
153}
154
155impl Encodable for MuxCommandParams {
156 type Error = FrameParseError;
157
158 fn encoded_len(&self) -> usize {
159 match self {
160 Self::ParameterNegotiation(cmd) => cmd.encoded_len(),
161 Self::FlowControlOn(cmd) => cmd.encoded_len(),
162 Self::FlowControlOff(cmd) => cmd.encoded_len(),
163 Self::ModemStatus(cmd) => cmd.encoded_len(),
164 Self::NonSupported(cmd) => cmd.encoded_len(),
165 Self::RemoteLineStatus(cmd) => cmd.encoded_len(),
166 Self::RemotePortNegotiation(cmd) => cmd.encoded_len(),
167 Self::Test(cmd) => cmd.encoded_len(),
168 }
169 }
170
171 fn encode(&self, buf: &mut [u8]) -> Result<(), FrameParseError> {
172 match self {
173 Self::ParameterNegotiation(cmd) => cmd.encode(buf),
174 Self::FlowControlOn(cmd) => cmd.encode(buf),
175 Self::FlowControlOff(cmd) => cmd.encode(buf),
176 Self::ModemStatus(cmd) => cmd.encode(buf),
177 Self::NonSupported(cmd) => cmd.encode(buf),
178 Self::RemoteLineStatus(cmd) => cmd.encode(buf),
179 Self::RemotePortNegotiation(cmd) => cmd.encode(buf),
180 Self::Test(cmd) => cmd.encode(buf),
181 }
182 }
183}
184
185fn length_to_ea_format(mut length: usize) -> Vec<u8> {
188 if length == 0 {
189 let mut length_field = LengthField(0);
191 length_field.set_ea_bit(true);
192 return vec![length_field.0];
193 }
194
195 let mut octets = vec![];
196 let mask = 0b01111111;
197 while length != 0 {
199 let mut length_field = LengthField(0);
200 let length_octet = (length & mask) as u8;
201 length_field.set_length(length_octet);
202 length_field.set_ea_bit(false);
203 octets.push(length_field);
204 length >>= MUX_COMMAND_LENGTH_SHIFT;
205 }
206 let last_idx = octets.len() - 1;
208 octets[last_idx].set_ea_bit(true);
209
210 octets.iter().map(|l| l.0).collect()
211}
212
213#[derive(Debug, Eq, Hash, PartialEq)]
217pub struct MuxCommandIdentifier(pub Option<DLCI>, pub MuxCommandMarker);
218
219#[derive(Clone, Debug, PartialEq)]
221pub struct MuxCommand {
222 pub params: MuxCommandParams,
224
225 pub command_response: CommandResponse,
227}
228
229impl MuxCommand {
230 pub fn dlci(&self) -> Option<DLCI> {
237 match &self.params {
238 MuxCommandParams::ParameterNegotiation(pn) => Some(pn.dlci),
239 MuxCommandParams::ModemStatus(status) => Some(status.dlci),
240 MuxCommandParams::RemoteLineStatus(rls) => Some(rls.dlci),
241 MuxCommandParams::RemotePortNegotiation(rpn) => Some(rpn.dlci),
242 _ => None,
243 }
244 }
245
246 pub fn identifier(&self) -> MuxCommandIdentifier {
249 MuxCommandIdentifier(self.dlci(), self.params.marker())
250 }
251}
252
253impl Decodable for MuxCommand {
254 type Error = FrameParseError;
255
256 fn decode(buf: &[u8]) -> Result<Self, FrameParseError> {
257 if buf.len() < MIN_MUX_COMMAND_SIZE {
258 return Err(FrameParseError::BufferTooSmall);
259 }
260
261 let type_field = TypeField(buf[MUX_COMMAND_TYPE_IDX]);
263 let command_response = type_field.command_response();
264 let command_type = type_field.command_type()?;
265
266 const MAX_LENGTH_OCTETS: usize = 8;
270 let mut length: u64 = 0;
271 let mut num_length_octets: usize = 0;
272
273 for i in MUX_COMMAND_LENGTH_IDX..buf.len() {
274 let length_field = LengthField(buf[i]);
275 let length_octet: u64 = length_field.length().into();
276 length |= length_octet << (MUX_COMMAND_LENGTH_SHIFT * num_length_octets);
277 num_length_octets += 1;
278
279 if length_field.ea_bit() {
281 break;
282 }
283
284 if num_length_octets > MAX_LENGTH_OCTETS {
285 return Err(FrameParseError::InvalidFrame);
286 }
287 }
288
289 let header_len = 1 + num_length_octets;
293 let calculated_buf_size: u64 = header_len as u64 + length;
294 if (buf.len() as u64) < calculated_buf_size {
295 return Err(FrameParseError::BufferTooSmall);
296 }
297
298 let params_payload = &buf[header_len..calculated_buf_size as usize];
299 let params = MuxCommandParams::decode(&command_type, params_payload)?;
300
301 Ok(Self { params, command_response })
302 }
303}
304
305impl Encodable for MuxCommand {
306 type Error = FrameParseError;
307
308 fn encoded_len(&self) -> usize {
311 let length = self.params.encoded_len();
312 1 + length_to_ea_format(length).len() + length
313 }
314
315 fn encode(&self, buf: &mut [u8]) -> Result<(), FrameParseError> {
316 if buf.len() < self.encoded_len() {
317 return Err(FrameParseError::BufferTooSmall);
318 }
319
320 let cr_bit = if self.command_response == CommandResponse::Command { true } else { false };
322
323 let mut type_field = TypeField(0);
325 type_field.set_ea_bit(true);
326 type_field.set_cr_bit(cr_bit);
327 type_field.set_command_type(u8::from(&self.params.marker()));
328 buf[0] = type_field.0;
329
330 let length = self.params.encoded_len();
332 let length_octets = length_to_ea_format(length);
333 let length_end_idx = MUX_COMMAND_LENGTH_IDX + length_octets.len();
334 buf[MUX_COMMAND_LENGTH_IDX..length_end_idx].copy_from_slice(&length_octets);
335
336 self.params.encode(&mut buf[length_end_idx..])?;
338
339 Ok(())
340 }
341}
342
343#[cfg(test)]
344mod tests {
345 use super::*;
346
347 use assert_matches::assert_matches;
348 use modem_status::ModemStatusSignals;
349
350 #[test]
351 fn test_decode_mux_command_empty_buf() {
352 let empty_buf = [];
353 assert_matches!(MuxCommand::decode(&empty_buf[..]), Err(FrameParseError::BufferTooSmall));
354 }
355
356 #[test]
357 fn test_decode_mux_command_invalid_command_type() {
358 let buf = [
359 0b11111101, 0b00000001, ];
362 assert_matches!(
363 MuxCommand::decode(&buf[..]),
364 Err(FrameParseError::UnsupportedMuxCommandType(0b111111))
365 );
366 }
367
368 #[test]
369 fn test_decode_mux_command_too_large_length() {
370 let buf = [
371 0b10000001, 0b00000010, 0b00000010, 0b00000010, 0b00000010, 0b00000010, 0b00000010, 0b00000010, 0b00000010, 0b00000010, 0b00000000, ];
383 assert_matches!(MuxCommand::decode(&buf[..]), Err(FrameParseError::InvalidFrame));
384 }
385
386 #[test]
387 fn test_decode_mux_command_missing_length_octets() {
388 let buf = [
389 0b10000001, 0b00000101, 0b00000010, ];
394 assert_matches!(MuxCommand::decode(&buf[..]), Err(FrameParseError::BufferTooSmall));
395 }
396
397 #[test]
398 fn test_decode_dlc_parameter_negotiation_command() {
399 let buf = [
400 0b10000011, 0b00010001, 0b00000000, 0b11110000, 0b00001100, 0b00000000, 0b00010100, 0b00000000, 0b00000000, 0b00000001, ];
411 let expected = MuxCommand {
412 params: MuxCommandParams::ParameterNegotiation(ParameterNegotiationParams {
413 dlci: DLCI::try_from(0).unwrap(),
414 credit_based_flow_handshake: CreditBasedFlowHandshake::SupportedRequest,
415 priority: 12,
416 max_frame_size: 20,
417 initial_credits: 1,
418 }),
419 command_response: CommandResponse::Command,
420 };
421 assert_eq!(MuxCommand::decode(&buf[..]).unwrap(), expected);
422 }
423
424 #[test]
425 fn test_decode_test_command() {
426 let buf = [
427 0b00100011, 0b00001001, 0b00000000, 0b00000000, 0b00000000, 0b00000000, ];
434 let expected = MuxCommand {
435 params: MuxCommandParams::Test(TestCommandParams {
436 test_pattern: vec![0x00, 0x00, 0x00, 0x00],
437 }),
438 command_response: CommandResponse::Command,
439 };
440 assert_eq!(MuxCommand::decode(&buf[..]).unwrap(), expected);
441 }
442
443 #[test]
444 fn test_decode_flow_control_on_command() {
445 let buf = [
446 0b10100001, 0b00000001, ];
449 let expected = MuxCommand {
450 params: MuxCommandParams::FlowControlOn(FlowControlParams {}),
451 command_response: CommandResponse::Response,
452 };
453 assert_eq!(MuxCommand::decode(&buf[..]).unwrap(), expected);
454 }
455
456 #[test]
457 fn test_decode_flow_control_off_command() {
458 let buf = [
459 0b01100011, 0b00000001, ];
462 let expected = MuxCommand {
463 params: MuxCommandParams::FlowControlOff(FlowControlParams {}),
464 command_response: CommandResponse::Command,
465 };
466 assert_eq!(MuxCommand::decode(&buf[..]).unwrap(), expected);
467 }
468
469 #[test]
470 fn test_decode_modem_status_command() {
471 let buf = [
472 0b11100011, 0b00000111, 0b00001111, 0b00000000, 0b00000001, ];
478 let expected = MuxCommand {
479 params: MuxCommandParams::ModemStatus(ModemStatusParams {
480 dlci: DLCI::try_from(3).unwrap(),
481 signals: ModemStatusSignals(0),
482 break_value: None,
483 }),
484 command_response: CommandResponse::Command,
485 };
486 assert_eq!(MuxCommand::decode(&buf[..]).unwrap(), expected);
487 }
488
489 #[test]
490 fn test_decode_not_supported_command_response() {
491 let buf = [
492 0b00010001, 0b00000011, 0b00000001, ];
496 let expected = MuxCommand {
497 params: MuxCommandParams::NonSupported(NonSupportedCommandParams {
498 cr_bit: false,
499 non_supported_command: 0,
500 }),
501 command_response: CommandResponse::Response,
502 };
503 assert_eq!(MuxCommand::decode(&buf[..]).unwrap(), expected);
504 }
505
506 #[test]
507 fn test_decode_rpn_command() {
508 let buf = [
509 0b10010011, 0b00000011, 0b00011111, ];
513 let expected = MuxCommand {
514 params: MuxCommandParams::RemotePortNegotiation(RemotePortNegotiationParams {
515 dlci: DLCI::try_from(7).unwrap(),
516 port_values: None,
517 }),
518 command_response: CommandResponse::Command,
519 };
520 assert_eq!(MuxCommand::decode(&buf[..]).unwrap(), expected);
521 }
522
523 #[test]
524 fn test_decode_rls_command() {
525 let buf = [
526 0b01010011, 0b00000101, 0b00011111, 0b00000000, ];
531 let expected = MuxCommand {
532 params: MuxCommandParams::RemoteLineStatus(RemoteLineStatusParams::new(
533 DLCI::try_from(7).unwrap(),
534 None,
535 )),
536 command_response: CommandResponse::Command,
537 };
538 assert_eq!(MuxCommand::decode(&buf[..]).unwrap(), expected);
539 }
540
541 #[test]
542 fn test_encode_invalid_buffer() {
543 let command = MuxCommand {
544 params: MuxCommandParams::RemotePortNegotiation(RemotePortNegotiationParams {
545 dlci: DLCI::try_from(5).unwrap(),
546 port_values: None,
547 }),
548 command_response: CommandResponse::Command,
549 };
550 let mut buf = vec![];
551 assert_matches!(command.encode(&mut buf[..]), Err(FrameParseError::BufferTooSmall));
552 }
553
554 #[test]
555 fn test_encode_rpn_response() {
556 let command = MuxCommand {
557 params: MuxCommandParams::RemotePortNegotiation(RemotePortNegotiationParams {
558 dlci: DLCI::try_from(5).unwrap(),
559 port_values: None,
560 }),
561 command_response: CommandResponse::Response,
562 };
563 let mut buf = vec![0; command.encoded_len()];
564 assert!(command.encode(&mut buf[..]).is_ok());
565 let expected = vec![
566 0b10010001, 0b00000011, 0b00010111, ];
570 assert_eq!(buf, expected);
571 }
572
573 #[test]
576 fn test_encode_long_test_command() {
577 let test_pattern = vec![
579 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
580 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
581 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
582 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
583 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
584 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03,
585 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01,
586 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
587 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
588 0x0e, 0x0f,
589 ];
590 let command = MuxCommand {
591 params: MuxCommandParams::Test(TestCommandParams {
592 test_pattern: test_pattern.clone(),
593 }),
594 command_response: CommandResponse::Command,
595 };
596 let mut buf = vec![0; command.encoded_len()];
597 assert!(command.encode(&mut buf[..]).is_ok());
598 let expected = vec![
599 0b00100011, 0b00000000, 0b00000011, ];
603 let expected = vec![expected, test_pattern].concat();
604 assert_eq!(buf, expected);
605 }
606
607 #[test]
608 fn test_zero_length_to_ea_format() {
609 let length = 0;
610 let expected = [0b00000001];
611 assert_eq!(length_to_ea_format(length), expected);
612 }
613
614 #[test]
615 fn test_small_length_to_ea_format() {
616 let small_length = 8;
617 let expected = [0b00010001];
618 assert_eq!(length_to_ea_format(small_length), expected);
619 }
620
621 #[test]
622 fn test_two_octet_length_to_ea_format() {
623 let two_octet_length = 245;
624 let expected = [0b11101010, 0b00000011];
625 assert_eq!(length_to_ea_format(two_octet_length), expected);
626 }
627
628 #[test]
629 fn test_multi_octet_length_to_ea_format() {
630 let multi_octet_length = 0b100000001100001001000;
631 let expected = [0b10010000, 0b01100000, 0b10000001];
632 assert_eq!(length_to_ea_format(multi_octet_length), expected);
633 }
634}