]>
code.octet-stream.net Git - m17rt/blob - m17core/src/kiss.rs
b8c2f1fc76e261f66fa1d797031f51680445ebc4
1 // Note FEND and FESC both have the top two bits set. In the header byte this corresponds
2 // to high port numbers which are never used by M17 so we needn't bother (un)escaping it.
6 const TFEND
: u8 = 0xDC;
7 const TFESC
: u8 = 0xDD;
9 pub const PORT_PACKET_BASIC
: u8 = 0;
10 pub const PORT_PACKET_FULL
: u8 = 1;
11 pub const PORT_STREAM
: u8 = 2;
13 /// Maximum theoretical frame size for any valid M17 KISS frame.
15 /// In M17 Full Packet Mode a 30-byte LSF is merged with a packet which may be up to
16 /// 825 bytes in length. Supposing an (impossible) worst case that every byte is FEND
17 /// or FESC, 1710 bytes is the maximum expected payload. With a FEND at each end and
18 /// the KISS frame header byte we get 1713.
19 pub const MAX_FRAME_LEN
: usize = 1713;
21 /// Holder for any valid M17 KISS frame.
23 /// For efficiency, `data` and `len` are exposed directly and received KISS data may
24 /// be streamed directly into a pre-allocated `KissFrame`.
25 #[derive(Debug, PartialEq, Eq, Clone)]
26 pub struct KissFrame
{
27 pub data
: [u8; MAX_FRAME_LEN
],
32 /// Construct empty frame
33 pub fn new_empty() -> Self {
35 data
: [0u8; MAX_FRAME_LEN
],
40 /// Request to transmit a data packet (basic mode).
42 /// A raw payload up to 822 bytes can be provided. The TNC will mark it as Raw format
43 /// and automatically calculate the checksum. If required it will also chunk the packet
44 /// into individual frames and transmit them sequentially.
45 pub fn new_basic_packet(payload
: &[u8]) -> Result
<Self, KissError
> {
46 // M17 packet payloads can be up to 825 bytes in length
47 // Type prefix (RAW = 0x00) occupies the first byte
48 // Last 2 bytes are checksum
49 if payload
.len() > 822 {
50 return Err(KissError
::PayloadTooBig
);
52 let mut data
= [0u8; MAX_FRAME_LEN
];
54 push(&mut data
, &mut i
, FEND
);
58 kiss_header(PORT_PACKET_BASIC
, KissCommand
::DataFrame
.proto_value()),
61 i
+= escape(payload
, &mut data
[i
..]);
62 push(&mut data
, &mut i
, FEND
);
64 Ok(KissFrame
{ data
, len
: i
})
67 /// Request to transmit a data packet (full mode).
69 /// Sender must provide a 30-byte LSF and a full packet payload (up to 825 bytes)
70 /// that will be combined into the frame. The packet payload must include the type
71 /// code prefix and the CRC, both of which would have been calculated by the TNC if
72 /// it was basic mode.
73 pub fn new_full_packet(lsf
: &[u8], packet
: &[u8]) -> Result
<Self, KissError
> {
75 return Err(KissError
::LsfWrongSize
);
77 if packet
.len() > 825 {
78 return Err(KissError
::PayloadTooBig
);
80 let mut data
= [0u8; MAX_FRAME_LEN
];
82 push(&mut data
, &mut i
, FEND
);
86 kiss_header(PORT_PACKET_FULL
, KissCommand
::DataFrame
.proto_value()),
88 i
+= escape(lsf
, &mut data
[i
..]);
89 i
+= escape(packet
, &mut data
[i
..]);
90 push(&mut data
, &mut i
, FEND
);
92 Ok(KissFrame
{ data
, len
: i
})
95 /// Request to begin a stream data transfer (e.g. voice).
97 /// An LSF payload of exactly 30 bytes must be provided.
99 /// This must be followed by at least one stream data payload, ending with one that
100 /// has the end of stream (EOS) bit set.
101 pub fn new_stream_setup(lsf
: &[u8]) -> Result
<Self, KissError
> {
103 return Err(KissError
::LsfWrongSize
);
105 let mut data
= [0u8; MAX_FRAME_LEN
];
107 push(&mut data
, &mut i
, FEND
);
111 kiss_header(PORT_STREAM
, KissCommand
::DataFrame
.proto_value()),
113 i
+= escape(lsf
, &mut data
[i
..]);
114 push(&mut data
, &mut i
, FEND
);
116 Ok(KissFrame
{ data
, len
: i
})
119 /// Transmit a segment of data in a stream transfer (e.g. voice).
121 /// A data payload of 26 bytes including metadata must be provided. This must follow
122 /// exactly the prescribed format (H.5.2 in the spec). The TNC will be watching for
123 /// the EOS flag to know that this transmission has ended.
124 pub fn new_stream_data(stream_data
: &[u8]) -> Result
<Self, KissError
> {
125 if stream_data
.len() != 26 {
126 return Err(KissError
::StreamDataWrongSize
);
128 let mut data
= [0u8; MAX_FRAME_LEN
];
130 push(&mut data
, &mut i
, FEND
);
134 kiss_header(PORT_STREAM
, KissCommand
::DataFrame
.proto_value()),
136 i
+= escape(stream_data
, &mut data
[i
..]);
137 push(&mut data
, &mut i
, FEND
);
139 Ok(KissFrame
{ data
, len
: i
})
142 /// Request to set the TxDelay
143 pub fn new_set_tx_delay(port
: u8, units
: u8) -> Self {
144 let mut data
= [0u8; MAX_FRAME_LEN
];
146 push(&mut data
, &mut i
, FEND
);
150 kiss_header(port
, KissCommand
::TxDelay
.proto_value()),
152 push(&mut data
, &mut i
, units
);
153 push(&mut data
, &mut i
, FEND
);
155 KissFrame
{ data
, len
: i
}
158 /// Request to set the persistence parameter P
159 pub fn new_set_p(port
: u8, units
: u8) -> Self {
160 let mut data
= [0u8; MAX_FRAME_LEN
];
162 push(&mut data
, &mut i
, FEND
);
166 kiss_header(port
, KissCommand
::P
.proto_value()),
168 push(&mut data
, &mut i
, units
);
169 push(&mut data
, &mut i
, FEND
);
171 KissFrame
{ data
, len
: i
}
174 /// Request to set full duplex or not
175 pub fn set_full_duplex(port
: u8, full_duplex
: bool
) -> Self {
176 let mut data
= [0u8; MAX_FRAME_LEN
];
178 push(&mut data
, &mut i
, FEND
);
182 kiss_header(port
, KissCommand
::FullDuplex
.proto_value()),
184 push(&mut data
, &mut i
, if full_duplex
{ 1 } else { 0 });
185 push(&mut data
, &mut i
, FEND
);
187 KissFrame
{ data
, len
: i
}
190 /// Return this frame's KISS command type.
191 pub fn command(&self) -> Result
<KissCommand
, KissError
> {
192 KissCommand
::from_proto(self.header_byte()?
& 0x0f)
195 /// Return the KISS port to which this frame relates. Should be 0, 1 or 2.
196 pub fn port(&self) -> Result
<u8, KissError
> {
197 Ok(self.header_byte()?
>> 4)
200 /// Payload part of the frame between the header byte and the trailing FEND, unescaped.
201 pub fn decode_payload(&self, out
: &mut [u8]) -> Result
<usize, KissError
> {
206 .skip_while(|(_
, b
)| **b
== FEND
)
209 .ok_or(KissError
::MalformedKissFrame
)?
211 let end
= self.data
[start
..]
214 .skip_while(|(_
, b
)| **b
!= FEND
)
216 .ok_or(KissError
::MalformedKissFrame
)?
219 Ok(unescape(&self.data
[start
..end
], out
))
222 /// Borrow the frame as a slice
223 pub fn as_bytes(&self) -> &[u8] {
224 &self.data
[..self.len
]
227 /// Return the header byte of the KISS frame, skipping over 0 or more prepended FENDs.
228 fn header_byte(&self) -> Result
<u8, KissError
> {
232 .skip_while(|b
| **b
== FEND
)
235 .ok_or(KissError
::MalformedKissFrame
)?
)
239 fn kiss_header(port
: u8, command
: u8) -> u8 {
240 (port
<< 4) | (command
& 0x0f)
243 fn push(data
: &mut [u8], idx
: &mut usize, value
: u8) {
248 #[derive(Debug, PartialEq, Eq, Clone)]
249 pub enum KissCommand
{
257 fn from_proto(value
: u8) -> Result
<Self, KissError
> {
259 0 => KissCommand
::DataFrame
,
260 1 => KissCommand
::TxDelay
,
262 5 => KissCommand
::FullDuplex
,
263 _
=> return Err(KissError
::UnsupportedKissCommand
),
267 fn proto_value(&self) -> u8 {
269 KissCommand
::DataFrame
=> 0,
270 KissCommand
::TxDelay
=> 1,
272 KissCommand
::FullDuplex
=> 5,
277 /// Accepts raw KISS data and emits one frame at a time.
279 /// A frame will be emitted if there is at least one byte between FEND markers. It is up to the consumer
280 /// to determine whether it's actually a valid frame.
281 pub struct KissBuffer
{
282 /// Provisional frame, whose buffer might contain more than one sequential frame at a time
284 /// Number of bytes that have been written into `frame.data`, which may be more than the the length
285 /// of the first valid frame, `frame.len`.
287 /// Whether we have emitted the first frame in `frame`'s buffer and now need to flush it out.
288 first_frame_returned
: bool
,
292 /// Create new buffer
293 pub fn new() -> Self {
295 frame
: KissFrame
::new_empty(),
297 first_frame_returned
: false,
301 /// Return the space remaining for more data
302 pub fn buf_remaining(&mut self) -> &mut [u8] {
303 self.fl
ush
_first
_frame
();
304 if self.written
== self.frame
.data
.len() {
305 // full buffer with no data means oversized frame
306 // sender is doing something weird or a FEND got dropped
307 // either way: flush it all and try to sync up again
310 &mut self.frame
.data
[self.written
..]
313 /// Indicate how much data was written into the buffer provided by `buf_remaining()`.
314 pub fn did_write(&mut self, len
: usize) {
318 /// Try to construct and retrieve the next frame in the buffer
319 pub fn next_frame(&mut self) -> Option
<&KissFrame
> {
320 self.fl
ush
_first
_frame
();
322 // If we have any data without a leading FEND, scan past it
324 while i
< self.written
&& self.frame
.data
[i
] != FEND
{
327 self.move_to_start(i
);
329 // If we do have a leading FEND, scan up up to the last one in the series
331 while (i
+ 1) < self.written
&& self.frame
.data
[i
+ 1] == FEND
{
335 self.move_to_start(i
);
338 // Now, if we have FEND-something-FEND, return it
339 if self.written
>= 2 && self.frame
.data
[0] == FEND
&& self.frame
.data
[1] != FEND
{
341 while i
< self.written
&& self.frame
.data
[i
] != FEND
{
344 if i
< self.written
&& self.frame
.data
[i
] == FEND
{
345 self.frame
.len
= i
+ 1;
346 self.first
_frame
_ret
urned
= true;
347 return Some(&self.frame
);
354 /// Check if we just returned a frame; if so, clear it out and position the buffer for the next frame.
355 fn flush_first_frame(&mut self) {
356 if !self.first
_frame
_ret
urned
{
359 self.first
_frame
_ret
urned
= false;
360 // If we have previously returned a valid frame, in the simplest case `frame.data` contains FEND-something-FEND
361 // So to find the trailing FEND we can start at index 2
362 // Loop forward until we find that FEND, which must exist, and leave its index in `i`
364 while self.frame
.data
[i
] != FEND
{
367 // However if we have consecutive trailing FENDs we want to ignore them
368 // Having found the trailing FEND, increment past any additional FENDs until we reach the end or something else
369 while (i
+ 1) < self.written
&& self.frame
.data
[i
+ 1] == FEND
{
372 // Now take that final FEND and make it the start of our frame
373 self.move_to_start(i
);
376 /// Shift all data in the buffer back to the beginning starting from the given index.
377 fn move_to_start(&mut self, idx
: usize) {
378 for i
in idx
..self.written
{
379 self.frame
.data
[i
- idx
] = self.frame
.data
[i
];
385 #[derive(Debug, PartialEq, Eq, Clone)]
388 UnsupportedKissCommand
,
394 fn escape(src
: &[u8], dst
: &mut [u8]) -> usize {
397 while i
< src
.len() && j
< dst
.len() {
402 } else if src
[i
] == FESC
{
415 fn unescape(src
: &[u8], dst
: &mut [u8]) -> usize {
418 while i
< src
.len() && j
< dst
.len() {
420 if i
== src
.len() - 1 {
426 } else if src
[i
] == TFESC
{
444 let mut buf
= [0u8; 1024];
446 let src
= [0, 1, 2, 3, 4, 5];
447 let n
= escape(&src
, &mut buf
);
449 assert_eq
!(&buf
[0..6], src
);
451 let src
= [0, 1, TFESC
, 3, TFEND
, 5];
452 let n
= escape(&src
, &mut buf
);
454 assert_eq
!(&buf
[0..6], src
);
456 let src
= [0, 1, FEND
, 3, 4, 5];
457 let n
= escape(&src
, &mut buf
);
459 assert_eq
!(&buf
[0..7], &[0, 1, FESC
, TFEND
, 3, 4, 5]);
461 let src
= [0, 1, 2, 3, 4, FESC
];
462 let n
= escape(&src
, &mut buf
);
464 assert_eq
!(&buf
[0..7], &[0, 1, 2, 3, 4, FESC
, TFESC
]);
469 let mut buf
= [0u8; 1024];
471 let src
= [0, 1, 2, 3, 4, 5];
472 let n
= unescape(&src
, &mut buf
);
474 assert_eq
!(&buf
[0..6], src
);
476 let src
= [0, 1, TFESC
, 3, TFEND
, 5];
477 let n
= unescape(&src
, &mut buf
);
479 assert_eq
!(&buf
[0..6], src
);
481 let src
= [0, 1, FESC
, TFEND
, 3, 4, 5];
482 let n
= unescape(&src
, &mut buf
);
484 assert_eq
!(&buf
[0..6], &[0, 1, FEND
, 3, 4, 5]);
486 let src
= [0, 1, 2, 3, 4, FESC
, TFESC
];
487 let n
= unescape(&src
, &mut buf
);
489 assert_eq
!(&buf
[0..6], &[0, 1, 2, 3, 4, FESC
]);
493 fn basic_packet_roundtrip() {
494 let f
= KissFrame
::new_basic_packet(&[0, 1, 2, 3]).unwrap
();
495 assert_eq
!(f
.as_bytes(), &[FEND
, 0, 0, 1, 2, 3, FEND
]);
496 let mut buf
= [0u8; 1024];
497 let n
= f
.decode_payload(&mut buf
).unwrap
();
498 assert_eq
!(&buf
[..n
], &[0, 1, 2, 3]);
502 fn test_buffer_basic() {
503 let mut buffer
= KissBuffer
::new();
505 // initial write is not a complete frame
506 let buf
= buffer
.buf_remaining();
509 assert
!(buffer
.next_frame().is
_none
());
511 // complete the frame
512 let buf
= buffer
.buf_remaining();
518 // everything should parse
519 let next
= buffer
.next_frame().unwrap
();
520 assert_eq
!(next
.len
, 4);
521 assert_eq
!(&next
.data
[0..4], &[FEND
, 0x10, 0x01, FEND
]);
522 assert_eq
!(next
.port().unwrap
(), 1);
523 assert_eq
!(next
.command().unwrap
(), KissCommand
::DataFrame
);
524 let mut payload_buf
= [0u8; 1024];
525 let n
= next
.decode_payload(&mut payload_buf
).unwrap
();
527 assert_eq
!(&payload_buf
[0..n
], &[0x01]);
531 fn test_buffer_double() {
532 let mut buffer
= KissBuffer
::new();
533 let buf
= buffer
.buf_remaining();
534 buf
[0..8].copy_from_slice(&[FEND
, 0x10, 0x01, FEND
, FEND
, 0x20, 02, FEND
]);
537 let next
= buffer
.next_frame().unwrap
();
538 assert_eq
!(next
.port().unwrap
(), 1);
539 let next
= buffer
.next_frame().unwrap
();
540 assert_eq
!(next
.port().unwrap
(), 2);
541 assert
!(buffer
.next_frame().is
_none
());
545 fn test_buffer_double_shared_fend() {
546 let mut buffer
= KissBuffer
::new();
547 let buf
= buffer
.buf_remaining();
548 buf
[0..7].copy_from_slice(&[FEND
, 0x10, 0x01, FEND
, 0x20, 02, FEND
]);
551 let next
= buffer
.next_frame().unwrap
();
552 assert_eq
!(next
.port().unwrap
(), 1);
553 let next
= buffer
.next_frame().unwrap
();
554 assert_eq
!(next
.port().unwrap
(), 2);
555 assert
!(buffer
.next_frame().is
_none
());
559 fn test_buffer_extra_fend() {
560 let mut buffer
= KissBuffer
::new();
561 let buf
= buffer
.buf_remaining();
562 buf
[0..10].copy_from_slice(&[FEND
, FEND
, FEND
, 0x10, 0x01, FEND
, FEND
, 0x20, 02, FEND
]);
563 buffer
.did_write(10);
565 let next
= buffer
.next_frame().unwrap
();
566 assert_eq
!(next
.port().unwrap
(), 1);
567 let next
= buffer
.next_frame().unwrap
();
568 assert_eq
!(next
.port().unwrap
(), 2);
569 assert
!(buffer
.next_frame().is
_none
());
573 fn test_buffer_oversize_frame() {
574 let mut buffer
= KissBuffer
::new();
575 let buf
= buffer
.buf_remaining();
578 assert_eq
!(len
, MAX_FRAME_LEN
);
579 buffer
.did_write(len
);
580 assert
!(buffer
.next_frame().is
_none
());
582 let buf
= buffer
.buf_remaining();
584 assert_eq
!(len
, MAX_FRAME_LEN
); // should have flushed
585 for i
in 0..len
/ 2 {
588 buffer
.did_write(len
/ 2);
589 assert
!(buffer
.next_frame().is
_none
());
591 // confirm we resync if input goes back to normal
592 let buf
= buffer
.buf_remaining();
593 buf
[0..4].copy_from_slice(&[FEND
, 0x10, 0x01, FEND
]);
595 let next
= buffer
.next_frame().unwrap
();
596 assert_eq
!(next
.port().unwrap
(), 1);
597 assert
!(buffer
.next_frame().is
_none
());