]>
code.octet-stream.net Git - m17rt/blob - m17core/src/kiss.rs
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
)
220 .ok_or(KissError
::MalformedKissFrame
)?
222 let end
= self.data
[start
..]
225 .skip_while(|(_
, b
)| **b
!= FEND
)
227 .ok_or(KissError
::MalformedKissFrame
)?
230 Ok(unescape(&self.data
[start
..end
], out
))
233 /// Borrow the frame as a slice
234 pub fn as_bytes(&self) -> &[u8] {
235 &self.data
[..self.len
]
238 /// Return the header byte of the KISS frame, skipping over 0 or more prepended FENDs.
239 fn header_byte(&self) -> Result
<u8, KissError
> {
243 .skip_while(|b
| **b
== FEND
)
246 .ok_or(KissError
::MalformedKissFrame
)?
)
250 fn kiss_header(port
: u8, command
: u8) -> u8 {
251 (port
<< 4) | (command
& 0x0f)
254 fn push(data
: &mut [u8], idx
: &mut usize, value
: u8) {
259 #[derive(Debug, PartialEq, Eq, Clone)]
260 pub enum KissCommand
{
268 fn from_proto(value
: u8) -> Result
<Self, KissError
> {
270 0 => KissCommand
::DataFrame
,
271 1 => KissCommand
::TxDelay
,
273 5 => KissCommand
::FullDuplex
,
274 _
=> return Err(KissError
::UnsupportedKissCommand
),
278 fn proto_value(&self) -> u8 {
280 KissCommand
::DataFrame
=> 0,
281 KissCommand
::TxDelay
=> 1,
283 KissCommand
::FullDuplex
=> 5,
288 /// Accepts raw KISS data and emits one frame at a time.
290 /// A frame will be emitted if there is at least one byte between FEND markers. It is up to the consumer
291 /// to determine whether it's actually a valid frame.
292 pub struct KissBuffer
{
293 /// Provisional frame, whose buffer might contain more than one sequential frame at a time
295 /// Number of bytes that have been written into `frame.data`, which may be more than the the length
296 /// of the first valid frame, `frame.len`.
298 /// Whether we have emitted the first frame in `frame`'s buffer and now need to flush it out.
299 first_frame_returned
: bool
,
303 /// Create new buffer
304 pub fn new() -> Self {
306 frame
: KissFrame
::new_empty(),
308 first_frame_returned
: false,
312 /// Return the space remaining for more data
313 pub fn buf_remaining(&mut self) -> &mut [u8] {
314 self.fl
ush
_first
_frame
();
315 if self.written
== self.frame
.data
.len() {
316 // full buffer with no data means oversized frame
317 // sender is doing something weird or a FEND got dropped
318 // either way: flush it all and try to sync up again
321 &mut self.frame
.data
[self.written
..]
324 /// Indicate how much data was written into the buffer provided by `buf_remaining()`.
325 pub fn did_write(&mut self, len
: usize) {
329 /// Try to construct and retrieve the next frame in the buffer
330 pub fn next_frame(&mut self) -> Option
<&KissFrame
> {
331 self.fl
ush
_first
_frame
();
333 // If we have any data without a leading FEND, scan past it
335 while i
< self.written
&& self.frame
.data
[i
] != FEND
{
338 self.move_to_start(i
);
340 // If we do have a leading FEND, scan up up to the last one in the series
342 while (i
+ 1) < self.written
&& self.frame
.data
[i
+ 1] == FEND
{
346 self.move_to_start(i
);
349 // Now, if we have FEND-something-FEND, return it
350 if self.written
>= 2 && self.frame
.data
[0] == FEND
&& self.frame
.data
[1] != FEND
{
352 while i
< self.written
&& self.frame
.data
[i
] != FEND
{
355 if i
< self.written
&& self.frame
.data
[i
] == FEND
{
356 self.frame
.len
= i
+ 1;
357 self.first
_frame
_ret
urned
= true;
358 return Some(&self.frame
);
365 /// Check if we just returned a frame; if so, clear it out and position the buffer for the next frame.
366 fn flush_first_frame(&mut self) {
367 if !self.first
_frame
_ret
urned
{
370 self.first
_frame
_ret
urned
= false;
371 // If we have previously returned a valid frame, in the simplest case `frame.data` contains FEND-something-FEND
372 // So to find the trailing FEND we can start at index 2
373 // Loop forward until we find that FEND, which must exist, and leave its index in `i`
375 while self.frame
.data
[i
] != FEND
{
378 // However if we have consecutive trailing FENDs we want to ignore them
379 // Having found the trailing FEND, increment past any additional FENDs until we reach the end or something else
380 while (i
+ 1) < self.written
&& self.frame
.data
[i
+ 1] == FEND
{
383 // Now take that final FEND and make it the start of our frame
384 self.move_to_start(i
);
387 /// Shift all data in the buffer back to the beginning starting from the given index.
388 fn move_to_start(&mut self, idx
: usize) {
389 for i
in idx
..self.written
{
390 self.frame
.data
[i
- idx
] = self.frame
.data
[i
];
396 #[derive(Debug, PartialEq, Eq, Clone)]
399 UnsupportedKissCommand
,
404 fn escape(src
: &[u8], dst
: &mut [u8]) -> usize {
407 while i
< src
.len() && j
< dst
.len() {
412 } else if src
[i
] == FESC
{
425 fn unescape(src
: &[u8], dst
: &mut [u8]) -> usize {
428 while i
< src
.len() && j
< dst
.len() {
430 if i
== src
.len() - 1 {
436 } else if src
[i
] == TFESC
{
454 let mut buf
= [0u8; 1024];
456 let src
= [0, 1, 2, 3, 4, 5];
457 let n
= escape(&src
, &mut buf
);
459 assert_eq
!(&buf
[0..6], src
);
461 let src
= [0, 1, TFESC
, 3, TFEND
, 5];
462 let n
= escape(&src
, &mut buf
);
464 assert_eq
!(&buf
[0..6], src
);
466 let src
= [0, 1, FEND
, 3, 4, 5];
467 let n
= escape(&src
, &mut buf
);
469 assert_eq
!(&buf
[0..7], &[0, 1, FESC
, TFEND
, 3, 4, 5]);
471 let src
= [0, 1, 2, 3, 4, FESC
];
472 let n
= escape(&src
, &mut buf
);
474 assert_eq
!(&buf
[0..7], &[0, 1, 2, 3, 4, FESC
, TFESC
]);
479 let mut buf
= [0u8; 1024];
481 let src
= [0, 1, 2, 3, 4, 5];
482 let n
= unescape(&src
, &mut buf
);
484 assert_eq
!(&buf
[0..6], src
);
486 let src
= [0, 1, TFESC
, 3, TFEND
, 5];
487 let n
= unescape(&src
, &mut buf
);
489 assert_eq
!(&buf
[0..6], src
);
491 let src
= [0, 1, FESC
, TFEND
, 3, 4, 5];
492 let n
= unescape(&src
, &mut buf
);
494 assert_eq
!(&buf
[0..6], &[0, 1, FEND
, 3, 4, 5]);
496 let src
= [0, 1, 2, 3, 4, FESC
, TFESC
];
497 let n
= unescape(&src
, &mut buf
);
499 assert_eq
!(&buf
[0..6], &[0, 1, 2, 3, 4, FESC
]);
503 fn basic_packet_roundtrip() {
504 let f
= KissFrame
::new_basic_packet(&[0, 1, 2, 3]).unwrap
();
505 assert_eq
!(f
.as_bytes(), &[FEND
, 0, 0, 1, 2, 3, FEND
]);
506 let mut buf
= [0u8; 1024];
507 let n
= f
.decode_payload(&mut buf
).unwrap
();
508 assert_eq
!(&buf
[..n
], &[0, 1, 2, 3]);
512 fn test_buffer_basic() {
513 let mut buffer
= KissBuffer
::new();
515 // initial write is not a complete frame
516 let buf
= buffer
.buf_remaining();
519 assert
!(buffer
.next_frame().is
_none
());
521 // complete the frame
522 let buf
= buffer
.buf_remaining();
528 // everything should parse
529 let next
= buffer
.next_frame().unwrap
();
530 assert_eq
!(next
.len
, 4);
531 assert_eq
!(&next
.data
[0..4], &[FEND
, 0x10, 0x01, FEND
]);
532 assert_eq
!(next
.port().unwrap
(), 1);
533 assert_eq
!(next
.command().unwrap
(), KissCommand
::DataFrame
);
534 let mut payload_buf
= [0u8; 1024];
535 let n
= next
.decode_payload(&mut payload_buf
).unwrap
();
537 assert_eq
!(&payload_buf
[0..n
], &[0x01]);
541 fn test_buffer_double() {
542 let mut buffer
= KissBuffer
::new();
543 let buf
= buffer
.buf_remaining();
544 buf
[0..8].copy_from_slice(&[FEND
, 0x10, 0x01, FEND
, FEND
, 0x20, 02, FEND
]);
547 let next
= buffer
.next_frame().unwrap
();
548 assert_eq
!(next
.port().unwrap
(), 1);
549 let next
= buffer
.next_frame().unwrap
();
550 assert_eq
!(next
.port().unwrap
(), 2);
551 assert
!(buffer
.next_frame().is
_none
());
555 fn test_buffer_double_shared_fend() {
556 let mut buffer
= KissBuffer
::new();
557 let buf
= buffer
.buf_remaining();
558 buf
[0..7].copy_from_slice(&[FEND
, 0x10, 0x01, FEND
, 0x20, 02, FEND
]);
561 let next
= buffer
.next_frame().unwrap
();
562 assert_eq
!(next
.port().unwrap
(), 1);
563 let next
= buffer
.next_frame().unwrap
();
564 assert_eq
!(next
.port().unwrap
(), 2);
565 assert
!(buffer
.next_frame().is
_none
());
569 fn test_buffer_extra_fend() {
570 let mut buffer
= KissBuffer
::new();
571 let buf
= buffer
.buf_remaining();
572 buf
[0..10].copy_from_slice(&[FEND
, FEND
, FEND
, 0x10, 0x01, FEND
, FEND
, 0x20, 02, FEND
]);
573 buffer
.did_write(10);
575 let next
= buffer
.next_frame().unwrap
();
576 assert_eq
!(next
.port().unwrap
(), 1);
577 let next
= buffer
.next_frame().unwrap
();
578 assert_eq
!(next
.port().unwrap
(), 2);
579 assert
!(buffer
.next_frame().is
_none
());
583 fn test_buffer_oversize_frame() {
584 let mut buffer
= KissBuffer
::new();
585 let buf
= buffer
.buf_remaining();
588 assert_eq
!(len
, MAX_FRAME_LEN
);
589 buffer
.did_write(len
);
590 assert
!(buffer
.next_frame().is
_none
());
592 let buf
= buffer
.buf_remaining();
594 assert_eq
!(len
, MAX_FRAME_LEN
); // should have flushed
595 for i
in 0..len
/ 2 {
598 buffer
.did_write(len
/ 2);
599 assert
!(buffer
.next_frame().is
_none
());
601 // confirm we resync if input goes back to normal
602 let buf
= buffer
.buf_remaining();
603 buf
[0..4].copy_from_slice(&[FEND
, 0x10, 0x01, FEND
]);
605 let next
= buffer
.next_frame().unwrap
();
606 assert_eq
!(next
.port().unwrap
(), 1);
607 assert
!(buffer
.next_frame().is
_none
());