overnet_core/
handle_info.rs
1use anyhow::{bail, Error};
6use fidl::HandleRef;
7use fidl_fuchsia_overnet_protocol::{ChannelRights, EventPairRights, SocketRights, SocketType};
8
9#[cfg(target_os = "fuchsia")]
10use fidl::AsHandleRef;
11
12#[cfg(not(target_os = "fuchsia"))]
13use fidl::EmulatedHandleRef;
14
15#[cfg(target_os = "fuchsia")]
16pub(crate) type HandleKey = zx::Koid;
17
18#[cfg(not(target_os = "fuchsia"))]
19pub(crate) type HandleKey = u64;
20
21#[derive(Copy, Clone, Debug)]
24pub(crate) enum HandleType {
25 Channel(ChannelRights),
27 Socket(SocketType, SocketRights),
28 EventPair,
29}
30
31#[derive(Copy, Clone, Debug)]
32pub(crate) struct HandleInfo {
33 pub(crate) handle_type: HandleType,
34 pub(crate) this_handle_key: HandleKey,
35 pub(crate) pair_handle_key: HandleKey,
36}
37
38#[cfg(not(target_os = "fuchsia"))]
39pub(crate) fn handle_info(hdl: HandleRef<'_>) -> Result<HandleInfo, Error> {
40 let handle_type = match hdl.object_type() {
41 fidl::ObjectType::CHANNEL => {
42 HandleType::Channel(ChannelRights::READ | ChannelRights::WRITE)
43 }
44 fidl::ObjectType::SOCKET => {
45 HandleType::Socket(SocketType::Stream, SocketRights::READ | SocketRights::WRITE)
46 }
47 fidl::ObjectType::EVENTPAIR => HandleType::EventPair,
48 _ => bail!("Unsupported handle type"),
49 };
50 let (this_handle_key, pair_handle_key) = hdl.koid_pair();
51 Ok(HandleInfo { handle_type, this_handle_key, pair_handle_key })
52}
53
54#[cfg(target_os = "fuchsia")]
55pub(crate) fn handle_info(handle: HandleRef<'_>) -> Result<HandleInfo, Error> {
56 let basic_info = handle.basic_info()?;
57
58 let handle_type = match basic_info.object_type {
59 zx::ObjectType::CHANNEL => {
60 let mut rights = ChannelRights::empty();
61 rights.set(ChannelRights::READ, basic_info.rights.contains(zx::Rights::READ));
62 rights.set(ChannelRights::WRITE, basic_info.rights.contains(zx::Rights::WRITE));
63 HandleType::Channel(rights)
64 }
65 zx::ObjectType::SOCKET => {
66 let socket = handle.cast::<zx::Socket>();
67 let info = socket.info()?;
68 let socket_type = match info.options {
69 zx::SocketOpts::STREAM => SocketType::Stream,
70 zx::SocketOpts::DATAGRAM => SocketType::Datagram,
71 _ => bail!("Unhandled socket options"),
72 };
73 let mut rights = SocketRights::empty();
74 rights.set(SocketRights::READ, basic_info.rights.contains(zx::Rights::READ));
75 rights.set(SocketRights::WRITE, basic_info.rights.contains(zx::Rights::WRITE));
76 HandleType::Socket(socket_type, rights)
77 }
78 zx::ObjectType::EVENTPAIR => HandleType::EventPair,
79 _ => bail!("Handle type not proxyable {:?}", handle.basic_info()?.object_type),
80 };
81
82 Ok(HandleInfo {
83 handle_type,
84 this_handle_key: basic_info.koid,
85 pair_handle_key: basic_info.related_koid,
86 })
87}
88
89pub(crate) trait WithRights {
90 type Rights;
91 fn with_rights(self, rights: Self::Rights) -> Result<Self, Error>
92 where
93 Self: Sized;
94}
95
96#[cfg(target_os = "fuchsia")]
97impl WithRights for fidl::Channel {
98 type Rights = ChannelRights;
99 fn with_rights(self, rights: ChannelRights) -> Result<Self, Error> {
100 use zx::HandleBased;
101 let mut zx_rights = self.basic_info()?.rights;
102 zx_rights.set(zx::Rights::READ, rights.contains(ChannelRights::READ));
103 zx_rights.set(zx::Rights::WRITE, rights.contains(ChannelRights::WRITE));
104 zx_rights.insert(zx::Rights::TRANSFER);
105 Ok(self.replace_handle(zx_rights)?)
106 }
107}
108
109#[cfg(target_os = "fuchsia")]
110impl WithRights for fidl::Socket {
111 type Rights = SocketRights;
112 fn with_rights(self, rights: SocketRights) -> Result<Self, Error> {
113 use zx::HandleBased;
114 let mut zx_rights = self.basic_info()?.rights;
115 zx_rights.set(zx::Rights::READ, rights.contains(SocketRights::READ));
116 zx_rights.set(zx::Rights::WRITE, rights.contains(SocketRights::WRITE));
117 zx_rights.insert(zx::Rights::TRANSFER);
118 Ok(self.replace_handle(zx_rights)?)
119 }
120}
121
122#[cfg(not(target_os = "fuchsia"))]
123impl WithRights for fidl::Channel {
124 type Rights = ChannelRights;
125 fn with_rights(self, rights: ChannelRights) -> Result<Self, Error> {
126 if rights != ChannelRights::READ | ChannelRights::WRITE {
127 bail!("Restricted rights not supported on non-Fuchsia platforms");
128 }
129 Ok(self)
130 }
131}
132
133#[cfg(not(target_os = "fuchsia"))]
134impl WithRights for fidl::Socket {
135 type Rights = SocketRights;
136 fn with_rights(self, rights: SocketRights) -> Result<Self, Error> {
137 if rights != SocketRights::READ | SocketRights::WRITE {
138 bail!("Restricted rights not supported on non-Fuchsia platforms");
139 }
140 Ok(self)
141 }
142}
143
144impl WithRights for fidl::EventPair {
145 type Rights = EventPairRights;
146 fn with_rights(self, rights: EventPairRights) -> Result<Self, Error> {
147 if !rights.is_empty() {
148 bail!("Non-empty rights ({:?}) not supported for event pair", rights);
149 }
150 Ok(self)
151 }
152}