Skip to main content

fdomain_client/
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_fuchsia_fdomain as proto;
6use fidl_message::TransactionHeader;
7use fuchsia_sync::Mutex;
8use futures::FutureExt;
9use futures::channel::oneshot::Sender as OneshotSender;
10use futures::stream::Stream as StreamTrait;
11use std::collections::{HashMap, HashSet, VecDeque};
12use std::convert::Infallible;
13use std::future::Future;
14use std::num::NonZeroU32;
15use std::pin::Pin;
16use std::sync::{Arc, LazyLock, Weak};
17use std::task::{Context, Poll, Waker, ready};
18
19mod channel;
20mod event;
21mod event_pair;
22mod handle;
23mod responder;
24mod socket;
25mod vmo;
26
27#[cfg(test)]
28mod test;
29
30pub mod fidl;
31pub mod fidl_next;
32
33use responder::Responder;
34
35pub use channel::{
36    AnyHandle, Channel, ChannelMessageStream, ChannelWriter, HandleInfo, HandleOp, MessageBuf,
37};
38pub use event::Event;
39pub use event_pair::Eventpair as EventPair;
40pub use handle::unowned::Unowned;
41pub use handle::{
42    AsHandleRef, Handle, HandleBased, HandleRef, NullableHandle, OnFDomainSignals, Peered,
43};
44pub use proto::{Error as FDomainError, VmoOptions, WriteChannelError, WriteSocketError};
45pub use socket::{Socket, SocketDisposition, SocketReadStream, SocketWriter};
46pub use vmo::Vmo;
47
48// Unsupported handle types.
49#[rustfmt::skip]
50pub use Handle as Clock;
51#[rustfmt::skip]
52pub use Handle as Exception;
53#[rustfmt::skip]
54pub use Handle as Fifo;
55#[rustfmt::skip]
56pub use Handle as Iob;
57#[rustfmt::skip]
58pub use Handle as Job;
59#[rustfmt::skip]
60pub use Handle as Process;
61#[rustfmt::skip]
62pub use Handle as Resource;
63#[rustfmt::skip]
64pub use Handle as Stream;
65#[rustfmt::skip]
66pub use Handle as Thread;
67#[rustfmt::skip]
68pub use Handle as Vmar;
69#[rustfmt::skip]
70pub use Handle as Counter;
71#[rustfmt::skip]
72pub use Handle as Port;
73
74use proto::f_domain_ordinals as ordinals;
75
76fn write_fdomain_error(error: &FDomainError, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77    match error {
78        FDomainError::TargetError(e) => {
79            let e = zx_status::Status::err_from_raw(*e);
80            write!(f, "Target-side error {e}")
81        }
82        FDomainError::BadHandleId(proto::BadHandleId { id }) => {
83            write!(f, "Tried to use invalid handle id {id}")
84        }
85        FDomainError::WrongHandleType(proto::WrongHandleType { expected, got }) => write!(
86            f,
87            "Tried to use handle as {expected:?} but target reported handle was of type {got:?}"
88        ),
89        FDomainError::StreamingReadInProgress(proto::StreamingReadInProgress {}) => {
90            write!(f, "Handle is occupied delivering streaming reads")
91        }
92        FDomainError::NoReadInProgress(proto::NoReadInProgress {}) => {
93            write!(f, "No streaming read was in progress")
94        }
95        FDomainError::NewHandleIdOutOfRange(proto::NewHandleIdOutOfRange { id }) => {
96            write!(
97                f,
98                "Tried to create a handle with id {id}, which is outside the valid range for client handles"
99            )
100        }
101        FDomainError::NewHandleIdReused(proto::NewHandleIdReused { id, same_call }) => {
102            if *same_call {
103                write!(f, "Tried to create two or more new handles with the same id {id}")
104            } else {
105                write!(
106                    f,
107                    "Tried to create a new handle with id {id}, which is already the id of an existing handle"
108                )
109            }
110        }
111        FDomainError::WroteToSelf(proto::WroteToSelf {}) => {
112            write!(f, "Tried to write a channel into itself")
113        }
114        FDomainError::ClosedDuringRead(proto::ClosedDuringRead {}) => {
115            write!(f, "Handle closed while being read")
116        }
117        FDomainError::SignalsUnknown(signals_unknown) => {
118            write!(f, "Unknown signals: {:x}", signals_unknown.signals)
119        }
120        FDomainError::RightsUnknown(rights_unknown) => {
121            write!(f, "Unknown rights: {:x}", rights_unknown.rights)
122        }
123        FDomainError::SocketDispositionUnknown(socket_disposition_unknown) => {
124            write!(f, "Unknown socket disposition: {:?}", socket_disposition_unknown.disposition)
125        }
126        FDomainError::SocketTypeUnknown(socket_type_unknown) => {
127            write!(f, "Unknown socket type: {:?}", socket_type_unknown.type_)
128        }
129        e => write!(f, "Unknown FDomain error: {e:?}"),
130    }
131}
132
133/// Result type alias.
134pub type Result<T, E = Error> = std::result::Result<T, E>;
135
136/// Error type emitted by FDomain operations.
137#[derive(Clone)]
138pub enum Error {
139    SocketWrite(WriteSocketError),
140    ChannelWrite(WriteChannelError),
141    FDomain(FDomainError),
142    Protocol(::fidl::Error),
143    ProtocolObjectTypeIncompatible,
144    ProtocolRightsIncompatible,
145    ProtocolSignalsIncompatible,
146    ProtocolStreamEventIncompatible,
147    Transport(Option<Arc<std::io::Error>>),
148    ConnectionMismatch,
149    StreamingAborted,
150}
151
152impl std::fmt::Display for Error {
153    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
154        match self {
155            Self::SocketWrite(proto::WriteSocketError { error, wrote }) => {
156                write!(f, "While writing socket (after {wrote} bytes written successfully): ")?;
157                write_fdomain_error(error, f)
158            }
159            Self::ChannelWrite(proto::WriteChannelError::Error(error)) => {
160                write!(f, "While writing channel: ")?;
161                write_fdomain_error(error, f)
162            }
163            Self::ChannelWrite(proto::WriteChannelError::OpErrors(errors)) => {
164                write!(f, "Couldn't write all handles into a channel:")?;
165                for (pos, error) in
166                    errors.iter().enumerate().filter_map(|(num, x)| x.as_ref().map(|y| (num, &**y)))
167                {
168                    write!(f, "\n  Handle in position {pos}: ")?;
169                    write_fdomain_error(error, f)?;
170                }
171                Ok(())
172            }
173            Self::ProtocolObjectTypeIncompatible => {
174                write!(
175                    f,
176                    "The FDomain protocol received an unrecognized or incompatible object type"
177                )
178            }
179            Self::ProtocolRightsIncompatible => {
180                write!(
181                    f,
182                    "The FDomain protocol received unrecognized or incompatible handle rights"
183                )
184            }
185            Self::ProtocolSignalsIncompatible => {
186                write!(f, "The FDomain protocol received unrecognized or incompatible signals")
187            }
188            Self::ProtocolStreamEventIncompatible => {
189                write!(
190                    f,
191                    "The FDomain protocol received an unrecognized or incompatible streaming IO event"
192                )
193            }
194            Self::FDomain(e) => write_fdomain_error(e, f),
195            Self::Protocol(e) => write!(f, "Protocol error: {e}"),
196            Self::Transport(Some(e)) => write!(f, "Transport error: {e}"),
197            Self::Transport(None) => {
198                write!(f, "Transport error: Connection to the device has been lost")
199            }
200            Self::ConnectionMismatch => {
201                write!(
202                    f,
203                    "Tried to use an FDomain handle with a different connection than the one it was created on"
204                )
205            }
206            Self::StreamingAborted => write!(f, "Streaming on this channel has been aborted"),
207        }
208    }
209}
210
211impl std::fmt::Debug for Error {
212    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
213        match self {
214            Self::SocketWrite(e) => f.debug_tuple("SocketWrite").field(e).finish(),
215            Self::ChannelWrite(e) => f.debug_tuple("ChannelWrite").field(e).finish(),
216            Self::FDomain(e) => f.debug_tuple("FDomain").field(e).finish(),
217            Self::Protocol(e) => f.debug_tuple("Protocol").field(e).finish(),
218            Self::Transport(e) => f.debug_tuple("Transport").field(e).finish(),
219            Self::ProtocolObjectTypeIncompatible => write!(f, "ProtocolObjectTypeIncompatible "),
220            Self::ProtocolRightsIncompatible => write!(f, "ProtocolRightsIncompatible "),
221            Self::ProtocolSignalsIncompatible => write!(f, "ProtocolSignalsIncompatible "),
222            Self::ProtocolStreamEventIncompatible => write!(f, "ProtocolStreamEventIncompatible"),
223            Self::ConnectionMismatch => write!(f, "ConnectionMismatch"),
224            Self::StreamingAborted => write!(f, "StreamingAborted"),
225        }
226    }
227}
228
229impl std::error::Error for Error {}
230
231impl From<FDomainError> for Error {
232    fn from(other: FDomainError) -> Self {
233        Self::FDomain(other)
234    }
235}
236
237impl From<::fidl::Error> for Error {
238    fn from(other: ::fidl::Error) -> Self {
239        Self::Protocol(other)
240    }
241}
242
243impl From<WriteSocketError> for Error {
244    fn from(other: WriteSocketError) -> Self {
245        Self::SocketWrite(other)
246    }
247}
248
249impl From<WriteChannelError> for Error {
250    fn from(other: WriteChannelError) -> Self {
251        Self::ChannelWrite(other)
252    }
253}
254
255/// An error emitted internally by the client. Similar to [`Error`] but does not
256/// contain several variants which are irrelevant in the contexts where it is
257/// used.
258#[derive(Clone)]
259enum InnerError {
260    Protocol(::fidl::Error),
261    ProtocolStreamEventIncompatible,
262    Transport(Option<Arc<std::io::Error>>),
263}
264
265impl From<InnerError> for Error {
266    fn from(other: InnerError) -> Self {
267        match other {
268            InnerError::Protocol(p) => Error::Protocol(p),
269            InnerError::ProtocolStreamEventIncompatible => Error::ProtocolStreamEventIncompatible,
270            InnerError::Transport(t) => Error::Transport(t),
271        }
272    }
273}
274
275impl From<::fidl::Error> for InnerError {
276    fn from(other: ::fidl::Error) -> Self {
277        InnerError::Protocol(other)
278    }
279}
280
281// TODO(399717689) Figure out if we could just use AsyncRead/Write instead of a special trait.
282/// Implemented by objects which provide a transport over which we can speak the
283/// FDomain protocol.
284///
285/// The implementer must provide two things:
286/// 1) An incoming stream of messages presented as `Vec<u8>`. This is provided
287///    via the `Stream` trait, which this trait requires.
288/// 2) A way to send messages. This is provided by implementing the
289///    `poll_send_message` method.
290pub trait FDomainTransport: StreamTrait<Item = Result<Box<[u8]>, std::io::Error>> + Send {
291    /// Attempt to send a message asynchronously. Messages should be sent so
292    /// that they arrive at the target in order.
293    fn poll_send_message(
294        self: Pin<&mut Self>,
295        msg: &[u8],
296        ctx: &mut Context<'_>,
297    ) -> Poll<Result<(), Option<std::io::Error>>>;
298
299    /// Optional debug information outlet.
300    fn debug_fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
301        Ok(())
302    }
303
304    /// Whether `debug_fmt` does anything.
305    fn has_debug_fmt(&self) -> bool {
306        false
307    }
308}
309
310/// Wrapper for an `FDomainTransport` implementer that:
311/// 1) Provides a queue for outgoing messages so we need not have an await point
312///    when we submit a message.
313/// 2) Drops the transport on error, then returns the last observed error for
314///    all future operations.
315enum Transport {
316    Transport(Pin<Box<dyn FDomainTransport>>, VecDeque<Box<[u8]>>, Vec<Waker>),
317    Error(InnerError),
318}
319
320impl Transport {
321    /// Get the failure mode of the transport if it has failed.
322    fn error(&self) -> Option<InnerError> {
323        match self {
324            Transport::Transport(_, _, _) => None,
325            Transport::Error(inner_error) => Some(inner_error.clone()),
326        }
327    }
328
329    /// Enqueue a message to be sent on this transport.
330    fn push_msg(&mut self, msg: Box<[u8]>) -> Result<(), InnerError> {
331        match self {
332            Transport::Transport(_, v, w) => {
333                v.push_back(msg);
334                w.drain(..).for_each(Waker::wake);
335                Ok(())
336            }
337            Transport::Error(e) => Err(e.clone()),
338        }
339    }
340
341    /// Push messages in the send queue out through the transport.
342    fn poll_send_messages(&mut self, ctx: &mut Context<'_>) -> Poll<InnerError> {
343        match self {
344            Transport::Error(e) => Poll::Ready(e.clone()),
345            Transport::Transport(t, v, w) => {
346                while let Some(msg) = v.front() {
347                    match t.as_mut().poll_send_message(msg, ctx) {
348                        Poll::Ready(Ok(())) => {
349                            v.pop_front();
350                        }
351                        Poll::Ready(Err(e)) => {
352                            let e = e.map(Arc::new);
353                            return Poll::Ready(InnerError::Transport(e));
354                        }
355                        Poll::Pending => return Poll::Pending,
356                    }
357                }
358
359                if v.is_empty() {
360                    w.push(ctx.waker().clone());
361                } else {
362                    ctx.waker().wake_by_ref();
363                }
364                Poll::Pending
365            }
366        }
367    }
368
369    /// Get the next incoming message from the transport.
370    fn poll_next(&mut self, ctx: &mut Context<'_>) -> Poll<Result<Box<[u8]>, InnerError>> {
371        match self {
372            Transport::Error(e) => Poll::Ready(Err(e.clone())),
373            Transport::Transport(t, _, _) => match ready!(t.as_mut().poll_next(ctx)) {
374                Some(Ok(x)) => Poll::Ready(Ok(x)),
375                Some(Err(e)) => Poll::Ready(Err(InnerError::Transport(Some(Arc::new(e))))),
376                Option::None => Poll::Ready(Err(InnerError::Transport(None))),
377            },
378        }
379    }
380}
381
382impl Drop for Transport {
383    fn drop(&mut self) {
384        if let Transport::Transport(_, _, wakers) = self {
385            wakers.drain(..).for_each(Waker::wake);
386        }
387    }
388}
389
390/// State of a socket that is or has been read from.
391struct SocketReadState {
392    wakers: Vec<Waker>,
393    queued: VecDeque<Result<SocketReadChunk, Error>>,
394    read_request_pending: bool,
395    is_streaming: bool,
396}
397
398#[derive(Debug)]
399struct SocketReadChunk {
400    data: proto::SocketData,
401    offset: usize,
402}
403
404impl SocketReadChunk {
405    fn new(data: proto::SocketData) -> Self {
406        Self { data, offset: 0 }
407    }
408}
409
410impl SocketReadState {
411    /// Handle an incoming message, which is either a channel streaming event or
412    /// response to a `ChannelRead` request.
413    fn handle_incoming_message(&mut self, msg: Result<proto::SocketData, Error>) -> Vec<Waker> {
414        self.queued.push_back(msg.map(SocketReadChunk::new));
415        std::mem::replace(&mut self.wakers, Vec::new())
416    }
417}
418
419/// State of a channel that is or has been read from.
420struct ChannelReadState {
421    wakers: Vec<Waker>,
422    queued: VecDeque<Result<proto::ChannelMessage, Error>>,
423    read_request_pending: bool,
424    is_streaming: bool,
425}
426
427impl ChannelReadState {
428    /// Handle an incoming message, which is either a channel streaming event or
429    /// response to a `ChannelRead` request.
430    fn handle_incoming_message(&mut self, msg: Result<proto::ChannelMessage, Error>) -> Vec<Waker> {
431        self.queued.push_back(msg);
432        std::mem::replace(&mut self.wakers, Vec::new())
433    }
434}
435
436/// Lock-protected interior of `Client`
437struct ClientInner {
438    transport: Transport,
439    transactions: HashMap<NonZeroU32, responder::Responder>,
440    channel_read_states: HashMap<proto::HandleId, ChannelReadState>,
441    socket_read_states: HashMap<proto::HandleId, SocketReadState>,
442    handles: HashSet<proto::HandleId>,
443    next_tx_id: u32,
444    waiting_to_close: Vec<proto::HandleId>,
445    waiting_to_close_waker: Waker,
446
447    /// There is a lock around `ClientInner`, and sometimes the FIDL bindings
448    /// give us wakers that want to do handle operations synchronously on wake,
449    /// which means we can double-take the lock if we wake a waker while we hold
450    /// it. This is a place to store wakers that we'd like to be woken as soon
451    /// as we're not holding that lock, to avoid these weird reentrancy issues.
452    wakers_to_wake: Vec<Waker>,
453}
454
455impl ClientInner {
456    /// Allocate a new HID, which should be suitable for use with the connected FDomain.
457    fn new_hid(&mut self) -> proto::NewHandleId {
458        self.process_waiting_to_close();
459        loop {
460            let id = rand::random::<u32>() >> 1;
461            let hid = proto::HandleId { id };
462            if id != 0 && self.handles.insert(hid) {
463                return proto::NewHandleId { id };
464            }
465        }
466    }
467
468    /// Serialize and enqueue a new transaction, including header and transaction ID.
469    fn request<S: fidl_message::Body>(&mut self, ordinal: u64, request: S, responder: Responder) {
470        if ordinal != ordinals::CLOSE {
471            self.process_waiting_to_close();
472        }
473        let tx_id = self.next_tx_id;
474
475        let header = TransactionHeader::new(tx_id, ordinal, fidl_message::DynamicFlags::FLEXIBLE);
476        let msg = fidl_message::encode_message(header, request).expect("Could not encode request!");
477        self.next_tx_id += 1;
478        if let Err(e) = self.transport.push_msg(msg.into()) {
479            let _ = responder.handle(self, Err(e.into()));
480        } else {
481            assert!(
482                self.transactions.insert(tx_id.try_into().unwrap(), responder).is_none(),
483                "Allocated same tx id twice!"
484            );
485        }
486    }
487
488    fn process_waiting_to_close(&mut self) {
489        if !self.waiting_to_close.is_empty() {
490            let handles = std::mem::replace(&mut self.waiting_to_close, Vec::new());
491            // We've dropped the handle object. Nobody is going to wait to read
492            // the buffers anymore. This is a safe time to drop the read state.
493            for handle in &handles {
494                let _ = self.channel_read_states.remove(handle);
495                let _ = self.socket_read_states.remove(handle);
496                self.handles.remove(handle);
497            }
498            self.request(
499                ordinals::CLOSE,
500                proto::FDomainCloseRequest { handles },
501                Responder::Ignore,
502            );
503        }
504    }
505
506    /// Polls the underlying transport to ensure any incoming or outgoing
507    /// messages are processed as far as possible. Errors if the transport has failed.
508    fn try_poll_transport(
509        &mut self,
510        ctx: &mut Context<'_>,
511    ) -> Poll<Result<Infallible, InnerError>> {
512        self.process_waiting_to_close();
513
514        self.waiting_to_close_waker = ctx.waker().clone();
515
516        loop {
517            if let Poll::Ready(e) = self.transport.poll_send_messages(ctx) {
518                return Poll::Ready(Err(e));
519            }
520            let Poll::Ready(result) = self.transport.poll_next(ctx) else {
521                return Poll::Pending;
522            };
523            let data = result?;
524            let (header, data) = fidl_message::decode_transaction_header(&data)?;
525
526            let Some(tx_id) = NonZeroU32::new(header.tx_id) else {
527                let wakers = self.process_event(header, data)?;
528                self.wakers_to_wake.extend(wakers);
529                continue;
530            };
531
532            let tx = self.transactions.remove(&tx_id).ok_or(::fidl::Error::InvalidResponseTxid)?;
533            tx.handle(self, Ok((header, data)))?;
534        }
535    }
536
537    /// Process an incoming message that arose from an event rather than a transaction reply.
538    fn process_event(
539        &mut self,
540        header: TransactionHeader,
541        data: &[u8],
542    ) -> Result<Vec<Waker>, InnerError> {
543        match header.ordinal {
544            ordinals::ON_SOCKET_STREAMING_DATA => {
545                let msg = fidl_message::decode_message::<proto::SocketOnSocketStreamingDataRequest>(
546                    header, data,
547                )?;
548                let o =
549                    self.socket_read_states.entry(msg.handle).or_insert_with(|| SocketReadState {
550                        wakers: Vec::new(),
551                        queued: VecDeque::new(),
552                        is_streaming: false,
553                        read_request_pending: false,
554                    });
555                match msg.socket_message {
556                    proto::SocketMessage::Data(data) => Ok(o.handle_incoming_message(Ok(data))),
557                    proto::SocketMessage::Stopped(proto::AioStopped { error }) => {
558                        let ret = if let Some(error) = error {
559                            o.handle_incoming_message(Err(Error::FDomain(*error)))
560                        } else {
561                            Vec::new()
562                        };
563                        o.is_streaming = false;
564                        Ok(ret)
565                    }
566                    _ => Err(InnerError::ProtocolStreamEventIncompatible),
567                }
568            }
569            ordinals::ON_CHANNEL_STREAMING_DATA => {
570                let msg = fidl_message::decode_message::<
571                    proto::ChannelOnChannelStreamingDataRequest,
572                >(header, data)?;
573                let o = self.channel_read_states.entry(msg.handle).or_insert_with(|| {
574                    ChannelReadState {
575                        wakers: Vec::new(),
576                        queued: VecDeque::new(),
577                        is_streaming: false,
578                        read_request_pending: false,
579                    }
580                });
581                match msg.channel_sent {
582                    proto::ChannelSent::Message(data) => Ok(o.handle_incoming_message(Ok(data))),
583                    proto::ChannelSent::Stopped(proto::AioStopped { error }) => {
584                        let ret = if let Some(error) = error {
585                            o.handle_incoming_message(Err(Error::FDomain(*error)))
586                        } else {
587                            Vec::new()
588                        };
589                        o.is_streaming = false;
590                        Ok(ret)
591                    }
592                    _ => Err(InnerError::ProtocolStreamEventIncompatible),
593                }
594            }
595            _ => Err(::fidl::Error::UnknownOrdinal {
596                ordinal: header.ordinal,
597                protocol_name:
598                    <proto::FDomainMarker as ::fidl::endpoints::ProtocolMarker>::DEBUG_NAME,
599            }
600            .into()),
601        }
602    }
603
604    /// Polls the underlying transport to ensure any incoming or outgoing
605    /// messages are processed as far as possible. If a failure occurs, puts the
606    /// transport into an error state and fails all pending transactions.
607    fn poll_transport(&mut self, ctx: &mut Context<'_>) -> Poll<()> {
608        if let Poll::Ready(Err(e)) = self.try_poll_transport(ctx) {
609            for (_, v) in std::mem::take(&mut self.transactions) {
610                let _ = v.handle(self, Err(e.clone()));
611            }
612            for mut state in std::mem::take(&mut self.socket_read_states).into_values() {
613                state.queued.push_back(Err(Error::from(e.clone())));
614                self.wakers_to_wake.extend(state.wakers);
615            }
616            for (_, mut state) in self.channel_read_states.drain() {
617                state.queued.push_back(Err(Error::from(e.clone())));
618                self.wakers_to_wake.extend(state.wakers);
619            }
620            if matches!(self.transport, Transport::Transport(_, _, _)) {
621                self.transport = Transport::Error(e);
622            }
623
624            Poll::Ready(())
625        } else {
626            Poll::Pending
627        }
628    }
629
630    /// Handles the response to a `SocketRead` protocol message.
631    pub(crate) fn handle_socket_read_response(
632        &mut self,
633        msg: Result<proto::SocketData, Error>,
634        id: proto::HandleId,
635    ) {
636        let state = self.socket_read_states.entry(id).or_insert_with(|| SocketReadState {
637            wakers: Vec::new(),
638            queued: VecDeque::new(),
639            is_streaming: false,
640            read_request_pending: false,
641        });
642        let wakers = state.handle_incoming_message(msg);
643        self.wakers_to_wake.extend(wakers);
644        state.read_request_pending = false;
645    }
646
647    /// Handles the response to a `ChannelRead` protocol message.
648    pub(crate) fn handle_channel_read_response(
649        &mut self,
650        msg: Result<proto::ChannelMessage, Error>,
651        id: proto::HandleId,
652    ) {
653        let state = self.channel_read_states.entry(id).or_insert_with(|| ChannelReadState {
654            wakers: Vec::new(),
655            queued: VecDeque::new(),
656            is_streaming: false,
657            read_request_pending: false,
658        });
659        let wakers = state.handle_incoming_message(msg);
660        self.wakers_to_wake.extend(wakers);
661        state.read_request_pending = false;
662    }
663}
664
665impl Drop for ClientInner {
666    fn drop(&mut self) {
667        let responders = self.transactions.drain().map(|x| x.1).collect::<Vec<_>>();
668        for responder in responders {
669            let _ = responder.handle(self, Err(InnerError::Transport(None)));
670        }
671        for state in self.channel_read_states.values_mut() {
672            state.wakers.drain(..).for_each(Waker::wake);
673        }
674        for state in self.socket_read_states.values_mut() {
675            state.wakers.drain(..).for_each(Waker::wake);
676        }
677        self.waiting_to_close_waker.wake_by_ref();
678        self.wakers_to_wake.drain(..).for_each(Waker::wake);
679    }
680}
681
682/// Represents a connection to an FDomain.
683///
684/// The client is constructed by passing it a transport object which represents
685/// the raw connection to the remote FDomain. The `Client` wrapper then allows
686/// us to construct and use handles which behave similarly to their counterparts
687/// on a Fuchsia device.
688pub struct Client(pub(crate) Mutex<ClientInner>);
689
690impl std::fmt::Debug for Client {
691    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
692        let inner = self.0.lock();
693        match &inner.transport {
694            Transport::Transport(transport, ..) if transport.has_debug_fmt() => {
695                write!(f, "Client(")?;
696                transport.debug_fmt(f)?;
697                write!(f, ")")
698            }
699            Transport::Error(error) => {
700                let error = Error::from(error.clone());
701                write!(f, "Client(Failed: {error})")
702            }
703            _ => f.debug_tuple("Client").field(&"<transport>").finish(),
704        }
705    }
706}
707
708/// A client which is always disconnected. Handles that lose their clients
709/// connect to this client instead, which always returns a "Client Lost"
710/// transport failure.
711pub(crate) static DEAD_CLIENT: LazyLock<Arc<Client>> = LazyLock::new(|| {
712    Arc::new(Client(Mutex::new(ClientInner {
713        transport: Transport::Error(InnerError::Transport(None)),
714        transactions: HashMap::new(),
715        channel_read_states: HashMap::new(),
716        socket_read_states: HashMap::new(),
717        handles: HashSet::new(),
718        next_tx_id: 1,
719        waiting_to_close: Vec::new(),
720        waiting_to_close_waker: std::task::Waker::noop().clone(),
721        wakers_to_wake: Vec::new(),
722    })))
723});
724
725/// A wrapper around the FDomain client background future that ensures
726/// all pending transactions and reads are failed if the loop is dropped.
727///
728/// This prevents hangs when the transport is abruptly closed (e.g. during target reboot)
729/// by waking up any futures waiting for responses or data on channels/sockets.
730pub struct ClientLoop {
731    client: Weak<Client>,
732    fut: Pin<Box<dyn Future<Output = ()> + Send + 'static>>,
733}
734
735impl Future for ClientLoop {
736    type Output = ();
737    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
738        self.fut.as_mut().poll(cx)
739    }
740}
741
742impl Drop for ClientLoop {
743    fn drop(&mut self) {
744        let Some(client) = self.client.upgrade() else {
745            return;
746        };
747
748        let (channel_read_states, socket_read_states, deferred_wakers) = {
749            let mut inner = client.0.lock();
750            if matches!(inner.transport, Transport::Transport(_, _, _)) {
751                inner.transport = Transport::Error(InnerError::Transport(None));
752            }
753
754            let transactions = std::mem::take(&mut inner.transactions);
755            log::debug!("ClientLoop dropped, failing {} transactions", transactions.len());
756            for (_, v) in transactions {
757                let _ = v.handle(&mut *inner, Err(InnerError::Transport(None)));
758            }
759
760            let channel_read_states = std::mem::take(&mut inner.channel_read_states);
761            let socket_read_states = std::mem::take(&mut inner.socket_read_states);
762
763            let deferred_wakers = std::mem::replace(&mut inner.wakers_to_wake, Vec::new());
764
765            (channel_read_states, socket_read_states, deferred_wakers)
766        };
767
768        log::debug!("Failing reads on {} channels", channel_read_states.len());
769        for (_, mut state) in channel_read_states {
770            state.queued.push_back(Err(Error::Transport(None)));
771            state.wakers.into_iter().for_each(Waker::wake);
772        }
773
774        log::debug!("Failing reads on {} sockets", socket_read_states.len());
775        for (_, mut state) in socket_read_states {
776            state.queued.push_back(Err(Error::Transport(None)));
777            state.wakers.into_iter().for_each(Waker::wake);
778        }
779
780        deferred_wakers.into_iter().for_each(Waker::wake);
781    }
782}
783
784impl Client {
785    pub fn transport_status(&self) -> Result<()> {
786        match &self.0.lock().transport {
787            Transport::Error(e) => Err(e.clone().into()),
788            Transport::Transport(_, _, _) => Ok(()),
789        }
790    }
791    /// Create a new FDomain client. The `transport` argument should contain the
792    /// established connection to the target, ready to communicate the FDomain
793    /// protocol.
794    ///
795    /// The second return item is a future that must be polled to keep
796    /// transactions running.
797    pub fn new(
798        transport: impl FDomainTransport + 'static,
799    ) -> (Arc<Self>, impl Future<Output = ()> + Send + 'static) {
800        let ret = Arc::new(Client(Mutex::new(ClientInner {
801            transport: Transport::Transport(Box::pin(transport), VecDeque::new(), Vec::new()),
802            transactions: HashMap::new(),
803            socket_read_states: HashMap::new(),
804            channel_read_states: HashMap::new(),
805            handles: HashSet::new(),
806            next_tx_id: 1,
807            waiting_to_close: Vec::new(),
808            waiting_to_close_waker: std::task::Waker::noop().clone(),
809            wakers_to_wake: Vec::new(),
810        })));
811
812        let client_weak = Arc::downgrade(&ret);
813        let fut = futures::future::poll_fn(move |ctx| {
814            let Some(client) = client_weak.upgrade() else {
815                return Poll::Ready(());
816            };
817
818            let (ret, deferred_wakers) = {
819                let mut inner = client.0.lock();
820                let ret = inner.poll_transport(ctx);
821                let deferred_wakers = std::mem::replace(&mut inner.wakers_to_wake, Vec::new());
822                (ret, deferred_wakers)
823            };
824            deferred_wakers.into_iter().for_each(Waker::wake);
825            ret
826        });
827
828        let client_loop = ClientLoop { client: Arc::downgrade(&ret), fut: Box::pin(fut) };
829
830        (ret, client_loop)
831    }
832
833    /// Get the namespace for the connected FDomain. Calling this more than once is an error.
834    pub async fn namespace(self: &Arc<Self>) -> Result<Channel, Error> {
835        let new_handle = self.new_hid();
836        let channel = Channel(Handle { id: new_handle.id, client: Arc::downgrade(self) });
837        self.transaction(
838            ordinals::GET_NAMESPACE,
839            proto::FDomainGetNamespaceRequest { new_handle },
840            Responder::Namespace,
841        )
842        .await?;
843        Ok(channel)
844    }
845
846    /// Create a new channel in the connected FDomain.
847    pub fn create_channel(self: &Arc<Self>) -> (Channel, Channel) {
848        let id_a = self.new_hid();
849        let id_b = self.new_hid();
850        let fut = self.transaction(
851            ordinals::CREATE_CHANNEL,
852            proto::ChannelCreateChannelRequest { handles: [id_a, id_b] },
853            Responder::CreateChannel,
854        );
855
856        fuchsia_async::Task::spawn(async move {
857            if let Err(e) = fut.await {
858                log::debug!("FDomain channel creation failed: {e}");
859            }
860        })
861        .detach();
862
863        (
864            Channel(Handle { id: id_a.id, client: Arc::downgrade(self) }),
865            Channel(Handle { id: id_b.id, client: Arc::downgrade(self) }),
866        )
867    }
868
869    /// Create a channel from a handle ID allocated by the connected FDomain.
870    pub fn channel_from_handle_id(self: &Arc<Self>, id: proto::HandleId) -> Channel {
871        Channel(Handle { id: id.id, client: Arc::downgrade(self) })
872    }
873
874    /// Creates client and server endpoints connected to by a channel.
875    pub fn create_endpoints<F: crate::fidl::ProtocolMarker>(
876        self: &Arc<Self>,
877    ) -> (crate::fidl::ClientEnd<F>, crate::fidl::ServerEnd<F>) {
878        let (client, server) = self.create_channel();
879        let client_end = crate::fidl::ClientEnd::<F>::new(client);
880        let server_end = crate::fidl::ServerEnd::new(server);
881        (client_end, server_end)
882    }
883
884    /// Creates a client proxy and a server endpoint connected by a channel.
885    pub fn create_proxy<F: crate::fidl::ProtocolMarker>(
886        self: &Arc<Self>,
887    ) -> (F::Proxy, crate::fidl::ServerEnd<F>) {
888        let (client_end, server_end) = self.create_endpoints::<F>();
889        (client_end.into_proxy(), server_end)
890    }
891
892    /// Creates a client proxy and a server request stream connected by a channel.
893    pub fn create_proxy_and_stream<F: crate::fidl::ProtocolMarker>(
894        self: &Arc<Self>,
895    ) -> (F::Proxy, F::RequestStream) {
896        let (client_end, server_end) = self.create_endpoints::<F>();
897        (client_end.into_proxy(), server_end.into_stream())
898    }
899
900    /// Creates a client end and a server request stream connected by a channel.
901    pub fn create_request_stream<F: crate::fidl::ProtocolMarker>(
902        self: &Arc<Self>,
903    ) -> (crate::fidl::ClientEnd<F>, F::RequestStream) {
904        let (client_end, server_end) = self.create_endpoints::<F>();
905        (client_end, server_end.into_stream())
906    }
907
908    /// Create a new socket in the connected FDomain.
909    fn create_socket(self: &Arc<Self>, options: proto::SocketType) -> (Socket, Socket) {
910        let id_a = self.new_hid();
911        let id_b = self.new_hid();
912        let fut = self.transaction(
913            ordinals::CREATE_SOCKET,
914            proto::SocketCreateSocketRequest { handles: [id_a, id_b], options },
915            Responder::CreateSocket,
916        );
917
918        fuchsia_async::Task::spawn(async move {
919            if let Err(e) = fut.await {
920                log::debug!("FDomain socket creation failed: {e}");
921            }
922        })
923        .detach();
924
925        (
926            Socket(Handle { id: id_a.id, client: Arc::downgrade(self) }),
927            Socket(Handle { id: id_b.id, client: Arc::downgrade(self) }),
928        )
929    }
930
931    /// Create a new streaming socket in the connected FDomain.
932    pub fn create_stream_socket(self: &Arc<Self>) -> (Socket, Socket) {
933        self.create_socket(proto::SocketType::Stream)
934    }
935
936    /// Create a new datagram socket in the connected FDomain.
937    pub fn create_datagram_socket(self: &Arc<Self>) -> (Socket, Socket) {
938        self.create_socket(proto::SocketType::Datagram)
939    }
940
941    /// Create a new event pair in the connected FDomain.
942    pub fn create_event_pair(self: &Arc<Self>) -> (EventPair, EventPair) {
943        let id_a = self.new_hid();
944        let id_b = self.new_hid();
945        let fut = self.transaction(
946            ordinals::CREATE_EVENT_PAIR,
947            proto::EventPairCreateEventPairRequest { handles: [id_a, id_b] },
948            Responder::CreateEventPair,
949        );
950
951        fuchsia_async::Task::spawn(async move {
952            if let Err(e) = fut.await {
953                log::debug!("FDomain event pair creation failed: {e}");
954            }
955        })
956        .detach();
957
958        (
959            EventPair(Handle { id: id_a.id, client: Arc::downgrade(self) }),
960            EventPair(Handle { id: id_b.id, client: Arc::downgrade(self) }),
961        )
962    }
963
964    /// Create a new event handle in the connected FDomain.
965    pub fn create_event(self: &Arc<Self>) -> Event {
966        let id = self.new_hid();
967        let fut = self.transaction(
968            ordinals::CREATE_EVENT,
969            proto::EventCreateEventRequest { handle: id },
970            Responder::CreateEvent,
971        );
972
973        fuchsia_async::Task::spawn(async move {
974            if let Err(e) = fut.await {
975                log::debug!("FDomain event creation failed: {e}");
976            }
977        })
978        .detach();
979
980        Event(Handle { id: id.id, client: Arc::downgrade(self) })
981    }
982
983    /// Create a new VMO in the connected FDomain with the given options.
984    pub fn create_vmo(self: &Arc<Self>, options: proto::VmoOptions, size: u64) -> Vmo {
985        let id = self.new_hid();
986        let fut = self.transaction(
987            ordinals::CREATE_VMO,
988            proto::VmoCreateVmoRequest { handle: id, size, options },
989            Responder::CreateVmo,
990        );
991
992        fuchsia_async::Task::spawn(async move {
993            if let Err(e) = fut.await {
994                log::debug!("FDomain vmo creation failed: {e}");
995            }
996        })
997        .detach();
998
999        Vmo(Handle { id: id.id, client: Arc::downgrade(self) })
1000    }
1001
1002    /// Allocate a new HID, which should be suitable for use with the connected FDomain.
1003    pub(crate) fn new_hid(&self) -> proto::NewHandleId {
1004        self.0.lock().new_hid()
1005    }
1006
1007    /// Create a future which sends a FIDL message to the connected FDomain and
1008    /// waits for a response.
1009    ///
1010    /// Calling this method queues the transaction synchronously. Awaiting is
1011    /// only necessary to wait for the response.
1012    pub(crate) fn transaction<S: fidl_message::Body, R: 'static, F>(
1013        self: &Arc<Self>,
1014        ordinal: u64,
1015        request: S,
1016        f: F,
1017    ) -> impl Future<Output = Result<R, Error>> + 'static + use<S, R, F>
1018    where
1019        F: Fn(OneshotSender<Result<R, Error>>) -> Responder,
1020    {
1021        let mut inner = self.0.lock();
1022
1023        let (sender, receiver) = futures::channel::oneshot::channel();
1024        inner.request(ordinal, request, f(sender));
1025        receiver.map(|x| x.expect("Oneshot went away without reply!"))
1026    }
1027
1028    /// Start getting streaming events for socket reads.
1029    pub(crate) fn start_socket_streaming(&self, id: proto::HandleId) -> Result<(), Error> {
1030        let mut inner = self.0.lock();
1031        if let Some(e) = inner.transport.error() {
1032            return Err(e.into());
1033        }
1034
1035        let state = inner.socket_read_states.entry(id).or_insert_with(|| SocketReadState {
1036            wakers: Vec::new(),
1037            queued: VecDeque::new(),
1038            is_streaming: false,
1039            read_request_pending: false,
1040        });
1041
1042        assert!(!state.is_streaming, "Initiated streaming twice!");
1043        state.is_streaming = true;
1044
1045        inner.request(
1046            ordinals::READ_SOCKET_STREAMING_START,
1047            proto::SocketReadSocketStreamingStartRequest { handle: id },
1048            Responder::Ignore,
1049        );
1050        Ok(())
1051    }
1052
1053    /// Stop getting streaming events for socket reads. Doesn't return errors
1054    /// because it's exclusively called in destructors where we have nothing to
1055    /// do with them.
1056    pub(crate) fn stop_socket_streaming(&self, id: proto::HandleId) {
1057        let mut inner = self.0.lock();
1058        if let Some(state) = inner.socket_read_states.get_mut(&id) {
1059            if state.is_streaming {
1060                state.is_streaming = false;
1061                // TODO: Log?
1062                let _ = inner.request(
1063                    ordinals::READ_SOCKET_STREAMING_STOP,
1064                    proto::SocketReadSocketStreamingStopRequest { handle: id },
1065                    Responder::Ignore,
1066                );
1067            }
1068        }
1069    }
1070
1071    /// Start getting streaming events for socket reads.
1072    pub(crate) fn start_channel_streaming(&self, id: proto::HandleId) -> Result<(), Error> {
1073        let mut inner = self.0.lock();
1074        if let Some(e) = inner.transport.error() {
1075            return Err(e.into());
1076        }
1077        let state = inner.channel_read_states.entry(id).or_insert_with(|| ChannelReadState {
1078            wakers: Vec::new(),
1079            queued: VecDeque::new(),
1080            is_streaming: false,
1081            read_request_pending: false,
1082        });
1083
1084        assert!(!state.is_streaming, "Initiated streaming twice!");
1085        state.is_streaming = true;
1086
1087        inner.request(
1088            ordinals::READ_CHANNEL_STREAMING_START,
1089            proto::ChannelReadChannelStreamingStartRequest { handle: id },
1090            Responder::Ignore,
1091        );
1092
1093        Ok(())
1094    }
1095
1096    /// Stop getting streaming events for socket reads. Doesn't return errors
1097    /// because it's exclusively called in destructors where we have nothing to
1098    /// do with them.
1099    pub(crate) fn stop_channel_streaming(&self, id: proto::HandleId) {
1100        let mut inner = self.0.lock();
1101        if let Some(state) = inner.channel_read_states.get_mut(&id) {
1102            if state.is_streaming {
1103                state.is_streaming = false;
1104                // TODO: Log?
1105                let _ = inner.request(
1106                    ordinals::READ_CHANNEL_STREAMING_STOP,
1107                    proto::ChannelReadChannelStreamingStopRequest { handle: id },
1108                    Responder::Ignore,
1109                );
1110            }
1111        }
1112    }
1113
1114    /// Execute a read from a channel.
1115    pub(crate) fn poll_socket(
1116        &self,
1117        id: proto::HandleId,
1118        ctx: &mut Context<'_>,
1119        out: &mut [u8],
1120    ) -> Poll<Result<usize, Error>> {
1121        let mut inner = self.0.lock();
1122        if let Some(error) = inner.transport.error() {
1123            return Poll::Ready(Err(error.into()));
1124        }
1125
1126        let state = inner.socket_read_states.entry(id).or_insert_with(|| SocketReadState {
1127            wakers: Vec::new(),
1128            queued: VecDeque::new(),
1129            is_streaming: false,
1130            read_request_pending: false,
1131        });
1132
1133        let mut total_read = 0;
1134        while let Some(got) = state.queued.pop_front() {
1135            match got {
1136                Ok(mut chunk) => {
1137                    let available = &chunk.data.data[chunk.offset..];
1138                    let remaining_out = &mut out[total_read..];
1139                    let read_size = std::cmp::min(available.len(), remaining_out.len());
1140                    remaining_out[..read_size].copy_from_slice(&available[..read_size]);
1141                    total_read += read_size;
1142                    chunk.offset += read_size;
1143
1144                    let is_datagram = chunk.data.is_datagram;
1145                    let is_done = chunk.offset == chunk.data.data.len() || is_datagram;
1146
1147                    if !is_done {
1148                        state.queued.push_front(Ok(chunk));
1149                    }
1150
1151                    if is_datagram || total_read == out.len() {
1152                        break;
1153                    }
1154                }
1155                Err(err) => {
1156                    if total_read > 0 {
1157                        state.queued.push_front(Err(err));
1158                        break;
1159                    }
1160                    return Poll::Ready(Err(err));
1161                }
1162            }
1163        }
1164
1165        if total_read > 0 {
1166            return Poll::Ready(Ok(total_read));
1167        } else if !state.wakers.iter().any(|x| ctx.waker().will_wake(x)) {
1168            state.wakers.push(ctx.waker().clone());
1169        }
1170
1171        if !state.read_request_pending && !state.is_streaming {
1172            state.read_request_pending = true;
1173            inner.request(
1174                ordinals::READ_SOCKET,
1175                proto::SocketReadSocketRequest { handle: id, max_bytes: out.len() as u64 },
1176                Responder::ReadSocket(id),
1177            );
1178        }
1179
1180        Poll::Pending
1181    }
1182
1183    /// Execute a read from a channel.
1184    pub(crate) fn poll_channel(
1185        &self,
1186        id: proto::HandleId,
1187        ctx: &mut Context<'_>,
1188        for_stream: bool,
1189    ) -> Poll<Option<Result<proto::ChannelMessage, Error>>> {
1190        let mut inner = self.0.lock();
1191        if let Some(error) = inner.transport.error() {
1192            return Poll::Ready(Some(Err(error.into())));
1193        }
1194
1195        let state = inner.channel_read_states.entry(id).or_insert_with(|| ChannelReadState {
1196            wakers: Vec::new(),
1197            queued: VecDeque::new(),
1198            is_streaming: false,
1199            read_request_pending: false,
1200        });
1201
1202        if let Some(got) = state.queued.pop_front() {
1203            return Poll::Ready(Some(got));
1204        } else if for_stream && !state.is_streaming {
1205            return Poll::Ready(None);
1206        } else if !state.wakers.iter().any(|x| ctx.waker().will_wake(x)) {
1207            state.wakers.push(ctx.waker().clone());
1208        }
1209
1210        if !state.read_request_pending && !state.is_streaming {
1211            state.read_request_pending = true;
1212            inner.request(
1213                ordinals::READ_CHANNEL,
1214                proto::ChannelReadChannelRequest { handle: id },
1215                Responder::ReadChannel(id),
1216            );
1217        }
1218
1219        Poll::Pending
1220    }
1221
1222    /// Check whether this channel is streaming
1223    pub(crate) fn channel_is_streaming(&self, id: proto::HandleId) -> bool {
1224        let inner = self.0.lock();
1225        let Some(state) = inner.channel_read_states.get(&id) else {
1226            return false;
1227        };
1228        state.is_streaming
1229    }
1230
1231    /// Check that all the given handles are safe to transfer through a channel
1232    /// e.g. that there's no chance of in-flight reads getting dropped.
1233    pub(crate) fn clear_handles_for_transfer(&self, handles: &proto::Handles) {
1234        let mut inner = self.0.lock();
1235        match handles {
1236            proto::Handles::Handles(handles) => {
1237                for handle in handles {
1238                    assert!(
1239                        !(inner.channel_read_states.contains_key(handle)
1240                            || inner.socket_read_states.contains_key(handle)),
1241                        "Tried to transfer handle after reading"
1242                    );
1243                    inner.handles.remove(handle);
1244                }
1245            }
1246            proto::Handles::Dispositions(dispositions) => {
1247                for disposition in dispositions {
1248                    match &disposition.handle {
1249                        proto::HandleOp::Move_(handle) => {
1250                            assert!(
1251                                !(inner.channel_read_states.contains_key(handle)
1252                                    || inner.socket_read_states.contains_key(handle)),
1253                                "Tried to transfer handle after reading"
1254                            );
1255                            inner.handles.remove(handle);
1256                        }
1257                        // Pretty sure this should be fine regardless of read state.
1258                        proto::HandleOp::Duplicate(_) => (),
1259                    }
1260                }
1261            }
1262        }
1263    }
1264}