]>
code.octet-stream.net Git - m17rt/blob - m17core/src/tnc.rs
   1 use crate::address
::{Address
, Callsign
}; 
   2 use crate::kiss
::{KissBuffer
, KissFrame
, PORT_PACKET_BASIC
, PORT_PACKET_FULL
, PORT_STREAM
}; 
   3 use crate::modem
::ModulatorFrame
; 
   5     Frame
, LichCollection
, LsfFrame
, Mode
, PacketFrame
, PacketFrameCounter
, StreamFrame
, 
   8 /// Handles the KISS protocol and frame management for `SoftModulator` and `SoftDemodulator`. 
  10 /// These components work alongside each other. User is responsible for chaining them together 
  11 /// or doing something else with the data. 
  13     /// Handle framing of KISS commands from the host, which may arrive in arbitrary binary blobs. 
  14     kiss_buffer
: KissBuffer
, 
  16     /// Kiss message that needs to be sent to the host. 
  17     outgoing_kiss
: Option
<OutgoingKiss
>, 
  19     /// Current RX or TX function of the TNC. 
  22     /// Latest state of data carrier detect from demodulator - controls whether we can go to TX 
  25     /// Current monotonic time, counted in samples 
  28     // TODO: use a static ring buffer crate of some sort? 
  29     /// Circular buffer of packets enqueued for transmission 
  30     packet_queue
: [PendingPacket
; 4], 
  35     /// Current packet index, which is either partly transmitted or not transmitted at all. 
  38     /// If true, packet_next == packet_curr implies full queue. packet_next is invalid. 
  39     /// If false, it implies empty queue. 
  42     /// The LSF for a stream we are going to start transmitting. 
  44     /// This serves as a general indicator that we want to tx a stream. 
  45     stream_pending_lsf
: Option
<LsfFrame
>, 
  47     /// Circular buffer of stream data enqueued for transmission. 
  49     /// When the queue empties out, we hope that the last one has the end-of-stream flag set. 
  50     /// Otherwise a buffer underrun has occurred. 
  52     /// Overruns are less troublesome - we can drop frames and receiving stations should cope. 
  53     stream_queue
: [StreamFrame
; 8], 
  58     /// Current unsent stream frame index 
  61     /// True if stream_next == stream_curr because the queue is full. stream_next is invalid. 
  64     /// Should PTT be on right now? Polled by external 
  69     pub fn new() -> Self { 
  71             kiss_buffer
: KissBuffer
::new(), 
  76             packet_queue
: Default
::default(), 
  80             stream_pending_lsf
: None
, 
  81             stream_queue
: Default
::default(), 
  89     /// Process an individual `Frame` that has been decoded by the modem. 
  90     pub fn handle_frame(&mut self, frame
: Frame
) { 
  93                 // A new LSF implies a clean slate. 
  94                 // If we were partway through decoding something else then we missed it. 
  97                         self.state 
= State
::RxPacket(RxPacketState 
{ 
 104                         let kiss 
= KissFrame
::new_stream_setup(&lsf
.0).unwrap
(); 
 105                         self.kiss_to_host(kiss
); 
 106                         self.state 
= State
::RxStream(RxStreamState 
{ lsf
, index
: 0 }); 
 110             Frame
::Packet(packet
) => { 
 111                 match &mut self.state 
{ 
 112                     State
::RxPacket(ref mut rx
) => { 
 113                         match packet
.counter 
{ 
 114                             PacketFrameCounter
::Frame 
{ index 
} => { 
 115                                 if index 
== rx
.count 
&& index 
< 32 { 
 116                                     let start 
= 25 * index
; 
 117                                     rx
.packet
[start
..(start 
+ 25)].copy_from_slice(&packet
.payload
); 
 120                                     // unexpected order - something has gone wrong 
 121                                     self.state 
= State
::Idle
; 
 124                             PacketFrameCounter
::FinalFrame 
{ payload_len 
} => { 
 125                                 let start 
= 25 * rx
.count
; 
 126                                 let end 
= start 
+ payload_len
; 
 127                                 rx
.packet
[start
..(start 
+ payload_len
)] 
 128                                     .copy_from_slice(&packet
.payload
); 
 129                                 // TODO: compatible packets should be sent on port 0 too 
 131                                     KissFrame
::new_full_packet(&rx
.lsf
.0, &rx
.packet
[0..end
]) 
 133                                 self.kiss_to_host(kiss
); 
 134                                 self.state 
= State
::Idle
; 
 139                         // Invalid transition 
 140                         self.state 
= State
::Idle
; 
 144             Frame
::Stream(stream
) => { 
 145                 match &mut self.state 
{ 
 146                     State
::RxStream(ref mut rx
) => { 
 147                         // TODO: consider wraparound from 0x7fff 
 148                         if stream
.frame
_n
umber 
< rx
.index 
{ 
 149                             let mut lich 
= LichCollection
::new(); 
 150                             lich
.set_segment(stream
.lich_idx
, stream
.lich_part
); 
 151                             self.state 
= State
::RxAcquiringStream(RxAcquiringStreamState 
{ lich 
}); 
 153                             rx
.index 
= stream
.frame
_n
umber 
+ 1; 
 154                             let kiss 
= KissFrame
::new_stream_data(&stream
).unwrap
(); 
 155                             self.kiss_to_host(kiss
); 
 156                             // TODO: end stream if LICH updates indicate non-META part has changed 
 157                             // (this implies a new station) 
 158                             if stream
.end_of_stream 
{ 
 159                                 self.state 
= State
::Idle
; 
 163                     State
::RxAcquiringStream(ref mut rx
) => { 
 164                         rx
.lich
.set_segment(stream
.lich_idx
, stream
.lich_part
); 
 165                         if let Some(maybe_lsf
) = rx
.lich
.try_assemble() { 
 166                             let lsf 
= LsfFrame(maybe_lsf
); 
 167                             // LICH can change mid-transmission so wait until the CRC is correct 
 168                             // to ensure (to high probability) we haven't done a "torn read" 
 169                             if lsf
.check_crc() == 0 { 
 170                                 let kiss 
= KissFrame
::new_stream_setup(&lsf
.0).unwrap
(); 
 171                                 self.kiss_to_host(kiss
); 
 172                                 // TODO: avoid discarding the first data payload here 
 173                                 // need a queue depth of 2 for outgoing kiss 
 174                                 self.state 
= State
::RxStream(RxStreamState 
{ 
 176                                     index
: stream
.frame
_n
umber 
+ 1, 
 182                         // If coming from another state, we have missed something. 
 183                         // Never mind, let's start tracking LICH. 
 184                         let mut lich 
= LichCollection
::new(); 
 185                         lich
.set_segment(stream
.lich_idx
, stream
.lich_part
); 
 186                         self.state 
= State
::RxAcquiringStream(RxAcquiringStreamState 
{ lich 
}) 
 193     pub fn set_data_carrier_detect(&mut self, dcd
: bool
) { 
 197     pub fn set_now(&mut self, now_samples
: u64) { 
 198         self.now 
= now_samples
; 
 200             State
::TxEndingAtTime(time
) => { 
 201                 if now_samples 
>= time 
{ 
 203                     self.state 
= State
::Idle
; 
 210     pub fn ptt(&self) -> bool 
{ 
 214     pub fn set_tx_end_time(&mut self, in_samples
: usize) { 
 215         log
::debug
!("tnc has been told that tx will complete in {in_samples} samples"); 
 218                 self.state 
= State
::TxEndingAtTime(self.now 
+ in_samples 
as u64); 
 224     pub fn read_tx_frame(&mut self) -> Option
<ModulatorFrame
> { 
 226             State
::Idle 
| State
::RxAcquiringStream(_
) | State
::RxStream(_
) | State
::RxPacket(_
) => { 
 227                 // We will let CSMA decide whether to actually go ahead. 
 228                 // That's not implemented yet, so let's just check DCD. 
 229                 let channel_free 
= !self.dcd
; 
 230                 let stream_wants_to_tx 
= self.stream_pending_lsf
.is
_some
(); 
 231                 let packet_wants_to_tx 
= self.packet_full 
|| (self.packet_next 
!= self.packet_curr
); 
 232                 if channel_free 
&& stream_wants_to_tx 
{ 
 233                     self.state 
= State
::TxStream
; 
 234                 } else if channel_free 
&& packet_wants_to_tx 
{ 
 235                     self.state 
= State
::TxPacket
; 
 240                 // TODO: true txdelay 
 241                 Some(ModulatorFrame
::Preamble 
{ tx_delay
: 0 }) 
 244                 if !self.stream_full 
&& self.stream_next 
== self.stream_curr 
{ 
 247                 if let Some(lsf
) = self.stream_pending_lsf
.take() { 
 248                     return Some(ModulatorFrame
::Lsf(lsf
)); 
 250                 let frame 
= self.stream_queue
[self.stream_curr
].clone(); 
 251                 if self.stream_full 
{ 
 252                     self.stream_full 
= false; 
 254                 self.stream_curr 
= (self.stream_curr 
+ 1) % 8; 
 255                 if frame
.end_of_stream 
{ 
 256                     self.state 
= State
::TxStreamSentEndOfStream
; 
 258                 Some(ModulatorFrame
::Stream(frame
)) 
 260             State
::TxStreamSentEndOfStream 
=> { 
 261                 self.state 
= State
::TxEnding
; 
 262                 Some(ModulatorFrame
::EndOfTransmission
) 
 265                 if !self.packet_full 
&& self.packet_next 
== self.packet_curr 
{ 
 268                 while self.packet_next 
!= self.packet_curr 
{ 
 269                     match self.packet_queue
[self.packet_curr
].next_frame() { 
 274                             self.packet_curr 
= (self.packet_curr 
+ 1) % 4; 
 278                 self.state 
= State
::TxEnding
; 
 279                 Some(ModulatorFrame
::EndOfTransmission
) 
 281             State
::TxEnding 
| State
::TxEndingAtTime(_
) => { 
 282                 // Once we have signalled EOT we withold any new frames until 
 283                 // the channel fully clears and we are ready to TX again 
 289     /// Read KISS message to be sent to host. 
 291     /// After each frame input, this should be consumed in a loop until length 0 is returned. 
 292     /// This component will never block. Upstream interface can provide blocking `read()` if desired. 
 293     pub fn read_kiss(&mut self, target_buf
: &mut [u8]) -> usize { 
 294         match self.outgoing_kiss
.as_mut() { 
 296                 let n 
= (outgoing
.kiss_frame
.len 
- outgoing
.sent
).min(target_buf
.len()); 
 298                     .copy_from_slice(&outgoing
.kiss_frame
.data
[outgoing
.sent
..(outgoing
.sent 
+ n
)]); 
 300                 if outgoing
.sent 
== outgoing
.kiss_frame
.len 
{ 
 301                     self.outgoing_kiss 
= None
; 
 309     /// Host sends in some KISS data. 
 310     pub fn write_kiss(&mut self, buf
: &[u8]) -> usize { 
 311         let target_buf 
= self.kiss_buffer
.buf_remaining(); 
 312         let n 
= buf
.len().min(target_buf
.len()); 
 313         target_buf
[0..n
].copy_from_slice(&buf
[0..n
]); 
 314         self.kiss_buffer
.did_write(n
); 
 315         while let Some(kiss_frame
) = self.kiss_buffer
.next_frame() { 
 316             let Ok(port
) = kiss_frame
.port() else { 
 319             if port 
== PORT_PACKET_BASIC 
{ 
 320                 if self.packet_full 
{ 
 323                 let mut pending 
= PendingPacket
::new(); 
 324                 pending
.app_data
[0] = 0x00; // RAW 
 325                 let Ok(mut len
) = kiss_frame
.decode_payload(&mut pending
.app_data
[1..]) else { 
 328                 len 
+= 1; // for RAW prefix 
 329                 let packet_crc 
= crate::crc
::m17_crc(&pending
.app_data
[0..len
]); 
 330                 pending
.app_data
[len
..len 
+ 2].copy_from_slice(&packet_crc
.to_be_bytes()); 
 331                 pending
.app_data_len 
= len 
+ 2; 
 332                 pending
.lsf 
= Some(LsfFrame
::new_packet( 
 333                     &Address
::Callsign(Callsign(b
"M17RT-PKT".clone())), 
 336                 self.packet_queue
[self.packet_next
] = pending
; 
 337                 self.packet_next 
= (self.packet_next 
+ 1) % 4; 
 338                 if self.packet_next 
== self.packet_curr 
{ 
 339                     self.packet_full 
= true; 
 341             } else if port 
== PORT_PACKET_FULL 
{ 
 342                 if self.packet_full 
{ 
 345                 let mut pending 
= PendingPacket
::new(); 
 346                 let mut payload 
= [0u8; 855]; 
 347                 let Ok(len
) = kiss_frame
.decode_payload(&mut payload
) else { 
 353                 let mut lsf 
= LsfFrame([0u8; 30]); 
 354                 lsf
.0.copy_from_slice(&payload
[0..30]); 
 355                 if lsf
.check_crc() != 0 { 
 358                 pending
.lsf 
= Some(lsf
); 
 359                 let app_data_len 
= len 
- 30; 
 360                 pending
.app_data
[0..app_data_len
].copy_from_slice(&payload
[30..]); 
 361                 pending
.app_data_len 
= app_data_len
; 
 362                 self.packet_queue
[self.packet_next
] = pending
; 
 363                 self.packet_next 
= (self.packet_next 
+ 1) % 4; 
 364                 if self.packet_next 
== self.packet_curr 
{ 
 365                     self.packet_full 
= true; 
 367             } else if port 
== PORT_STREAM 
{ 
 368                 let mut payload 
= [0u8; 30]; 
 369                 let Ok(len
) = kiss_frame
.decode_payload(&mut payload
) else { 
 373                     log
::debug
!("payload len too short"); 
 377                     let lsf 
= LsfFrame(payload
); 
 378                     if lsf
.check_crc() != 0 { 
 381                     self.stream_pending_lsf 
= Some(lsf
); 
 383                     if self.stream_full 
{ 
 384                         log
::debug
!("stream full"); 
 387                     let frame_num_part 
= u16::from_be_bytes([payload
[6], payload
[7]]); 
 388                     self.stream_queue
[self.stream_next
] = StreamFrame 
{ 
 389                         lich_idx
: payload
[5] >> 5, 
 390                         lich_part
: payload
[0..5].try_into().unwrap
(), 
 391                         frame_number
: frame_num_part 
& 0x7fff, 
 392                         end_of_stream
: frame_num_part 
& 0x8000 > 0, 
 393                         stream_data
: payload
[8..24].try_into().unwrap
(), 
 395                     self.stream_next 
= (self.stream_next 
+ 1) % 8; 
 396                     if self.stream_next 
== self.stream_curr 
{ 
 397                         self.stream_full 
= true; 
 405     fn kiss_to_host(&mut self, kiss_frame
: KissFrame
) { 
 406         self.outgoing_kiss 
= Some(OutgoingKiss 
{ 
 413 #[derive(Debug, PartialEq, Eq, Clone)] 
 414 pub enum SoftTncError 
{ 
 415     General(&'
static str), 
 419 struct OutgoingKiss 
{ 
 420     kiss_frame
: KissFrame
, 
 425     /// Nothing happening. We may have TX data queued but we won't act on it until CSMA opens up. 
 428     /// We received some stream data but missed the leading LSF so we are trying to assemble from LICH. 
 429     RxAcquiringStream(RxAcquiringStreamState
), 
 431     /// We have acquired an identified stream transmission and are sending data payloads to the host. 
 432     RxStream(RxStreamState
), 
 434     /// We are receiving a packet. All is well so far, and there is more data to come before we tell the host. 
 435     RxPacket(RxPacketState
), 
 437     /// PTT is on and this is a stream-type transmission. New data may be added. 
 440     /// We have delivered the last frame in the current stream 
 441     TxStreamSentEndOfStream
, 
 443     /// PTT is on and this is a packet-type transmission. New packets may be enqueued. 
 446     /// We gave modulator an EndOfTransmission. PTT is still on, waiting for modulator to advise end time. 
 449     /// Ending transmission, PTT remains on, but we know the timestamp at which we should disengage it. 
 453 struct RxAcquiringStreamState 
{ 
 454     /// Partial assembly of LSF by accumulating LICH fields. 
 455     lich
: LichCollection
, 
 458 struct RxStreamState 
{ 
 459     /// Track identifying information for this transmission so we can tell if it changes. 
 462     /// Expected next frame number. Allowed to skip values on RX, but not go backwards. 
 466 struct RxPacketState 
{ 
 470     /// Accumulation of packet data that we have received so far. 
 473     /// Number of payload frames we have received. If we are stably in the RxPacket state, 
 474     /// this will be between 0 and 32 inclusive. 
 478 struct PendingPacket 
{ 
 479     lsf
: Option
<LsfFrame
>, 
 483     app_data_transmitted
: usize, 
 490             app_data
: [0u8; 825], 
 492             app_data_transmitted
: 0, 
 496     /// Returns next frame, not including preamble or EOT. 
 498     /// False means all data frames have been sent. 
 499     fn next_frame(&mut self) -> Option
<ModulatorFrame
> { 
 500         if let Some(lsf
) = self.lsf
.take() { 
 501             return Some(ModulatorFrame
::Lsf(lsf
)); 
 503         if self.app_data_len 
== self.app_data_transmitted 
{ 
 506         let remaining 
= self.app_data_len 
- self.app_data_transmitted
; 
 507         let (counter
, data_len
) = if remaining 
<= 25 { 
 509                 PacketFrameCounter
::FinalFrame 
{ 
 510                     payload_len
: remaining
, 
 516                 PacketFrameCounter
::Frame 
{ 
 517                     index
: self.app_data_transmitted 
/ 25, 
 522         let mut payload 
= [0u8; 25]; 
 523         payload
.copy_from_slice( 
 524             &self.app_data
[self.app_data_transmitted
..(self.app_data_transmitted 
+ data_len
)], 
 526         self.app_data_transmitted 
+= data_len
; 
 527         Some(ModulatorFrame
::Packet(PacketFrame 
{ payload
, counter 
})) 
 531 impl Default 
for PendingPacket 
{ 
 532     fn default() -> Self { 
 535             app_data
: [0u8; 825], 
 537             app_data_transmitted
: 0, 
 545     use crate::kiss
::{KissCommand
, PORT_STREAM
}; 
 546     use crate::protocol
::StreamFrame
; 
 548     // TODO: finish all handle_frame tests as below 
 549     // this will be much more straightforward when we have a way to create LSFs programatically 
 551     // receiving a single-frame packet 
 553     // receiving a multi-frame packet 
 555     // part of one packet and then another 
 558     fn tnc_receive_stream() { 
 560             255, 255, 255, 255, 255, 255, 0, 0, 0, 159, 221, 81, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 561             0, 0, 0, 0, 0, 131, 53, 
 563         let stream1 
= StreamFrame 
{ 
 565             lich_part
: [255, 255, 255, 255, 255], 
 567             end_of_stream
: false, 
 569                 128, 0, 119, 115, 220, 252, 41, 235, 8, 0, 116, 195, 94, 244, 45, 75, 
 572         let stream2 
= StreamFrame 
{ 
 574             lich_part
: [255, 0, 0, 0, 159], 
 578                 17, 0, 94, 82, 216, 135, 181, 15, 30, 0, 125, 195, 152, 183, 41, 57, 
 581         let mut tnc 
= SoftTnc
::new(); 
 582         let mut kiss 
= KissFrame
::new_empty(); 
 583         assert_eq
!(tnc
.read_kiss(&mut kiss
.data
), 0); 
 585         tnc
.handle_frame(Frame
::Lsf(lsf
)); 
 586         kiss
.len 
= tnc
.read_kiss(&mut kiss
.data
); 
 587         assert_eq
!(kiss
.command().unwrap
(), KissCommand
::DataFrame
); 
 588         assert_eq
!(kiss
.port().unwrap
(), PORT_STREAM
); 
 590         let mut payload_buf 
= [0u8; 2048]; 
 591         let n 
= kiss
.decode_payload(&mut payload_buf
).unwrap
(); 
 594         tnc
.handle_frame(Frame
::Stream(stream1
)); 
 595         kiss
.len 
= tnc
.read_kiss(&mut kiss
.data
); 
 596         assert_eq
!(kiss
.command().unwrap
(), KissCommand
::DataFrame
); 
 597         assert_eq
!(kiss
.port().unwrap
(), PORT_STREAM
); 
 599         let n 
= kiss
.decode_payload(&mut payload_buf
).unwrap
(); 
 602         tnc
.handle_frame(Frame
::Stream(stream2
)); 
 603         kiss
.len 
= tnc
.read_kiss(&mut kiss
.data
); 
 604         assert_eq
!(kiss
.command().unwrap
(), KissCommand
::DataFrame
); 
 605         assert_eq
!(kiss
.port().unwrap
(), PORT_STREAM
); 
 607         let n 
= kiss
.decode_payload(&mut payload_buf
).unwrap
(); 
 612     fn tnc_acquire_stream() { 
 616                 lich_part
: [255, 255, 255, 255, 255], 
 618                 end_of_stream
: false, 
 620                     128, 0, 119, 115, 220, 252, 41, 235, 8, 0, 116, 195, 94, 244, 45, 75, 
 625                 lich_part
: [255, 0, 0, 0, 159], 
 627                 end_of_stream
: false, 
 629                     17, 0, 94, 82, 216, 135, 181, 15, 30, 0, 125, 195, 152, 183, 41, 57, 
 634                 lich_part
: [221, 81, 5, 5, 0], 
 636                 end_of_stream
: false, 
 638                     17, 128, 93, 74, 154, 167, 169, 11, 20, 0, 116, 91, 158, 220, 45, 111, 
 643                 lich_part
: [0, 0, 0, 0, 0], 
 645                 end_of_stream
: false, 
 647                     15, 128, 114, 83, 218, 252, 59, 111, 31, 128, 116, 91, 84, 231, 45, 105, 
 652                 lich_part
: [0, 0, 0, 0, 0], 
 654                 end_of_stream
: false, 
 656                     9, 128, 119, 115, 220, 220, 57, 15, 48, 128, 124, 83, 158, 236, 181, 91, 
 661                 lich_part
: [0, 0, 0, 131, 53], 
 663                 end_of_stream
: false, 
 665                     52, 0, 116, 90, 152, 167, 225, 216, 32, 0, 116, 83, 156, 212, 33, 216, 
 670         let mut tnc 
= SoftTnc
::new(); 
 671         let mut kiss 
= KissFrame
::new_empty(); 
 673             tnc
.handle_frame(Frame
::Stream(f
)); 
 675         kiss
.len 
= tnc
.read_kiss(&mut kiss
.data
); 
 676         let mut payload_buf 
= [0u8; 2048]; 
 677         let n 
= kiss
.decode_payload(&mut payload_buf
).unwrap
(); 
 682                 255, 255, 255, 255, 255, 255, 0, 0, 0, 159, 221, 81, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 
 683                 0, 0, 0, 0, 0, 0, 131, 53, 
 689     fn tnc_handle_skipped_stream_frame() { 
 691             255, 255, 255, 255, 255, 255, 0, 0, 0, 159, 221, 81, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 692             0, 0, 0, 0, 0, 131, 53, 
 694         let stream1 
= StreamFrame 
{ 
 696             lich_part
: [255, 255, 255, 255, 255], 
 698             end_of_stream
: false, 
 700                 128, 0, 119, 115, 220, 252, 41, 235, 8, 0, 116, 195, 94, 244, 45, 75, 
 703         let stream3 
= StreamFrame 
{ 
 705             lich_part
: [221, 81, 5, 5, 0], 
 707             end_of_stream
: false, 
 709                 17, 128, 93, 74, 154, 167, 169, 11, 20, 0, 116, 91, 158, 220, 45, 111, 
 712         let mut tnc 
= SoftTnc
::new(); 
 713         let mut kiss 
= KissFrame
::new_empty(); 
 714         assert_eq
!(tnc
.read_kiss(&mut kiss
.data
), 0); 
 716         tnc
.handle_frame(Frame
::Lsf(lsf
)); 
 717         kiss
.len 
= tnc
.read_kiss(&mut kiss
.data
); 
 718         assert_eq
!(kiss
.command().unwrap
(), KissCommand
::DataFrame
); 
 719         assert_eq
!(kiss
.port().unwrap
(), PORT_STREAM
); 
 721         let mut payload_buf 
= [0u8; 2048]; 
 722         let n 
= kiss
.decode_payload(&mut payload_buf
).unwrap
(); 
 725         tnc
.handle_frame(Frame
::Stream(stream1
)); 
 726         kiss
.len 
= tnc
.read_kiss(&mut kiss
.data
); 
 727         assert_eq
!(kiss
.command().unwrap
(), KissCommand
::DataFrame
); 
 728         assert_eq
!(kiss
.port().unwrap
(), PORT_STREAM
); 
 730         let n 
= kiss
.decode_payload(&mut payload_buf
).unwrap
(); 
 733         tnc
.handle_frame(Frame
::Stream(stream3
)); 
 734         kiss
.len 
= tnc
.read_kiss(&mut kiss
.data
); 
 735         assert_eq
!(kiss
.command().unwrap
(), KissCommand
::DataFrame
); 
 736         assert_eq
!(kiss
.port().unwrap
(), PORT_STREAM
); 
 738         let n 
= kiss
.decode_payload(&mut payload_buf
).unwrap
();