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