Skip to main content

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, HandleDisposition, HandleInfo, HandleOp, HandleRef, Koid, MessageBufEtc,
21        NullableHandle, ObjectType, Peered, Rights, Signals, Status,
22    };
23
24    pub use fuchsia_async::invoke_for_handle_types;
25
26    macro_rules! fuchsia_handle {
27
28        ($x:tt, $docname:expr, $name:ident, $value:expr, $availability:tt) => {
29            pub use zx::$x;
30        };
31    }
32
33    invoke_for_handle_types!(fuchsia_handle);
34
35    pub use zx::SocketOpts;
36}
37
38/// Non-Fuchsia implementation of handles
39#[cfg(not(target_os = "fuchsia"))]
40pub mod non_fuchsia_handles {
41    pub use fuchsia_async::emulated_handle::{
42        AsHandleRef, EmulatedHandleRef, Handle, Handle as NullableHandle, HandleDisposition,
43        HandleInfo, HandleOp, HandleRef, Koid, MessageBufEtc, ObjectType, Peered, Rights, Signals,
44        SocketOpts,
45    };
46    pub use zx_status::Status;
47
48    pub use fuchsia_async::invoke_for_handle_types;
49
50    macro_rules! declare_unsupported_fidl_handle {
51        ($name:ident) => {
52            /// An unimplemented Zircon-like $name
53            #[derive(PartialEq, Eq, Debug, PartialOrd, Ord, Hash)]
54            pub struct $name;
55
56            impl From<$crate::handle::NullableHandle> for $name {
57                fn from(_: $crate::handle::NullableHandle) -> $name {
58                    $name
59                }
60            }
61            impl From<$name> for NullableHandle {
62                fn from(_: $name) -> $crate::handle::NullableHandle {
63                    $crate::handle::NullableHandle::invalid()
64                }
65            }
66            impl AsHandleRef for $name {
67                fn as_handle_ref(&self) -> HandleRef<'_> {
68                    HandleRef::invalid()
69                }
70            }
71        };
72    }
73
74    macro_rules! declare_fidl_handle {
75        ($name:ident) => {
76            pub use fuchsia_async::emulated_handle::$name;
77        };
78    }
79
80    macro_rules! host_handle {
81        ($x:tt, $docname:expr, $name:ident, $zx_name:ident, Everywhere) => {
82            declare_fidl_handle! {$x}
83        };
84        ($x:tt, $docname:expr, $name:ident, $zx_name:ident, $availability:ident) => {
85            declare_unsupported_fidl_handle! {$x}
86        };
87    }
88
89    invoke_for_handle_types!(host_handle);
90}
91
92#[allow(clippy::too_long_first_doc_paragraph)]
93/// Converts a vector of `HandleDisposition` (handles bundled with their
94/// intended object type and rights) to a vector of `HandleInfo` (handles
95/// bundled with their actual type and rights, guaranteed by the kernel).
96///
97/// This makes a `zx_handle_replace` syscall for each handle unless the rights
98/// are `Rights::SAME_RIGHTS`.
99///
100/// # Panics
101///
102/// Panics if any of the handle dispositions uses `HandleOp::Duplicate`. This is
103/// never the case for handle dispositions return by `standalone_encode`.
104pub fn convert_handle_dispositions_to_infos(
105    handle_dispositions: Vec<HandleDisposition<'_>>,
106) -> crate::Result<Vec<HandleInfo>> {
107    handle_dispositions
108        .into_iter()
109        .map(|mut hd| {
110            Ok(HandleInfo::new(
111                match hd.take_op() {
112                    HandleOp::Move(h) if hd.rights == Rights::SAME_RIGHTS => h,
113                    HandleOp::Move(h) => {
114                        h.replace_handle(hd.rights).map_err(crate::Error::HandleReplace)?
115                    }
116                    HandleOp::Duplicate(_) => panic!("unexpected HandleOp::Duplicate"),
117                },
118                hd.object_type,
119                hd.rights,
120            ))
121        })
122        .collect()
123}