fidl_next_protocol/
transport.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 core::error::Error;
6use core::pin::Pin;
7use core::task::{Context, Poll};
8
9use fidl_next_codec::{Decoder, Encoder};
10
11/// A transport backend which can send and receive messages.
12///
13/// # Terminology
14///
15/// Note that this trait does not correspond directly with the FIDL notion of a
16/// transport. For clarity, implementors of this trait should be called
17/// "transport backends", as they are specific implementations of the more
18/// general notion of a "transport" in FIDL.
19///
20/// In FIDL, protocols can be assigned a "transport" such as "Channel" or
21/// "Driver". The choice of transport for a protocol controls the concrete types
22/// used for client ends and server ends of that protocol. A protocol with
23/// "Channel" transport will have client and server ends that are Zircon
24/// channels; a protocol with "Driver" transport will have client and server
25/// ends that are Driver channels.
26///
27/// All transport backends must be able to send and receive buffers of bytes. In
28/// addition to those bytes, transport backends may also support sending and
29/// receiving resource types like Zircon and Driver handles with those bytes.
30/// The additional resource types a transport backend supports defines which
31/// protocols can be run over that transport backend: a protocol can be run over
32/// a transport backend if all of the resource types its messages may contain
33/// can be sent and received using that transport backend. This may or may not
34/// have a correlation with the FIDL transport of that protocol.
35///
36/// # Implementation
37///
38/// The futures provided by this trait should be cancel-safe, which constrains
39/// their behavior:
40///
41/// - Operations should not partially complete.
42/// - Operations should only complete during polling.
43///
44/// `SendFuture` should return `Poll::Ready` with an error when polled after the
45/// transport backend is closed.
46pub trait Transport {
47    /// The error type for the transport backend.
48    type Error: Clone + Error + Send + Sync + 'static;
49
50    /// Splits the transport backend into shared and exclusive pieces.
51    fn split(self) -> (Self::Shared, Self::Exclusive);
52
53    /// The shared part of the transport backend. It is provided by shared
54    /// reference while sending and receiving. For an MPSC, this would contain a
55    /// sender.
56    type Shared: Send + Sync;
57    /// The exclusive part of the transport backend. It is provided by mutable
58    /// reference only while receiving. For an MPSC, this would contain a
59    /// receiver.
60    type Exclusive: Send;
61
62    /// The buffer type for sending.
63    type SendBuffer: Encoder + Send;
64    /// The future state for send operations.
65    type SendFutureState: Send;
66
67    /// Acquires an empty send buffer for the transport backend.
68    fn acquire(shared: &Self::Shared) -> Self::SendBuffer;
69
70    /// Begins sending a `SendBuffer` over this transport backend.
71    ///
72    /// Returns the state for a future which can be polled with `poll_send`.
73    fn begin_send(shared: &Self::Shared, buffer: Self::SendBuffer) -> Self::SendFutureState;
74
75    /// Polls a `SendFutureState` for completion with the shared part of the
76    /// transport backend.
77    ///
78    /// When ready, polling returns one of three values:
79    /// - `Ok(())` if the buffer was successfully sent.
80    /// - `Err(None)` if the connection was terminated normally (e.g. with
81    ///   `PEER_CLOSED`).
82    /// - `Err(Some(error))` if the connection was terminated abnormally.
83    fn poll_send(
84        future: Pin<&mut Self::SendFutureState>,
85        cx: &mut Context<'_>,
86        shared: &Self::Shared,
87    ) -> Poll<Result<(), Option<Self::Error>>>;
88
89    /// The future state for receive operations.
90    type RecvFutureState: Send;
91    /// The buffer type for receivers.
92    type RecvBuffer: Decoder + Send;
93
94    /// Begins receiving a `RecvBuffer` over this transport backend.
95    ///
96    /// Returns the state for a future which can be polled with `poll_recv`.
97    fn begin_recv(shared: &Self::Shared, exclusive: &mut Self::Exclusive) -> Self::RecvFutureState;
98
99    /// Polls a `RecvFutureState` for completion with a receiver.
100    ///
101    /// When ready, polling returns one of three values:
102    /// - `Ok(buffer)` if `buffer` was successfully received.
103    /// - `Err(None)` if the connection was terminated normally (e.g. with
104    ///   `PEER_CLOSED`).
105    /// - `Err(Some(error))` if the connection was terminated abnormally.
106    fn poll_recv(
107        future: Pin<&mut Self::RecvFutureState>,
108        cx: &mut Context<'_>,
109        shared: &Self::Shared,
110        exclusive: &mut Self::Exclusive,
111    ) -> Poll<Result<Self::RecvBuffer, Option<Self::Error>>>;
112}
113
114/// A transport backend which can send messages without blocking.
115///
116/// Because failed sends return immediately without waiting for an epitaph to be
117/// read, `send_immediately` may observe transport backend closure prematurely.
118///
119/// Non-blocking send operations cannot apply backpressure, which can cause
120/// memory exhaustion across the system. `NonBlockingTransport` is intended for
121/// use only while porting existing code.
122pub trait NonBlockingTransport: Transport {
123    /// Completes a `SendFutureState` with the shared part of the transport
124    /// backend without blocking.
125    fn send_immediately(
126        future_state: &mut Self::SendFutureState,
127        shared: &Self::Shared,
128    ) -> Result<(), Option<Self::Error>>;
129}