fuchsia_bluetooth/types/channel/
fidl_server.rs1use fidl::endpoints::Responder;
6use fuchsia_sync::Mutex;
7use futures::channel::{mpsc, oneshot};
8use futures::future::{BoxFuture, FusedFuture};
9use futures::sink::Sink;
10use futures::stream::Stream;
11use futures::{Future, FutureExt, SinkExt, StreamExt, ready};
12use log::{trace, warn};
13
14use fidl_fuchsia_bluetooth as fidl_bt;
15use fidl_fuchsia_bluetooth_bredr as bredr;
16use fuchsia_async as fasync;
17use std::collections::VecDeque;
18use std::pin::Pin;
19use std::sync::atomic::{AtomicBool, Ordering};
20use std::sync::{Arc, OnceLock};
21use std::task::{Context, Poll};
22use zx;
23
24use super::{Connection, ConnectionBackendType};
25
26struct FlushState {
27 outstanding_packets: std::sync::atomic::AtomicUsize,
28 waker: Mutex<Option<std::task::Waker>>,
29}
30
31pub struct FidlServerConnection {
33 flush_state: Arc<FlushState>,
35 terminal_error: Arc<OnceLock<zx::Status>>,
37 send_tx: Mutex<mpsc::Sender<Vec<u8>>>,
39 recv_rx: mpsc::Receiver<Vec<u8>>,
41 _task: fasync::Task<()>,
43 is_closed: Arc<AtomicBool>,
45 close_fut: futures::future::Shared<BoxFuture<'static, Result<(), zx::Status>>>,
47 max_tx_size: usize,
49}
50
51impl std::fmt::Debug for FidlServerConnection {
52 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
53 f.debug_struct("FidlServerConnection")
54 .field("is_closed", &self.is_closed.load(Ordering::Relaxed))
55 .finish()
56 }
57}
58
59impl FidlServerConnection {
60 pub const SEND_BUFFER_SIZE: usize = 32;
61
62 pub fn new(request_stream: fidl_bt::ChannelRequestStream, max_tx_size: usize) -> Self {
63 let (send_tx, send_rx) = mpsc::channel(Self::SEND_BUFFER_SIZE - 1);
65 let (recv_tx, recv_rx) = mpsc::channel(Self::SEND_BUFFER_SIZE);
66 let is_closed = Arc::new(AtomicBool::new(false));
67 let (close_tx, close_rx) = oneshot::channel();
68 let flush_state = Arc::new(FlushState {
69 outstanding_packets: std::sync::atomic::AtomicUsize::new(0),
70 waker: Mutex::new(None),
71 });
72
73 let task = fasync::Task::spawn(Self::background_task(
74 request_stream,
75 send_rx,
76 recv_tx,
77 is_closed.clone(),
78 close_tx,
79 flush_state.clone(),
80 ));
81
82 let close_fut = async move {
83 let _ = close_rx.await;
84 Ok(())
85 }
86 .boxed()
87 .shared();
88
89 Self {
90 flush_state,
91 terminal_error: Arc::new(OnceLock::new()),
92 send_tx: Mutex::new(send_tx),
93 recv_rx,
94 _task: task,
95 is_closed,
96 close_fut,
97 max_tx_size,
98 }
99 }
100
101 fn send_packet(&self, packet: Vec<u8>) -> Result<(), zx::Status> {
102 trace!("FidlServerConnection: Enqueuing outgoing packet of size {}", packet.len());
103 if packet.len() > self.max_tx_size {
104 return Err(zx::Status::OUT_OF_RANGE);
105 }
106 let mut send_tx = self.send_tx.lock();
107 let _ = self.flush_state.outstanding_packets.fetch_add(1, Ordering::Relaxed);
108 if let Err(err) = send_tx.try_send(packet) {
109 let _ = self.flush_state.outstanding_packets.fetch_sub(1, Ordering::Relaxed);
110 if err.is_full() {
111 return Err(zx::Status::SHOULD_WAIT);
112 } else {
113 return Err(zx::Status::PEER_CLOSED);
114 }
115 }
116 Ok(())
117 }
118
119 fn batch_packets(send_queue: &mut VecDeque<Vec<u8>>) -> Vec<fidl_bt::Packet> {
120 let mut batch = Vec::new();
121 let mut batch_bytes = 0;
122
123 while let Some(packet) = send_queue.front() {
124 if batch_bytes + packet.len() + super::PACKET_OVERHEAD > super::MAX_BATCH_SIZE_BYTES {
125 if batch.is_empty() {
126 let packet = send_queue.pop_front().unwrap();
128 batch.push(fidl_bt::Packet { packet });
129 }
130 break;
131 }
132 let packet = send_queue.pop_front().unwrap();
133 batch_bytes += packet.len() + super::PACKET_OVERHEAD;
134 batch.push(fidl_bt::Packet { packet });
135 }
136 batch
137 }
138
139 async fn background_task(
140 mut stream: fidl_bt::ChannelRequestStream,
141 mut send_rx: mpsc::Receiver<Vec<u8>>,
142 recv_tx: mpsc::Sender<Vec<u8>>,
143 is_closed: Arc<AtomicBool>,
144 close_tx: oneshot::Sender<()>,
145 flush_state: Arc<FlushState>,
146 ) {
147 let mut pending_receive: Option<fidl_bt::ChannelReceiveResponder> = None;
148 let mut send_queue = VecDeque::<Vec<u8>>::new();
149
150 let mut incoming_data =
152 VecDeque::<(VecDeque<Vec<u8>>, fidl_bt::ChannelSend_Responder)>::new();
153 let mut incoming_data_forward_fut =
155 futures::future::Fuse::<BoxFuture<'static, Result<(), mpsc::SendError>>>::terminated();
156
157 trace!("FidlServerConnection: background task started");
158
159 loop {
160 if incoming_data_forward_fut.is_terminated() {
162 if let Some((packets, _)) = incoming_data.front_mut() {
163 let Some(packet) = packets.pop_front() else {
165 if let Some((_, responder)) = incoming_data.pop_front() {
167 let _ = responder.send();
168 }
169 continue; };
171
172 let mut tx = recv_tx.clone();
174 incoming_data_forward_fut =
175 (async move { tx.send(packet).await }).boxed().fuse();
176 }
177 }
178
179 let mut outgoing_fut = if send_queue.len() < Self::SEND_BUFFER_SIZE {
182 send_rx.next().left_future()
183 } else {
184 futures::future::pending().right_future()
185 };
186
187 futures::select! {
188 forward_res = incoming_data_forward_fut => {
189 if let Err(e) = forward_res {
190 warn!(e:?; "FidlServerConnection: Failed to forward packet to bt-rfcomm");
191 break;
192 }
193 }
194 request = stream.next() => {
195 let Some(item) = request else {
196 warn!("FidlServerConnection: FIDL request stream closed");
197 break;
198 };
199 let Ok(request) = item else {
200 warn!("FIDL request stream error: {:?}", item.unwrap_err());
201 break;
202 };
203 match request {
204 fidl_bt::ChannelRequest::Send_ { packets, responder } => {
205 trace!("FidlServerConnection: Received Send_ request with {} packets", packets.len());
206 let packet_data: Vec<Vec<u8>> = packets.into_iter().map(|p| p.packet).collect();
207 incoming_data.push_back((VecDeque::from(packet_data), responder));
208 }
209 fidl_bt::ChannelRequest::Receive { responder } => {
210 trace!("FidlServerConnection: Received Receive request, send_queue len: {}", send_queue.len());
211 if !send_queue.is_empty() {
212 let packets = Self::batch_packets(&mut send_queue);
213 let _ = responder.send(&packets);
214 } else {
215 if let Some(_old) = pending_receive.replace(responder) {
216 warn!("Multiple outstanding Receive requests are not allowed!");
217 break;
218 }
219 }
220 }
221 fidl_bt::ChannelRequest::WatchChannelParameters { responder } => {
222 warn!("FidlServerConnection: got WatchChannelParameters request, which is currently not handled");
223 responder.drop_without_shutdown();
224 }
225 other => {
226 warn!("Unknown FIDL method received: {other:?}");
227 }
228 }
229 }
230 outgoing = outgoing_fut => {
231 let Some(data) = outgoing else {
232 warn!("FidlServerConnection: send_rx closed");
233 break;
234 };
235 send_queue.push_back(data);
236 let mut processed = 1;
237 while send_queue.len() < Self::SEND_BUFFER_SIZE {
238 match send_rx.try_next() {
239 Ok(Some(packet)) => {
240 send_queue.push_back(packet);
241 processed += 1;
242 }
243 _ => break,
244 }
245 }
246 let outstanding = flush_state.outstanding_packets.fetch_sub(processed, Ordering::Relaxed) - processed;
247 if outstanding == 0 {
248 if let Some(waker) = flush_state.waker.lock().take() {
249 waker.wake();
250 }
251 }
252 if let Some(resp) = pending_receive.take() {
253 let packets = Self::batch_packets(&mut send_queue);
254 let _ = resp.send(&packets);
255 }
256 }
257 }
258 }
259 trace!("FidlServerConnection: background task exiting");
260 is_closed.store(true, Ordering::Relaxed);
261 let _ = close_tx.send(());
262 }
263}
264
265impl Connection for FidlServerConnection {
266 fn closed<'a>(&'a self) -> Pin<Box<dyn Future<Output = Result<(), zx::Status>> + 'a>> {
267 Box::pin(self.close_fut.clone())
268 }
269
270 fn connection_type(&self) -> ConnectionBackendType {
271 ConnectionBackendType::FidlServer
272 }
273
274 fn write(&self, bytes: &[u8]) -> Result<usize, zx::Status> {
275 if let Some(err) = self.terminal_error.get() {
276 return Err(*err);
277 }
278 self.send_packet(bytes.to_vec())?;
279 Ok(bytes.len())
280 }
281
282 fn is_closed(&self) -> bool {
283 self.is_closed.load(Ordering::Relaxed)
284 }
285
286 fn into_fidl_channel(self: Box<Self>) -> Result<bredr::Channel, zx::Status> {
287 Err(zx::Status::NOT_SUPPORTED)
288 }
289}
290
291impl Stream for FidlServerConnection {
292 type Item = Result<Vec<u8>, zx::Status>;
293
294 fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
295 self.recv_rx.poll_next_unpin(cx).map(|opt| opt.map(Ok))
296 }
297}
298
299impl Sink<Vec<u8>> for FidlServerConnection {
300 type Error = zx::Status;
301
302 fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
303 let this = self.get_mut();
304 if let Some(err) = this.terminal_error.get() {
305 return Poll::Ready(Err(*err));
306 }
307 let mut send_tx = this.send_tx.lock();
308 Pin::new(&mut *send_tx).poll_ready(cx).map_err(|_| zx::Status::PEER_CLOSED)
309 }
310
311 fn start_send(self: Pin<&mut Self>, item: Vec<u8>) -> Result<(), Self::Error> {
312 if let Some(err) = self.terminal_error.get() {
313 return Err(*err);
314 }
315 self.send_packet(item)
316 }
317
318 fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
319 let this = self.get_mut();
320 if let Some(err) = this.terminal_error.get() {
321 return Poll::Ready(Err(*err));
322 }
323
324 if this.flush_state.outstanding_packets.load(Ordering::Relaxed) == 0 {
325 return Poll::Ready(Ok(()));
326 }
327
328 *this.flush_state.waker.lock() = Some(cx.waker().clone());
329
330 if this.flush_state.outstanding_packets.load(Ordering::Relaxed) == 0 {
331 let _ = this.flush_state.waker.lock().take();
332 return Poll::Ready(Ok(()));
333 }
334
335 Poll::Pending
336 }
337
338 fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
339 ready!(Sink::poll_flush(self.as_mut(), cx))?;
340 let this = self.get_mut();
341 this.send_tx.lock().close_channel();
342 Poll::Ready(Ok(()))
343 }
344}
345
346#[cfg(test)]
347mod tests {
348 use super::*;
349 use crate::types::Channel;
350 use fidl::endpoints::create_proxy_and_stream;
351 use fuchsia_async as fasync;
352 use futures::stream::FusedStream;
353 use futures::{SinkExt, StreamExt};
354 use std::pin::pin;
355
356 #[test]
357 fn channel_sync_write() {
358 let mut exec = fasync::TestExecutor::new();
359 let (proxy, stream) = create_proxy_and_stream::<fidl_bt::ChannelMarker>();
360 let channel = Channel::from_fidl_server(stream, Channel::DEFAULT_MAX_TX);
361
362 let data = vec![1, 2, 3];
363
364 for _ in 0..32 {
366 let size = channel.write(&data).expect("sync write to succeed");
367 assert_eq!(size, data.len());
368 }
369
370 let result = channel.write(&data);
372 assert_eq!(result, Err(zx::Status::SHOULD_WAIT));
373
374 let stream_fut = proxy.receive();
376 let mut stream_fut = pin!(stream_fut);
377
378 let _ = exec.run_until_stalled(&mut futures::future::pending::<()>());
380
381 match exec.run_until_stalled(&mut stream_fut) {
382 Poll::Ready(Ok(packets)) => {
383 assert_eq!(packets.len(), 32);
384 for packet in packets {
385 assert_eq!(packet.packet, data);
386 }
387 }
388 x => panic!("Expected packets from Receive, got {:?}", x),
389 }
390
391 let size = channel.write(&data).expect("sync write to succeed again");
393 assert_eq!(size, data.len());
394 }
395
396 #[test]
397 fn channel_write_too_large() {
398 let mut exec = fasync::TestExecutor::new();
399 let (_proxy, stream) = create_proxy_and_stream::<fidl_bt::ChannelMarker>();
400 let mut channel = Channel::from_fidl_server(stream, 10);
401
402 let data = vec![1; 11];
404 let result = channel.write(&data);
405 assert_eq!(result, Err(zx::Status::OUT_OF_RANGE));
406
407 let mut send_fut = channel.send(data);
409 let result = exec.run_until_stalled(&mut send_fut);
410 assert_eq!(result, Poll::Ready(Err(zx::Status::OUT_OF_RANGE)));
411 }
412
413 #[test]
414 fn channel_into_fidl() {
415 let _exec = fasync::TestExecutor::new();
416 let (_proxy, stream) = create_proxy_and_stream::<fidl_bt::ChannelMarker>();
417 let conn = FidlServerConnection::new(stream, Channel::DEFAULT_MAX_TX);
418
419 let result = Box::new(conn).into_fidl_channel();
420 assert_eq!(result.unwrap_err(), zx::Status::NOT_SUPPORTED);
421 }
422
423 #[test]
424 fn channel_closed() {
425 let mut exec = fasync::TestExecutor::new_with_fake_time();
426 let (proxy, stream) = create_proxy_and_stream::<fidl_bt::ChannelMarker>();
427 let channel = Channel::from_fidl_server(stream, Channel::DEFAULT_MAX_TX);
428
429 let mut closed_fut = channel.closed();
430 assert!(exec.run_until_stalled(&mut closed_fut).is_pending());
431 assert!(!channel.is_closed());
432
433 drop(proxy); let _ = exec.run_until_stalled(&mut futures::future::pending::<()>());
437
438 assert!(exec.run_until_stalled(&mut closed_fut).is_ready());
439 assert!(channel.is_closed());
440 }
441
442 #[test]
443 fn channel_sink() {
444 let mut exec = fasync::TestExecutor::new();
445 let (proxy, stream) = create_proxy_and_stream::<fidl_bt::ChannelMarker>();
446 let mut channel = Channel::from_fidl_server(stream, Channel::DEFAULT_MAX_TX);
447
448 let data = vec![1, 2, 3];
449
450 let receive_fut = proxy.receive();
452 let mut receive_fut = pin!(receive_fut);
453
454 assert!(exec.run_until_stalled(&mut receive_fut).is_pending());
456
457 let mut send_fut = channel.send(data.clone());
459
460 assert!(exec.run_until_stalled(&mut send_fut).is_ready());
462
463 match exec.run_until_stalled(&mut receive_fut) {
465 Poll::Ready(Ok(packets)) => {
466 assert_eq!(packets.len(), 1);
467 assert_eq!(packets[0].packet, data);
468 }
469 x => panic!("Expected packets from Receive, got {:?}", x),
470 }
471
472 let _ = proxy;
474 }
475
476 #[test]
477 fn channel_stream() {
478 let mut exec = fasync::TestExecutor::new();
479 let (proxy, stream) = create_proxy_and_stream::<fidl_bt::ChannelMarker>();
480 let mut channel = Channel::from_fidl_server(stream, Channel::DEFAULT_MAX_TX);
481
482 let data = vec![4, 5, 6];
483
484 let send_fut = proxy.send_(&[fidl_bt::Packet { packet: data.clone() }]);
486 let mut send_fut = pin!(send_fut);
487
488 let _ = exec.run_until_stalled(&mut futures::future::pending::<()>());
490
491 assert!(exec.run_until_stalled(&mut send_fut).is_ready());
492
493 let mut next_fut = channel.next();
494 match exec.run_until_stalled(&mut next_fut) {
495 Poll::Ready(Some(Ok(received))) => {
496 assert_eq!(received, data);
497 }
498 x => panic!("Expected data from stream, got {:?}", x),
499 }
500
501 drop(proxy);
503
504 let _ = exec.run_until_stalled(&mut futures::future::pending::<()>());
505
506 let mut next_fut = channel.next();
507 let Poll::Ready(None) = exec.run_until_stalled(&mut next_fut) else {
508 panic!("Expected None from the stream")
509 };
510
511 assert!(channel.is_terminated());
512 }
513}