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