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