1 // Copyright 2017 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 //! Type-safe bindings for Zircon channel objects.
6
7 use {AsHandleRef, HandleBased, Handle, HandleRef, Peered, Status, Time, usize_into_u32, size_to_u32_sat};
8 use {sys, ok};
9 use std::mem;
10
11 /// An object representing a Zircon
12 /// [channel](https://fuchsia.googlesource.com/zircon/+/master/docs/objects/channel.md).
13 ///
14 /// As essentially a subtype of `Handle`, it can be freely interconverted.
15 #[derive(Debug, Eq, PartialEq, Hash)]
16 pub struct Channel(Handle);
17 impl_handle_based!(Channel);
18 impl Peered for Channel {}
19
20 impl Channel {
21 /// Create a channel, resulting an a pair of `Channel` objects representing both
22 /// sides of the channel. Messages written into one maybe read from the opposite.
23 ///
24 /// Wraps the
25 /// [zx_channel_create](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/channel_create.md)
26 /// syscall.
create() -> Result<(Channel, Channel), Status>27 pub fn create() -> Result<(Channel, Channel), Status> {
28 unsafe {
29 let mut handle0 = 0;
30 let mut handle1 = 0;
31 let opts = 0;
32 ok(sys::zx_channel_create(opts, &mut handle0, &mut handle1))?;
33 Ok((
34 Self::from(Handle::from_raw(handle0)),
35 Self::from(Handle::from_raw(handle1))
36 ))
37 }
38 }
39
40 /// Read a message from a channel. Wraps the
41 /// [zx_channel_read](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/channel_read.md)
42 /// syscall.
43 ///
44 /// If the `MessageBuf` lacks the capacity to hold the pending message,
45 /// returns an `Err` with the number of bytes and number of handles needed.
46 /// Otherwise returns an `Ok` with the result as usual.
read_raw(&self, buf: &mut MessageBuf) -> Result<Result<(), Status>, (usize, usize)>47 pub fn read_raw(&self, buf: &mut MessageBuf)
48 -> Result<Result<(), Status>, (usize, usize)>
49 {
50 let opts = 0;
51 unsafe {
52 buf.clear();
53 let raw_handle = self.raw_handle();
54 let mut num_bytes: u32 = size_to_u32_sat(buf.bytes.capacity());
55 let mut num_handles: u32 = size_to_u32_sat(buf.handles.capacity());
56 let status = ok(sys::zx_channel_read(raw_handle, opts,
57 buf.bytes.as_mut_ptr(), buf.handles.as_mut_ptr() as *mut _,
58 num_bytes, num_handles, &mut num_bytes, &mut num_handles));
59 if status == Err(Status::BUFFER_TOO_SMALL) {
60 Err((num_bytes as usize, num_handles as usize))
61 } else {
62 Ok(status.map(|()| {
63 buf.bytes.set_len(num_bytes as usize);
64 buf.handles.set_len(num_handles as usize);
65 }))
66 }
67 }
68 }
69
70 /// Read a message from a channel.
71 ///
72 /// Note that this method can cause internal reallocations in the `MessageBuf`
73 /// if it is lacks capacity to hold the full message. If such reallocations
74 /// are not desirable, use `read_raw` instead.
read(&self, buf: &mut MessageBuf) -> Result<(), Status>75 pub fn read(&self, buf: &mut MessageBuf) -> Result<(), Status> {
76 loop {
77 match self.read_raw(buf) {
78 Ok(result) => return result,
79 Err((num_bytes, num_handles)) => {
80 buf.ensure_capacity_bytes(num_bytes);
81 buf.ensure_capacity_handles(num_handles);
82 }
83 }
84 }
85 }
86
87 /// Write a message to a channel. Wraps the
88 /// [zx_channel_write](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/channel_write.md)
89 /// syscall.
write(&self, bytes: &[u8], handles: &mut Vec<Handle>) -> Result<(), Status>90 pub fn write(&self, bytes: &[u8], handles: &mut Vec<Handle>)
91 -> Result<(), Status>
92 {
93 let opts = 0;
94 let n_bytes = try!(usize_into_u32(bytes.len()).map_err(|_| Status::OUT_OF_RANGE));
95 let n_handles = try!(usize_into_u32(handles.len()).map_err(|_| Status::OUT_OF_RANGE));
96 unsafe {
97 let status = sys::zx_channel_write(self.raw_handle(), opts, bytes.as_ptr(), n_bytes,
98 handles.as_ptr() as *const sys::zx_handle_t, n_handles);
99 ok(status)?;
100 // Handles were successfully transferred, forget them on sender side
101 handles.set_len(0);
102 Ok(())
103 }
104 }
105
106 /// Send a message consisting of the given bytes and handles to a channel and await a reply. The
107 /// bytes should start with a four byte 'txid' which is used to identify the matching reply.
108 ///
109 /// Wraps the
110 /// [zx_channel_call](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/channel_call.md)
111 /// syscall.
112 ///
113 /// Note that unlike [`read`][read], the caller must ensure that the MessageBuf has enough
114 /// capacity for the bytes and handles which will be received, as replies which are too large
115 /// are discarded.
116 ///
117 /// On failure returns the both the main and read status.
118 ///
119 /// [read]: struct.Channel.html#method.read
call(&self, timeout: Time, bytes: &[u8], handles: &mut Vec<Handle>, buf: &mut MessageBuf) -> Result<(), (Status, Status)>120 pub fn call(&self, timeout: Time, bytes: &[u8], handles: &mut Vec<Handle>,
121 buf: &mut MessageBuf) -> Result<(), (Status, Status)>
122 {
123 let write_num_bytes = try!(usize_into_u32(bytes.len()).map_err(
124 |_| (Status::OUT_OF_RANGE, Status::OK)));
125 let write_num_handles = try!(usize_into_u32(handles.len()).map_err(
126 |_| (Status::OUT_OF_RANGE, Status::OK)));
127 buf.clear();
128 let read_num_bytes: u32 = size_to_u32_sat(buf.bytes.capacity());
129 let read_num_handles: u32 = size_to_u32_sat(buf.handles.capacity());
130 let args = sys::zx_channel_call_args_t {
131 wr_bytes: bytes.as_ptr(),
132 wr_handles: handles.as_ptr() as *const sys::zx_handle_t,
133 rd_bytes: buf.bytes.as_mut_ptr(),
134 rd_handles: buf.handles.as_mut_ptr() as *mut _,
135 wr_num_bytes: write_num_bytes,
136 wr_num_handles: write_num_handles,
137 rd_num_bytes: read_num_bytes,
138 rd_num_handles: read_num_handles,
139 };
140 let mut actual_read_bytes: u32 = 0;
141 let mut actual_read_handles: u32 = 0;
142 let mut read_status = Status::OK.into_raw();
143 let options = 0;
144 let status = unsafe {
145 Status::from_raw(
146 sys::zx_channel_call(
147 self.raw_handle(), options, timeout.nanos(), &args, &mut actual_read_bytes,
148 &mut actual_read_handles, &mut read_status))
149 };
150
151 match status {
152 Status::OK |
153 Status::TIMED_OUT |
154 Status::CALL_FAILED => {
155 // Handles were successfully transferred,
156 // even if we didn't get a response, so forget
157 // them on the sender side.
158 unsafe { handles.set_len(0); }
159 }
160 _ => {}
161 }
162
163 unsafe {
164 buf.bytes.set_len(actual_read_bytes as usize);
165 buf.handles.set_len(actual_read_handles as usize);
166 }
167 if Status::OK == status {
168 Ok(())
169 } else {
170 Err((status, Status::from_raw(read_status)))
171 }
172 }
173 }
174
175 #[test]
test_handle_repr()176 pub fn test_handle_repr() {
177 assert_eq!(::std::mem::size_of::<sys::zx_handle_t>(), 4);
178 assert_eq!(::std::mem::size_of::<Handle>(), 4);
179 assert_eq!(::std::mem::align_of::<sys::zx_handle_t>(), ::std::mem::align_of::<Handle>());
180
181 // This test asserts that repr(transparent) still works for Handle -> zx_handle_t
182
183 let n: Vec<sys::zx_handle_t> = vec![0, 100, 2<<32-1];
184 let v: Vec<Handle> = n.iter().map(|h| unsafe { Handle::from_raw(*h) } ).collect();
185
186 for (handle, raw) in v.iter().zip(n.iter()) {
187 unsafe {
188 assert_eq!(*(handle as *const _ as *const [u8; 4]), *(raw as *const _ as *const [u8; 4]));
189 }
190 }
191
192 for h in v.into_iter() {
193 ::std::mem::forget(h);
194 }
195 }
196
197 impl AsRef<Channel> for Channel {
as_ref(&self) -> &Self198 fn as_ref(&self) -> &Self {
199 &self
200 }
201 }
202
203 /// A buffer for _receiving_ messages from a channel.
204 ///
205 /// A `MessageBuf` is essentially a byte buffer and a vector of
206 /// handles, but move semantics for "taking" handles requires special handling.
207 ///
208 /// Note that for sending messages to a channel, the caller manages the buffers,
209 /// using a plain byte slice and `Vec<Handle>`.
210 #[derive(Default)]
211 #[derive(Debug)]
212 pub struct MessageBuf {
213 bytes: Vec<u8>,
214 handles: Vec<Handle>,
215 }
216
217 impl MessageBuf {
218 /// Create a new, empty, message buffer.
new() -> Self219 pub fn new() -> Self {
220 Default::default()
221 }
222
223 /// Create a new non-empty message buffer.
new_with(v: Vec<u8>, h: Vec<Handle>) -> Self224 pub fn new_with(v: Vec<u8>, h: Vec<Handle>) -> Self {
225 Self{
226 bytes: v,
227 handles: h,
228 }
229 }
230
231 /// Ensure that the buffer has the capacity to hold at least `n_bytes` bytes.
ensure_capacity_bytes(&mut self, n_bytes: usize)232 pub fn ensure_capacity_bytes(&mut self, n_bytes: usize) {
233 ensure_capacity(&mut self.bytes, n_bytes);
234 }
235
236 /// Ensure that the buffer has the capacity to hold at least `n_handles` handles.
ensure_capacity_handles(&mut self, n_handles: usize)237 pub fn ensure_capacity_handles(&mut self, n_handles: usize) {
238 ensure_capacity(&mut self.handles, n_handles);
239 }
240
241 /// Ensure that at least n_bytes bytes are initialized (0 fill).
ensure_initialized_bytes(&mut self, n_bytes: usize)242 pub fn ensure_initialized_bytes(&mut self, n_bytes: usize) {
243 if n_bytes <= self.bytes.len() {
244 return;
245 }
246 self.bytes.resize(n_bytes, 0);
247 }
248
249 /// Get a reference to the bytes of the message buffer, as a `&[u8]` slice.
bytes(&self) -> &[u8]250 pub fn bytes(&self) -> &[u8] {
251 self.bytes.as_slice()
252 }
253
254 /// The number of handles in the message buffer. Note this counts the number
255 /// available when the message was received; `take_handle` does not affect
256 /// the count.
n_handles(&self) -> usize257 pub fn n_handles(&self) -> usize {
258 self.handles.len()
259 }
260
261 /// Take the handle at the specified index from the message buffer. If the
262 /// method is called again with the same index, it will return `None`, as
263 /// will happen if the index exceeds the number of handles available.
take_handle(&mut self, index: usize) -> Option<Handle>264 pub fn take_handle(&mut self, index: usize) -> Option<Handle> {
265 self.handles.get_mut(index).and_then(|handle|
266 if handle.is_invalid() {
267 None
268 } else {
269 Some(mem::replace(handle, Handle::invalid()))
270 }
271 )
272 }
273
274 /// Clear the bytes and handles contained in the buf. This will drop any
275 /// contained handles, resulting in their resources being freed.
clear(&mut self)276 pub fn clear(&mut self) {
277 self.bytes.clear();
278 self.handles.clear();
279 }
280 }
281
ensure_capacity<T>(vec: &mut Vec<T>, size: usize)282 fn ensure_capacity<T>(vec: &mut Vec<T>, size: usize) {
283 let len = vec.len();
284 if size > len {
285 vec.reserve(size - len);
286 }
287 }
288
289 #[cfg(test)]
290 mod tests {
291 use super::*;
292 use {DurationNum, Rights, Signals, Vmo};
293 use std::thread;
294
295 #[test]
channel_basic()296 fn channel_basic() {
297 let (p1, p2) = Channel::create().unwrap();
298
299 let mut empty = vec![];
300 assert!(p1.write(b"hello", &mut empty).is_ok());
301
302 let mut buf = MessageBuf::new();
303 assert!(p2.read(&mut buf).is_ok());
304 assert_eq!(buf.bytes(), b"hello");
305 }
306
307 #[test]
channel_read_raw_too_small()308 fn channel_read_raw_too_small() {
309 let (p1, p2) = Channel::create().unwrap();
310
311 let mut empty = vec![];
312 assert!(p1.write(b"hello", &mut empty).is_ok());
313
314 let mut buf = MessageBuf::new();
315 let result = p2.read_raw(&mut buf);
316 assert_eq!(result, Err((5, 0)));
317 assert_eq!(buf.bytes(), b"");
318 }
319
320 #[test]
channel_send_handle()321 fn channel_send_handle() {
322 let hello_length: usize = 5;
323
324 // Create a pair of channels and a virtual memory object.
325 let (p1, p2) = Channel::create().unwrap();
326 let vmo = Vmo::create(hello_length as u64).unwrap();
327
328 // Duplicate VMO handle and send it down the channel.
329 let duplicate_vmo_handle = vmo.duplicate_handle(Rights::SAME_RIGHTS).unwrap().into();
330 let mut handles_to_send: Vec<Handle> = vec![duplicate_vmo_handle];
331 assert!(p1.write(b"", &mut handles_to_send).is_ok());
332 // Handle should be removed from vector.
333 assert!(handles_to_send.is_empty());
334
335 // Read the handle from the receiving channel.
336 let mut buf = MessageBuf::new();
337 assert!(p2.read(&mut buf).is_ok());
338 assert_eq!(buf.n_handles(), 1);
339 // Take the handle from the buffer.
340 let received_handle = buf.take_handle(0).unwrap();
341 // Should not affect number of handles.
342 assert_eq!(buf.n_handles(), 1);
343 // Trying to take it again should fail.
344 assert!(buf.take_handle(0).is_none());
345
346 // Now to test that we got the right handle, try writing something to it...
347 let received_vmo = Vmo::from(received_handle);
348 assert_eq!(received_vmo.write(b"hello", 0).unwrap(), hello_length);
349
350 // ... and reading it back from the original VMO.
351 let mut read_vec = vec![0; hello_length];
352 assert_eq!(vmo.read(&mut read_vec, 0).unwrap(), hello_length);
353 assert_eq!(read_vec, b"hello");
354 }
355
356 #[test]
channel_call_timeout()357 fn channel_call_timeout() {
358 let ten_ms = 10.millis();
359
360 // Create a pair of channels and a virtual memory object.
361 let (p1, p2) = Channel::create().unwrap();
362 let vmo = Vmo::create(0 as u64).unwrap();
363
364 // Duplicate VMO handle and send it along with the call.
365 let duplicate_vmo_handle = vmo.duplicate_handle(Rights::SAME_RIGHTS).unwrap().into();
366 let mut handles_to_send: Vec<Handle> = vec![duplicate_vmo_handle];
367 let mut buf = MessageBuf::new();
368 assert_eq!(p1.call(ten_ms.after_now(), b"call", &mut handles_to_send, &mut buf),
369 Err((Status::TIMED_OUT, Status::OK)));
370 // Handle should be removed from vector even though we didn't get a response, as it was
371 // still sent over the channel.
372 assert!(handles_to_send.is_empty());
373
374 // Should be able to read call even though it timed out waiting for a response.
375 let mut buf = MessageBuf::new();
376 assert!(p2.read(&mut buf).is_ok());
377 assert_eq!(buf.bytes(), b"call");
378 assert_eq!(buf.n_handles(), 1);
379 }
380
381 #[test]
channel_call()382 fn channel_call() {
383 // Create a pair of channels
384 let (p1, p2) = Channel::create().unwrap();
385
386 // create an mpsc channel for communicating the call data for later assertion
387 let (tx, rx) = ::std::sync::mpsc::channel();
388
389 // Start a new thread to respond to the call.
390 thread::spawn(move || {
391 let mut buf = MessageBuf::new();
392 // if either the read or the write fail, this thread will panic,
393 // resulting in tx being dropped, which will be noticed by the rx.
394 p2.wait_handle(Signals::CHANNEL_READABLE, 1.seconds().after_now()).expect("callee wait error");
395 p2.read(&mut buf).expect("callee read error");
396 p2.write(b"txidresponse", &mut vec![]).expect("callee write error");
397 tx.send(buf).expect("callee mpsc send error");
398 });
399
400 // Make the call.
401 let mut buf = MessageBuf::new();
402 buf.ensure_capacity_bytes(12);
403 // NOTE(raggi): CQ has been seeing some long stalls from channel call,
404 // and it's as yet unclear why. The timeout here has been made much
405 // larger in order to avoid that, as the issues are not issues with this
406 // crate's concerns. The timeout is here just to prevent the tests from
407 // stalling forever if a developer makes a mistake locally in this
408 // crate. Tests of Zircon behavior or virtualization behavior should be
409 // covered elsewhere. See ZX-1324.
410 p1.call(30.seconds().after_now(), b"txidcall", &mut vec![], &mut buf).expect("channel call error");
411 assert_eq!(buf.bytes(), b"txidresponse");
412 assert_eq!(buf.n_handles(), 0);
413
414 let sbuf = rx.recv().expect("mpsc channel recv error");
415 assert_eq!(sbuf.bytes(), b"txidcall");
416 assert_eq!(sbuf.n_handles(), 0);
417 }
418 }
419