OLD | NEW |
| (Empty) |
1 // Copyright 2016 The Chromium 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 use std::mem; | |
6 use std::vec; | |
7 use std::ptr; | |
8 | |
9 use system::ffi; | |
10 use system::handle; | |
11 use system::handle::{CastHandle, Handle}; | |
12 // This full import is intentional; nearly every type in mojo_types needs to be
used. | |
13 use system::mojo_types::*; | |
14 | |
15 #[repr(u32)] | |
16 /// Create flags for message pipes | |
17 pub enum Create { | |
18 None = 0, | |
19 } | |
20 | |
21 #[repr(u32)] | |
22 /// Write flags for message pipes | |
23 pub enum Write { | |
24 None = 0, | |
25 } | |
26 | |
27 #[repr(u32)] | |
28 /// Read flags for message pipes | |
29 pub enum Read { | |
30 None = 0, | |
31 | |
32 /// If the message is unable to be | |
33 /// read for whatever reason, dequeue | |
34 /// it anyway | |
35 MayDiscard = 1 << 0, | |
36 } | |
37 | |
38 /// Creates a message pipe in Mojo and gives back two | |
39 /// MessageEndpoints which represent the endpoints of the | |
40 /// message pipe | |
41 pub fn create(flags: CreateFlags) -> Result<(MessageEndpoint, MessageEndpoint),
MojoResult> { | |
42 let mut handle0: MojoHandle = 0; | |
43 let mut handle1: MojoHandle = 0; | |
44 let opts = ffi::MojoCreateMessagePipeOptions { | |
45 struct_size: mem::size_of::<ffi::MojoCreateMessagePipeOptions>() as u32, | |
46 flags: flags, | |
47 _align: [], | |
48 }; | |
49 let raw_opts = &opts as *const ffi::MojoCreateMessagePipeOptions; | |
50 let r = MojoResult::from_code(unsafe { | |
51 ffi::MojoCreateMessagePipe(raw_opts, | |
52 &mut handle0 as *mut MojoHandle, | |
53 &mut handle1 as *mut MojoHandle) | |
54 }); | |
55 if r != MojoResult::Okay { | |
56 Err(r) | |
57 } else { | |
58 Ok((MessageEndpoint { handle: unsafe { handle::acquire(handle0) } }, | |
59 MessageEndpoint { handle: unsafe { handle::acquire(handle1) } })) | |
60 } | |
61 } | |
62 | |
63 /// Represents the one endpoint of a message pipe. | |
64 /// This data structure wraps a handle and acts | |
65 /// effectively as a typed handle. | |
66 pub struct MessageEndpoint { | |
67 handle: handle::UntypedHandle, | |
68 } | |
69 | |
70 impl MessageEndpoint { | |
71 /// Read the next message from the endpoint. Messages in Mojo | |
72 /// are some set of bytes plus a bunch of handles, so we | |
73 /// return both a vector of bytes and a vector of untyped handles. | |
74 /// | |
75 /// Because the handles are untyped, it is up to the user of this | |
76 /// library to know what type the handle actually is and to use | |
77 /// from_untyped in order to convert the handle to the correct type. | |
78 /// This is abstracted away, however, when using the Mojo bindings | |
79 /// generator where you may specify your interface in Mojom. | |
80 /// | |
81 /// If an empty message (that is, it has neither data nor handles) | |
82 /// is received, it will show up as an Err() containing MojoResult::Okay. | |
83 pub fn read(&self, | |
84 flags: ReadFlags) | |
85 -> Result<(vec::Vec<u8>, vec::Vec<handle::UntypedHandle>), MojoR
esult> { | |
86 let mut num_bytes: u32 = 0; | |
87 let mut num_handles: u32 = 0; | |
88 let result_prelim = MojoResult::from_code(unsafe { | |
89 ffi::MojoReadMessage(self.handle.get_native_handle(), | |
90 ptr::null_mut(), | |
91 &mut num_bytes as *mut u32, | |
92 ptr::null_mut(), | |
93 &mut num_handles as *mut u32, | |
94 flags) | |
95 }); | |
96 if result_prelim != MojoResult::ResourceExhausted { | |
97 return Err(result_prelim); | |
98 } | |
99 let mut buf: vec::Vec<u8> = vec::Vec::with_capacity(num_bytes as usize); | |
100 let mut raw_handles: vec::Vec<MojoHandle> = vec::Vec::with_capacity(num_
handles as usize); | |
101 let buf_ptr; | |
102 if num_bytes == 0 { | |
103 buf_ptr = ptr::null_mut(); | |
104 } else { | |
105 buf_ptr = buf.as_mut_ptr() as *mut ffi::c_void; | |
106 } | |
107 let raw_handles_ptr; | |
108 if num_handles == 0 { | |
109 raw_handles_ptr = ptr::null_mut(); | |
110 } else { | |
111 raw_handles_ptr = raw_handles.as_mut_ptr(); | |
112 } | |
113 let r = MojoResult::from_code(unsafe { | |
114 ffi::MojoReadMessage(self.handle.get_native_handle(), | |
115 buf_ptr, | |
116 &mut num_bytes as *mut u32, | |
117 raw_handles_ptr, | |
118 &mut num_handles as *mut u32, | |
119 flags) | |
120 }); | |
121 unsafe { | |
122 buf.set_len(num_bytes as usize); | |
123 raw_handles.set_len(num_handles as usize); | |
124 } | |
125 let mut handles: vec::Vec<handle::UntypedHandle> = | |
126 vec::Vec::with_capacity(num_handles as usize); | |
127 for raw_handle in raw_handles.iter() { | |
128 handles.push(unsafe { handle::acquire(*raw_handle) }); | |
129 } | |
130 if r != MojoResult::Okay { | |
131 Err(r) | |
132 } else { | |
133 Ok((buf, handles)) | |
134 } | |
135 } | |
136 | |
137 /// Write a message to the endpoint. Messages in Mojo | |
138 /// are some set of bytes plus a bunch of handles, so we | |
139 /// return both a vector of bytes and a vector of untyped handles. | |
140 /// | |
141 /// Because the handles are untyped, it is up to the user of this | |
142 /// library to know what type the handle actually is and to use | |
143 /// from_untyped in order to convert the handle to the correct type. | |
144 /// This is abstracted away, however, when using the Mojo bindings | |
145 /// generator where you may specify your interface in Mojom. | |
146 /// | |
147 /// Additionally, the handles passed in are consumed. This is because | |
148 /// Mojo handles operate on move semantics much like Rust data types. | |
149 /// When a handle is sent through a message pipe it is invalidated and | |
150 /// may not even be represented by the same integer on the other side, | |
151 /// so care must be taken to design your application with this in mind. | |
152 pub fn write(&self, | |
153 bytes: &[u8], | |
154 mut handles: vec::Vec<handle::UntypedHandle>, | |
155 flags: WriteFlags) | |
156 -> MojoResult { | |
157 let bytes_ptr; | |
158 if bytes.len() == 0 { | |
159 bytes_ptr = ptr::null(); | |
160 } else { | |
161 bytes_ptr = bytes.as_ptr() as *const ffi::c_void; | |
162 } | |
163 let mut raw_handles: vec::Vec<MojoHandle> = vec::Vec::with_capacity(hand
les.len()); | |
164 for handle in handles.iter_mut() { | |
165 unsafe { | |
166 raw_handles.push(handle.get_native_handle()); | |
167 handle.invalidate(); | |
168 } | |
169 } | |
170 let raw_handles_ptr; | |
171 if raw_handles.len() == 0 { | |
172 raw_handles_ptr = ptr::null(); | |
173 } else { | |
174 raw_handles_ptr = raw_handles.as_ptr(); | |
175 } | |
176 return MojoResult::from_code(unsafe { | |
177 ffi::MojoWriteMessage(self.handle.get_native_handle(), | |
178 bytes_ptr, | |
179 bytes.len() as u32, | |
180 raw_handles_ptr, | |
181 raw_handles.len() as u32, | |
182 flags) | |
183 }); | |
184 } | |
185 } | |
186 | |
187 impl CastHandle for MessageEndpoint { | |
188 /// Generates a MessageEndpoint from an untyped handle wrapper | |
189 /// See mojo::system::handle for information on untyped vs. typed | |
190 unsafe fn from_untyped(handle: handle::UntypedHandle) -> Self { | |
191 MessageEndpoint { handle: handle } | |
192 } | |
193 | |
194 /// Consumes this object and produces a plain handle wrapper | |
195 /// See mojo::system::handle for information on untyped vs. typed | |
196 fn as_untyped(self) -> handle::UntypedHandle { | |
197 self.handle | |
198 } | |
199 } | |
200 | |
201 impl Handle for MessageEndpoint { | |
202 /// Returns the native handle wrapped by this structure. | |
203 /// | |
204 /// See mojo::system::handle for information on handle wrappers | |
205 fn get_native_handle(&self) -> MojoHandle { | |
206 self.handle.get_native_handle() | |
207 } | |
208 } | |
OLD | NEW |