fdf_fidl/
lib.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
5mod wire;
6
7use std::marker::PhantomData;
8use std::num::NonZero;
9use std::pin::Pin;
10use std::ptr::NonNull;
11use std::task::{Context, Poll};
12
13use fidl_next::Chunk;
14use zx::Status;
15
16use fdf_channel::arena::{Arena, ArenaBox};
17use fdf_channel::channel::Channel;
18use fdf_channel::futures::ReadMessageState;
19use fdf_channel::message::Message;
20use fdf_core::dispatcher::{CurrentDispatcher, OnDispatcher};
21use fdf_core::handle::{DriverHandle, MixedHandle, MixedHandleType};
22
23pub use self::wire::*;
24
25/// A fidl-compatible driver channel that also holds a reference to the
26/// dispatcher. Defaults to using [`CurrentDispatcher`].
27#[derive(Debug)]
28pub struct DriverChannel<D = CurrentDispatcher> {
29    dispatcher: D,
30    channel: Channel<[Chunk]>,
31}
32
33impl<D> DriverChannel<D> {
34    /// Create a new driver fidl channel that will perform its operations on the given
35    /// dispatcher handle.
36    pub fn new_with_dispatcher(dispatcher: D, channel: Channel<[Chunk]>) -> Self {
37        Self { dispatcher, channel }
38    }
39
40    /// Create a new driver fidl channel pair that will perform its operations on the given
41    /// dispatcher handles.
42    pub fn create_with_dispatchers(dispatcher1: D, dispatcher2: D) -> (Self, Self) {
43        let (channel1, channel2) = Channel::create();
44        (
45            Self { dispatcher: dispatcher1, channel: channel1 },
46            Self { dispatcher: dispatcher2, channel: channel2 },
47        )
48    }
49
50    /// Create a new driver fidl channel pair that will perform its operations on the given
51    /// dispatcher handle, if the dispatcher implements [`Clone`]
52    pub fn create_with_dispatcher(dispatcher: D) -> (Self, Self)
53    where
54        D: Clone,
55    {
56        Self::create_with_dispatchers(dispatcher.clone(), dispatcher)
57    }
58
59    /// Returns the underlying data channel
60    pub fn into_channel(self) -> Channel<[Chunk]> {
61        self.channel
62    }
63
64    /// Returns the underlying `fdf_handle_t` for this channel
65    pub fn into_driver_handle(self) -> DriverHandle {
66        self.channel.into_driver_handle()
67    }
68}
69
70impl DriverChannel<CurrentDispatcher> {
71    /// Create a new driver fidl channel that will perform its operations on the
72    /// [`CurrentDispatcher`].
73    pub fn new(channel: Channel<[Chunk]>) -> Self {
74        Self::new_with_dispatcher(CurrentDispatcher, channel)
75    }
76
77    /// Create a new driver fidl channel pair that will perform its operations on the
78    /// [`CurrentDispatcher`].
79    pub fn create() -> (Self, Self) {
80        Self::create_with_dispatcher(CurrentDispatcher)
81    }
82}
83
84/// Creates a pair of [`fidl_next::ClientEnd`] and [`fidl_next::ServerEnd`] backed by a new
85/// pair of [`DriverChannel`]s using dispatchers of type `D`.
86pub fn create_channel_with_dispatchers<P, D>(
87    client_dispatcher: D,
88    server_dispatcher: D,
89) -> (fidl_next::ClientEnd<P, DriverChannel<D>>, fidl_next::ServerEnd<P, DriverChannel<D>>) {
90    let (client_channel, server_channel) =
91        DriverChannel::create_with_dispatchers(client_dispatcher, server_dispatcher);
92    (
93        fidl_next::ClientEnd::from_untyped(client_channel),
94        fidl_next::ServerEnd::from_untyped(server_channel),
95    )
96}
97
98/// Creates a pair of [`fidl_next::ClientEnd`] and [`fidl_next::ServerEnd`] backed by a new
99/// pair of [`DriverChannel`]s using dispatchers of type `D`, where `D` implements [`Clone`]
100pub fn create_channel_with_dispatcher<P, D: Clone>(
101    dispatcher: D,
102) -> (fidl_next::ClientEnd<P, DriverChannel<D>>, fidl_next::ServerEnd<P, DriverChannel<D>>) {
103    create_channel_with_dispatchers(dispatcher.clone(), dispatcher)
104}
105
106/// Creates a pair of [`fidl_next::ClientEnd`] and [`fidl_next::ServerEnd`] backed by a new
107/// pair of [`DriverChannel`]s using the default [`CurrentDispatcher`]
108pub fn create_channel<P>()
109-> (fidl_next::ClientEnd<P, DriverChannel>, fidl_next::ServerEnd<P, DriverChannel>) {
110    create_channel_with_dispatcher(CurrentDispatcher)
111}
112
113/// A channel buffer.
114pub struct SendBuffer {
115    handles: Vec<Option<MixedHandle>>,
116    data: Vec<Chunk>,
117}
118
119impl SendBuffer {
120    fn new() -> Self {
121        Self { handles: Vec::new(), data: Vec::new() }
122    }
123}
124
125impl fidl_next::Encoder for SendBuffer {
126    #[inline]
127    fn bytes_written(&self) -> usize {
128        fidl_next::Encoder::bytes_written(&self.data)
129    }
130
131    #[inline]
132    fn write(&mut self, bytes: &[u8]) {
133        fidl_next::Encoder::write(&mut self.data, bytes)
134    }
135
136    #[inline]
137    fn rewrite(&mut self, pos: usize, bytes: &[u8]) {
138        fidl_next::Encoder::rewrite(&mut self.data, pos, bytes)
139    }
140
141    fn write_zeroes(&mut self, len: usize) {
142        fidl_next::Encoder::write_zeroes(&mut self.data, len);
143    }
144}
145
146impl fidl_next::encoder::InternalHandleEncoder for SendBuffer {
147    #[inline]
148    fn __internal_handle_count(&self) -> usize {
149        self.handles.len()
150    }
151}
152
153impl fidl_next::fuchsia::HandleEncoder for SendBuffer {
154    fn push_handle(&mut self, handle: zx::Handle) -> Result<(), fidl_next::EncodeError> {
155        if let Some(handle) = MixedHandle::from_zircon_handle(handle) {
156            if handle.is_driver() {
157                return Err(fidl_next::EncodeError::ExpectedZirconHandle);
158            }
159            self.handles.push(Some(handle));
160        } else {
161            self.handles.push(None);
162        }
163        Ok(())
164    }
165
166    unsafe fn push_raw_driver_handle(&mut self, handle: u32) -> Result<(), fidl_next::EncodeError> {
167        if let Some(handle) = NonZero::new(handle) {
168            // SAFETY: the fidl framework is responsible for providing us with a valid, otherwise
169            // unowned handle.
170            let handle = unsafe { MixedHandle::from_raw(handle) };
171            if !handle.is_driver() {
172                return Err(fidl_next::EncodeError::ExpectedDriverHandle);
173            }
174            self.handles.push(Some(handle));
175        } else {
176            self.handles.push(None);
177        }
178        Ok(())
179    }
180
181    fn handles_pushed(&self) -> usize {
182        self.handles.len()
183    }
184}
185
186pub struct RecvBuffer {
187    buffer: Option<Message<[Chunk]>>,
188    data_offset: usize,
189    handle_offset: usize,
190}
191
192impl RecvBuffer {
193    fn next_handle(&self) -> Result<&MixedHandle, fidl_next::DecodeError> {
194        let Some(buffer) = &self.buffer else {
195            return Err(fidl_next::DecodeError::InsufficientHandles);
196        };
197
198        let Some(handles) = buffer.handles() else {
199            return Err(fidl_next::DecodeError::InsufficientHandles);
200        };
201        if handles.len() < self.handle_offset + 1 {
202            return Err(fidl_next::DecodeError::InsufficientHandles);
203        }
204        handles[self.handle_offset].as_ref().ok_or(fidl_next::DecodeError::RequiredHandleAbsent)
205    }
206}
207
208// SAFETY: The decoder implementation stores the data buffer in a [`Message`] tied to an [`Arena`],
209// and the memory in an [`Arena`] is guaranteed not to move while the arena is valid.
210// Also, since we own the [`Message`] and nothing else can, it is ok to treat its contents
211// as mutable through an `&mut self` reference to the struct.
212unsafe impl fidl_next::Decoder for RecvBuffer {
213    // SAFETY: if the caller requests a number of [`Chunk`]s that we can't supply, we return
214    // `InsufficientData`.
215    fn take_chunks_raw(&mut self, count: usize) -> Result<NonNull<Chunk>, fidl_next::DecodeError> {
216        let Some(buffer) = &mut self.buffer else {
217            return Err(fidl_next::DecodeError::InsufficientData);
218        };
219
220        let Some(data) = buffer.data_mut() else {
221            return Err(fidl_next::DecodeError::InsufficientData);
222        };
223        if data.len() < self.data_offset + count {
224            return Err(fidl_next::DecodeError::InsufficientData);
225        }
226        let pos = self.data_offset;
227        self.data_offset += count;
228        Ok(unsafe { NonNull::new_unchecked((&mut data[pos..(pos + count)]).as_mut_ptr()) })
229    }
230
231    fn commit(&mut self) {
232        if let Some(handles) = self.buffer.as_mut().and_then(Message::handles_mut) {
233            for i in 0..self.handle_offset {
234                core::mem::forget(handles[i].take());
235            }
236        }
237    }
238
239    fn finish(&self) -> Result<(), fidl_next::DecodeError> {
240        if let Some(buffer) = &self.buffer {
241            let data_len = buffer.data().unwrap_or(&[]).len();
242            if self.data_offset != data_len {
243                return Err(fidl_next::DecodeError::ExtraBytes {
244                    num_extra: data_len - self.data_offset,
245                });
246            }
247            let handle_len = buffer.handles().unwrap_or(&[]).len();
248            if self.handle_offset != handle_len {
249                return Err(fidl_next::DecodeError::ExtraHandles {
250                    num_extra: handle_len - self.handle_offset,
251                });
252            }
253        }
254
255        Ok(())
256    }
257}
258
259impl fidl_next::decoder::InternalHandleDecoder for RecvBuffer {
260    fn __internal_take_handles(&mut self, count: usize) -> Result<(), fidl_next::DecodeError> {
261        let Some(handles) = self.buffer.as_mut().and_then(Message::handles_mut) else {
262            return Err(fidl_next::DecodeError::InsufficientHandles);
263        };
264        if handles.len() < self.handle_offset + count {
265            return Err(fidl_next::DecodeError::InsufficientHandles);
266        }
267        let pos = self.handle_offset;
268        self.handle_offset = pos + count;
269        Ok(())
270    }
271
272    fn __internal_handles_remaining(&self) -> usize {
273        self.buffer
274            .as_ref()
275            .map(|buffer| buffer.handles().unwrap_or(&[]).len() - self.handle_offset)
276            .unwrap_or(0)
277    }
278}
279
280impl fidl_next::fuchsia::HandleDecoder for RecvBuffer {
281    fn take_raw_handle(&mut self) -> Result<zx::sys::zx_handle_t, fidl_next::DecodeError> {
282        let result = {
283            let handle = self.next_handle()?.resolve_ref();
284            let MixedHandleType::Zircon(handle) = handle else {
285                return Err(fidl_next::DecodeError::ExpectedZirconHandle);
286            };
287            handle.raw_handle()
288        };
289        let pos = self.handle_offset;
290        self.handle_offset = pos + 1;
291        Ok(result)
292    }
293
294    fn take_raw_driver_handle(&mut self) -> Result<u32, fidl_next::DecodeError> {
295        let result = {
296            let handle = self.next_handle()?.resolve_ref();
297            let MixedHandleType::Driver(handle) = handle else {
298                return Err(fidl_next::DecodeError::ExpectedDriverHandle);
299            };
300            unsafe { handle.get_raw().get() }
301        };
302        let pos = self.handle_offset;
303        self.handle_offset = pos + 1;
304        Ok(result)
305    }
306
307    fn handles_remaining(&mut self) -> usize {
308        fidl_next::decoder::InternalHandleDecoder::__internal_handles_remaining(self)
309    }
310}
311
312/// The inner state of a receive future used by [`fidl_next::protocol::Transport`].
313pub struct DriverRecvState(ReadMessageState);
314
315/// The shared part of a driver channel.
316pub struct Shared<D> {
317    channel: DriverChannel<D>,
318}
319
320impl<D> Shared<D> {
321    fn new(channel: DriverChannel<D>) -> Self {
322        Self { channel }
323    }
324}
325
326/// The exclusive part of a driver channel.
327pub struct Exclusive {
328    _phantom: PhantomData<()>,
329}
330
331impl<D: OnDispatcher> fidl_next::Transport for DriverChannel<D> {
332    type Error = Status;
333
334    fn split(self) -> (Self::Shared, Self::Exclusive) {
335        (Shared::new(self), Exclusive { _phantom: PhantomData })
336    }
337
338    type Shared = Shared<D>;
339
340    type SendBuffer = SendBuffer;
341
342    type SendFutureState = SendBuffer;
343
344    fn acquire(_shared: &Self::Shared) -> Self::SendBuffer {
345        SendBuffer::new()
346    }
347
348    type Exclusive = Exclusive;
349
350    type RecvFutureState = DriverRecvState;
351
352    type RecvBuffer = RecvBuffer;
353
354    fn begin_send(_shared: &Self::Shared, buffer: Self::SendBuffer) -> Self::SendFutureState {
355        buffer
356    }
357
358    fn poll_send(
359        mut buffer: Pin<&mut Self::SendFutureState>,
360        _cx: &mut Context<'_>,
361        shared: &Self::Shared,
362    ) -> Poll<Result<(), Option<Self::Error>>> {
363        let arena = Arena::new();
364        let message = Message::new_with(arena, |arena| {
365            let data = arena.insert_slice(&buffer.data);
366            let handles = buffer.handles.split_off(0);
367            let handles = arena.insert_from_iter(handles.into_iter());
368            (Some(data), Some(handles))
369        });
370        let result = match shared.channel.channel.write(message) {
371            Ok(()) => Ok(()),
372            Err(Status::PEER_CLOSED) => Err(None),
373            Err(e) => Err(Some(e)),
374        };
375        Poll::Ready(result)
376    }
377
378    fn begin_recv(
379        shared: &Self::Shared,
380        _exclusive: &mut Self::Exclusive,
381    ) -> Self::RecvFutureState {
382        // SAFETY: The `receiver` owns the channel we're using here and will be the same
383        // receiver given to `poll_recv`, so must outlive the state object we're constructing.
384        let state = unsafe { ReadMessageState::new(shared.channel.channel.driver_handle()) };
385        DriverRecvState(state)
386    }
387
388    fn poll_recv(
389        mut future: Pin<&mut Self::RecvFutureState>,
390        cx: &mut Context<'_>,
391        shared: &Self::Shared,
392        _exclusive: &mut Self::Exclusive,
393    ) -> Poll<Result<Self::RecvBuffer, Option<Self::Error>>> {
394        use std::task::Poll::*;
395        match future.as_mut().0.poll_with_dispatcher(cx, shared.channel.dispatcher.clone()) {
396            Ready(Ok(maybe_buffer)) => {
397                let buffer = maybe_buffer.map(|buffer| {
398                    buffer.map_data(|_, data| {
399                        let bytes = data.len();
400                        assert_eq!(
401                            0,
402                            bytes % size_of::<Chunk>(),
403                            "Received driver channel buffer was not a multiple of {} bytes",
404                            size_of::<Chunk>()
405                        );
406                        // SAFETY: we verified that the size of the message we received was the correct
407                        // multiple of chunks and we know that the data pointer is otherwise valid and
408                        // from the correct arena by construction.
409                        let new_box = unsafe {
410                            let ptr = ArenaBox::into_ptr(data).cast();
411                            ArenaBox::new(NonNull::slice_from_raw_parts(
412                                ptr,
413                                bytes / size_of::<Chunk>(),
414                            ))
415                        };
416                        new_box
417                    })
418                });
419
420                Ready(Ok(RecvBuffer { buffer, data_offset: 0, handle_offset: 0 }))
421            }
422            Ready(Err(err)) => {
423                if err == Status::PEER_CLOSED {
424                    Ready(Err(None))
425                } else {
426                    Ready(Err(Some(err)))
427                }
428            }
429            Pending => Pending,
430        }
431    }
432}
433
434impl<D> fidl_next::RunsTransport<DriverChannel<D>> for fidl_next::fuchsia_async::FuchsiaAsync {}
435
436impl<D> fidl_next::HasExecutor for DriverChannel<D> {
437    type Executor = fidl_next::fuchsia_async::FuchsiaAsync;
438
439    fn executor(&self) -> Self::Executor {
440        fidl_next::fuchsia_async::FuchsiaAsync
441    }
442}
443
444#[cfg(test)]
445mod test {
446    use fidl_next::{Client, ClientEnd, Responder, Server, ServerEnd, ServerSender};
447    use fidl_next_fuchsia_examples_gizmo::device::{GetEvent, GetHardwareId};
448    use fidl_next_fuchsia_examples_gizmo::{
449        Device, DeviceClientHandler, DeviceGetEventResponse, DeviceGetHardwareIdResponse,
450        DeviceServerHandler,
451    };
452    use fuchsia_async::OnSignals;
453    use zx::{AsHandleRef, Event, Signals};
454
455    use super::*;
456    use fdf_core::dispatcher::{CurrentDispatcher, OnDispatcher};
457    use fdf_env::test::spawn_in_driver;
458
459    struct DeviceServer;
460    impl DeviceServerHandler<DriverChannel> for DeviceServer {
461        async fn get_hardware_id(
462            &mut self,
463            sender: &ServerSender<Device, DriverChannel>,
464            responder: Responder<GetHardwareId>,
465        ) {
466            responder
467                .respond(
468                    &sender,
469                    Result::<_, i32>::Ok(DeviceGetHardwareIdResponse { response: 4004 }),
470                )
471                .await
472                .unwrap();
473        }
474
475        async fn get_event(
476            &mut self,
477            sender: &ServerSender<Device, DriverChannel>,
478            responder: Responder<GetEvent>,
479        ) {
480            let event = Event::create();
481            event.signal_handle(Signals::empty(), Signals::USER_0).unwrap();
482            let response = DeviceGetEventResponse { event };
483            responder.respond(&sender, response).await.unwrap();
484        }
485    }
486
487    struct DeviceClient;
488    impl DeviceClientHandler<DriverChannel> for DeviceClient {}
489
490    #[test]
491    fn driver_fidl_server() {
492        spawn_in_driver("driver fidl server", async {
493            let (server_chan, client_chan) = Channel::<[Chunk]>::create();
494            let client_end: ClientEnd<Device, _> =
495                ClientEnd::<Device, _>::from_untyped(DriverChannel::new(client_chan));
496            let server_end: ServerEnd<Device, _> =
497                ServerEnd::from_untyped(DriverChannel::new(server_chan));
498            let client = Client::new(client_end);
499            let server = Server::new(server_end);
500            let client_sender = client.sender().clone();
501
502            CurrentDispatcher
503                .spawn_task(async {
504                    server.run(DeviceServer).await.unwrap();
505                    println!("server task finished");
506                })
507                .unwrap();
508            CurrentDispatcher
509                .spawn_task(async {
510                    client.run(DeviceClient).await.unwrap();
511                    println!("client task finished");
512                })
513                .unwrap();
514
515            {
516                let res = client_sender.get_hardware_id().await.unwrap();
517                let hardware_id = res.unwrap();
518                assert_eq!(hardware_id.response, 4004);
519            }
520
521            {
522                let res = client_sender.get_event().await.unwrap().take::<DeviceGetEventResponse>();
523
524                // wait for the event on a fuchsia_async executor
525                let mut executor = fuchsia_async::LocalExecutor::new();
526                let signalled = executor
527                    .run_singlethreaded(OnSignals::new(res.event, Signals::USER_0))
528                    .unwrap();
529                assert_eq!(Signals::USER_0, signalled);
530            }
531        });
532    }
533}