]>
code.octet-stream.net Git - m17rt/blob - m17core/src/kiss.rs
4ada6dca77184ecad4508671a2de95b0b02c4deb
1 use crate::protocol
::StreamFrame
;
3 // Note FEND and FESC both have the top two bits set. In the header byte this corresponds
4 // to high port numbers which are never used by M17 so we needn't bother (un)escaping it.
8 const TFEND
: u8 = 0xDC;
9 const TFESC
: u8 = 0xDD;
11 pub const PORT_PACKET_BASIC
: u8 = 0;
12 pub const PORT_PACKET_FULL
: u8 = 1;
13 pub const PORT_STREAM
: u8 = 2;
15 /// Maximum theoretical frame size for any valid M17 KISS frame.
17 /// In M17 Full Packet Mode a 30-byte LSF is merged with a packet which may be up to
18 /// 825 bytes in length. Supposing an (impossible) worst case that every byte is FEND
19 /// or FESC, 1710 bytes is the maximum expected payload. With a FEND at each end and
20 /// the KISS frame header byte we get 1713.
21 pub const MAX_FRAME_LEN
: usize = 1713;
23 /// Holder for any valid M17 KISS frame.
25 /// For efficiency, `data` and `len` are exposed directly and received KISS data may
26 /// be streamed directly into a pre-allocated `KissFrame`.
27 #[derive(Debug, PartialEq, Eq, Clone)]
28 pub struct KissFrame
{
29 pub data
: [u8; MAX_FRAME_LEN
],
34 /// Construct empty frame
35 pub fn new_empty() -> Self {
37 data
: [0u8; MAX_FRAME_LEN
],
42 /// Request to transmit a data packet (basic mode).
44 /// A raw payload up to 822 bytes can be provided. The TNC will mark it as Raw format
45 /// and automatically calculate the checksum. If required it will also chunk the packet
46 /// into individual frames and transmit them sequentially.
47 pub fn new_basic_packet(payload
: &[u8]) -> Result
<Self, KissError
> {
48 // M17 packet payloads can be up to 825 bytes in length
49 // Type prefix (RAW = 0x00) occupies the first byte
50 // Last 2 bytes are checksum
51 if payload
.len() > 822 {
52 return Err(KissError
::PayloadTooBig
);
54 let mut data
= [0u8; MAX_FRAME_LEN
];
56 push(&mut data
, &mut i
, FEND
);
60 kiss_header(PORT_PACKET_BASIC
, KissCommand
::DataFrame
.proto_value()),
63 i
+= escape(payload
, &mut data
[i
..]);
64 push(&mut data
, &mut i
, FEND
);
66 Ok(KissFrame
{ data
, len
: i
})
69 /// Request to transmit a data packet (full mode).
71 /// Sender must provide a 30-byte LSF and a full packet payload (up to 825 bytes)
72 /// that will be combined into the frame. The packet payload must include the type
73 /// code prefix and the CRC, both of which would have been calculated by the TNC if
74 /// it was basic mode.
75 pub fn new_full_packet(lsf
: &[u8], packet
: &[u8]) -> Result
<Self, KissError
> {
77 return Err(KissError
::LsfWrongSize
);
79 if packet
.len() > 825 {
80 return Err(KissError
::PayloadTooBig
);
82 let mut data
= [0u8; MAX_FRAME_LEN
];
84 push(&mut data
, &mut i
, FEND
);
88 kiss_header(PORT_PACKET_FULL
, KissCommand
::DataFrame
.proto_value()),
90 i
+= escape(lsf
, &mut data
[i
..]);
91 i
+= escape(packet
, &mut data
[i
..]);
92 push(&mut data
, &mut i
, FEND
);
94 Ok(KissFrame
{ data
, len
: i
})
97 /// Request to begin a stream data transfer (e.g. voice).
99 /// An LSF payload of exactly 30 bytes must be provided.
101 /// This must be followed by at least one stream data payload, ending with one that
102 /// has the end of stream (EOS) bit set.
103 pub fn new_stream_setup(lsf
: &[u8]) -> Result
<Self, KissError
> {
105 return Err(KissError
::LsfWrongSize
);
107 let mut data
= [0u8; MAX_FRAME_LEN
];
109 push(&mut data
, &mut i
, FEND
);
113 kiss_header(PORT_STREAM
, KissCommand
::DataFrame
.proto_value()),
115 i
+= escape(lsf
, &mut data
[i
..]);
116 push(&mut data
, &mut i
, FEND
);
118 Ok(KissFrame
{ data
, len
: i
})
121 /// Transmit a segment of data in a stream transfer (e.g. voice).
122 pub fn new_stream_data(frame
: &StreamFrame
) -> Result
<Self, KissError
> {
123 let mut data
= [0u8; MAX_FRAME_LEN
];
125 push(&mut data
, &mut i
, FEND
);
129 kiss_header(PORT_STREAM
, KissCommand
::DataFrame
.proto_value()),
132 // 5 bytes LICH content
133 i
+= escape(&frame
.lich_part
, &mut data
[i
..]);
134 // 1 byte LICH metadata
135 i
+= escape(&[frame
.lich_idx
<< 5], &mut data
[i
..]);
137 // 2 bytes frame number/EOS + 16 bytes payload + 2 bytes CRC
138 let mut inner_data
= [0u8; 20];
139 let frame_num
= frame
.frame
_n
umber
.to_be_bytes();
140 inner_data
[0] = frame_num
[0] | if frame
.end_of_stream
{ 0x80 } else { 0 };
141 inner_data
[1] = frame_num
[1];
142 inner_data
[2..18].copy_from_slice(&frame
.stream_data
);
143 let crc
= crate::crc
::m17_crc(&inner_data
[0..18]);
144 let crc_be
= crc
.to_be_bytes();
145 inner_data
[18] = crc_be
[0];
146 inner_data
[19] = crc_be
[1];
147 i
+= escape(&inner_data
, &mut data
[i
..]);
149 push(&mut data
, &mut i
, FEND
);
150 Ok(KissFrame
{ data
, len
: i
})
153 /// Request to set the TxDelay
154 pub fn new_set_tx_delay(port
: u8, units
: u8) -> Self {
155 let mut data
= [0u8; MAX_FRAME_LEN
];
157 push(&mut data
, &mut i
, FEND
);
161 kiss_header(port
, KissCommand
::TxDelay
.proto_value()),
163 push(&mut data
, &mut i
, units
);
164 push(&mut data
, &mut i
, FEND
);
166 KissFrame
{ data
, len
: i
}
169 /// Request to set the persistence parameter P
170 pub fn new_set_p(port
: u8, units
: u8) -> Self {
171 let mut data
= [0u8; MAX_FRAME_LEN
];
173 push(&mut data
, &mut i
, FEND
);
177 kiss_header(port
, KissCommand
::P
.proto_value()),
179 push(&mut data
, &mut i
, units
);
180 push(&mut data
, &mut i
, FEND
);
182 KissFrame
{ data
, len
: i
}
185 /// Request to set full duplex or not
186 pub fn set_full_duplex(port
: u8, full_duplex
: bool
) -> Self {
187 let mut data
= [0u8; MAX_FRAME_LEN
];
189 push(&mut data
, &mut i
, FEND
);
193 kiss_header(port
, KissCommand
::FullDuplex
.proto_value()),
195 push(&mut data
, &mut i
, if full_duplex
{ 1 } else { 0 });
196 push(&mut data
, &mut i
, FEND
);
198 KissFrame
{ data
, len
: i
}
201 /// Return this frame's KISS command type.
202 pub fn command(&self) -> Result
<KissCommand
, KissError
> {
203 KissCommand
::from_proto(self.header_byte()?
& 0x0f)
206 /// Return the KISS port to which this frame relates. Should be 0, 1 or 2.
207 pub fn port(&self) -> Result
<u8, KissError
> {
208 Ok(self.header_byte()?
>> 4)
211 /// Payload part of the frame between the header byte and the trailing FEND, unescaped.
212 pub fn decode_payload(&self, out
: &mut [u8]) -> Result
<usize, KissError
> {
217 .skip_while(|(_
, b
)| **b
== FEND
)
219 .ok_or(KissError
::MalformedKissFrame
)?
221 let end
= self.data
[start
..]
224 .find
(|(_
, b
)| **b
== FEND
)
225 .ok_or(KissError
::MalformedKissFrame
)?
228 Ok(unescape(&self.data
[start
..end
], out
))
231 /// Borrow the frame as a slice
232 pub fn as_bytes(&self) -> &[u8] {
233 &self.data
[..self.len
]
236 /// Return the header byte of the KISS frame, skipping over 0 or more prepended FENDs.
237 fn header_byte(&self) -> Result
<u8, KissError
> {
240 .find
(|b
| **b
!= FEND
)
242 .ok_or(KissError
::MalformedKissFrame
)
246 fn kiss_header(port
: u8, command
: u8) -> u8 {
247 (port
<< 4) | (command
& 0x0f)
250 fn push(data
: &mut [u8], idx
: &mut usize, value
: u8) {
255 #[derive(Debug, PartialEq, Eq, Clone)]
256 pub enum KissCommand
{
264 fn from_proto(value
: u8) -> Result
<Self, KissError
> {
266 0 => KissCommand
::DataFrame
,
267 1 => KissCommand
::TxDelay
,
269 5 => KissCommand
::FullDuplex
,
270 _
=> return Err(KissError
::UnsupportedKissCommand
),
274 fn proto_value(&self) -> u8 {
276 KissCommand
::DataFrame
=> 0,
277 KissCommand
::TxDelay
=> 1,
279 KissCommand
::FullDuplex
=> 5,
284 /// Accepts raw KISS data and emits one frame at a time.
286 /// A frame will be emitted if there is at least one byte between FEND markers. It is up to the consumer
287 /// to determine whether it's actually a valid frame.
288 pub struct KissBuffer
{
289 /// Provisional frame, whose buffer might contain more than one sequential frame at a time
291 /// Number of bytes that have been written into `frame.data`, which may be more than the the length
292 /// of the first valid frame, `frame.len`.
294 /// Whether we have emitted the first frame in `frame`'s buffer and now need to flush it out.
295 first_frame_returned
: bool
,
299 /// Create new buffer
300 pub fn new() -> Self {
302 frame
: KissFrame
::new_empty(),
304 first_frame_returned
: false,
308 /// Return the space remaining for more data
309 pub fn buf_remaining(&mut self) -> &mut [u8] {
310 self.fl
ush
_first
_frame
();
311 if self.written
== self.frame
.data
.len() {
312 // full buffer with no data means oversized frame
313 // sender is doing something weird or a FEND got dropped
314 // either way: flush it all and try to sync up again
317 &mut self.frame
.data
[self.written
..]
320 /// Indicate how much data was written into the buffer provided by `buf_remaining()`.
321 pub fn did_write(&mut self, len
: usize) {
325 /// Try to construct and retrieve the next frame in the buffer
326 pub fn next_frame(&mut self) -> Option
<&KissFrame
> {
327 self.fl
ush
_first
_frame
();
329 // If we have any data without a leading FEND, scan past it
331 while i
< self.written
&& self.frame
.data
[i
] != FEND
{
334 self.move_to_start(i
);
336 // If we do have a leading FEND, scan up up to the last one in the series
338 while (i
+ 1) < self.written
&& self.frame
.data
[i
+ 1] == FEND
{
342 self.move_to_start(i
);
345 // Now, if we have FEND-something-FEND, return it
346 if self.written
>= 2 && self.frame
.data
[0] == FEND
&& self.frame
.data
[1] != FEND
{
348 while i
< self.written
&& self.frame
.data
[i
] != FEND
{
351 if i
< self.written
&& self.frame
.data
[i
] == FEND
{
352 self.frame
.len
= i
+ 1;
353 self.first
_frame
_ret
urned
= true;
354 return Some(&self.frame
);
361 /// Check if we just returned a frame; if so, clear it out and position the buffer for the next frame.
362 fn flush_first_frame(&mut self) {
363 if !self.first
_frame
_ret
urned
{
366 self.first
_frame
_ret
urned
= false;
367 // If we have previously returned a valid frame, in the simplest case `frame.data` contains FEND-something-FEND
368 // So to find the trailing FEND we can start at index 2
369 // Loop forward until we find that FEND, which must exist, and leave its index in `i`
371 while self.frame
.data
[i
] != FEND
{
374 // However if we have consecutive trailing FENDs we want to ignore them
375 // Having found the trailing FEND, increment past any additional FENDs until we reach the end or something else
376 while (i
+ 1) < self.written
&& self.frame
.data
[i
+ 1] == FEND
{
379 // Now take that final FEND and make it the start of our frame
380 self.move_to_start(i
);
383 /// Shift all data in the buffer back to the beginning starting from the given index.
384 fn move_to_start(&mut self, idx
: usize) {
385 for i
in idx
..self.written
{
386 self.frame
.data
[i
- idx
] = self.frame
.data
[i
];
392 impl Default
for KissBuffer
{
393 fn default() -> Self {
398 #[derive(Debug, PartialEq, Eq, Clone)]
401 UnsupportedKissCommand
,
406 fn escape(src
: &[u8], dst
: &mut [u8]) -> usize {
409 while i
< src
.len() && j
< dst
.len() {
414 } else if src
[i
] == FESC
{
427 fn unescape(src
: &[u8], dst
: &mut [u8]) -> usize {
430 while i
< src
.len() && j
< dst
.len() {
432 if i
== src
.len() - 1 {
438 } else if src
[i
] == TFESC
{
456 let mut buf
= [0u8; 1024];
458 let src
= [0, 1, 2, 3, 4, 5];
459 let n
= escape(&src
, &mut buf
);
461 assert_eq
!(&buf
[0..6], src
);
463 let src
= [0, 1, TFESC
, 3, TFEND
, 5];
464 let n
= escape(&src
, &mut buf
);
466 assert_eq
!(&buf
[0..6], src
);
468 let src
= [0, 1, FEND
, 3, 4, 5];
469 let n
= escape(&src
, &mut buf
);
471 assert_eq
!(&buf
[0..7], &[0, 1, FESC
, TFEND
, 3, 4, 5]);
473 let src
= [0, 1, 2, 3, 4, FESC
];
474 let n
= escape(&src
, &mut buf
);
476 assert_eq
!(&buf
[0..7], &[0, 1, 2, 3, 4, FESC
, TFESC
]);
481 let mut buf
= [0u8; 1024];
483 let src
= [0, 1, 2, 3, 4, 5];
484 let n
= unescape(&src
, &mut buf
);
486 assert_eq
!(&buf
[0..6], src
);
488 let src
= [0, 1, TFESC
, 3, TFEND
, 5];
489 let n
= unescape(&src
, &mut buf
);
491 assert_eq
!(&buf
[0..6], src
);
493 let src
= [0, 1, FESC
, TFEND
, 3, 4, 5];
494 let n
= unescape(&src
, &mut buf
);
496 assert_eq
!(&buf
[0..6], &[0, 1, FEND
, 3, 4, 5]);
498 let src
= [0, 1, 2, 3, 4, FESC
, TFESC
];
499 let n
= unescape(&src
, &mut buf
);
501 assert_eq
!(&buf
[0..6], &[0, 1, 2, 3, 4, FESC
]);
505 fn basic_packet_roundtrip() {
506 let f
= KissFrame
::new_basic_packet(&[0, 1, 2, 3]).unwrap
();
507 assert_eq
!(f
.as_bytes(), &[FEND
, 0, 0, 1, 2, 3, FEND
]);
508 let mut buf
= [0u8; 1024];
509 let n
= f
.decode_payload(&mut buf
).unwrap
();
510 assert_eq
!(&buf
[..n
], &[0, 1, 2, 3]);
514 fn test_buffer_basic() {
515 let mut buffer
= KissBuffer
::new();
517 // initial write is not a complete frame
518 let buf
= buffer
.buf_remaining();
521 assert
!(buffer
.next_frame().is
_none
());
523 // complete the frame
524 let buf
= buffer
.buf_remaining();
530 // everything should parse
531 let next
= buffer
.next_frame().unwrap
();
532 assert_eq
!(next
.len
, 4);
533 assert_eq
!(&next
.data
[0..4], &[FEND
, 0x10, 0x01, FEND
]);
534 assert_eq
!(next
.port().unwrap
(), 1);
535 assert_eq
!(next
.command().unwrap
(), KissCommand
::DataFrame
);
536 let mut payload_buf
= [0u8; 1024];
537 let n
= next
.decode_payload(&mut payload_buf
).unwrap
();
539 assert_eq
!(&payload_buf
[0..n
], &[0x01]);
543 fn test_buffer_double() {
544 let mut buffer
= KissBuffer
::new();
545 let buf
= buffer
.buf_remaining();
546 buf
[0..8].copy_from_slice(&[FEND
, 0x10, 0x01, FEND
, FEND
, 0x20, 02, FEND
]);
549 let next
= buffer
.next_frame().unwrap
();
550 assert_eq
!(next
.port().unwrap
(), 1);
551 let next
= buffer
.next_frame().unwrap
();
552 assert_eq
!(next
.port().unwrap
(), 2);
553 assert
!(buffer
.next_frame().is
_none
());
557 fn test_buffer_double_shared_fend() {
558 let mut buffer
= KissBuffer
::new();
559 let buf
= buffer
.buf_remaining();
560 buf
[0..7].copy_from_slice(&[FEND
, 0x10, 0x01, FEND
, 0x20, 02, FEND
]);
563 let next
= buffer
.next_frame().unwrap
();
564 assert_eq
!(next
.port().unwrap
(), 1);
565 let next
= buffer
.next_frame().unwrap
();
566 assert_eq
!(next
.port().unwrap
(), 2);
567 assert
!(buffer
.next_frame().is
_none
());
571 fn test_buffer_extra_fend() {
572 let mut buffer
= KissBuffer
::new();
573 let buf
= buffer
.buf_remaining();
574 buf
[0..10].copy_from_slice(&[FEND
, FEND
, FEND
, 0x10, 0x01, FEND
, FEND
, 0x20, 02, FEND
]);
575 buffer
.did_write(10);
577 let next
= buffer
.next_frame().unwrap
();
578 assert_eq
!(next
.port().unwrap
(), 1);
579 let next
= buffer
.next_frame().unwrap
();
580 assert_eq
!(next
.port().unwrap
(), 2);
581 assert
!(buffer
.next_frame().is
_none
());
585 fn test_buffer_oversize_frame() {
586 let mut buffer
= KissBuffer
::new();
587 let buf
= buffer
.buf_remaining();
590 assert_eq
!(len
, MAX_FRAME_LEN
);
591 buffer
.did_write(len
);
592 assert
!(buffer
.next_frame().is
_none
());
594 let buf
= buffer
.buf_remaining();
596 assert_eq
!(len
, MAX_FRAME_LEN
); // should have flushed
597 for i
in 0..len
/ 2 {
600 buffer
.did_write(len
/ 2);
601 assert
!(buffer
.next_frame().is
_none
());
603 // confirm we resync if input goes back to normal
604 let buf
= buffer
.buf_remaining();
605 buf
[0..4].copy_from_slice(&[FEND
, 0x10, 0x01, FEND
]);
607 let next
= buffer
.next_frame().unwrap
();
608 assert_eq
!(next
.port().unwrap
(), 1);
609 assert
!(buffer
.next_frame().is
_none
());