fuchsia_zircon/
handle.rs

1use {Port, Rights, Signals, Status, Time, WaitAsyncOpts, ok, sys};
2use std::marker::PhantomData;
3use std::mem;
4
5/// An object representing a Zircon
6/// [handle](https://fuchsia.googlesource.com/zircon/+/master/docs/handles.md).
7///
8/// Internally, it is represented as a 32-bit integer, but this wrapper enforces
9/// strict ownership semantics. The `Drop` implementation closes the handle.
10///
11/// This type represents the most general reference to a kernel object, and can
12/// be interconverted to and from more specific types. Those conversions are not
13/// enforced in the type system; attempting to use them will result in errors
14/// returned by the kernel. These conversions don't change the underlying
15/// representation, but do change the type and thus what operations are available.
16#[derive(Debug, Eq, PartialEq, Hash)]
17pub struct Handle(sys::zx_handle_t);
18
19impl AsHandleRef for Handle {
20    fn as_handle_ref(&self) -> HandleRef {
21        HandleRef { handle: self.0, phantom: Default::default() }
22    }
23}
24
25impl HandleBased for Handle {}
26
27impl Drop for Handle {
28    fn drop(&mut self) {
29        if self.0 != sys::ZX_HANDLE_INVALID {
30            unsafe { sys::zx_handle_close(self.0) };
31        }
32    }
33}
34
35impl Handle {
36    /// Initialize a handle backed by ZX_HANDLE_INVALID, the only safe non-handle.
37    pub fn invalid() -> Handle {
38        Handle(sys::ZX_HANDLE_INVALID)
39    }
40
41    /// If a raw handle is obtained from some other source, this method converts
42    /// it into a type-safe owned handle.
43    pub unsafe fn from_raw(raw: sys::zx_handle_t) -> Handle {
44        Handle(raw)
45    }
46
47    pub fn is_invalid(&self) -> bool {
48        self.0 == sys::ZX_HANDLE_INVALID
49    }
50
51    pub fn replace(self, rights: Rights) -> Result<Handle, Status> {
52        let handle = self.0;
53        let mut out = 0;
54        let status = unsafe { sys::zx_handle_replace(handle, rights.bits(), &mut out) };
55        ok(status).map(|()| Handle(out))
56    }
57}
58
59/// A borrowed reference to a `Handle`.
60///
61/// Mostly useful as part of a `WaitItem`.
62#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
63pub struct HandleRef<'a> {
64    handle: sys::zx_handle_t,
65    phantom: PhantomData<&'a sys::zx_handle_t>,
66}
67
68impl<'a> HandleRef<'a> {
69    pub fn raw_handle(&self) -> sys::zx_handle_t {
70        self.handle
71    }
72
73    pub fn duplicate(&self, rights: Rights) -> Result<Handle, Status> {
74        let handle = self.handle;
75        let mut out = 0;
76        let status = unsafe { sys::zx_handle_duplicate(handle, rights.bits(), &mut out) };
77        ok(status).map(|()| Handle(out))
78    }
79
80    pub fn signal(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
81        let handle = self.handle;
82        let status = unsafe { sys::zx_object_signal(handle, clear_mask.bits(), set_mask.bits()) };
83        ok(status)
84    }
85
86    pub fn wait(&self, signals: Signals, deadline: Time) -> Result<Signals, Status> {
87        let handle = self.handle;
88        let mut pending = Signals::empty().bits();
89        let status = unsafe {
90            sys::zx_object_wait_one(handle, signals.bits(), deadline.nanos(), &mut pending)
91        };
92        ok(status).map(|()| Signals::from_bits_truncate(pending))
93    }
94
95    pub fn wait_async(&self, port: &Port, key: u64, signals: Signals, options: WaitAsyncOpts)
96        -> Result<(), Status>
97    {
98        let handle = self.handle;
99        let status = unsafe {
100            sys::zx_object_wait_async(
101                handle, port.raw_handle(), key, signals.bits(), options as u32)
102        };
103        ok(status)
104    }
105}
106
107/// A trait to get a reference to the underlying handle of an object.
108pub trait AsHandleRef {
109    /// Get a reference to the handle. One important use of such a reference is
110    /// for `object_wait_many`.
111    fn as_handle_ref(&self) -> HandleRef;
112
113    /// Interpret the reference as a raw handle (an integer type). Two distinct
114    /// handles will have different raw values (so it can perhaps be used as a
115    /// key in a data structure).
116    fn raw_handle(&self) -> sys::zx_handle_t {
117        self.as_handle_ref().raw_handle()
118    }
119
120    /// Set and clear userspace-accessible signal bits on an object. Wraps the
121    /// [zx_object_signal](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_signal.md)
122    /// syscall.
123    fn signal_handle(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
124        self.as_handle_ref().signal(clear_mask, set_mask)
125    }
126
127    /// Waits on a handle. Wraps the
128    /// [zx_object_wait_one](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_wait_one.md)
129    /// syscall.
130    fn wait_handle(&self, signals: Signals, deadline: Time) -> Result<Signals, Status> {
131        self.as_handle_ref().wait(signals, deadline)
132    }
133
134    /// Causes packet delivery on the given port when the object changes state and matches signals.
135    /// [zx_object_wait_async](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_wait_async.md)
136    /// syscall.
137    fn wait_async_handle(&self, port: &Port, key: u64, signals: Signals, options: WaitAsyncOpts)
138        -> Result<(), Status>
139    {
140        self.as_handle_ref().wait_async(port, key, signals, options)
141    }
142}
143
144impl<'a> AsHandleRef for HandleRef<'a> {
145    fn as_handle_ref(&self) -> HandleRef { *self }
146}
147
148/// A trait implemented by all handle-based types.
149///
150/// Note: it is reasonable for user-defined objects wrapping a handle to implement
151/// this trait. For example, a specific interface in some protocol might be
152/// represented as a newtype of `Channel`, and implement the `as_handle_ref`
153/// method and the `From<Handle>` trait to facilitate conversion from and to the
154/// interface.
155pub trait HandleBased: AsHandleRef + From<Handle> + Into<Handle> {
156    /// Duplicate a handle, possibly reducing the rights available. Wraps the
157    /// [zx_handle_duplicate](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/handle_duplicate.md)
158    /// syscall.
159    fn duplicate_handle(&self, rights: Rights) -> Result<Self, Status> {
160        self.as_handle_ref().duplicate(rights).map(|handle| Self::from(handle))
161    }
162
163    /// Create a replacement for a handle, possibly reducing the rights available. This invalidates
164    /// the original handle. Wraps the
165    /// [zx_handle_replace](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/handle_replace.md)
166    /// syscall.
167    fn replace_handle(self, rights: Rights) -> Result<Self, Status> {
168        <Self as Into<Handle>>::into(self)
169            .replace(rights).map(|handle| Self::from(handle))
170    }
171
172    /// Converts the value into its inner handle.
173    ///
174    /// This is a convenience function which simply forwards to the `Into` trait.
175    fn into_handle(self) -> Handle {
176        self.into()
177    }
178
179    /// Converts the handle into it's raw representation.
180    ///
181    /// The caller takes ownership over the raw handle, and must close or transfer it to avoid a handle leak.
182    fn into_raw(self) -> sys::zx_handle_t {
183        let h = self.into_handle();
184        let r = h.0;
185        mem::forget(h);
186        r
187   }
188
189    /// Creates an instance of this type from a handle.
190    ///
191    /// This is a convenience function which simply forwards to the `From` trait.
192    fn from_handle(handle: Handle) -> Self {
193        Self::from(handle)
194    }
195
196    /// Creates an instance of another handle-based type from this value's inner handle.
197    fn into_handle_based<H: HandleBased>(self) -> H {
198        H::from_handle(self.into_handle())
199    }
200
201    /// Creates an instance of this type from the inner handle of another
202    /// handle-based type.
203    fn from_handle_based<H: HandleBased>(h: H) -> Self {
204        Self::from_handle(h.into_handle())
205    }
206}
207
208/// A trait implemented by all handles for objects which have a peer.
209pub trait Peered: HandleBased {
210    /// Set and clear userspace-accessible signal bits on the object's peer. Wraps the
211    /// [zx_object_signal_peer](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_signal.md)
212    /// syscall.
213    fn signal_peer(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
214        let handle = self.as_handle_ref().handle;
215        let status = unsafe {
216            sys::zx_object_signal_peer(handle, clear_mask.bits(), set_mask.bits())
217        };
218        ok(status)
219    }
220}
221
222/// A trait implemented by all handles for objects which can have a cookie attached.
223pub trait Cookied: HandleBased {
224    /// Get the cookie attached to this object, if any. Wraps the
225    /// [zx_object_get_cookie](https://fuchsia.googlesource.com/zircon/+/HEAD/docs/syscalls/object_get_cookie.md)
226    /// syscall.
227    fn get_cookie(&self, scope: &HandleRef) -> Result<u64, Status> {
228        let handle = self.as_handle_ref().handle;
229        let mut cookie = 0;
230        let status = unsafe { sys::zx_object_get_cookie(handle, scope.handle, &mut cookie) };
231        ok(status).map(|()| cookie)
232    }
233
234    /// Attach an opaque cookie to this object with the given scope. The cookie may be read or
235    /// changed in future only with the same scope. Wraps the
236    /// [zx_object_set_cookie](https://fuchsia.googlesource.com/zircon/+/HEAD/docs/syscalls/object_set_cookie.md)
237    /// syscall.
238    fn set_cookie(&self, scope: &HandleRef, cookie: u64) -> Result<(), Status> {
239        let handle = self.as_handle_ref().handle;
240        let status = unsafe { sys::zx_object_set_cookie(handle, scope.handle, cookie) };
241        ok(status)
242    }
243}