1use crate::error::{Result, TargetDriverError};
8use crate::serial::{SerialRead, SerialReader};
9use futures::channel::mpsc;
10use log::{info, warn};
11use uart_fpl::{
12 AckTracker, CONTROL_CHANNEL_ID, FrameStatus, FrameType, HandshakeResponse, HandshakeStatus,
13 ProtocolId, ResendReceiver, encode_frame,
14};
15
16#[derive(Clone, Debug, PartialEq, Eq)]
18pub enum SerialEvent {
19 SerialData { channel_id: u16, data: Vec<u8> },
21 SerialClose { channel_id: u16 },
23}
24
25const NEGOTIATE_RESP_SEQ: u8 = 1;
26
27#[derive(Clone, Copy, Debug, PartialEq, Eq)]
28enum SessionCheck {
29 Valid,
30 Discard,
31}
32
33fn validate_frame_session(
34 frame: &uart_fpl::Frame,
35 current_session_id: u32,
36) -> Result<SessionCheck> {
37 if frame.session_id == 0 {
38 warn!("Received {:?} frame with invalid session_id 0; discarding", frame.frame_type);
39 return Ok(SessionCheck::Discard);
40 }
41 if frame.session_id == current_session_id {
42 if frame.frame_type == FrameType::Reset
43 || (frame.frame_type == FrameType::Close && frame.channel_id == CONTROL_CHANNEL_ID)
44 {
45 info!(
46 "Received {:?} frame on control channel from host. Restarting bridge...",
47 frame.frame_type
48 );
49 return Err(TargetDriverError::ResetRequested);
50 }
51 return Ok(SessionCheck::Valid);
52 }
53 if frame.frame_type == FrameType::NegotiateReq && frame.channel_id == CONTROL_CHANNEL_ID {
54 info!("Session ID changed from {} to {}, restarting", current_session_id, frame.session_id);
55 return Err(TargetDriverError::SessionIdChanged);
56 }
57 warn!(
58 "Received frame with mismatched session ID (got {}, expected {}) type {:?} channel {}; discarding",
59 frame.session_id, current_session_id, frame.frame_type, frame.channel_id
60 );
61 Ok(SessionCheck::Discard)
62}
63
64fn handle_duplicate_negotiate_req(rx_session_id: u32, data_tx: &mut mpsc::Sender<Vec<u8>>) {
65 info!(
66 "Received duplicate NegotiateReq for active session {}, re-transmitting NegotiateResp",
67 rx_session_id
68 );
69 let resp = HandshakeResponse {
70 status: HandshakeStatus::Success,
71 selected: Some(ProtocolId::ResendSP),
72 };
73 if let Ok(serialized) = resp.serialize()
74 && let Ok(resp_frame) = encode_frame(
75 rx_session_id,
76 CONTROL_CHANNEL_ID,
77 NEGOTIATE_RESP_SEQ,
78 FrameType::NegotiateResp,
79 &serialized,
80 )
81 && let Err(e) = data_tx.try_send(resp_frame)
82 {
83 warn!("Failed to send duplicate NegotiateResp: {:?}", e);
84 }
85}
86
87fn handle_sequenced_serial_event(
90 receiver: &mut ResendReceiver,
91 rx_session_id: u32,
92 seq: u8,
93 event: SerialEvent,
94 serial_tx: &mut mpsc::Sender<SerialEvent>,
95 ack_tracker: &AckTracker,
96) -> Result<()> {
97 match receiver.inspect(seq) {
100 FrameStatus::InOrder { .. } => match serial_tx.try_send(event) {
101 Ok(()) => ack_tracker.set_ack(rx_session_id, receiver.advance_in_order(seq)?),
102 Err(e) if e.is_full() => {
103 if let Some(ack_seq) = receiver.current_ack_seq() {
108 ack_tracker.set_ack(rx_session_id, ack_seq);
109 }
110 }
111 Err(e) => {
112 let msg = format!("Failed to send event to coordinator: {e:?}");
113 return Err(TargetDriverError::ChannelSend(msg));
114 }
115 },
116 FrameStatus::OutOfOrder { ack_seq, .. } => {
117 if let Some(ack_seq) = ack_seq {
120 ack_tracker.set_ack(rx_session_id, ack_seq);
121 }
122 }
123 }
124 Ok(())
125}
126
127fn handle_ack_frame(seq: u8, ack_tx: &mut mpsc::Sender<u8>) -> Result<()> {
128 if let Err(e) = ack_tx.try_send(seq) {
129 if e.is_full() {
130 warn!("ack_tx full, dropping ACK event seq={}", seq);
131 } else {
132 return Err(TargetDriverError::ChannelSend(format!(
133 "Failed to enqueue ACK event: {:?}",
134 e
135 )));
136 }
137 }
138 Ok(())
139}
140
141fn dispatch_receiver_frame(
142 frame: uart_fpl::Frame,
143 receiver: &mut ResendReceiver,
144 serial_tx: &mut mpsc::Sender<SerialEvent>,
145 ack_tracker: &AckTracker,
146 ack_tx: &mut mpsc::Sender<u8>,
147 data_tx: &mut mpsc::Sender<Vec<u8>>,
148) -> Result<()> {
149 let (session_id, channel_id, seq, payload) =
150 (frame.session_id, frame.channel_id, frame.seq, frame.payload);
151 match frame.frame_type {
152 FrameType::NegotiateReq if channel_id == CONTROL_CHANNEL_ID => {
153 handle_duplicate_negotiate_req(session_id, data_tx);
154 }
155 FrameType::NegotiateReq => {
156 warn!(
157 "Received unexpected NegotiateReq on non-control channel {}; discarding",
158 channel_id
159 );
160 }
161 FrameType::Data if channel_id == CONTROL_CHANNEL_ID => {
162 warn!("Received unexpected DATA frame on CONTROL_CHANNEL_ID; discarding");
163 }
164 FrameType::Data => {
165 let event = SerialEvent::SerialData { channel_id, data: payload };
166 handle_sequenced_serial_event(
167 receiver,
168 session_id,
169 seq,
170 event,
171 serial_tx,
172 ack_tracker,
173 )?;
174 }
175 FrameType::Ack => handle_ack_frame(seq, ack_tx)?,
176 FrameType::Close => {
177 let event = SerialEvent::SerialClose { channel_id };
178 handle_sequenced_serial_event(
179 receiver,
180 session_id,
181 seq,
182 event,
183 serial_tx,
184 ack_tracker,
185 )?;
186 }
187 other => warn!("Unknown frame type: {:?}", other),
188 }
189 Ok(())
190}
191
192pub async fn receiver_task<R: SerialRead>(
201 reader: &mut SerialReader<R>,
202 mut serial_tx: mpsc::Sender<SerialEvent>,
203 ack_tracker: AckTracker,
204 mut ack_tx: mpsc::Sender<u8>,
205 session_id: u32,
206 mut data_tx: mpsc::Sender<Vec<u8>>,
207) -> Result<()> {
208 let mut receiver = ResendReceiver::new();
209 loop {
210 fuchsia_async::yield_now().await;
216 let frame = reader.next_frame().await?;
217 match validate_frame_session(&frame, session_id) {
218 Ok(SessionCheck::Valid) => {}
219 Ok(SessionCheck::Discard) => continue,
220 Err(TargetDriverError::SessionIdChanged) => {
221 reader.requeue_frame(&frame);
226 return Err(TargetDriverError::SessionIdChanged);
227 }
228 Err(e) => return Err(e),
229 }
230 dispatch_receiver_frame(
231 frame,
232 &mut receiver,
233 &mut serial_tx,
234 &ack_tracker,
235 &mut ack_tx,
236 &mut data_tx,
237 )?;
238 }
239}
240
241#[cfg(test)]
242mod tests {
243 use super::*;
244 use crate::serial::MockSerial;
245 use futures::prelude::*;
246 use uart_fpl::{FrameParser, HostHandshake};
247
248 struct MockSerialPending {
249 read_data: Vec<Vec<u8>>,
250 }
251
252 impl SerialRead for MockSerialPending {
253 async fn serial_read(&mut self) -> Result<Vec<u8>> {
254 if self.read_data.is_empty() {
255 futures::future::pending().await
256 } else {
257 Ok(self.read_data.remove(0))
258 }
259 }
260 }
261
262 struct TestReceiverHarness {
263 ack_tracker: AckTracker,
264 serial_rx: mpsc::Receiver<SerialEvent>,
265 data_rx: mpsc::Receiver<Vec<u8>>,
266 _ack_rx: mpsc::Receiver<u8>,
267 task: fuchsia_async::Task<Result<()>>,
268 }
269
270 fn spawn_test_receiver<R: SerialRead + 'static>(
271 client: R,
272 session_id: u32,
273 ) -> TestReceiverHarness {
274 let mut reader = SerialReader::new(client);
275 let ack_tracker = AckTracker::new();
276 let (ack_tx, _ack_rx) = mpsc::channel(10);
277 let (serial_tx, serial_rx) = mpsc::channel(10);
278 let (data_tx, data_rx) = mpsc::channel(10);
279 let ack_clone = ack_tracker.clone();
280 let task = fuchsia_async::Task::local(async move {
281 receiver_task(&mut reader, serial_tx, ack_clone, ack_tx, session_id, data_tx).await
282 });
283 TestReceiverHarness { ack_tracker, serial_rx, data_rx, _ack_rx, task }
284 }
285
286 async fn run_receiver_once(frames: Vec<Vec<u8>>, session_id: u32) -> (Result<()>, Vec<u8>) {
287 let mock_serial = MockSerial { read_data: frames, write_data: Vec::new() };
288 let mut reader = SerialReader::new(mock_serial);
289 let ack_tracker = AckTracker::new();
290 let (ack_tx, _ack_rx) = mpsc::channel(10);
291 let (serial_tx, _serial_rx) = mpsc::channel(10);
292 let (data_tx, _data_rx) = mpsc::channel(10);
293 let res =
294 receiver_task(&mut reader, serial_tx, ack_tracker, ack_tx, session_id, data_tx).await;
295 (res, reader.take_unconsumed())
296 }
297
298 #[fuchsia::test]
299 async fn test_receiver_task_happy_path() {
300 let payload = b"hello rcs";
301 let (session_id, channel_id) = (12345u32, 42u16);
302 let data_frame = encode_frame(session_id, channel_id, 0, FrameType::Data, payload).unwrap();
303 let mock_serial = MockSerial { read_data: vec![data_frame], write_data: Vec::new() };
304 let mut harness = spawn_test_receiver(mock_serial, session_id);
305 let event = harness.serial_rx.next().await.unwrap();
306 assert_eq!(event, SerialEvent::SerialData { channel_id, data: payload.to_vec() });
307 assert_eq!(harness.ack_tracker.take_ack(), Some((session_id, 0)));
308 }
309
310 #[fuchsia::test]
311 async fn test_receiver_task_discards_zero_session_id() {
312 let (valid_sid, channel_id) = (12345u32, 42u16);
313 let zero_frame = encode_frame(0, channel_id, 0, FrameType::Data, b"bad").unwrap();
314 let valid_frame = encode_frame(valid_sid, channel_id, 0, FrameType::Data, b"ok").unwrap();
315 let mock_serial =
316 MockSerial { read_data: vec![zero_frame, valid_frame], write_data: Vec::new() };
317 let mut harness = spawn_test_receiver(mock_serial, valid_sid);
318 let event = harness.serial_rx.next().await.unwrap();
319 assert_eq!(event, SerialEvent::SerialData { channel_id, data: b"ok".to_vec() });
320 }
321
322 #[fuchsia::test]
323 async fn test_receiver_task_out_of_order_reacks() {
324 let (session_id, channel_id) = (12345u32, 42u16);
325 let frame_0 = encode_frame(session_id, channel_id, 0, FrameType::Data, b"first").unwrap();
326 let frame_2 = encode_frame(session_id, channel_id, 2, FrameType::Data, b"third").unwrap();
327 let frame_1 = encode_frame(session_id, channel_id, 1, FrameType::Data, b"second").unwrap();
328 let mock_serial =
329 MockSerial { read_data: vec![frame_0, frame_2, frame_1], write_data: Vec::new() };
330 let mut harness = spawn_test_receiver(mock_serial, session_id);
331 let ev0 = harness.serial_rx.next().await.unwrap();
332 assert_eq!(ev0, SerialEvent::SerialData { channel_id, data: b"first".to_vec() });
333 let ev1 = harness.serial_rx.next().await.unwrap();
334 assert_eq!(ev1, SerialEvent::SerialData { channel_id, data: b"second".to_vec() });
335 assert_eq!(harness.ack_tracker.take_ack(), Some((session_id, 1)));
336 }
337
338 #[fuchsia::test]
339 async fn test_receiver_task_session_change_discard() {
340 let (session_id_1, session_id_2, channel_id) = (12345u32, 67890u32, 42u16);
341 let frame_1 =
342 encode_frame(session_id_2, channel_id, 0, FrameType::Data, b"discard me").unwrap();
343 let frame_2 =
344 encode_frame(session_id_1, channel_id, 0, FrameType::Data, b"accept me").unwrap();
345 let mock_serial = MockSerial { read_data: vec![frame_1, frame_2], write_data: Vec::new() };
346 let mut harness = spawn_test_receiver(mock_serial, session_id_1);
347 let event = harness.serial_rx.next().await.unwrap();
348 assert_eq!(event, SerialEvent::SerialData { channel_id, data: b"accept me".to_vec() });
349 }
350
351 #[fuchsia::test]
352 async fn test_receiver_task_session_change_negotiate_reboot() {
353 let (session_id_1, session_id_2) = (12345u32, 67890u32);
354 let frame_1 =
355 encode_frame(session_id_2, CONTROL_CHANNEL_ID, 0, FrameType::NegotiateReq, &[1, 1])
356 .unwrap();
357 let (result, unconsumed) = run_receiver_once(vec![frame_1.clone()], session_id_1).await;
358 assert!(matches!(result, Err(TargetDriverError::SessionIdChanged)));
359 assert_eq!(unconsumed, frame_1);
360 }
361
362 #[fuchsia::test]
363 async fn test_session_id_resiliency_adversarial() {
364 let (sid_current, sid_forged) = (100u32, 200u32);
365 let frame_bad = encode_frame(sid_forged, 42, 0, FrameType::Data, b"discard").unwrap();
366 let frame_ok = encode_frame(sid_current, 42, 0, FrameType::Data, b"accept").unwrap();
367 let mock_serial =
368 MockSerial { read_data: vec![frame_bad, frame_ok], write_data: Vec::new() };
369 let mut harness = spawn_test_receiver(mock_serial, sid_current);
370 let event = harness.serial_rx.next().await.unwrap();
371 assert_eq!(event, SerialEvent::SerialData { channel_id: 42, data: b"accept".to_vec() });
372 }
373
374 #[fuchsia::test]
375 async fn test_crc_noise_collision_resiliency() {
376 let (sid_current, sid_noise) = (0xABCDEFu32, 0x99999999u32);
377 let noise_frame = encode_frame(sid_noise, 1, 0, FrameType::Data, b"noisebytes").unwrap();
378 let valid_frame = encode_frame(sid_current, 1, 0, FrameType::Data, b"validbytes").unwrap();
379 let mock_serial = MockSerialPending { read_data: vec![noise_frame, valid_frame] };
380 let mut harness = spawn_test_receiver(mock_serial, sid_current);
381 let event = harness.serial_rx.next().await.unwrap();
382 assert_eq!(event, SerialEvent::SerialData { channel_id: 1, data: b"validbytes".to_vec() });
383 assert!(futures::poll!(&mut harness.task).is_pending());
384 }
385
386 #[fuchsia::test]
387 async fn test_receiver_task_duplicate_negotiate_req_retransmits_resp() {
388 let session_id = 99999u32;
389 let host = HostHandshake::new(vec![ProtocolId::ResendSP]);
390 let (frame_type, payload) = host.start().unwrap();
391 let dup_req =
392 encode_frame(session_id, CONTROL_CHANNEL_ID, 0, frame_type, &payload).unwrap();
393 let mock_serial = MockSerial { read_data: vec![dup_req], write_data: Vec::new() };
394 let mut harness = spawn_test_receiver(mock_serial, session_id);
395 let resp_bytes = harness.data_rx.next().await.expect("Expected NegotiateResp");
396 let mut parser = FrameParser::new();
397 parser.feed(&resp_bytes);
398 let resp_frame = parser.next_frame().expect("Should parse NegotiateResp frame");
399 assert_eq!(resp_frame.session_id, session_id);
400 assert_eq!(resp_frame.channel_id, CONTROL_CHANNEL_ID);
401 assert_eq!(resp_frame.frame_type, FrameType::NegotiateResp);
402 let resp = HandshakeResponse::try_from(resp_frame.payload.as_slice()).unwrap();
403 assert_eq!(resp.status, HandshakeStatus::Success);
404 assert_eq!(resp.selected, Some(ProtocolId::ResendSP));
405 }
406
407 #[fuchsia::test]
408 async fn test_receiver_task_handles_reset_frame() {
409 let session_id = 12345u32;
410 let zero_reset = encode_frame(0, CONTROL_CHANNEL_ID, 0, FrameType::Reset, &[]).unwrap();
411 let stale_reset =
412 encode_frame(99999, CONTROL_CHANNEL_ID, 0, FrameType::Reset, &[]).unwrap();
413 let valid_reset =
414 encode_frame(session_id, CONTROL_CHANNEL_ID, 0, FrameType::Reset, &[]).unwrap();
415 let (result, _) =
416 run_receiver_once(vec![zero_reset, stale_reset, valid_reset], session_id).await;
417 assert!(matches!(result, Err(TargetDriverError::ResetRequested)));
418 }
419
420 #[fuchsia::test]
421 async fn test_receiver_task_discards_control_channel_data() {
422 let session_id = 12345u32;
423 let bad_frame = encode_frame(
424 session_id,
425 CONTROL_CHANNEL_ID,
426 0,
427 FrameType::Data,
428 b"spurious control data",
429 )
430 .unwrap();
431 let good_frame =
432 encode_frame(session_id, 42, 0, FrameType::Data, b"valid user data").unwrap();
433 let mock_serial =
434 MockSerial { read_data: vec![bad_frame, good_frame], write_data: Vec::new() };
435 let mut harness = spawn_test_receiver(mock_serial, session_id);
436 let event = harness.serial_rx.next().await.unwrap();
437 assert_eq!(
438 event,
439 SerialEvent::SerialData { channel_id: 42, data: b"valid user data".to_vec() }
440 );
441 }
442}