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