Skip to main content

fdomain_container/
lib.rs

1// Copyright 2024 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use fidl::AsHandleRef;
6use fidl::endpoints::ClientEnd;
7use fidl_fuchsia_fdomain as proto;
8use fidl_fuchsia_io as fio;
9use fuchsia_async as fasync;
10use futures::prelude::*;
11use replace_with::replace_with;
12use std::collections::hash_map::Entry;
13use std::collections::{HashMap, VecDeque};
14use std::num::NonZeroU32;
15use std::pin::Pin;
16use std::sync::Arc;
17use std::sync::atomic::{AtomicU32, Ordering};
18use std::task::{Context, Poll, Waker};
19
20mod handles;
21pub mod wire;
22
23#[cfg(test)]
24mod test;
25
26pub type Result<T, E = proto::Error> = std::result::Result<T, E>;
27
28use handles::{AnyHandle, HandleType as _, IsDatagramSocket};
29
30/// A queue. Wraps a `VecDeque` but insures we are waking a waker when we push
31/// items into the queue.
32struct Queue<T>(VecDeque<T>);
33
34impl<T> Queue<T> {
35    /// Create a new queue.
36    fn new() -> Self {
37        Queue(VecDeque::new())
38    }
39
40    /// Whether the queue is empty.
41    fn is_empty(&self) -> bool {
42        self.0.is_empty()
43    }
44
45    /// Removes and discards the first element in the queue.
46    ///
47    /// # Panics
48    /// There *must* be a first element or this will panic.
49    fn destroy_front(&mut self) {
50        assert!(self.0.pop_front().is_some(), "Expected to find a value!");
51    }
52
53    /// Pop the first element from the queue if available.
54    fn pop_front(&mut self) -> Option<T> {
55        self.0.pop_front()
56    }
57
58    /// Return an element to the front of the queue. Does not wake any waiters
59    /// as it is assumed the waiter is the one who popped it to begin with.
60    ///
61    /// This is used when we'd *like* to use `front_mut` but we can't borrow the
62    /// source of `self` for that long without giving ourselves lifetime
63    /// headaches.
64    fn push_front_no_wake(&mut self, t: T) {
65        self.0.push_front(t)
66    }
67
68    /// Push a new element to the back of the queue, waking the given waker.
69    fn push_back(&mut self, t: T, waker: &Waker) {
70        self.0.push_back(t);
71        waker.wake_by_ref();
72    }
73
74    /// Get a mutable reference to the first element in the queue.
75    fn front_mut(&mut self) -> Option<&mut T> {
76        self.0.front_mut()
77    }
78}
79
80/// Maximum amount to read for an async socket read.
81// LINT.IfChange
82const ASYNC_READ_BUFSIZE: u64 = 256 * 1024;
83// LINT.ThenChange(
84//     //src/developer/ffx/lib/target/src/target_connector.rs,
85//     //src/developer/remote-control/fdomain-runner/src/main.rs,
86//     //src/developer/remote-control/runner/src/main.rs
87// )
88
89/// Wraps the various FIDL Event types that can be produced by an FDomain
90#[derive(Debug)]
91pub enum FDomainEvent {
92    ChannelStreamingReadStart(NonZeroU32, Result<()>),
93    ChannelStreamingReadStop(NonZeroU32, Result<()>),
94    SocketStreamingReadStart(NonZeroU32, Result<()>),
95    SocketStreamingReadStop(NonZeroU32, Result<()>),
96    WaitForSignals(NonZeroU32, Result<proto::FDomainWaitForSignalsResponse>),
97    SocketData(NonZeroU32, Result<proto::SocketData>),
98    SocketStreamingData(proto::SocketOnSocketStreamingDataRequest),
99    SocketDispositionSet(NonZeroU32, Result<()>),
100    WroteSocket(NonZeroU32, Result<proto::SocketWriteSocketResponse, proto::WriteSocketError>),
101    ChannelData(NonZeroU32, Result<proto::ChannelMessage>),
102    ChannelStreamingData(proto::ChannelOnChannelStreamingDataRequest),
103    WroteChannel(NonZeroU32, Result<(), proto::WriteChannelError>),
104    ClosedHandle(NonZeroU32, Result<()>),
105    ReplacedHandle(NonZeroU32, Result<()>),
106}
107
108/// An [`FDomainEvent`] that needs a bit more processing before it can be sent.
109/// I.e. it still contains `fidl::NullableHandle` objects that need to be replaced with
110/// FDomain IDs.
111enum UnprocessedFDomainEvent {
112    Ready(FDomainEvent),
113    ChannelData(NonZeroU32, fidl::MessageBufEtc),
114    ChannelStreamingData(proto::HandleId, fidl::MessageBufEtc),
115}
116
117impl From<FDomainEvent> for UnprocessedFDomainEvent {
118    fn from(other: FDomainEvent) -> UnprocessedFDomainEvent {
119        UnprocessedFDomainEvent::Ready(other)
120    }
121}
122
123/// Operations on a handle which are processed from the read queue.
124enum ReadOp {
125    /// Enable or disable async reads on a channel.
126    StreamingChannel(NonZeroU32, bool),
127    /// Enable or disable async reads on a socket.
128    StreamingSocket(NonZeroU32, bool),
129    Socket(NonZeroU32, u64),
130    Channel(NonZeroU32),
131}
132
133/// An in-progress socket write. It may take multiple syscalls to write to a
134/// socket, so this tracks how many bytes were written already and how many
135/// remain to be written.
136struct SocketWrite {
137    tid: NonZeroU32,
138    wrote: usize,
139    to_write: Vec<u8>,
140}
141
142/// Operations on a handle which are processed from the write queue.
143enum WriteOp {
144    Socket(SocketWrite),
145    Channel(NonZeroU32, Vec<u8>, HandlesToWrite),
146    SetDisposition(NonZeroU32, proto::SocketDisposition, proto::SocketDisposition),
147}
148
149/// A handle which is being moved out of the FDomain by a channel write call or
150/// closure/replacement.  There may still be operations to perform on this
151/// handle, so the write should not proceed while the handle is in the `InUse`
152/// state.
153enum ShuttingDownHandle {
154    InUse(proto::HandleId, HandleState),
155    Ready(AnyHandle),
156}
157
158impl ShuttingDownHandle {
159    fn poll_ready(
160        &mut self,
161        event_queue: &mut VecDeque<UnprocessedFDomainEvent>,
162        ctx: &mut Context<'_>,
163    ) -> Poll<()> {
164        replace_with(self, |this| match this {
165            this @ ShuttingDownHandle::Ready(_) => this,
166            ShuttingDownHandle::InUse(hid, mut state) => {
167                state.poll(event_queue, ctx);
168
169                if state.write_queue.is_empty() {
170                    while let Some(op) = state.read_queue.pop_front() {
171                        match op {
172                            ReadOp::StreamingChannel(tid, start) => {
173                                let err = Err(proto::Error::BadHandleId(proto::BadHandleId {
174                                    id: hid.id,
175                                }));
176                                let event = if start {
177                                    FDomainEvent::ChannelStreamingReadStart(tid, err)
178                                } else {
179                                    FDomainEvent::ChannelStreamingReadStop(tid, err)
180                                };
181                                event_queue.push_back(event.into());
182                            }
183                            ReadOp::StreamingSocket(tid, start) => {
184                                let err = Err(proto::Error::BadHandleId(proto::BadHandleId {
185                                    id: hid.id,
186                                }));
187                                let event = if start {
188                                    FDomainEvent::SocketStreamingReadStart(tid, err)
189                                } else {
190                                    FDomainEvent::SocketStreamingReadStop(tid, err)
191                                };
192                                event_queue.push_back(event.into());
193                            }
194                            ReadOp::Channel(tid) => {
195                                let err = state
196                                    .handle
197                                    .expected_type(fidl::ObjectType::CHANNEL)
198                                    .err()
199                                    .unwrap_or(proto::Error::ClosedDuringRead(
200                                        proto::ClosedDuringRead,
201                                    ));
202                                event_queue
203                                    .push_back(FDomainEvent::ChannelData(tid, Err(err)).into());
204                            }
205                            ReadOp::Socket(tid, _max_bytes) => {
206                                let err = state
207                                    .handle
208                                    .expected_type(fidl::ObjectType::SOCKET)
209                                    .err()
210                                    .unwrap_or(proto::Error::ClosedDuringRead(
211                                        proto::ClosedDuringRead,
212                                    ));
213                                event_queue
214                                    .push_back(FDomainEvent::SocketData(tid, Err(err)).into());
215                            }
216                        }
217                    }
218
219                    if state.async_read_in_progress {
220                        match &*state.handle {
221                            AnyHandle::Channel(_) => event_queue.push_back(
222                                FDomainEvent::ChannelStreamingData(
223                                    proto::ChannelOnChannelStreamingDataRequest {
224                                        handle: hid,
225                                        channel_sent: proto::ChannelSent::Stopped(
226                                            proto::AioStopped { error: None },
227                                        ),
228                                    },
229                                )
230                                .into(),
231                            ),
232                            AnyHandle::Socket(_) => event_queue.push_back(
233                                FDomainEvent::SocketStreamingData(
234                                    proto::SocketOnSocketStreamingDataRequest {
235                                        handle: hid,
236                                        socket_message: proto::SocketMessage::Stopped(
237                                            proto::AioStopped { error: None },
238                                        ),
239                                    },
240                                )
241                                .into(),
242                            ),
243                            AnyHandle::EventPair(_)
244                            | AnyHandle::Event(_)
245                            | AnyHandle::Vmo(_)
246                            | AnyHandle::Unknown(_) => unreachable!(),
247                        }
248                    }
249
250                    state.signal_waiters.clear();
251                    state.io_waiter = None;
252
253                    ShuttingDownHandle::Ready(
254                        Arc::into_inner(state.handle).expect("Unaccounted-for handle reference!"),
255                    )
256                } else {
257                    ShuttingDownHandle::InUse(hid, state)
258                }
259            }
260        });
261
262        if matches!(self, ShuttingDownHandle::Ready(_)) { Poll::Ready(()) } else { Poll::Pending }
263    }
264}
265
266/// A vector of [`ShuttingDownHandle`] paired with rights for the new handles, which
267/// can transition into being a vector of [`fidl::HandleDisposition`] when all the
268/// handles are ready.
269enum HandlesToWrite {
270    SomeInUse(Vec<(ShuttingDownHandle, fidl::Rights)>),
271    AllReady(Vec<fidl::HandleDisposition<'static>>),
272}
273
274impl HandlesToWrite {
275    fn poll_ready(
276        &mut self,
277        event_queue: &mut VecDeque<UnprocessedFDomainEvent>,
278        ctx: &mut Context<'_>,
279    ) -> Poll<&mut Vec<fidl::HandleDisposition<'static>>> {
280        match self {
281            HandlesToWrite::AllReady(s) => Poll::Ready(s),
282            HandlesToWrite::SomeInUse(handles) => {
283                let mut ready = true;
284                for (handle, _) in handles.iter_mut() {
285                    ready = ready && handle.poll_ready(event_queue, ctx).is_ready();
286                }
287
288                if !ready {
289                    return Poll::Pending;
290                }
291
292                *self = HandlesToWrite::AllReady(
293                    handles
294                        .drain(..)
295                        .map(|(handle, rights)| {
296                            let ShuttingDownHandle::Ready(handle) = handle else { unreachable!() };
297
298                            fidl::HandleDisposition::new(
299                                fidl::HandleOp::Move(handle.into()),
300                                fidl::ObjectType::NONE,
301                                rights,
302                                Ok(()),
303                            )
304                        })
305                        .collect(),
306                );
307
308                let HandlesToWrite::AllReady(s) = self else { unreachable!() };
309                Poll::Ready(s)
310            }
311        }
312    }
313}
314
315struct AnyHandleRef(Arc<AnyHandle>);
316
317impl AsHandleRef for AnyHandleRef {
318    fn as_handle_ref(&self) -> fidl::HandleRef<'_> {
319        self.0.as_handle_ref()
320    }
321}
322
323#[cfg(target_os = "fuchsia")]
324type OnSignals = fasync::OnSignals<'static, AnyHandleRef>;
325
326#[cfg(not(target_os = "fuchsia"))]
327type OnSignals = fasync::OnSignalsRef<'static>;
328
329/// Represents a `WaitForSignals` transaction from a client. When the contained
330/// `OnSignals` polls to completion we can reply to the transaction.
331struct SignalWaiter {
332    tid: NonZeroU32,
333    waiter: Pin<Box<OnSignals>>,
334}
335
336/// Information about a single handle within the [`FDomain`].
337struct HandleState {
338    /// The handle itself.
339    handle: Arc<AnyHandle>,
340    /// Our handle ID.
341    hid: proto::HandleId,
342    /// Whether this is a datagram socket. We have to handle data coming out of
343    /// datagram sockets a bit differently to preserve their semantics from the
344    /// perspective of the host and avoid data loss.
345    is_datagram_socket: bool,
346    /// Indicates we are sending `On*StreamingData` events to the client
347    /// presently. It is an error for the user to try to move the handle out of
348    /// the FDomain (e.g. send it through a channel or close it) until after
349    /// they request that streaming events stop.
350    async_read_in_progress: bool,
351    /// Queue of client requests to read from the handle. We have to queue read
352    /// requests because they may block, and we don't want to block the event
353    /// loop or be unable to handle further requests while a long read request
354    /// is blocking. Also we want to retire read requests in the order they were
355    /// submitted, otherwise pipelined reads could return data in a strange order.
356    read_queue: Queue<ReadOp>,
357    /// Queue of client requests to write to the handle. We have to queue write
358    /// requests for the same reason we have to queue read requests. Since we
359    /// process the queue one at a time, we need a separate queue for writes
360    /// otherwise we'd effectively make handles half-duplex, with read requests
361    /// unable to proceed if a write request is blocked at the head of the
362    /// queue.
363    write_queue: Queue<WriteOp>,
364    /// List of outstanding `WaitForSignals` transactions.
365    signal_waiters: Vec<SignalWaiter>,
366    /// Contains a waiter on this handle for IO reading and writing. Populated
367    /// whenever we need to block on IO to service a request.
368    io_waiter: Option<Pin<Box<OnSignals>>>,
369}
370
371impl HandleState {
372    fn new(handle: AnyHandle, hid: proto::HandleId) -> Result<Self, proto::Error> {
373        let is_datagram_socket = match handle.is_datagram_socket() {
374            IsDatagramSocket::Unknown => {
375                return Err(proto::Error::SocketTypeUnknown(proto::SocketTypeUnknown {
376                    type_: proto::SocketType::unknown(),
377                }));
378            }
379            other => other.is_datagram(),
380        };
381        Ok(HandleState {
382            handle: Arc::new(handle),
383            hid,
384            async_read_in_progress: false,
385            is_datagram_socket,
386            read_queue: Queue::new(),
387            write_queue: Queue::new(),
388            signal_waiters: Vec::new(),
389            io_waiter: None,
390        })
391    }
392
393    /// Poll this handle state. Lets us handle our IO queues and wait for the
394    /// next IO event.
395    fn poll(&mut self, event_queue: &mut VecDeque<UnprocessedFDomainEvent>, ctx: &mut Context<'_>) {
396        self.signal_waiters.retain_mut(|x| {
397            let Poll::Ready(result) = x.waiter.poll_unpin(ctx) else {
398                return true;
399            };
400
401            event_queue.push_back(
402                FDomainEvent::WaitForSignals(
403                    x.tid,
404                    result
405                        .map(|x| proto::FDomainWaitForSignalsResponse { signals: x.bits() })
406                        .map_err(|e| proto::Error::TargetError(e.into_raw())),
407                )
408                .into(),
409            );
410
411            false
412        });
413
414        let read_signals = self.handle.read_signals();
415        let write_signals = self.handle.write_signals();
416
417        loop {
418            if let Some(signal_waiter) = self.io_waiter.as_mut() {
419                if let Poll::Ready(sigs) = signal_waiter.poll_unpin(ctx) {
420                    if let Ok(sigs) = sigs {
421                        if sigs.intersects(read_signals) {
422                            self.process_read_queue(event_queue);
423                        }
424                        if sigs.intersects(write_signals) {
425                            self.process_write_queue(event_queue, ctx);
426                        }
427                    }
428                } else {
429                    let need_read = matches!(
430                        self.read_queue.front_mut(),
431                        Some(ReadOp::StreamingChannel(_, _) | ReadOp::StreamingSocket(_, _))
432                    );
433                    let need_write = matches!(
434                        self.write_queue.front_mut(),
435                        Some(WriteOp::SetDisposition(_, _, _))
436                    );
437
438                    self.process_read_queue(event_queue);
439                    self.process_write_queue(event_queue, ctx);
440
441                    if !(need_read || need_write) {
442                        break;
443                    }
444                }
445            }
446
447            let subscribed_signals =
448                if self.async_read_in_progress || !self.read_queue.is_empty() {
449                    read_signals
450                } else {
451                    fidl::Signals::NONE
452                } | if !self.write_queue.is_empty() { write_signals } else { fidl::Signals::NONE };
453
454            if !subscribed_signals.is_empty() {
455                self.io_waiter = Some(Box::pin(OnSignals::new(
456                    AnyHandleRef(Arc::clone(&self.handle)),
457                    subscribed_signals,
458                )));
459            } else {
460                self.io_waiter = None;
461                break;
462            }
463        }
464    }
465
466    /// Set `async_read_in_progress` to `true`. Return an error if it was already `true`.
467    fn try_enable_async_read(&mut self) -> Result<()> {
468        if self.async_read_in_progress {
469            Err(proto::Error::StreamingReadInProgress(proto::StreamingReadInProgress))
470        } else {
471            self.async_read_in_progress = true;
472            Ok(())
473        }
474    }
475
476    /// Set `async_read_in_progress` to `false`. Return an error if it was already `false`.
477    fn try_disable_async_read(&mut self) -> Result<()> {
478        if !self.async_read_in_progress {
479            Err(proto::Error::NoReadInProgress(proto::NoReadInProgress))
480        } else {
481            self.async_read_in_progress = false;
482            Ok(())
483        }
484    }
485
486    /// Handle events from the front of the read queue.
487    fn process_read_queue(&mut self, event_queue: &mut VecDeque<UnprocessedFDomainEvent>) {
488        while let Some(op) = self.read_queue.front_mut() {
489            match op {
490                ReadOp::StreamingChannel(tid, true) => {
491                    let tid = *tid;
492                    let result = self.try_enable_async_read();
493                    event_queue
494                        .push_back(FDomainEvent::ChannelStreamingReadStart(tid, result).into());
495                    self.read_queue.destroy_front();
496                }
497                ReadOp::StreamingChannel(tid, false) => {
498                    let tid = *tid;
499                    let result = self.try_disable_async_read();
500                    event_queue
501                        .push_back(FDomainEvent::ChannelStreamingReadStop(tid, result).into());
502                    self.read_queue.destroy_front();
503                }
504                ReadOp::StreamingSocket(tid, true) => {
505                    let tid = *tid;
506                    let result = self.try_enable_async_read();
507                    event_queue
508                        .push_back(FDomainEvent::SocketStreamingReadStart(tid, result).into());
509                    self.read_queue.destroy_front();
510                }
511                ReadOp::StreamingSocket(tid, false) => {
512                    let tid = *tid;
513                    let result = self.try_disable_async_read();
514                    event_queue
515                        .push_back(FDomainEvent::SocketStreamingReadStop(tid, result).into());
516                    self.read_queue.destroy_front();
517                }
518                ReadOp::Socket(tid, max_bytes) => {
519                    let (tid, max_bytes) = (*tid, *max_bytes);
520                    if let Some(event) = self.do_read_socket(tid, max_bytes) {
521                        let _ = self.read_queue.pop_front();
522                        event_queue.push_back(event.into());
523                    } else {
524                        break;
525                    }
526                }
527                ReadOp::Channel(tid) => {
528                    let tid = *tid;
529                    if let Some(event) = self.do_read_channel(tid) {
530                        let _ = self.read_queue.pop_front();
531                        event_queue.push_back(event.into());
532                    } else {
533                        break;
534                    }
535                }
536            }
537        }
538
539        if self.async_read_in_progress {
540            // We should have error'd out of any blocking operations if we had a
541            // read in progress.
542            assert!(self.read_queue.is_empty());
543            self.process_async_read(event_queue);
544        }
545    }
546
547    fn process_async_read(&mut self, event_queue: &mut VecDeque<UnprocessedFDomainEvent>) {
548        assert!(self.async_read_in_progress);
549
550        match &*self.handle {
551            AnyHandle::Channel(_) => {
552                'read_loop: while let Some(result) = self.handle.read_channel().transpose() {
553                    match result {
554                        Ok(msg) => event_queue.push_back(
555                            UnprocessedFDomainEvent::ChannelStreamingData(self.hid, msg),
556                        ),
557                        Err(e) => {
558                            event_queue.push_back(
559                                FDomainEvent::ChannelStreamingData(
560                                    proto::ChannelOnChannelStreamingDataRequest {
561                                        handle: self.hid,
562                                        channel_sent: proto::ChannelSent::Stopped(
563                                            proto::AioStopped { error: Some(Box::new(e)) },
564                                        ),
565                                    },
566                                )
567                                .into(),
568                            );
569                            self.async_read_in_progress = false;
570                            break 'read_loop;
571                        }
572                    }
573                }
574            }
575
576            AnyHandle::Socket(_) => {
577                'read_loop: while let Some(result) =
578                    self.handle.read_socket(ASYNC_READ_BUFSIZE).transpose()
579                {
580                    match result {
581                        Ok(data) => {
582                            event_queue.push_back(
583                                FDomainEvent::SocketStreamingData(
584                                    proto::SocketOnSocketStreamingDataRequest {
585                                        handle: self.hid,
586                                        socket_message: proto::SocketMessage::Data(
587                                            proto::SocketData {
588                                                data,
589                                                is_datagram: self.is_datagram_socket,
590                                            },
591                                        ),
592                                    },
593                                )
594                                .into(),
595                            );
596                        }
597                        Err(e) => {
598                            event_queue.push_back(
599                                FDomainEvent::SocketStreamingData(
600                                    proto::SocketOnSocketStreamingDataRequest {
601                                        handle: self.hid,
602                                        socket_message: proto::SocketMessage::Stopped(
603                                            proto::AioStopped { error: Some(Box::new(e)) },
604                                        ),
605                                    },
606                                )
607                                .into(),
608                            );
609                            self.async_read_in_progress = false;
610                            break 'read_loop;
611                        }
612                    }
613                }
614            }
615
616            _ => unreachable!("Processed async read for unreadable handle type!"),
617        }
618    }
619
620    /// Handle events from the front of the write queue.
621    fn process_write_queue(
622        &mut self,
623        event_queue: &mut VecDeque<UnprocessedFDomainEvent>,
624        ctx: &mut Context<'_>,
625    ) {
626        // We want to mutate and *maybe* pop the front of the write queue, but
627        // lifetime shenanigans mean we can't do that and also access `self`,
628        // which we need. So we pop the item always, and then maybe push it to
629        // the front again if we didn't actually want to pop it.
630        while let Some(op) = self.write_queue.pop_front() {
631            match op {
632                WriteOp::Socket(mut op) => {
633                    if let Some(event) = self.do_write_socket(&mut op) {
634                        event_queue.push_back(event.into());
635                    } else {
636                        self.write_queue.push_front_no_wake(WriteOp::Socket(op));
637                        break;
638                    }
639                }
640                WriteOp::SetDisposition(tid, disposition, disposition_peer) => {
641                    let result = { self.handle.socket_disposition(disposition, disposition_peer) };
642                    event_queue.push_back(FDomainEvent::SocketDispositionSet(tid, result).into())
643                }
644                WriteOp::Channel(tid, data, mut handles) => {
645                    if self
646                        .do_write_channel(tid, &data, &mut handles, event_queue, ctx)
647                        .is_pending()
648                    {
649                        self.write_queue.push_front_no_wake(WriteOp::Channel(tid, data, handles));
650                        break;
651                    }
652                }
653            }
654        }
655    }
656
657    /// Attempt to read from the handle in this [`HandleState`] as if it were a
658    /// socket. If the read succeeds or produces an error that should not be
659    /// retried, produce an [`FDomainEvent`] containing the result.
660    fn do_read_socket(&mut self, tid: NonZeroU32, max_bytes: u64) -> Option<FDomainEvent> {
661        if self.async_read_in_progress {
662            return Some(
663                FDomainEvent::SocketData(
664                    tid,
665                    Err(proto::Error::StreamingReadInProgress(proto::StreamingReadInProgress)),
666                )
667                .into(),
668            );
669        }
670
671        let max_bytes = if self.is_datagram_socket {
672            let AnyHandle::Socket(s) = &*self.handle else {
673                unreachable!("Read socket from state that wasn't for a socket!");
674            };
675            match s.info() {
676                Ok(x) => x.rx_buf_available as u64,
677                // We should always succeed. The only failures are if we don't
678                // have the rights or something's screwed up with the handle. We
679                // know we have the rights because figuring out this was a
680                // datagram socket to begin with meant calling the same call on
681                // the same handle earlier.
682                Err(e) => {
683                    return Some(FDomainEvent::SocketData(
684                        tid,
685                        Err(proto::Error::TargetError(e.into_raw())),
686                    ));
687                }
688            }
689        } else {
690            max_bytes
691        };
692        self.handle.read_socket(max_bytes).transpose().map(|x| {
693            FDomainEvent::SocketData(
694                tid,
695                x.map(|data| proto::SocketData { data, is_datagram: self.is_datagram_socket }),
696            )
697        })
698    }
699
700    /// Attempt to write to the handle in this [`HandleState`] as if it were a
701    /// socket. If the write succeeds or produces an error that should not be
702    /// retried, produce an [`FDomainEvent`] containing the result.
703    fn do_write_socket(&mut self, op: &mut SocketWrite) -> Option<FDomainEvent> {
704        match self.handle.write_socket(&op.to_write) {
705            Ok(wrote) => {
706                op.wrote += wrote;
707                op.to_write.drain(..wrote);
708
709                if op.to_write.is_empty() {
710                    Some(FDomainEvent::WroteSocket(
711                        op.tid,
712                        Ok(proto::SocketWriteSocketResponse {
713                            wrote: op.wrote.try_into().unwrap(),
714                        }),
715                    ))
716                } else {
717                    None
718                }
719            }
720            Err(error) => Some(FDomainEvent::WroteSocket(
721                op.tid,
722                Err(proto::WriteSocketError { error, wrote: op.wrote.try_into().unwrap() }),
723            )),
724        }
725    }
726
727    /// Attempt to write to the handle in this [`HandleState`] as if it were a
728    /// channel. If the write succeeds or produces an error that should not be
729    /// retried, produce an [`FDomainEvent`] containing the result.
730    fn do_write_channel(
731        &mut self,
732        tid: NonZeroU32,
733        data: &[u8],
734        handles: &mut HandlesToWrite,
735        event_queue: &mut VecDeque<UnprocessedFDomainEvent>,
736        ctx: &mut Context<'_>,
737    ) -> Poll<()> {
738        let Poll::Ready(handles) = handles.poll_ready(event_queue, ctx) else {
739            return Poll::Pending;
740        };
741
742        let ret = self.handle.write_channel(data, handles);
743        if let Some(ret) = ret {
744            event_queue.push_back(FDomainEvent::WroteChannel(tid, ret).into())
745        }
746        Poll::Ready(())
747    }
748
749    /// Attempt to read from the handle in this [`HandleState`] as if it were a
750    /// channel. If the read succeeds or produces an error that should not be
751    /// retried, produce an [`FDomainEvent`] containing the result.
752    fn do_read_channel(&mut self, tid: NonZeroU32) -> Option<UnprocessedFDomainEvent> {
753        if self.async_read_in_progress {
754            return Some(
755                FDomainEvent::ChannelData(
756                    tid,
757                    Err(proto::Error::StreamingReadInProgress(proto::StreamingReadInProgress)),
758                )
759                .into(),
760            );
761        }
762        match self.handle.read_channel() {
763            Ok(x) => x.map(|x| UnprocessedFDomainEvent::ChannelData(tid, x)),
764            Err(e) => Some(FDomainEvent::ChannelData(tid, Err(e)).into()),
765        }
766    }
767}
768
769/// State for a handle which is closing, but which needs its read and write
770/// queues flushed first.
771struct ClosingHandle {
772    action: Arc<CloseAction>,
773    state: Option<ShuttingDownHandle>,
774}
775
776impl ClosingHandle {
777    fn poll_ready(&mut self, fdomain: &mut FDomain, ctx: &mut Context<'_>) -> Poll<()> {
778        if let Some(state) = self.state.as_mut() {
779            if state.poll_ready(&mut fdomain.event_queue, ctx).is_ready() {
780                let state = self.state.take().unwrap();
781                let ShuttingDownHandle::Ready(handle) = state else {
782                    unreachable!();
783                };
784                self.action.perform(fdomain, handle);
785                Poll::Ready(())
786            } else {
787                Poll::Pending
788            }
789        } else {
790            Poll::Ready(())
791        }
792    }
793}
794
795/// When the client requests a handle to be closed or moved or otherwise
796/// destroyed, it goes into limbo for a bit while pending read and write actions
797/// are flushed. This is how we mark what should happen to the handle after that
798/// period ends.
799enum CloseAction {
800    Close { tid: NonZeroU32, count: AtomicU32, result: Result<()> },
801    Replace { tid: NonZeroU32, new_hid: proto::NewHandleId, rights: fidl::Rights },
802}
803
804impl CloseAction {
805    fn perform(&self, fdomain: &mut FDomain, handle: AnyHandle) {
806        match self {
807            CloseAction::Close { tid, count, result } => {
808                if count.fetch_sub(1, Ordering::Relaxed) == 1 {
809                    fdomain
810                        .event_queue
811                        .push_back(FDomainEvent::ClosedHandle(*tid, result.clone()).into());
812                }
813            }
814            CloseAction::Replace { tid, new_hid, rights } => {
815                let result = handle
816                    .replace(*rights)
817                    .and_then(|handle| fdomain.alloc_client_handles([*new_hid], [handle]));
818                fdomain.event_queue.push_back(FDomainEvent::ReplacedHandle(*tid, result).into());
819            }
820        }
821    }
822}
823
824enum Namespace {
825    Native(Box<dyn Fn() -> Result<ClientEnd<fio::DirectoryMarker>, fidl::Status> + Send>),
826    Channel(Box<dyn Fn(proto::HandleId) + Send>),
827}
828
829/// This is a container of handles that is manipulable via the FDomain protocol.
830/// See [RFC-0228].
831///
832/// Most of the methods simply handle FIDL requests from the FDomain protocol.
833#[pin_project::pin_project]
834pub struct FDomain {
835    namespace: Namespace,
836    handles: HashMap<proto::HandleId, HandleState>,
837    closing_handles: Vec<ClosingHandle>,
838    event_queue: VecDeque<UnprocessedFDomainEvent>,
839    waker: Waker,
840}
841
842impl FDomain {
843    /// Create a new FDomain. The new FDomain is empty and ready to be connected
844    /// to by a client.
845    pub fn new_empty() -> Self {
846        Self::new(|| Err(fidl::Status::NOT_FOUND))
847    }
848
849    /// Create a new FDomain populated with the given namespace entries.
850    pub fn new(
851        namespace: impl Fn() -> Result<ClientEnd<fio::DirectoryMarker>, fidl::Status> + Send + 'static,
852    ) -> Self {
853        FDomain {
854            namespace: Namespace::Native(Box::new(namespace)),
855            handles: HashMap::new(),
856            closing_handles: Vec::new(),
857            event_queue: VecDeque::new(),
858            waker: Waker::noop().clone(),
859        }
860    }
861
862    /// Create a new FDomain with a callback that receives a channel handle ID to serve.
863    pub fn new_with_namespace_channel(
864        namespace: impl Fn(proto::HandleId) + Send + 'static,
865    ) -> Self {
866        FDomain {
867            namespace: Namespace::Channel(Box::new(namespace)),
868            handles: HashMap::new(),
869            closing_handles: Vec::new(),
870            event_queue: VecDeque::new(),
871            waker: Waker::noop().clone(),
872        }
873    }
874
875    /// Add an event to be emitted by this FDomain.
876    fn push_event(&mut self, event: impl Into<UnprocessedFDomainEvent>) {
877        self.event_queue.push_back(event.into());
878        self.waker.wake_by_ref();
879    }
880
881    /// Given a [`fidl::MessageBufEtc`], load all of the handles from it into this
882    /// FDomain and return a [`ReadChannelPayload`](proto::ReadChannelPayload)
883    /// with the same data and the IDs for the handles.
884    fn process_message(
885        &mut self,
886        message: fidl::MessageBufEtc,
887    ) -> Result<proto::ChannelMessage, proto::Error> {
888        let (data, handles) = message.split();
889        let handles = handles
890            .into_iter()
891            .map(|info| {
892                let type_ = info.object_type;
893
894                let handle = match info.object_type {
895                    fidl::ObjectType::CHANNEL => {
896                        AnyHandle::Channel(fidl::Channel::from(info.handle))
897                    }
898                    fidl::ObjectType::SOCKET => AnyHandle::Socket(fidl::Socket::from(info.handle)),
899                    fidl::ObjectType::EVENTPAIR => {
900                        AnyHandle::EventPair(fidl::EventPair::from(info.handle))
901                    }
902                    fidl::ObjectType::EVENT => AnyHandle::Event(fidl::Event::from(info.handle)),
903                    fidl::ObjectType::VMO => AnyHandle::Vmo(fidl::Vmo::from(info.handle)),
904                    _ => AnyHandle::Unknown(handles::Unknown(info.handle, info.object_type)),
905                };
906
907                Ok(proto::HandleInfo {
908                    rights: info.rights,
909                    handle: self.alloc_fdomain_handle(handle)?,
910                    type_,
911                })
912            })
913            .collect::<Result<Vec<_>, proto::Error>>()?;
914
915        Ok(proto::ChannelMessage { data, handles })
916    }
917
918    /// Allocate `N` new handle IDs. These are allocated from
919    /// [`NewHandleId`](proto::NewHandleId) and are expected to follow the protocol
920    /// rules for client-allocated handle IDs.
921    ///
922    /// If any of the handles passed fail to allocate, none of the handles will
923    /// be allocated.
924    fn alloc_client_handles<const N: usize>(
925        &mut self,
926        ids: [proto::NewHandleId; N],
927        handles: [AnyHandle; N],
928    ) -> Result<(), proto::Error> {
929        for id in ids {
930            if id.id & (1 << 31) != 0 {
931                return Err(proto::Error::NewHandleIdOutOfRange(proto::NewHandleIdOutOfRange {
932                    id: id.id,
933                }));
934            }
935
936            if self.handles.contains_key(&proto::HandleId { id: id.id }) {
937                return Err(proto::Error::NewHandleIdReused(proto::NewHandleIdReused {
938                    id: id.id,
939                    same_call: false,
940                }));
941            }
942        }
943
944        let mut sorted_ids = ids;
945        sorted_ids.sort();
946
947        if let Some([a, _]) = sorted_ids.array_windows().find(|&[a, b]| a == b) {
948            Err(proto::Error::NewHandleIdReused(proto::NewHandleIdReused {
949                id: a.id,
950                same_call: true,
951            }))
952        } else {
953            let ids = ids.into_iter().map(|id| proto::HandleId { id: id.id });
954            let handles = ids
955                .zip(handles.into_iter())
956                .map(|(id, h)| HandleState::new(h, id).map(|x| (id, x)))
957                .collect::<Result<Vec<_>, proto::Error>>()?;
958
959            self.handles.extend(handles);
960
961            Ok(())
962        }
963    }
964
965    /// Allocate a new handle ID. These are allocated internally and are
966    /// expected to follow the protocol rules for FDomain-allocated handle IDs.
967    fn alloc_fdomain_handle(&mut self, handle: AnyHandle) -> Result<proto::HandleId, proto::Error> {
968        loop {
969            let id = proto::HandleId { id: rand::random::<u32>() | (1u32 << 31) };
970            if let Entry::Vacant(v) = self.handles.entry(id) {
971                v.insert(HandleState::new(handle, id)?);
972                break Ok(id);
973            }
974        }
975    }
976
977    /// If a handle exists in this FDomain, remove it.
978    fn take_handle(&mut self, handle: proto::HandleId) -> Result<HandleState, proto::Error> {
979        self.handles
980            .remove(&handle)
981            .ok_or(proto::Error::BadHandleId(proto::BadHandleId { id: handle.id }))
982    }
983
984    /// Use a handle in our handle table, if it exists.
985    fn using_handle<T>(
986        &mut self,
987        id: proto::HandleId,
988        f: impl FnOnce(&mut HandleState, &Waker) -> Result<T, proto::Error>,
989    ) -> Result<T, proto::Error> {
990        let waker = &self.waker;
991        if let Some(s) = self.handles.get_mut(&id) {
992            f(s, waker)
993        } else {
994            Err(proto::Error::BadHandleId(proto::BadHandleId { id: id.id }))
995        }
996    }
997
998    pub fn get_namespace(&mut self, request: proto::FDomainGetNamespaceRequest) -> Result<()> {
999        match &self.namespace {
1000            Namespace::Native(namespace) => {
1001                let endpoint = namespace();
1002                match endpoint {
1003                    Ok(endpoint) => self.alloc_client_handles(
1004                        [request.new_handle],
1005                        [AnyHandle::Channel(endpoint.into_channel())],
1006                    ),
1007                    Err(e) => Err(proto::Error::TargetError(e.into_raw())),
1008                }
1009            }
1010            Namespace::Channel(_) => {
1011                let (client_chan, server_chan) = fidl::Channel::create();
1012                self.alloc_client_handles([request.new_handle], [AnyHandle::Channel(client_chan)])?;
1013                let server_hid = self.alloc_fdomain_handle(AnyHandle::Channel(server_chan))?;
1014                if let Namespace::Channel(callback) = &self.namespace {
1015                    callback(server_hid);
1016                }
1017                Ok(())
1018            }
1019        }
1020    }
1021
1022    pub fn create_channel(&mut self, request: proto::ChannelCreateChannelRequest) -> Result<()> {
1023        let (a, b) = fidl::Channel::create();
1024        self.alloc_client_handles(request.handles, [AnyHandle::Channel(a), AnyHandle::Channel(b)])
1025    }
1026
1027    pub fn create_socket(&mut self, request: proto::SocketCreateSocketRequest) -> Result<()> {
1028        let (a, b) = match request.options {
1029            proto::SocketType::Stream => fidl::Socket::create_stream(),
1030            proto::SocketType::Datagram => fidl::Socket::create_datagram(),
1031            type_ => {
1032                return Err(proto::Error::SocketTypeUnknown(proto::SocketTypeUnknown { type_ }));
1033            }
1034        };
1035
1036        self.alloc_client_handles(request.handles, [AnyHandle::Socket(a), AnyHandle::Socket(b)])
1037    }
1038
1039    pub fn create_event_pair(
1040        &mut self,
1041        request: proto::EventPairCreateEventPairRequest,
1042    ) -> Result<()> {
1043        let (a, b) = fidl::EventPair::create();
1044        self.alloc_client_handles(
1045            request.handles,
1046            [AnyHandle::EventPair(a), AnyHandle::EventPair(b)],
1047        )
1048    }
1049
1050    pub fn create_event(&mut self, request: proto::EventCreateEventRequest) -> Result<()> {
1051        let a = fidl::Event::create();
1052        self.alloc_client_handles([request.handle], [AnyHandle::Event(a)])
1053    }
1054
1055    #[cfg(target_os = "fuchsia")]
1056    pub fn create_vmo(&mut self, request: proto::VmoCreateVmoRequest) -> Result<()> {
1057        let opts = zx::VmoOptions::from_bits_truncate(request.options.bits());
1058        let a = zx::Vmo::create_with_opts(opts, request.size)
1059            .map_err(|e| proto::Error::TargetError(e.into_raw()))?;
1060        self.alloc_client_handles([request.handle], [AnyHandle::Vmo(a.into())])
1061    }
1062
1063    #[cfg(not(target_os = "fuchsia"))]
1064    pub fn create_vmo(&mut self, _request: proto::VmoCreateVmoRequest) -> Result<()> {
1065        Err(proto::Error::TargetError(fidl::Status::NOT_SUPPORTED.into_raw()))
1066    }
1067
1068    pub fn read_vmo(
1069        &mut self,
1070        request: proto::VmoReadVmoRequest,
1071    ) -> Result<proto::VmoReadVmoResponse> {
1072        let handle = self
1073            .handles
1074            .get(&request.handle)
1075            .ok_or(proto::Error::BadHandleId(proto::BadHandleId { id: request.handle.id }))?;
1076        let data = handle.handle.read_vmo(request.offset, request.size)?;
1077        Ok(proto::VmoReadVmoResponse { data })
1078    }
1079
1080    pub fn write_vmo(&mut self, request: proto::VmoWriteVmoRequest) -> Result<()> {
1081        let handle = self
1082            .handles
1083            .get(&request.handle)
1084            .ok_or(proto::Error::BadHandleId(proto::BadHandleId { id: request.handle.id }))?;
1085        handle.handle.write_vmo(request.offset, &request.data)
1086    }
1087
1088    pub fn get_vmo_size(
1089        &mut self,
1090        request: proto::VmoGetVmoSizeRequest,
1091    ) -> Result<proto::VmoGetVmoSizeResponse> {
1092        let handle = self
1093            .handles
1094            .get(&request.handle)
1095            .ok_or(proto::Error::BadHandleId(proto::BadHandleId { id: request.handle.id }))?;
1096        let size = handle.handle.get_vmo_size()?;
1097        Ok(proto::VmoGetVmoSizeResponse { size })
1098    }
1099
1100    pub fn set_vmo_size(&mut self, request: proto::VmoSetVmoSizeRequest) -> Result<()> {
1101        let handle = self
1102            .handles
1103            .get(&request.handle)
1104            .ok_or(proto::Error::BadHandleId(proto::BadHandleId { id: request.handle.id }))?;
1105        handle.handle.set_vmo_size(request.size)
1106    }
1107
1108    pub fn get_vmo_stream_size(
1109        &mut self,
1110        request: proto::VmoGetVmoStreamSizeRequest,
1111    ) -> Result<proto::VmoGetVmoStreamSizeResponse> {
1112        let handle = self
1113            .handles
1114            .get(&request.handle)
1115            .ok_or(proto::Error::BadHandleId(proto::BadHandleId { id: request.handle.id }))?;
1116        let size = handle.handle.get_vmo_stream_size()?;
1117        Ok(proto::VmoGetVmoStreamSizeResponse { size })
1118    }
1119
1120    pub fn set_vmo_stream_size(
1121        &mut self,
1122        request: proto::VmoSetVmoStreamSizeRequest,
1123    ) -> Result<()> {
1124        let handle = self
1125            .handles
1126            .get(&request.handle)
1127            .ok_or(proto::Error::BadHandleId(proto::BadHandleId { id: request.handle.id }))?;
1128        handle.handle.set_vmo_stream_size(request.size)
1129    }
1130
1131    pub fn set_socket_disposition(
1132        &mut self,
1133        tid: NonZeroU32,
1134        request: proto::SocketSetSocketDispositionRequest,
1135    ) {
1136        if let Err(err) = self.using_handle(request.handle, |h, waker| {
1137            h.write_queue.push_back(
1138                WriteOp::SetDisposition(tid, request.disposition, request.disposition_peer),
1139                waker,
1140            );
1141            Ok(())
1142        }) {
1143            self.push_event(FDomainEvent::SocketDispositionSet(tid, Err(err)));
1144        }
1145    }
1146
1147    pub fn read_socket(&mut self, tid: NonZeroU32, request: proto::SocketReadSocketRequest) {
1148        if let Err(e) = self.using_handle(request.handle, |h, waker| {
1149            h.read_queue.push_back(ReadOp::Socket(tid, request.max_bytes), waker);
1150            Ok(())
1151        }) {
1152            self.push_event(FDomainEvent::SocketData(tid, Err(e)));
1153        }
1154    }
1155
1156    pub fn read_channel(&mut self, tid: NonZeroU32, request: proto::ChannelReadChannelRequest) {
1157        if let Err(e) = self.using_handle(request.handle, |h, waker| {
1158            h.read_queue.push_back(ReadOp::Channel(tid), waker);
1159            Ok(())
1160        }) {
1161            self.push_event(FDomainEvent::ChannelData(tid, Err(e)));
1162        }
1163    }
1164
1165    pub fn write_socket(&mut self, tid: NonZeroU32, request: proto::SocketWriteSocketRequest) {
1166        if let Err(error) = self.using_handle(request.handle, |h, waker| {
1167            h.write_queue.push_back(
1168                WriteOp::Socket(SocketWrite { tid, wrote: 0, to_write: request.data }),
1169                waker,
1170            );
1171            Ok(())
1172        }) {
1173            self.push_event(FDomainEvent::WroteSocket(
1174                tid,
1175                Err(proto::WriteSocketError { error, wrote: 0 }),
1176            ));
1177        }
1178    }
1179
1180    pub fn write_channel(&mut self, tid: NonZeroU32, request: proto::ChannelWriteChannelRequest) {
1181        // Go through the list of handles in the requests (which will either be
1182        // a simple list of handles or a list of HandleDispositions) and obtain
1183        // for each a `ShuttingDownHandle` which contains our handle state (the
1184        // "Shutting down" refers to the fact that we're pulling the handle out
1185        // of the FDomain in order to send it) and the rights the requester
1186        // would like the handle to have upon arrival at the other end of the
1187        // channel.
1188        let handles: Vec<Result<(ShuttingDownHandle, fidl::Rights)>> = match request.handles {
1189            proto::Handles::Handles(h) => h
1190                .into_iter()
1191                .map(|h| {
1192                    if h != request.handle {
1193                        self.take_handle(h).map(|handle_state| {
1194                            (ShuttingDownHandle::InUse(h, handle_state), fidl::Rights::SAME_RIGHTS)
1195                        })
1196                    } else {
1197                        Err(proto::Error::WroteToSelf(proto::WroteToSelf))
1198                    }
1199                })
1200                .collect(),
1201            proto::Handles::Dispositions(d) => d
1202                .into_iter()
1203                .map(|d| {
1204                    let res = match d.handle {
1205                        proto::HandleOp::Move_(h) => {
1206                            if h != request.handle {
1207                                self.take_handle(h).map(|x| ShuttingDownHandle::InUse(h, x))
1208                            } else {
1209                                Err(proto::Error::WroteToSelf(proto::WroteToSelf))
1210                            }
1211                        }
1212                        proto::HandleOp::Duplicate(h) => {
1213                            if h != request.handle {
1214                                // If the requester wants us to duplicate the
1215                                // handle, we do so now rather than letting
1216                                // `write_etc` do it. Otherwise we have to use a
1217                                // reference to the handle, and we get lifetime
1218                                // hell.
1219                                self.using_handle(h, |h, _| {
1220                                    h.handle.duplicate(fidl::Rights::SAME_RIGHTS)
1221                                })
1222                                .map(ShuttingDownHandle::Ready)
1223                            } else {
1224                                Err(proto::Error::WroteToSelf(proto::WroteToSelf))
1225                            }
1226                        }
1227                    };
1228
1229                    res.and_then(|x| Ok((x, d.rights)))
1230                })
1231                .collect(),
1232        };
1233
1234        if handles.iter().any(|x| x.is_err()) {
1235            let e = handles.into_iter().map(|x| x.err().map(Box::new)).collect();
1236
1237            self.push_event(FDomainEvent::WroteChannel(
1238                tid,
1239                Err(proto::WriteChannelError::OpErrors(e)),
1240            ));
1241            return;
1242        }
1243
1244        let handles = handles.into_iter().map(|x| x.unwrap()).collect::<Vec<_>>();
1245
1246        if let Err(e) = self.using_handle(request.handle, |h, waker| {
1247            h.write_queue.push_back(
1248                WriteOp::Channel(tid, request.data, HandlesToWrite::SomeInUse(handles)),
1249                waker,
1250            );
1251            Ok(())
1252        }) {
1253            self.push_event(FDomainEvent::WroteChannel(
1254                tid,
1255                Err(proto::WriteChannelError::Error(e)),
1256            ));
1257        }
1258    }
1259
1260    pub fn wait_for_signals(
1261        &mut self,
1262        tid: NonZeroU32,
1263        request: proto::FDomainWaitForSignalsRequest,
1264    ) {
1265        let result = self.using_handle(request.handle, |h, _| {
1266            let signals = fidl::Signals::from_bits_retain(request.signals);
1267            h.signal_waiters.push(SignalWaiter {
1268                tid,
1269                waiter: Box::pin(OnSignals::new(AnyHandleRef(Arc::clone(&h.handle)), signals)),
1270            });
1271            Ok(())
1272        });
1273
1274        if let Err(e) = result {
1275            self.push_event(FDomainEvent::WaitForSignals(tid, Err(e)));
1276        } else {
1277            self.waker.wake_by_ref();
1278        }
1279    }
1280
1281    pub fn close(&mut self, tid: NonZeroU32, request: proto::FDomainCloseRequest) {
1282        let mut states = Vec::with_capacity(request.handles.len());
1283        let mut result = Ok(());
1284        for hid in request.handles {
1285            match self.take_handle(hid) {
1286                Ok(state) => states.push((hid, state)),
1287
1288                Err(e) => {
1289                    result = result.and(Err(e));
1290                }
1291            }
1292        }
1293
1294        let action = Arc::new(CloseAction::Close {
1295            tid,
1296            count: AtomicU32::new(states.len().try_into().unwrap()),
1297            result: result.clone(),
1298        });
1299
1300        if states.is_empty() {
1301            self.push_event(FDomainEvent::ClosedHandle(tid, result));
1302        } else {
1303            for (hid, state) in states {
1304                self.closing_handles.push(ClosingHandle {
1305                    action: Arc::clone(&action),
1306                    state: Some(ShuttingDownHandle::InUse(hid, state)),
1307                });
1308            }
1309            self.waker.wake_by_ref();
1310        }
1311    }
1312
1313    pub fn duplicate(&mut self, request: proto::FDomainDuplicateRequest) -> Result<()> {
1314        let rights = request.rights;
1315        let handle = self.using_handle(request.handle, |h, _| h.handle.duplicate(rights));
1316        handle.and_then(|h| self.alloc_client_handles([request.new_handle], [h]))
1317    }
1318
1319    pub fn replace(
1320        &mut self,
1321        tid: NonZeroU32,
1322        request: proto::FDomainReplaceRequest,
1323    ) -> Result<()> {
1324        let rights = request.rights;
1325        let new_hid = request.new_handle;
1326        match self.take_handle(request.handle) {
1327            Ok(state) => {
1328                self.closing_handles.push(ClosingHandle {
1329                    action: Arc::new(CloseAction::Replace { tid, new_hid, rights }),
1330                    state: Some(ShuttingDownHandle::InUse(request.handle, state)),
1331                });
1332                self.waker.wake_by_ref();
1333            }
1334            Err(e) => self.push_event(FDomainEvent::ReplacedHandle(tid, Err(e))),
1335        }
1336
1337        Ok(())
1338    }
1339
1340    pub fn signal(&mut self, request: proto::FDomainSignalRequest) -> Result<()> {
1341        let set = fidl::Signals::from_bits_retain(request.set);
1342        let clear = fidl::Signals::from_bits_retain(request.clear);
1343
1344        self.using_handle(request.handle, |h, _| h.handle.signal(clear, set))
1345    }
1346
1347    pub fn signal_peer(&mut self, request: proto::FDomainSignalPeerRequest) -> Result<()> {
1348        let set = fidl::Signals::from_bits_retain(request.set);
1349        let clear = fidl::Signals::from_bits_retain(request.clear);
1350
1351        self.using_handle(request.handle, |h, _| h.handle.signal_peer(clear, set))
1352    }
1353
1354    pub fn get_koid(
1355        &mut self,
1356        request: proto::FDomainGetKoidRequest,
1357    ) -> Result<proto::FDomainGetKoidResponse> {
1358        self.using_handle(request.handle, |h, _| {
1359            h.handle
1360                .as_handle_ref()
1361                .koid()
1362                .map(|k| proto::FDomainGetKoidResponse { koid: k.raw_koid() })
1363                .map_err(|e| proto::Error::TargetError(e.into_raw()))
1364        })
1365    }
1366
1367    pub fn read_channel_streaming_start(
1368        &mut self,
1369        tid: NonZeroU32,
1370        request: proto::ChannelReadChannelStreamingStartRequest,
1371    ) {
1372        if let Err(err) = self.using_handle(request.handle, |h, waker| {
1373            h.handle.expected_type(fidl::ObjectType::CHANNEL)?;
1374            h.read_queue.push_back(ReadOp::StreamingChannel(tid, true), waker);
1375            Ok(())
1376        }) {
1377            self.push_event(FDomainEvent::ChannelStreamingReadStart(tid, Err(err)));
1378        }
1379    }
1380
1381    pub fn read_channel_streaming_stop(
1382        &mut self,
1383        tid: NonZeroU32,
1384        request: proto::ChannelReadChannelStreamingStopRequest,
1385    ) {
1386        if let Err(err) = self.using_handle(request.handle, |h, waker| {
1387            h.handle.expected_type(fidl::ObjectType::CHANNEL)?;
1388            h.read_queue.push_back(ReadOp::StreamingChannel(tid, false), waker);
1389            Ok(())
1390        }) {
1391            self.push_event(FDomainEvent::ChannelStreamingReadStop(tid, Err(err)));
1392        }
1393    }
1394
1395    pub fn read_socket_streaming_start(
1396        &mut self,
1397        tid: NonZeroU32,
1398        request: proto::SocketReadSocketStreamingStartRequest,
1399    ) {
1400        if let Err(err) = self.using_handle(request.handle, |h, waker| {
1401            h.handle.expected_type(fidl::ObjectType::SOCKET)?;
1402            h.read_queue.push_back(ReadOp::StreamingSocket(tid, true), waker);
1403            Ok(())
1404        }) {
1405            self.push_event(FDomainEvent::SocketStreamingReadStart(tid, Err(err)));
1406        }
1407    }
1408
1409    pub fn read_socket_streaming_stop(
1410        &mut self,
1411        tid: NonZeroU32,
1412        request: proto::SocketReadSocketStreamingStopRequest,
1413    ) {
1414        if let Err(err) = self.using_handle(request.handle, |h, waker| {
1415            h.handle.expected_type(fidl::ObjectType::SOCKET)?;
1416            h.read_queue.push_back(ReadOp::StreamingSocket(tid, false), waker);
1417            Ok(())
1418        }) {
1419            self.push_event(FDomainEvent::SocketStreamingReadStop(tid, Err(err)));
1420        }
1421    }
1422}
1423
1424/// [`FDomain`] implements a stream of events, for protocol events and for
1425/// replies to long-running methods.
1426impl futures::Stream for FDomain {
1427    type Item = FDomainEvent;
1428
1429    fn poll_next(
1430        mut self: std::pin::Pin<&mut Self>,
1431        ctx: &mut Context<'_>,
1432    ) -> Poll<Option<Self::Item>> {
1433        let this = &mut *self;
1434
1435        let mut closing_handles = std::mem::replace(&mut this.closing_handles, Vec::new());
1436        closing_handles.retain_mut(|x| x.poll_ready(this, ctx).is_pending());
1437        this.closing_handles = closing_handles;
1438
1439        let handles = &mut this.handles;
1440        let event_queue = &mut this.event_queue;
1441        for state in handles.values_mut() {
1442            state.poll(event_queue, ctx);
1443        }
1444
1445        if let Some(event) = self.event_queue.pop_front() {
1446            match event {
1447                UnprocessedFDomainEvent::Ready(event) => Poll::Ready(Some(event)),
1448                UnprocessedFDomainEvent::ChannelData(tid, message) => {
1449                    Poll::Ready(Some(FDomainEvent::ChannelData(tid, self.process_message(message))))
1450                }
1451                UnprocessedFDomainEvent::ChannelStreamingData(hid, message) => {
1452                    match self.process_message(message) {
1453                        Ok(message) => Poll::Ready(Some(FDomainEvent::ChannelStreamingData(
1454                            proto::ChannelOnChannelStreamingDataRequest {
1455                                handle: hid,
1456                                channel_sent: proto::ChannelSent::Message(message),
1457                            },
1458                        ))),
1459                        Err(e) => {
1460                            self.handles.get_mut(&hid).unwrap().async_read_in_progress = false;
1461                            Poll::Ready(Some(FDomainEvent::ChannelStreamingData(
1462                                proto::ChannelOnChannelStreamingDataRequest {
1463                                    handle: hid,
1464                                    channel_sent: proto::ChannelSent::Stopped(proto::AioStopped {
1465                                        error: Some(Box::new(e)),
1466                                    }),
1467                                },
1468                            )))
1469                        }
1470                    }
1471                }
1472            }
1473        } else {
1474            self.waker = ctx.waker().clone();
1475            Poll::Pending
1476        }
1477    }
1478}