Skip to main content

fdomain_client/fidl_next/
codec.rs

1// Copyright 2025 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 super::wire;
6use crate::responder::Responder;
7use crate::{AsHandleRef, Channel, ChannelMessageStream, ChannelWriter, Error, Handle};
8use fidl_fuchsia_fdomain as proto;
9use fidl_next::AsDecoder;
10use fidl_next_codec::decoder::InternalHandleDecoder;
11use fidl_next_codec::encoder::InternalHandleEncoder;
12use fidl_next_codec::{CHUNK_SIZE, Chunk, DecodeError, Decoder, EncodeError, Encoder};
13use fidl_next_protocol::Transport;
14use futures::channel::oneshot;
15use futures::{FutureExt, StreamExt};
16
17use core::slice;
18use std::pin::Pin;
19use std::task::{Context, Poll, ready};
20
21/// A decoder which supports FDomain handles.
22pub trait HandleDecoder {
23    /// Takes the next raw handle from the decoder.
24    ///
25    /// The returned raw handle must not be considered owned until the decoder is committed.
26    fn take_raw_handle(&mut self) -> Result<u32, DecodeError>;
27
28    /// Returns the number of handles remaining in the decoder.
29    fn handles_remaining(&mut self) -> usize;
30}
31
32/// An encoder which supports FDomain handles.
33pub trait HandleEncoder {
34    /// Pushes a handle into the encoder.
35    fn push_handle(&mut self, handle: Handle) -> Result<(), EncodeError>;
36
37    /// Returns the number of handles added to the encoder.
38    fn handles_pushed(&self) -> usize;
39}
40
41/// Send buffer for an FDomain channel.
42#[derive(Default)]
43pub struct SendBuffer {
44    handles: Vec<Handle>,
45    chunks: Vec<Chunk>,
46}
47
48impl SendBuffer {
49    /// New buffer.
50    pub fn new() -> Self {
51        Self::default()
52    }
53
54    /// Retrieve the handles.
55    pub fn handles(&self) -> &[Handle] {
56        &self.handles
57    }
58}
59
60impl InternalHandleEncoder for SendBuffer {
61    #[inline]
62    fn __internal_handle_count(&self) -> usize {
63        self.handles.len()
64    }
65}
66
67impl Encoder for SendBuffer {
68    #[inline]
69    fn bytes_written(&self) -> usize {
70        Encoder::bytes_written(&self.chunks)
71    }
72
73    #[inline]
74    fn write_zeroes(&mut self, len: usize) {
75        Encoder::write_zeroes(&mut self.chunks, len)
76    }
77
78    #[inline]
79    fn write(&mut self, bytes: &[u8]) {
80        Encoder::write(&mut self.chunks, bytes)
81    }
82
83    #[inline]
84    fn rewrite(&mut self, pos: usize, bytes: &[u8]) {
85        Encoder::rewrite(&mut self.chunks, pos, bytes)
86    }
87}
88
89impl HandleEncoder for SendBuffer {
90    fn push_handle(&mut self, handle: Handle) -> Result<(), EncodeError> {
91        self.handles.push(handle.into());
92        Ok(())
93    }
94
95    fn handles_pushed(&self) -> usize {
96        self.handles.len()
97    }
98}
99
100/// A receive buffer for an FDomain channel.
101pub struct RecvBuffer {
102    handles: Vec<wire::Handle>,
103    chunks: Vec<Chunk>,
104}
105
106pub struct BufferDecoder<'de> {
107    buffer: &'de mut RecvBuffer,
108    chunks_taken: usize,
109    handles_taken: usize,
110}
111
112unsafe impl<'de> AsDecoder<'de> for RecvBuffer {
113    type Decoder = BufferDecoder<'de>;
114
115    fn as_decoder(&'de mut self) -> Self::Decoder {
116        BufferDecoder { buffer: self, chunks_taken: 0, handles_taken: 0 }
117    }
118}
119
120impl<'de> Decoder<'de> for BufferDecoder<'de> {
121    fn take_chunks(&mut self, count: usize) -> Result<&'de mut [Chunk], DecodeError> {
122        if count > self.buffer.chunks.len() - self.chunks_taken {
123            return Err(DecodeError::InsufficientData);
124        }
125
126        let chunks = unsafe { self.buffer.chunks.as_mut_ptr().add(self.chunks_taken) };
127        self.chunks_taken += count;
128
129        unsafe { Ok(slice::from_raw_parts_mut(chunks, count)) }
130    }
131
132    fn commit(&mut self) {
133        for handle in &mut self.buffer.handles[0..self.handles_taken] {
134            handle.invalidate();
135        }
136    }
137
138    fn finish(&self) -> Result<(), DecodeError> {
139        if self.chunks_taken != self.buffer.chunks.len() {
140            return Err(DecodeError::ExtraBytes {
141                num_extra: (self.buffer.chunks.len() - self.chunks_taken) * CHUNK_SIZE,
142            });
143        }
144
145        if self.handles_taken != self.buffer.handles.len() {
146            return Err(DecodeError::ExtraHandles {
147                num_extra: self.buffer.handles.len() - self.handles_taken,
148            });
149        }
150
151        Ok(())
152    }
153}
154
155impl InternalHandleDecoder for BufferDecoder<'_> {
156    fn __internal_take_handles(&mut self, count: usize) -> Result<(), DecodeError> {
157        if count > self.buffer.handles.len() - self.handles_taken {
158            return Err(DecodeError::InsufficientHandles);
159        }
160
161        for i in self.handles_taken..self.handles_taken + count {
162            drop(self.buffer.handles[i].take_handle());
163        }
164        self.handles_taken += count;
165
166        Ok(())
167    }
168
169    fn __internal_handles_remaining(&self) -> usize {
170        self.buffer.handles.len() - self.handles_taken
171    }
172}
173
174impl HandleDecoder for BufferDecoder<'_> {
175    fn take_raw_handle(&mut self) -> Result<u32, DecodeError> {
176        if self.handles_taken >= self.buffer.handles.len() {
177            return Err(DecodeError::InsufficientHandles);
178        }
179
180        let handle = self.buffer.handles[self.handles_taken].as_raw_handle();
181        self.handles_taken += 1;
182
183        Ok(handle)
184    }
185
186    fn handles_remaining(&mut self) -> usize {
187        self.buffer.handles.len() - self.handles_taken
188    }
189}
190
191/// Sender for an FDomain channel.
192#[derive(Clone)]
193pub struct Shared {
194    writer: ChannelWriter,
195}
196
197/// The state for a channel send future.
198pub enum SendFutureState {
199    /// The message was too big to fit in a channel.
200    BadGeometry,
201    Wait(oneshot::Receiver<Result<(), Error>>),
202}
203
204/// A channel receiver.
205pub struct Exclusive {
206    stream: ChannelMessageStream,
207}
208
209impl Transport for Channel {
210    type Error = Error;
211
212    fn split(self) -> (Self::Shared, Self::Exclusive) {
213        let (stream, writer) = self.stream().expect("could not split channel");
214        (Shared { writer }, Exclusive { stream })
215    }
216
217    type Shared = Shared;
218    type SendBuffer = SendBuffer;
219    type SendFutureState = SendFutureState;
220
221    fn acquire(_: &Self::Shared) -> Self::SendBuffer {
222        SendBuffer::new()
223    }
224
225    fn begin_send(sender: &Self::Shared, buffer: Self::SendBuffer) -> Self::SendFutureState {
226        let client = sender.writer.as_channel().as_handle_ref().client();
227        let handle = sender.writer.as_channel().as_handle_ref().proto();
228        let data = buffer.chunks;
229        let handles = buffer.handles;
230
231        // SAFETY: It should be safe to byte-cast from chunks always.
232        let data = unsafe {
233            std::slice::from_raw_parts(data.as_ptr() as *const u8, data.len() * CHUNK_SIZE).to_vec()
234        };
235
236        if data.len() > zx_types::ZX_CHANNEL_MAX_MSG_BYTES as usize
237            || handles.len() > zx_types::ZX_CHANNEL_MAX_MSG_HANDLES as usize
238        {
239            SendFutureState::BadGeometry
240        } else {
241            let handles =
242                proto::Handles::Handles(handles.into_iter().map(|x| x.take_proto()).collect());
243            let (sender, receiver) = oneshot::channel();
244            let mut client = client.0.lock();
245            client.request(
246                crate::ordinals::WRITE_CHANNEL,
247                proto::ChannelWriteChannelRequest { handle, data, handles },
248                Responder::WriteChannel(sender),
249            );
250
251            SendFutureState::Wait(receiver)
252        }
253    }
254
255    fn poll_send(
256        mut future_state: Pin<&mut Self::SendFutureState>,
257        ctx: &mut Context<'_>,
258        _: &Self::Shared,
259    ) -> Poll<Result<(), Option<Self::Error>>> {
260        match &mut *future_state {
261            SendFutureState::BadGeometry => Poll::Ready(Err(Some(Error::FDomain(
262                proto::Error::TargetError(fidl::Status::OUT_OF_RANGE.into_raw()),
263            )))),
264            SendFutureState::Wait(receiver) => receiver.poll_unpin(ctx).map(|x| {
265                match x.expect("Receiver disappeared with no reply") {
266                    Ok(x) => Ok(x),
267                    Err(Error::FDomain(proto::Error::TargetError(e)))
268                        if e == fidl::Status::PEER_CLOSED.into_raw() =>
269                    {
270                        Err(None)
271                    }
272                    Err(e) => Err(Some(e)),
273                }
274            }),
275        }
276    }
277
278    type Exclusive = Exclusive;
279    type RecvFutureState = ();
280    type RecvBuffer = RecvBuffer;
281
282    fn begin_recv(_: &Self::Shared, _: &mut Self::Exclusive) -> Self::RecvFutureState {}
283
284    fn poll_recv(
285        _: Pin<&mut Self::RecvFutureState>,
286        ctx: &mut Context<'_>,
287        _: &Self::Shared,
288        exclusive: &mut Self::Exclusive,
289    ) -> Poll<Result<Self::RecvBuffer, Option<Self::Error>>> {
290        let poll_stream = exclusive.stream.poll_next_unpin(ctx);
291
292        let Some(msg) = ready!(poll_stream).transpose().map_err(Some)? else {
293            return Poll::Ready(Err(None));
294        };
295
296        // SAFETY: It should be safe to byte-cast to a chunk always.
297        let chunks = unsafe {
298            std::slice::from_raw_parts(
299                msg.bytes.as_ptr() as *const Chunk,
300                msg.bytes.len() / CHUNK_SIZE,
301            )
302            .to_vec()
303        };
304        let handles = msg.handles.into_iter().map(|x| Handle::from(x.handle).into()).collect();
305
306        Poll::Ready(Ok(RecvBuffer { handles, chunks }))
307    }
308}