fidl/
handle.rs

1// Copyright 2019 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
5//! A portable representation of handle-like objects for fidl.
6
7#[cfg(target_os = "fuchsia")]
8pub use fuchsia_handles::*;
9
10#[cfg(not(target_os = "fuchsia"))]
11pub use non_fuchsia_handles::*;
12
13pub use fuchsia_async::{Channel as AsyncChannel, OnSignalsRef, Socket as AsyncSocket};
14
15/// Fuchsia implementation of handles just aliases the zircon library
16#[cfg(target_os = "fuchsia")]
17pub mod fuchsia_handles {
18
19    pub use zx::{
20        AsHandleRef, HandleBased, HandleDisposition, HandleInfo, HandleOp, HandleRef,
21        MessageBufEtc, NullableHandle, ObjectType, Peered, Rights, Signals, Status,
22    };
23
24    pub use fuchsia_async::invoke_for_handle_types;
25
26    macro_rules! fuchsia_handle {
27        ($x:tt, $docname:expr, $name:ident, $zx_name:ident, Stub) => {
28            /// Stub implementation of Zircon handle type $x.
29            #[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
30            #[repr(transparent)]
31            pub struct $x(zx::NullableHandle);
32
33            impl zx::AsHandleRef for $x {
34                fn as_handle_ref(&self) -> HandleRef<'_> {
35                    self.0.as_handle_ref()
36                }
37            }
38            impl From<NullableHandle> for $x {
39                fn from(handle: NullableHandle) -> Self {
40                    $x(handle)
41                }
42            }
43            impl From<$x> for NullableHandle {
44                fn from(x: $x) -> NullableHandle {
45                    x.0
46                }
47            }
48            impl zx::HandleBased for $x {}
49        };
50        ($x:tt, $docname:expr, $name:ident, $value:expr, $availability:tt) => {
51            pub use zx::$x;
52        };
53    }
54
55    invoke_for_handle_types!(fuchsia_handle);
56
57    pub use zx::SocketOpts;
58}
59
60/// Non-Fuchsia implementation of handles
61#[cfg(not(target_os = "fuchsia"))]
62pub mod non_fuchsia_handles {
63    pub use fuchsia_async::emulated_handle::{
64        AsHandleRef, EmulatedHandleRef, Handle, Handle as NullableHandle, HandleBased,
65        HandleDisposition, HandleInfo, HandleOp, HandleRef, MessageBufEtc, ObjectType, Peered,
66        Rights, Signals, SocketOpts,
67    };
68    pub use zx_status::Status;
69
70    pub use fuchsia_async::invoke_for_handle_types;
71
72    macro_rules! declare_unsupported_fidl_handle {
73        ($name:ident) => {
74            /// An unimplemented Zircon-like $name
75            #[derive(PartialEq, Eq, Debug, PartialOrd, Ord, Hash)]
76            pub struct $name;
77
78            impl From<$crate::handle::NullableHandle> for $name {
79                fn from(_: $crate::handle::NullableHandle) -> $name {
80                    $name
81                }
82            }
83            impl From<$name> for NullableHandle {
84                fn from(_: $name) -> $crate::handle::NullableHandle {
85                    $crate::handle::NullableHandle::invalid()
86                }
87            }
88            impl HandleBased for $name {}
89            impl AsHandleRef for $name {
90                fn as_handle_ref(&self) -> HandleRef<'_> {
91                    HandleRef::invalid()
92                }
93            }
94        };
95    }
96
97    macro_rules! declare_fidl_handle {
98        ($name:ident) => {
99            pub use fuchsia_async::emulated_handle::$name;
100        };
101    }
102
103    macro_rules! host_handle {
104        ($x:tt, $docname:expr, $name:ident, $zx_name:ident, Everywhere) => {
105            declare_fidl_handle! {$x}
106        };
107        ($x:tt, $docname:expr, $name:ident, $zx_name:ident, $availability:ident) => {
108            declare_unsupported_fidl_handle! {$x}
109        };
110    }
111
112    invoke_for_handle_types!(host_handle);
113}
114
115#[allow(clippy::too_long_first_doc_paragraph)]
116/// Converts a vector of `HandleDisposition` (handles bundled with their
117/// intended object type and rights) to a vector of `HandleInfo` (handles
118/// bundled with their actual type and rights, guaranteed by the kernel).
119///
120/// This makes a `zx_handle_replace` syscall for each handle unless the rights
121/// are `Rights::SAME_RIGHTS`.
122///
123/// # Panics
124///
125/// Panics if any of the handle dispositions uses `HandleOp::Duplicate`. This is
126/// never the case for handle dispositions return by `standalone_encode`.
127pub fn convert_handle_dispositions_to_infos(
128    handle_dispositions: Vec<HandleDisposition<'_>>,
129) -> crate::Result<Vec<HandleInfo>> {
130    handle_dispositions
131        .into_iter()
132        .map(|mut hd| {
133            Ok(HandleInfo::new(
134                match hd.take_op() {
135                    HandleOp::Move(h) if hd.rights == Rights::SAME_RIGHTS => h,
136                    HandleOp::Move(h) => {
137                        h.replace(hd.rights).map_err(crate::Error::HandleReplace)?
138                    }
139                    HandleOp::Duplicate(_) => panic!("unexpected HandleOp::Duplicate"),
140                },
141                hd.object_type,
142                hd.rights,
143            ))
144        })
145        .collect()
146}