1 use {Port, Rights, Signals, Status, Time, WaitAsyncOpts, ok, sys}; 2 use std::marker::PhantomData; 3 use 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)] 17 pub struct Handle(sys::zx_handle_t); 18 19 impl AsHandleRef for Handle { as_handle_ref(&self) -> HandleRef20 fn as_handle_ref(&self) -> HandleRef { 21 HandleRef { handle: self.0, phantom: Default::default() } 22 } 23 } 24 25 impl HandleBased for Handle {} 26 27 impl Drop for Handle { drop(&mut self)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 35 impl Handle { 36 /// Initialize a handle backed by ZX_HANDLE_INVALID, the only safe non-handle. invalid() -> Handle37 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. from_raw(raw: sys::zx_handle_t) -> Handle43 pub unsafe fn from_raw(raw: sys::zx_handle_t) -> Handle { 44 Handle(raw) 45 } 46 is_invalid(&self) -> bool47 pub fn is_invalid(&self) -> bool { 48 self.0 == sys::ZX_HANDLE_INVALID 49 } 50 replace(self, rights: Rights) -> Result<Handle, Status>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)] 63 pub struct HandleRef<'a> { 64 handle: sys::zx_handle_t, 65 phantom: PhantomData<&'a sys::zx_handle_t>, 66 } 67 68 impl<'a> HandleRef<'a> { raw_handle(&self) -> sys::zx_handle_t69 pub fn raw_handle(&self) -> sys::zx_handle_t { 70 self.handle 71 } 72 duplicate(&self, rights: Rights) -> Result<Handle, Status>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 signal(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status>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 wait(&self, signals: Signals, deadline: Time) -> Result<Signals, Status>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 wait_async(&self, port: &Port, key: u64, signals: Signals, options: WaitAsyncOpts) -> Result<(), Status>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. 108 pub trait AsHandleRef { 109 /// Get a reference to the handle. One important use of such a reference is 110 /// for `object_wait_many`. as_handle_ref(&self) -> HandleRef111 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). raw_handle(&self) -> sys::zx_handle_t116 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. signal_handle(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status>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. wait_handle(&self, signals: Signals, deadline: Time) -> Result<Signals, Status>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. wait_async_handle(&self, port: &Port, key: u64, signals: Signals, options: WaitAsyncOpts) -> Result<(), Status>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 144 impl<'a> AsHandleRef for HandleRef<'a> { as_handle_ref(&self) -> HandleRef145 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. 155 pub 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. duplicate_handle(&self, rights: Rights) -> Result<Self, Status>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. replace_handle(self, rights: Rights) -> Result<Self, Status>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. into_handle(self) -> Handle175 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. into_raw(self) -> sys::zx_handle_t182 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. from_handle(handle: Handle) -> Self192 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. into_handle_based<H: HandleBased>(self) -> H197 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. from_handle_based<H: HandleBased>(h: H) -> Self203 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. 209 pub 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. signal_peer(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status>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. 223 pub 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. get_cookie(&self, scope: &HandleRef) -> Result<u64, Status>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. set_cookie(&self, scope: &HandleRef, cookie: u64) -> Result<(), Status>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 } 244