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}