]>
code.octet-stream.net Git - m17rt/blob - m17core/src/tnc.rs
8965499f2d7045b5d86fb5c4fad2a1ec93dfe3bb
   1 use crate::address
::{Address
, Callsign
}; 
   3     KissBuffer
, KissCommand
, KissFrame
, PORT_PACKET_BASIC
, PORT_PACKET_FULL
, PORT_STREAM
, 
   5 use crate::modem
::ModulatorFrame
; 
   7     Frame
, LichCollection
, LsfFrame
, Mode
, PacketFrame
, PacketFrameCounter
, StreamFrame
, 
  10 /// Handles the KISS protocol and frame management for `SoftModulator` and `SoftDemodulator`. 
  12 /// These components work alongside each other. User is responsible for chaining them together 
  13 /// or doing something else with the data. 
  15     /// Handle framing of KISS commands from the host, which may arrive in arbitrary binary blobs. 
  16     kiss_buffer
: KissBuffer
, 
  18     /// Kiss message that needs to be sent to the host. 
  19     outgoing_kiss
: Option
<OutgoingKiss
>, 
  21     /// Current RX or TX function of the TNC. 
  24     /// Latest state of data carrier detect from demodulator - controls whether we can go to TX 
  27     /// If CSMA declined to transmit into an idle slot, at what point do we next check it? 
  28     next_csma_check
: Option
<u64>, 
  30     /// Current monotonic time, counted in samples 
  33     // TODO: use a static ring buffer crate of some sort? 
  34     /// Circular buffer of packets enqueued for transmission 
  35     packet_queue
: [PendingPacket
; 4], 
  40     /// Current packet index, which is either partly transmitted or not transmitted at all. 
  43     /// If true, packet_next == packet_curr implies full queue. packet_next is invalid. 
  44     /// If false, it implies empty queue. 
  47     /// The LSF for a stream we are going to start transmitting. 
  49     /// This serves as a general indicator that we want to tx a stream. 
  50     stream_pending_lsf
: Option
<LsfFrame
>, 
  52     /// Circular buffer of stream data enqueued for transmission. 
  54     /// When the queue empties out, we hope that the last one has the end-of-stream flag set. 
  55     /// Otherwise a buffer underrun has occurred. 
  57     /// Overruns are less troublesome - we can drop frames and receiving stations should cope. 
  58     stream_queue
: [StreamFrame
; 8], 
  63     /// Current unsent stream frame index 
  66     /// True if stream_next == stream_curr because the queue is full. stream_next is invalid. 
  69     /// Should PTT be on right now? Polled by external 
  72     /// TxDelay raw value, number of 10ms units. We will optimistically start with default 0. 
  75     /// This is a full duplex channel so we do not need to monitor DCD or use CSMA. Default false. 
  80     pub fn new() -> Self { 
  82             kiss_buffer
: KissBuffer
::new(), 
  86             next_csma_check
: None
, 
  88             packet_queue
: Default
::default(), 
  92             stream_pending_lsf
: None
, 
  93             stream_queue
: Default
::default(), 
 103     /// Process an individual `Frame` that has been decoded by the modem. 
 104     pub fn handle_frame(&mut self, frame
: Frame
) { 
 106             // Ignore self-decodes 
 111                 // A new LSF implies a clean slate. 
 112                 // If we were partway through decoding something else then we missed it. 
 115                         self.state 
= State
::RxPacket(RxPacketState 
{ 
 122                         let kiss 
= KissFrame
::new_stream_setup(&lsf
.0).unwrap
(); 
 123                         self.kiss_to_host(kiss
); 
 124                         self.state 
= State
::RxStream(RxStreamState 
{ 
 131             Frame
::Packet(packet
) => { 
 132                 match &mut self.state 
{ 
 133                     State
::RxPacket(ref mut rx
) => { 
 134                         match packet
.counter 
{ 
 135                             PacketFrameCounter
::Frame 
{ index 
} => { 
 136                                 if index 
== rx
.count 
&& index 
< 32 { 
 137                                     let start 
= 25 * index
; 
 138                                     rx
.packet
[start
..(start 
+ 25)].copy_from_slice(&packet
.payload
); 
 141                                     // unexpected order - something has gone wrong 
 142                                     self.state 
= State
::Idle
; 
 145                             PacketFrameCounter
::FinalFrame 
{ payload_len 
} => { 
 146                                 let start 
= 25 * rx
.count
; 
 147                                 let end 
= start 
+ payload_len
; 
 148                                 rx
.packet
[start
..(start 
+ payload_len
)] 
 149                                     .copy_from_slice(&packet
.payload
[0..payload_len
]); 
 150                                 // TODO: compatible packets should be sent on port 0 too 
 152                                     KissFrame
::new_full_packet(&rx
.lsf
.0, &rx
.packet
[0..end
]) 
 154                                 self.kiss_to_host(kiss
); 
 155                                 self.state 
= State
::Idle
; 
 160                         // Invalid transition 
 161                         self.state 
= State
::Idle
; 
 165             Frame
::Stream(stream
) => { 
 166                 match &mut self.state 
{ 
 167                     State
::RxStream(ref mut rx
) => { 
 168                         // TODO: consider wraparound from 0x7fff 
 169                         if stream
.frame
_n
umber 
< rx
.index 
{ 
 170                             let mut lich 
= LichCollection
::new(); 
 171                             lich
.set_segment(stream
.lich_idx
, stream
.lich_part
); 
 172                             self.state 
= State
::RxAcquiringStream(RxAcquiringStreamState 
{ lich 
}); 
 174                             rx
.index 
= stream
.frame
_n
umber 
+ 1; 
 175                             let kiss 
= KissFrame
::new_stream_data(&stream
).unwrap
(); 
 176                             self.kiss_to_host(kiss
); 
 177                             // TODO: end stream if LICH updates indicate non-META part has changed 
 178                             // (this implies a new station) 
 179                             if stream
.end_of_stream 
{ 
 180                                 self.state 
= State
::Idle
; 
 184                     State
::RxAcquiringStream(ref mut rx
) => { 
 185                         rx
.lich
.set_segment(stream
.lich_idx
, stream
.lich_part
); 
 186                         if let Some(maybe_lsf
) = rx
.lich
.try_assemble() { 
 187                             let lsf 
= LsfFrame(maybe_lsf
); 
 188                             // LICH can change mid-transmission so wait until the CRC is correct 
 189                             // to ensure (to high probability) we haven't done a "torn read" 
 190                             if lsf
.check_crc() == 0 { 
 191                                 let kiss 
= KissFrame
::new_stream_setup(&lsf
.0).unwrap
(); 
 192                                 self.kiss_to_host(kiss
); 
 193                                 // TODO: avoid discarding the first data payload here 
 194                                 // need a queue depth of 2 for outgoing kiss 
 195                                 self.state 
= State
::RxStream(RxStreamState 
{ 
 197                                     index
: stream
.frame
_n
umber 
+ 1, 
 203                         // If coming from another state, we have missed something. 
 204                         // Never mind, let's start tracking LICH. 
 205                         let mut lich 
= LichCollection
::new(); 
 206                         lich
.set_segment(stream
.lich_idx
, stream
.lich_part
); 
 207                         self.state 
= State
::RxAcquiringStream(RxAcquiringStreamState 
{ lich 
}) 
 214     pub fn set_data_carrier_detect(&mut self, dcd
: bool
) { 
 218     pub fn set_now(&mut self, now_samples
: u64) { 
 219         self.now 
= now_samples
; 
 221             State
::TxEndingAtTime(time
) => { 
 222                 if now_samples 
>= time 
{ 
 224                     self.state 
= State
::Idle
; 
 231     pub fn ptt(&self) -> bool 
{ 
 235     pub fn set_tx_end_time(&mut self, in_samples
: usize) { 
 236         log
::debug
!("tnc has been told that tx will complete in {in_samples} samples"); 
 239                 self.state 
= State
::TxEndingAtTime(self.now 
+ in_samples 
as u64); 
 245     pub fn read_tx_frame(&mut self) -> Option
<ModulatorFrame
> { 
 247             State
::Idle 
| State
::RxAcquiringStream(_
) | State
::RxStream(_
) | State
::RxPacket(_
) => { 
 248                 let stream_wants_to_tx 
= self.stream_pending_lsf
.is
_some
(); 
 249                 let packet_wants_to_tx 
= self.packet_full 
|| (self.packet_next 
!= self.packet_curr
); 
 250                 if !stream_wants_to_tx 
&& !packet_wants_to_tx 
{ 
 254                 // We have something we might send if the channel is free 
 256                 // TODO: Proper full duplex support 
 257                 // A true full duplex TNC should be able to rx and tx concurrently, implying 
 259                 if !self.full
_d
uplex 
{ 
 260                     match self.next_csma_check 
{ 
 263                                 self.next_csma_check 
= Some(self.now 
+ 1920); 
 266                                 // channel is idle at the moment we get a frame to send 
 271                             if self.now 
< at_time 
{ 
 274                             // 25% chance that we'll transmit this slot. 
 275                             // Using self.now as random is probably fine so long as it's not being set in 
 276                             // a lumpy manner. m17app's soundmodem should be fine. 
 277                             // TODO: bring in prng to help in cases where `now` never ends in 0b11 
 278                             let p1_4 
= (self.now 
& 3) == 3; 
 279                             if !self.dcd 
|| !p1_4 
{ 
 280                                 self.next_csma_check 
= Some(self.now 
+ 1920); 
 283                                 self.next_csma_check 
= None
; 
 289                 if stream_wants_to_tx 
{ 
 290                     self.state 
= State
::TxStream
; 
 292                     self.state 
= State
::TxPacket
; 
 295                 Some(ModulatorFrame
::Preamble 
{ 
 296                     tx_delay
: self.tx_delay
, 
 300                 if !self.stream_full 
&& self.stream_next 
== self.stream_curr 
{ 
 303                 if let Some(lsf
) = self.stream_pending_lsf
.take() { 
 304                     return Some(ModulatorFrame
::Lsf(lsf
)); 
 306                 let frame 
= self.stream_queue
[self.stream_curr
].clone(); 
 307                 if self.stream_full 
{ 
 308                     self.stream_full 
= false; 
 310                 self.stream_curr 
= (self.stream_curr 
+ 1) % 8; 
 311                 if frame
.end_of_stream 
{ 
 312                     self.state 
= State
::TxStreamSentEndOfStream
; 
 314                 Some(ModulatorFrame
::Stream(frame
)) 
 316             State
::TxStreamSentEndOfStream 
=> { 
 317                 self.state 
= State
::TxEnding
; 
 318                 Some(ModulatorFrame
::EndOfTransmission
) 
 321                 if !self.packet_full 
&& self.packet_next 
== self.packet_curr 
{ 
 324                 while self.packet_next 
!= self.packet_curr 
{ 
 325                     match self.packet_queue
[self.packet_curr
].next_frame() { 
 330                             self.packet_curr 
= (self.packet_curr 
+ 1) % 4; 
 334                 self.state 
= State
::TxEnding
; 
 335                 Some(ModulatorFrame
::EndOfTransmission
) 
 337             State
::TxEnding 
| State
::TxEndingAtTime(_
) => { 
 338                 // Once we have signalled EOT we withold any new frames until 
 339                 // the channel fully clears and we are ready to TX again 
 345     /// Read KISS message to be sent to host. 
 347     /// After each frame input, this should be consumed in a loop until length 0 is returned. 
 348     /// This component will never block. Upstream interface can provide blocking `read()` if desired. 
 349     pub fn read_kiss(&mut self, target_buf
: &mut [u8]) -> usize { 
 350         match self.outgoing_kiss
.as_mut() { 
 352                 let n 
= (outgoing
.kiss_frame
.len 
- outgoing
.sent
).min(target_buf
.len()); 
 354                     .copy_from_slice(&outgoing
.kiss_frame
.data
[outgoing
.sent
..(outgoing
.sent 
+ n
)]); 
 356                 if outgoing
.sent 
== outgoing
.kiss_frame
.len 
{ 
 357                     self.outgoing_kiss 
= None
; 
 365     /// Host sends in some KISS data. 
 366     pub fn write_kiss(&mut self, buf
: &[u8]) -> usize { 
 367         let target_buf 
= self.kiss_buffer
.buf_remaining(); 
 368         let n 
= buf
.len().min(target_buf
.len()); 
 369         target_buf
[0..n
].copy_from_slice(&buf
[0..n
]); 
 370         self.kiss_buffer
.did_write(n
); 
 371         while let Some(kiss_frame
) = self.kiss_buffer
.next_frame() { 
 372             let Ok(port
) = kiss_frame
.port() else { 
 375             let Ok(command
) = kiss_frame
.command() else { 
 378             if port 
!= PORT_PACKET_BASIC 
&& port 
!= PORT_PACKET_FULL 
&& port 
!= PORT_STREAM 
{ 
 381             if command 
== KissCommand
::TxDelay 
{ 
 382                 let mut new_delay 
= [0u8; 1]; 
 383                 if kiss_frame
.decode_payload(&mut new_delay
) == Ok(1) { 
 384                     self.tx_delay 
= new_delay
[0]; 
 388             if command 
== KissCommand
::FullDuplex 
{ 
 389                 let mut new_duplex 
= [0u8; 1]; 
 390                 if kiss_frame
.decode_payload(&mut new_duplex
) == Ok(1) { 
 391                     self.full
_d
uplex 
= new_duplex
[0] != 0; 
 395             if command 
!= KissCommand
::DataFrame 
{ 
 396                 // Not supporting any other settings yet 
 397                 // TODO: allow adjusting P persistence parameter for CSMA 
 400             if port 
== PORT_PACKET_BASIC 
{ 
 401                 if self.packet_full 
{ 
 404                 let mut pending 
= PendingPacket
::new(); 
 405                 pending
.app_data
[0] = 0x00; // RAW 
 406                 let Ok(mut len
) = kiss_frame
.decode_payload(&mut pending
.app_data
[1..]) else { 
 409                 len 
+= 1; // for RAW prefix 
 410                 let packet_crc 
= crate::crc
::m17_crc(&pending
.app_data
[0..len
]); 
 411                 pending
.app_data
[len
..len 
+ 2].copy_from_slice(&packet_crc
.to_be_bytes()); 
 412                 pending
.app_data_len 
= len 
+ 2; 
 413                 pending
.lsf 
= Some(LsfFrame
::new_packet( 
 414                     &Address
::Callsign(Callsign(b
"M17RT-PKT".clone())), 
 417                 self.packet_queue
[self.packet_next
] = pending
; 
 418                 self.packet_next 
= (self.packet_next 
+ 1) % 4; 
 419                 if self.packet_next 
== self.packet_curr 
{ 
 420                     self.packet_full 
= true; 
 422             } else if port 
== PORT_PACKET_FULL 
{ 
 423                 if self.packet_full 
{ 
 426                 let mut pending 
= PendingPacket
::new(); 
 427                 let mut payload 
= [0u8; 855]; 
 428                 let Ok(len
) = kiss_frame
.decode_payload(&mut payload
) else { 
 434                 let mut lsf 
= LsfFrame([0u8; 30]); 
 435                 lsf
.0.copy_from_slice(&payload
[0..30]); 
 436                 if lsf
.check_crc() != 0 { 
 439                 pending
.lsf 
= Some(lsf
); 
 440                 let app_data_len 
= len 
- 30; 
 441                 pending
.app_data
[0..app_data_len
].copy_from_slice(&payload
[30..len
]); 
 442                 pending
.app_data_len 
= app_data_len
; 
 443                 self.packet_queue
[self.packet_next
] = pending
; 
 444                 self.packet_next 
= (self.packet_next 
+ 1) % 4; 
 445                 if self.packet_next 
== self.packet_curr 
{ 
 446                     self.packet_full 
= true; 
 448             } else if port 
== PORT_STREAM 
{ 
 449                 let mut payload 
= [0u8; 30]; 
 450                 let Ok(len
) = kiss_frame
.decode_payload(&mut payload
) else { 
 454                     log
::debug
!("payload len too short"); 
 458                     let lsf 
= LsfFrame(payload
); 
 459                     if lsf
.check_crc() != 0 { 
 462                     self.stream_pending_lsf 
= Some(lsf
); 
 464                     if self.stream_full 
{ 
 465                         log
::debug
!("stream full"); 
 468                     let frame_num_part 
= u16::from_be_bytes([payload
[6], payload
[7]]); 
 469                     self.stream_queue
[self.stream_next
] = StreamFrame 
{ 
 470                         lich_idx
: payload
[5] >> 5, 
 471                         lich_part
: payload
[0..5].try_into().unwrap
(), 
 472                         frame_number
: frame_num_part 
& 0x7fff, 
 473                         end_of_stream
: frame_num_part 
& 0x8000 > 0, 
 474                         stream_data
: payload
[8..24].try_into().unwrap
(), 
 476                     self.stream_next 
= (self.stream_next 
+ 1) % 8; 
 477                     if self.stream_next 
== self.stream_curr 
{ 
 478                         self.stream_full 
= true; 
 486     fn kiss_to_host(&mut self, kiss_frame
: KissFrame
) { 
 487         self.outgoing_kiss 
= Some(OutgoingKiss 
{ 
 494 #[derive(Debug, PartialEq, Eq, Clone)] 
 495 pub enum SoftTncError 
{ 
 496     General(&'
static str), 
 500 struct OutgoingKiss 
{ 
 501     kiss_frame
: KissFrame
, 
 506     /// Nothing happening. We may have TX data queued but we won't act on it until CSMA opens up. 
 509     /// We received some stream data but missed the leading LSF so we are trying to assemble from LICH. 
 510     RxAcquiringStream(RxAcquiringStreamState
), 
 512     /// We have acquired an identified stream transmission and are sending data payloads to the host. 
 513     RxStream(RxStreamState
), 
 515     /// We are receiving a packet. All is well so far, and there is more data to come before we tell the host. 
 516     RxPacket(RxPacketState
), 
 518     /// PTT is on and this is a stream-type transmission. New data may be added. 
 521     /// We have delivered the last frame in the current stream 
 522     TxStreamSentEndOfStream
, 
 524     /// PTT is on and this is a packet-type transmission. New packets may be enqueued. 
 527     /// We gave modulator an EndOfTransmission. PTT is still on, waiting for modulator to advise end time. 
 530     /// Ending transmission, PTT remains on, but we know the timestamp at which we should disengage it. 
 534 struct RxAcquiringStreamState 
{ 
 535     /// Partial assembly of LSF by accumulating LICH fields. 
 536     lich
: LichCollection
, 
 539 struct RxStreamState 
{ 
 540     /// Track identifying information for this transmission so we can tell if it changes. 
 543     /// Expected next frame number. Allowed to skip values on RX, but not go backwards. 
 547 struct RxPacketState 
{ 
 551     /// Accumulation of packet data that we have received so far. 
 554     /// Number of payload frames we have received. If we are stably in the RxPacket state, 
 555     /// this will be between 0 and 32 inclusive. 
 559 struct PendingPacket 
{ 
 560     lsf
: Option
<LsfFrame
>, 
 564     app_data_transmitted
: usize, 
 571             app_data
: [0u8; 825], 
 573             app_data_transmitted
: 0, 
 577     /// Returns next frame, not including preamble or EOT. 
 579     /// False means all data frames have been sent. 
 580     fn next_frame(&mut self) -> Option
<ModulatorFrame
> { 
 581         if let Some(lsf
) = self.lsf
.take() { 
 582             return Some(ModulatorFrame
::Lsf(lsf
)); 
 584         if self.app_data_len 
== self.app_data_transmitted 
{ 
 587         let remaining 
= self.app_data_len 
- self.app_data_transmitted
; 
 588         let (counter
, data_len
) = if remaining 
<= 25 { 
 590                 PacketFrameCounter
::FinalFrame 
{ 
 591                     payload_len
: remaining
, 
 597                 PacketFrameCounter
::Frame 
{ 
 598                     index
: self.app_data_transmitted 
/ 25, 
 603         let mut payload 
= [0u8; 25]; 
 604         payload
[0..data_len
].copy_from_slice( 
 605             &self.app_data
[self.app_data_transmitted
..(self.app_data_transmitted 
+ data_len
)], 
 607         self.app_data_transmitted 
+= data_len
; 
 608         Some(ModulatorFrame
::Packet(PacketFrame 
{ payload
, counter 
})) 
 612 impl Default 
for PendingPacket 
{ 
 613     fn default() -> Self { 
 616             app_data
: [0u8; 825], 
 618             app_data_transmitted
: 0, 
 626     use crate::kiss
::{KissCommand
, PORT_STREAM
}; 
 627     use crate::protocol
::StreamFrame
; 
 629     // TODO: finish all handle_frame tests as below 
 630     // this will be much more straightforward when we have a way to create LSFs programatically 
 632     // receiving a single-frame packet 
 634     // receiving a multi-frame packet 
 636     // part of one packet and then another 
 639     fn tnc_receive_stream() { 
 641             255, 255, 255, 255, 255, 255, 0, 0, 0, 159, 221, 81, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 642             0, 0, 0, 0, 0, 131, 53, 
 644         let stream1 
= StreamFrame 
{ 
 646             lich_part
: [255, 255, 255, 255, 255], 
 648             end_of_stream
: false, 
 650                 128, 0, 119, 115, 220, 252, 41, 235, 8, 0, 116, 195, 94, 244, 45, 75, 
 653         let stream2 
= StreamFrame 
{ 
 655             lich_part
: [255, 0, 0, 0, 159], 
 659                 17, 0, 94, 82, 216, 135, 181, 15, 30, 0, 125, 195, 152, 183, 41, 57, 
 662         let mut tnc 
= SoftTnc
::new(); 
 663         let mut kiss 
= KissFrame
::new_empty(); 
 664         assert_eq
!(tnc
.read_kiss(&mut kiss
.data
), 0); 
 666         tnc
.handle_frame(Frame
::Lsf(lsf
)); 
 667         kiss
.len 
= tnc
.read_kiss(&mut kiss
.data
); 
 668         assert_eq
!(kiss
.command().unwrap
(), KissCommand
::DataFrame
); 
 669         assert_eq
!(kiss
.port().unwrap
(), PORT_STREAM
); 
 671         let mut payload_buf 
= [0u8; 2048]; 
 672         let n 
= kiss
.decode_payload(&mut payload_buf
).unwrap
(); 
 675         tnc
.handle_frame(Frame
::Stream(stream1
)); 
 676         kiss
.len 
= tnc
.read_kiss(&mut kiss
.data
); 
 677         assert_eq
!(kiss
.command().unwrap
(), KissCommand
::DataFrame
); 
 678         assert_eq
!(kiss
.port().unwrap
(), PORT_STREAM
); 
 680         let n 
= kiss
.decode_payload(&mut payload_buf
).unwrap
(); 
 683         tnc
.handle_frame(Frame
::Stream(stream2
)); 
 684         kiss
.len 
= tnc
.read_kiss(&mut kiss
.data
); 
 685         assert_eq
!(kiss
.command().unwrap
(), KissCommand
::DataFrame
); 
 686         assert_eq
!(kiss
.port().unwrap
(), PORT_STREAM
); 
 688         let n 
= kiss
.decode_payload(&mut payload_buf
).unwrap
(); 
 693     fn tnc_acquire_stream() { 
 697                 lich_part
: [255, 255, 255, 255, 255], 
 699                 end_of_stream
: false, 
 701                     128, 0, 119, 115, 220, 252, 41, 235, 8, 0, 116, 195, 94, 244, 45, 75, 
 706                 lich_part
: [255, 0, 0, 0, 159], 
 708                 end_of_stream
: false, 
 710                     17, 0, 94, 82, 216, 135, 181, 15, 30, 0, 125, 195, 152, 183, 41, 57, 
 715                 lich_part
: [221, 81, 5, 5, 0], 
 717                 end_of_stream
: false, 
 719                     17, 128, 93, 74, 154, 167, 169, 11, 20, 0, 116, 91, 158, 220, 45, 111, 
 724                 lich_part
: [0, 0, 0, 0, 0], 
 726                 end_of_stream
: false, 
 728                     15, 128, 114, 83, 218, 252, 59, 111, 31, 128, 116, 91, 84, 231, 45, 105, 
 733                 lich_part
: [0, 0, 0, 0, 0], 
 735                 end_of_stream
: false, 
 737                     9, 128, 119, 115, 220, 220, 57, 15, 48, 128, 124, 83, 158, 236, 181, 91, 
 742                 lich_part
: [0, 0, 0, 131, 53], 
 744                 end_of_stream
: false, 
 746                     52, 0, 116, 90, 152, 167, 225, 216, 32, 0, 116, 83, 156, 212, 33, 216, 
 751         let mut tnc 
= SoftTnc
::new(); 
 752         let mut kiss 
= KissFrame
::new_empty(); 
 754             tnc
.handle_frame(Frame
::Stream(f
)); 
 756         kiss
.len 
= tnc
.read_kiss(&mut kiss
.data
); 
 757         let mut payload_buf 
= [0u8; 2048]; 
 758         let n 
= kiss
.decode_payload(&mut payload_buf
).unwrap
(); 
 763                 255, 255, 255, 255, 255, 255, 0, 0, 0, 159, 221, 81, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 
 764                 0, 0, 0, 0, 0, 0, 131, 53, 
 770     fn tnc_handle_skipped_stream_frame() { 
 772             255, 255, 255, 255, 255, 255, 0, 0, 0, 159, 221, 81, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 773             0, 0, 0, 0, 0, 131, 53, 
 775         let stream1 
= StreamFrame 
{ 
 777             lich_part
: [255, 255, 255, 255, 255], 
 779             end_of_stream
: false, 
 781                 128, 0, 119, 115, 220, 252, 41, 235, 8, 0, 116, 195, 94, 244, 45, 75, 
 784         let stream3 
= StreamFrame 
{ 
 786             lich_part
: [221, 81, 5, 5, 0], 
 788             end_of_stream
: false, 
 790                 17, 128, 93, 74, 154, 167, 169, 11, 20, 0, 116, 91, 158, 220, 45, 111, 
 793         let mut tnc 
= SoftTnc
::new(); 
 794         let mut kiss 
= KissFrame
::new_empty(); 
 795         assert_eq
!(tnc
.read_kiss(&mut kiss
.data
), 0); 
 797         tnc
.handle_frame(Frame
::Lsf(lsf
)); 
 798         kiss
.len 
= tnc
.read_kiss(&mut kiss
.data
); 
 799         assert_eq
!(kiss
.command().unwrap
(), KissCommand
::DataFrame
); 
 800         assert_eq
!(kiss
.port().unwrap
(), PORT_STREAM
); 
 802         let mut payload_buf 
= [0u8; 2048]; 
 803         let n 
= kiss
.decode_payload(&mut payload_buf
).unwrap
(); 
 806         tnc
.handle_frame(Frame
::Stream(stream1
)); 
 807         kiss
.len 
= tnc
.read_kiss(&mut kiss
.data
); 
 808         assert_eq
!(kiss
.command().unwrap
(), KissCommand
::DataFrame
); 
 809         assert_eq
!(kiss
.port().unwrap
(), PORT_STREAM
); 
 811         let n 
= kiss
.decode_payload(&mut payload_buf
).unwrap
(); 
 814         tnc
.handle_frame(Frame
::Stream(stream3
)); 
 815         kiss
.len 
= tnc
.read_kiss(&mut kiss
.data
); 
 816         assert_eq
!(kiss
.command().unwrap
(), KissCommand
::DataFrame
); 
 817         assert_eq
!(kiss
.port().unwrap
(), PORT_STREAM
); 
 819         let n 
= kiss
.decode_payload(&mut payload_buf
).unwrap
();