1use bitfield::bitfield;
6use packet_encoding::{Decodable, Encodable, decodable_enum};
7
8mod dlc_parameter_negotiation;
10pub use dlc_parameter_negotiation::{
11 CreditBasedFlowHandshake, DEFAULT_INITIAL_CREDITS, ParameterNegotiationParams,
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::DLCI;
39use crate::frame::{CommandResponse, FrameParseError};
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() { CommandResponse::Command } else { CommandResponse::Response }
81 }
82}
83
84const MUX_COMMAND_LENGTH_IDX: usize = 1;
87
88const MUX_COMMAND_LENGTH_SHIFT: usize = 7;
91
92bitfield! {
93 pub struct LengthField(u8);
94 impl Debug;
95 pub bool, ea_bit, set_ea_bit: 0;
96 pub u8, length, set_length: 7, 1;
97}
98
99#[derive(Clone, Debug, PartialEq)]
101pub enum MuxCommandParams {
102 ParameterNegotiation(ParameterNegotiationParams),
103 FlowControlOn(FlowControlParams),
104 FlowControlOff(FlowControlParams),
105 ModemStatus(ModemStatusParams),
106 NonSupported(NonSupportedCommandParams),
107 RemoteLineStatus(RemoteLineStatusParams),
108 RemotePortNegotiation(RemotePortNegotiationParams),
109 Test(TestCommandParams),
110}
111
112impl MuxCommandParams {
113 pub fn marker(&self) -> MuxCommandMarker {
114 match self {
115 Self::ParameterNegotiation(_) => MuxCommandMarker::ParameterNegotiation,
116 Self::FlowControlOn(_) => MuxCommandMarker::FlowControlOn,
117 Self::FlowControlOff(_) => MuxCommandMarker::FlowControlOff,
118 Self::ModemStatus(_) => MuxCommandMarker::ModemStatus,
119 Self::NonSupported(_) => MuxCommandMarker::NonSupportedCommand,
120 Self::RemoteLineStatus(_) => MuxCommandMarker::RemoteLineStatus,
121 Self::RemotePortNegotiation(_) => MuxCommandMarker::RemotePortNegotiation,
122 Self::Test(_) => MuxCommandMarker::Test,
123 }
124 }
125
126 fn decode(command_type: &MuxCommandMarker, buf: &[u8]) -> Result<Self, FrameParseError> {
127 let params = match command_type {
128 MuxCommandMarker::ParameterNegotiation => {
129 Self::ParameterNegotiation(ParameterNegotiationParams::decode(buf)?)
130 }
131 MuxCommandMarker::FlowControlOn => Self::FlowControlOn(FlowControlParams::decode(buf)?),
132 MuxCommandMarker::FlowControlOff => {
133 Self::FlowControlOff(FlowControlParams::decode(buf)?)
134 }
135 MuxCommandMarker::ModemStatus => Self::ModemStatus(ModemStatusParams::decode(buf)?),
136 MuxCommandMarker::NonSupportedCommand => {
137 Self::NonSupported(NonSupportedCommandParams::decode(buf)?)
138 }
139 MuxCommandMarker::RemoteLineStatus => {
140 Self::RemoteLineStatus(RemoteLineStatusParams::decode(buf)?)
141 }
142 MuxCommandMarker::RemotePortNegotiation => {
143 Self::RemotePortNegotiation(RemotePortNegotiationParams::decode(buf)?)
144 }
145 MuxCommandMarker::Test => Self::Test(TestCommandParams::decode(buf)?),
146 };
147 Ok(params)
148 }
149}
150
151impl Encodable for MuxCommandParams {
152 type Error = FrameParseError;
153
154 fn encoded_len(&self) -> usize {
155 match self {
156 Self::ParameterNegotiation(cmd) => cmd.encoded_len(),
157 Self::FlowControlOn(cmd) => cmd.encoded_len(),
158 Self::FlowControlOff(cmd) => cmd.encoded_len(),
159 Self::ModemStatus(cmd) => cmd.encoded_len(),
160 Self::NonSupported(cmd) => cmd.encoded_len(),
161 Self::RemoteLineStatus(cmd) => cmd.encoded_len(),
162 Self::RemotePortNegotiation(cmd) => cmd.encoded_len(),
163 Self::Test(cmd) => cmd.encoded_len(),
164 }
165 }
166
167 fn encode(&self, buf: &mut [u8]) -> Result<(), FrameParseError> {
168 match self {
169 Self::ParameterNegotiation(cmd) => cmd.encode(buf),
170 Self::FlowControlOn(cmd) => cmd.encode(buf),
171 Self::FlowControlOff(cmd) => cmd.encode(buf),
172 Self::ModemStatus(cmd) => cmd.encode(buf),
173 Self::NonSupported(cmd) => cmd.encode(buf),
174 Self::RemoteLineStatus(cmd) => cmd.encode(buf),
175 Self::RemotePortNegotiation(cmd) => cmd.encode(buf),
176 Self::Test(cmd) => cmd.encode(buf),
177 }
178 }
179}
180
181fn length_to_ea_format(mut length: usize) -> Vec<u8> {
184 if length == 0 {
185 let mut length_field = LengthField(0);
187 length_field.set_ea_bit(true);
188 return vec![length_field.0];
189 }
190
191 let mut octets = vec![];
192 let mask = 0b01111111;
193 while length != 0 {
195 let mut length_field = LengthField(0);
196 let length_octet = (length & mask) as u8;
197 length_field.set_length(length_octet);
198 length_field.set_ea_bit(false);
199 octets.push(length_field);
200 length >>= MUX_COMMAND_LENGTH_SHIFT;
201 }
202 let last_idx = octets.len() - 1;
204 octets[last_idx].set_ea_bit(true);
205
206 octets.iter().map(|l| l.0).collect()
207}
208
209#[derive(Debug, Eq, Hash, PartialEq)]
213pub struct MuxCommandIdentifier(pub Option<DLCI>, pub MuxCommandMarker);
214
215#[derive(Clone, Debug, PartialEq)]
217pub struct MuxCommand {
218 pub params: MuxCommandParams,
220
221 pub command_response: CommandResponse,
223}
224
225impl MuxCommand {
226 pub fn dlci(&self) -> Option<DLCI> {
233 match &self.params {
234 MuxCommandParams::ParameterNegotiation(pn) => Some(pn.dlci),
235 MuxCommandParams::ModemStatus(status) => Some(status.dlci),
236 MuxCommandParams::RemoteLineStatus(rls) => Some(rls.dlci),
237 MuxCommandParams::RemotePortNegotiation(rpn) => Some(rpn.dlci),
238 _ => None,
239 }
240 }
241
242 pub fn identifier(&self) -> MuxCommandIdentifier {
245 MuxCommandIdentifier(self.dlci(), self.params.marker())
246 }
247}
248
249impl Decodable for MuxCommand {
250 type Error = FrameParseError;
251
252 fn decode(buf: &[u8]) -> Result<Self, FrameParseError> {
253 if buf.len() < MIN_MUX_COMMAND_SIZE {
254 return Err(FrameParseError::BufferTooSmall);
255 }
256
257 let type_field = TypeField(buf[MUX_COMMAND_TYPE_IDX]);
259 let command_response = type_field.command_response();
260 let command_type = type_field.command_type()?;
261
262 const MAX_LENGTH_OCTETS: usize = 8;
266 let mut length: u64 = 0;
267 let mut num_length_octets: usize = 0;
268
269 for i in MUX_COMMAND_LENGTH_IDX..buf.len() {
270 let length_field = LengthField(buf[i]);
271 let length_octet: u64 = length_field.length().into();
272 length |= length_octet << (MUX_COMMAND_LENGTH_SHIFT * num_length_octets);
273 num_length_octets += 1;
274
275 if length_field.ea_bit() {
277 break;
278 }
279
280 if num_length_octets > MAX_LENGTH_OCTETS {
281 return Err(FrameParseError::InvalidFrame);
282 }
283 }
284
285 let header_len = 1 + num_length_octets;
289 let calculated_buf_size: u64 = header_len as u64 + length;
290 if (buf.len() as u64) < calculated_buf_size {
291 return Err(FrameParseError::BufferTooSmall);
292 }
293
294 let params_payload = &buf[header_len..calculated_buf_size as usize];
295 let params = MuxCommandParams::decode(&command_type, params_payload)?;
296
297 Ok(Self { params, command_response })
298 }
299}
300
301impl Encodable for MuxCommand {
302 type Error = FrameParseError;
303
304 fn encoded_len(&self) -> usize {
307 let length = self.params.encoded_len();
308 1 + length_to_ea_format(length).len() + length
309 }
310
311 fn encode(&self, buf: &mut [u8]) -> Result<(), FrameParseError> {
312 if buf.len() < self.encoded_len() {
313 return Err(FrameParseError::BufferTooSmall);
314 }
315
316 let cr_bit = if self.command_response == CommandResponse::Command { true } else { false };
318
319 let mut type_field = TypeField(0);
321 type_field.set_ea_bit(true);
322 type_field.set_cr_bit(cr_bit);
323 type_field.set_command_type(u8::from(&self.params.marker()));
324 buf[0] = type_field.0;
325
326 let length = self.params.encoded_len();
328 let length_octets = length_to_ea_format(length);
329 let length_end_idx = MUX_COMMAND_LENGTH_IDX + length_octets.len();
330 buf[MUX_COMMAND_LENGTH_IDX..length_end_idx].copy_from_slice(&length_octets);
331
332 self.params.encode(&mut buf[length_end_idx..])?;
334
335 Ok(())
336 }
337}
338
339#[cfg(test)]
340mod tests {
341 use super::*;
342
343 use assert_matches::assert_matches;
344 use modem_status::ModemStatusSignals;
345
346 #[test]
347 fn test_decode_mux_command_empty_buf() {
348 let empty_buf = [];
349 assert_matches!(MuxCommand::decode(&empty_buf[..]), Err(FrameParseError::BufferTooSmall));
350 }
351
352 #[test]
353 fn test_decode_mux_command_invalid_command_type() {
354 let buf = [
355 0b11111101, 0b00000001, ];
358 assert_matches!(
359 MuxCommand::decode(&buf[..]),
360 Err(FrameParseError::UnsupportedMuxCommandType(0b111111))
361 );
362 }
363
364 #[test]
365 fn test_decode_mux_command_too_large_length() {
366 let buf = [
367 0b10000001, 0b00000010, 0b00000010, 0b00000010, 0b00000010, 0b00000010, 0b00000010, 0b00000010, 0b00000010, 0b00000010, 0b00000000, ];
379 assert_matches!(MuxCommand::decode(&buf[..]), Err(FrameParseError::InvalidFrame));
380 }
381
382 #[test]
383 fn test_decode_mux_command_missing_length_octets() {
384 let buf = [
385 0b10000001, 0b00000101, 0b00000010, ];
390 assert_matches!(MuxCommand::decode(&buf[..]), Err(FrameParseError::BufferTooSmall));
391 }
392
393 #[test]
394 fn test_decode_dlc_parameter_negotiation_command() {
395 let buf = [
396 0b10000011, 0b00010001, 0b00000000, 0b11110000, 0b00001100, 0b00000000, 0b00010100, 0b00000000, 0b00000000, 0b00000001, ];
407 let expected = MuxCommand {
408 params: MuxCommandParams::ParameterNegotiation(ParameterNegotiationParams {
409 dlci: DLCI::try_from(0).unwrap(),
410 credit_based_flow_handshake: CreditBasedFlowHandshake::SupportedRequest,
411 priority: 12,
412 max_frame_size: 20,
413 initial_credits: 1,
414 }),
415 command_response: CommandResponse::Command,
416 };
417 assert_eq!(MuxCommand::decode(&buf[..]).unwrap(), expected);
418 }
419
420 #[test]
421 fn test_decode_test_command() {
422 let buf = [
423 0b00100011, 0b00001001, 0b00000000, 0b00000000, 0b00000000, 0b00000000, ];
430 let expected = MuxCommand {
431 params: MuxCommandParams::Test(TestCommandParams {
432 test_pattern: vec![0x00, 0x00, 0x00, 0x00],
433 }),
434 command_response: CommandResponse::Command,
435 };
436 assert_eq!(MuxCommand::decode(&buf[..]).unwrap(), expected);
437 }
438
439 #[test]
440 fn test_decode_flow_control_on_command() {
441 let buf = [
442 0b10100001, 0b00000001, ];
445 let expected = MuxCommand {
446 params: MuxCommandParams::FlowControlOn(FlowControlParams {}),
447 command_response: CommandResponse::Response,
448 };
449 assert_eq!(MuxCommand::decode(&buf[..]).unwrap(), expected);
450 }
451
452 #[test]
453 fn test_decode_flow_control_off_command() {
454 let buf = [
455 0b01100011, 0b00000001, ];
458 let expected = MuxCommand {
459 params: MuxCommandParams::FlowControlOff(FlowControlParams {}),
460 command_response: CommandResponse::Command,
461 };
462 assert_eq!(MuxCommand::decode(&buf[..]).unwrap(), expected);
463 }
464
465 #[test]
466 fn test_decode_modem_status_command() {
467 let buf = [
468 0b11100011, 0b00000111, 0b00001111, 0b00000000, 0b00000001, ];
474 let expected = MuxCommand {
475 params: MuxCommandParams::ModemStatus(ModemStatusParams {
476 dlci: DLCI::try_from(3).unwrap(),
477 signals: ModemStatusSignals(0),
478 break_value: None,
479 }),
480 command_response: CommandResponse::Command,
481 };
482 assert_eq!(MuxCommand::decode(&buf[..]).unwrap(), expected);
483 }
484
485 #[test]
486 fn test_decode_not_supported_command_response() {
487 let buf = [
488 0b00010001, 0b00000011, 0b00000001, ];
492 let expected = MuxCommand {
493 params: MuxCommandParams::NonSupported(NonSupportedCommandParams {
494 cr_bit: false,
495 non_supported_command: 0,
496 }),
497 command_response: CommandResponse::Response,
498 };
499 assert_eq!(MuxCommand::decode(&buf[..]).unwrap(), expected);
500 }
501
502 #[test]
503 fn test_decode_rpn_command() {
504 let buf = [
505 0b10010011, 0b00000011, 0b00011111, ];
509 let expected = MuxCommand {
510 params: MuxCommandParams::RemotePortNegotiation(RemotePortNegotiationParams {
511 dlci: DLCI::try_from(7).unwrap(),
512 port_values: None,
513 }),
514 command_response: CommandResponse::Command,
515 };
516 assert_eq!(MuxCommand::decode(&buf[..]).unwrap(), expected);
517 }
518
519 #[test]
520 fn test_decode_rls_command() {
521 let buf = [
522 0b01010011, 0b00000101, 0b00011111, 0b00000000, ];
527 let expected = MuxCommand {
528 params: MuxCommandParams::RemoteLineStatus(RemoteLineStatusParams::new(
529 DLCI::try_from(7).unwrap(),
530 None,
531 )),
532 command_response: CommandResponse::Command,
533 };
534 assert_eq!(MuxCommand::decode(&buf[..]).unwrap(), expected);
535 }
536
537 #[test]
538 fn test_encode_invalid_buffer() {
539 let command = MuxCommand {
540 params: MuxCommandParams::RemotePortNegotiation(RemotePortNegotiationParams {
541 dlci: DLCI::try_from(5).unwrap(),
542 port_values: None,
543 }),
544 command_response: CommandResponse::Command,
545 };
546 let mut buf = vec![];
547 assert_matches!(command.encode(&mut buf[..]), Err(FrameParseError::BufferTooSmall));
548 }
549
550 #[test]
551 fn test_encode_rpn_response() {
552 let command = MuxCommand {
553 params: MuxCommandParams::RemotePortNegotiation(RemotePortNegotiationParams {
554 dlci: DLCI::try_from(5).unwrap(),
555 port_values: None,
556 }),
557 command_response: CommandResponse::Response,
558 };
559 let mut buf = vec![0; command.encoded_len()];
560 assert!(command.encode(&mut buf[..]).is_ok());
561 let expected = vec![
562 0b10010001, 0b00000011, 0b00010111, ];
566 assert_eq!(buf, expected);
567 }
568
569 #[test]
572 fn test_encode_long_test_command() {
573 let test_pattern = vec![
575 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
576 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
577 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
578 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
579 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
580 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03,
581 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01,
582 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
583 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
584 0x0e, 0x0f,
585 ];
586 let command = MuxCommand {
587 params: MuxCommandParams::Test(TestCommandParams {
588 test_pattern: test_pattern.clone(),
589 }),
590 command_response: CommandResponse::Command,
591 };
592 let mut buf = vec![0; command.encoded_len()];
593 assert!(command.encode(&mut buf[..]).is_ok());
594 let expected = vec![
595 0b00100011, 0b00000000, 0b00000011, ];
599 let expected = vec![expected, test_pattern].concat();
600 assert_eq!(buf, expected);
601 }
602
603 #[test]
604 fn test_zero_length_to_ea_format() {
605 let length = 0;
606 let expected = [0b00000001];
607 assert_eq!(length_to_ea_format(length), expected);
608 }
609
610 #[test]
611 fn test_small_length_to_ea_format() {
612 let small_length = 8;
613 let expected = [0b00010001];
614 assert_eq!(length_to_ea_format(small_length), expected);
615 }
616
617 #[test]
618 fn test_two_octet_length_to_ea_format() {
619 let two_octet_length = 245;
620 let expected = [0b11101010, 0b00000011];
621 assert_eq!(length_to_ea_format(two_octet_length), expected);
622 }
623
624 #[test]
625 fn test_multi_octet_length_to_ea_format() {
626 let multi_octet_length = 0b100000001100001001000;
627 let expected = [0b10010000, 0b01100000, 0b10000001];
628 assert_eq!(length_to_ea_format(multi_octet_length), expected);
629 }
630}