OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 use bindings::decoding::{Decoder, ValidationError}; | 5 use bindings::decoding::{Decoder, ValidationError}; |
6 use bindings::encoding; | 6 use bindings::encoding; |
7 use bindings::encoding::{Bits, Encoder, Context, DATA_HEADER_SIZE, DataHeader, D
ataHeaderValue}; | 7 use bindings::encoding::{Bits, Encoder, Context, DATA_HEADER_SIZE, DataHeader, D
ataHeaderValue}; |
8 use bindings::message::MessageHeader; | 8 use bindings::message::MessageHeader; |
9 | 9 |
10 use std::cmp::Eq; | 10 use std::cmp::Eq; |
11 use std::collections::HashMap; | 11 use std::collections::HashMap; |
12 use std::hash::Hash; | 12 use std::hash::Hash; |
13 use std::mem; | 13 use std::mem; |
14 use std::panic; | 14 use std::panic; |
15 use std::ptr; | 15 use std::ptr; |
16 use std::vec::Vec; | 16 use std::vec::Vec; |
17 | 17 |
18 use system::{CastHandle, Handle, UntypedHandle}; | 18 use system::{MojoResult, CastHandle, Handle, UntypedHandle}; |
19 use system::data_pipe; | 19 use system::data_pipe; |
20 use system::message_pipe; | 20 use system::message_pipe; |
21 use system::shared_buffer; | 21 use system::shared_buffer; |
22 use system::wait_set; | 22 use system::wait_set; |
23 | 23 |
24 /// The size of a Mojom map plus header in bytes. | 24 /// The size of a Mojom map plus header in bytes. |
25 const MAP_SIZE: usize = 24; | 25 const MAP_SIZE: usize = 24; |
26 | 26 |
27 /// The sorted set of versions for a map. | 27 /// The sorted set of versions for a map. |
28 const MAP_VERSIONS: [(u32, u32); 1] = [(0, MAP_SIZE as u32)]; | 28 const MAP_VERSIONS: [(u32, u32); 1] = [(0, MAP_SIZE as u32)]; |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
197 /// interface, that is, a message pipe which conforms to some | 197 /// interface, that is, a message pipe which conforms to some |
198 /// messaging interface. | 198 /// messaging interface. |
199 /// | 199 /// |
200 /// We force an underlying message pipe to be used via the pipe() | 200 /// We force an underlying message pipe to be used via the pipe() |
201 /// and unwrap() routines. | 201 /// and unwrap() routines. |
202 pub trait MojomInterface: MojomEncodable { | 202 pub trait MojomInterface: MojomEncodable { |
203 /// Get the service name for this interface. | 203 /// Get the service name for this interface. |
204 fn service_name() -> &'static str; | 204 fn service_name() -> &'static str; |
205 | 205 |
206 /// Get the version for this interface. | 206 /// Get the version for this interface. |
207 fn version() -> u32; | 207 fn version(&self) -> u32; |
208 | 208 |
209 /// Access the underlying message pipe for this interface. | 209 /// Access the underlying message pipe for this interface. |
210 fn pipe(&self) -> &message_pipe::MessageEndpoint; | 210 fn pipe(&self) -> &message_pipe::MessageEndpoint; |
211 | 211 |
212 /// Unwrap the interface into its underlying message pipe. | 212 /// Unwrap the interface into its underlying message pipe. |
213 fn unwrap(self) -> message_pipe::MessageEndpoint; | 213 fn unwrap(self) -> message_pipe::MessageEndpoint; |
214 } | 214 } |
215 | 215 |
| 216 /// An error that may occur when sending data over a Mojom interface. |
| 217 #[derive(Debug)] |
| 218 pub enum MojomSendError { |
| 219 /// Failed to write to the underlying message pipe. |
| 220 FailedWrite(MojoResult), |
| 221 |
| 222 /// The version is too old to write the attempted message. |
| 223 OldVersion(u32, u32), |
| 224 } |
| 225 |
216 /// Whatever implements this trait is considered to be a Mojom | 226 /// Whatever implements this trait is considered to be a Mojom |
217 /// interface that may send messages of some generic type. | 227 /// interface that may send messages of some generic type. |
218 /// | 228 /// |
219 /// When implementing this trait, the correct way is to specify | 229 /// When implementing this trait, the correct way is to specify |
220 /// a tighter trait bound than MojomMessage that limits the types | 230 /// a tighter trait bound than MojomMessage that limits the types |
221 /// available for sending to those that are valid messages available | 231 /// available for sending to those that are valid messages available |
222 /// to the interface. | 232 /// to the interface. |
| 233 /// |
| 234 /// TODO(mknyszek): Add sending control messages |
223 pub trait MojomInterfaceSend<R: MojomMessage>: MojomInterface { | 235 pub trait MojomInterfaceSend<R: MojomMessage>: MojomInterface { |
224 /// Creates a message. | 236 /// Creates a message. |
225 fn create_request(&self, payload: R) -> (Vec<u8>, Vec<UntypedHandle>) { | 237 fn create_request(&self, req_id: u64, payload: R) -> (Vec<u8>, Vec<UntypedHa
ndle>) { |
226 let header = R::create_header(); | 238 let mut header = R::create_header(); |
227 // TODO(mknyszek): Calculate and set an actual request id | 239 header.request_id = req_id; |
228 let header_size = header.compute_size(Default::default()); | 240 let header_size = header.compute_size(Default::default()); |
229 let size = header_size + payload.compute_size(Default::default()); | 241 let size = header_size + payload.compute_size(Default::default()); |
230 let mut buffer: Vec<u8> = Vec::with_capacity(size); | 242 let mut buffer: Vec<u8> = Vec::with_capacity(size); |
231 buffer.resize(size, 0); | 243 buffer.resize(size, 0); |
232 let handles = { | 244 let handles = { |
233 let (header_buf, rest_buf) = buffer.split_at_mut(header_size); | 245 let (header_buf, rest_buf) = buffer.split_at_mut(header_size); |
234 let mut handles = header.serialize(header_buf); | 246 let mut handles = header.serialize(header_buf); |
235 handles.extend(payload.serialize(rest_buf).into_iter()); | 247 handles.extend(payload.serialize(rest_buf).into_iter()); |
236 handles | 248 handles |
237 }; | 249 }; |
238 (buffer, handles) | 250 (buffer, handles) |
239 } | 251 } |
240 | 252 |
241 /// Creates and sends a message. | 253 /// Creates and sends a message, and returns its request ID. |
242 fn send_request(&self, payload: R) { | 254 fn send_request(&self, req_id: u64, payload: R) -> Result<(), MojomSendError
> { |
243 let (buffer, handles) = self.create_request(payload); | 255 if self.version() < R::min_version() { |
244 self.pipe().write(&buffer, handles, mpflags!(Write::None)); | 256 return Err(MojomSendError::OldVersion(self.version(), R::min_version
())); |
| 257 } |
| 258 let (buffer, handles) = self.create_request(req_id, payload); |
| 259 match self.pipe().write(&buffer, handles, mpflags!(Write::None)) { |
| 260 MojoResult::Okay => Ok(()), |
| 261 err => Err(MojomSendError::FailedWrite(err)), |
| 262 } |
245 } | 263 } |
246 } | 264 } |
247 | 265 |
| 266 /// An error that may occur when attempting to recieve a message over a |
| 267 /// Mojom interface. |
| 268 #[derive(Debug)] |
| 269 pub enum MojomRecvError { |
| 270 /// Failed to read from the underlying message pipe. |
| 271 FailedRead(MojoResult), |
| 272 |
| 273 /// Failed to validate the buffer during decode. |
| 274 FailedValidation(ValidationError), |
| 275 } |
| 276 |
248 /// Whatever implements this trait is considered to be a Mojom | 277 /// Whatever implements this trait is considered to be a Mojom |
249 /// interface that may recieve messages for some interface. | 278 /// interface that may recieve messages for some interface. |
250 /// | 279 /// |
251 /// When implementing this trait, specify the container "union" type | 280 /// When implementing this trait, specify the container "union" type |
252 /// which can contain any of the potential messages that may be recieved. | 281 /// which can contain any of the potential messages that may be recieved. |
253 /// This way, we can return that type and let the user multiplex over | 282 /// This way, we can return that type and let the user multiplex over |
254 /// what message was received. | 283 /// what message was received. |
| 284 /// |
| 285 /// TODO(mknyszek): Add responding to control messages |
255 pub trait MojomInterfaceRecv: MojomInterface { | 286 pub trait MojomInterfaceRecv: MojomInterface { |
256 type Container: MojomMessageOption; | 287 type Container: MojomMessageOption; |
257 | 288 |
258 /// Tries to read a message from a pipe and decodes it. | 289 /// Tries to read a message from a pipe and decodes it. |
259 fn recv_response(&self) -> Result<Self::Container, ValidationError> { | 290 fn recv_response(&self) -> Result<(u64, Self::Container), MojomRecvError> { |
260 // TODO(mknyszek): Actually handle errors with reading | 291 match self.pipe().read(mpflags!(Read::None)) { |
261 let (buffer, handles) = self.pipe().read(mpflags!(Read::None)).unwrap(); | 292 Ok((buffer, handles)) => { |
262 Self::Container::decode_message(buffer, handles) | 293 match Self::Container::decode_message(buffer, handles) { |
| 294 Ok((req_id, val)) => Ok((req_id, val)), |
| 295 Err(err) => Err(MojomRecvError::FailedValidation(err)), |
| 296 } |
| 297 }, |
| 298 Err(err) => Err(MojomRecvError::FailedRead(err)), |
| 299 } |
263 } | 300 } |
264 } | 301 } |
265 | 302 |
266 /// Whatever implements this trait is considered to be a Mojom struct. | 303 /// Whatever implements this trait is considered to be a Mojom struct. |
267 /// | 304 /// |
268 /// Mojom structs are always the root of any Mojom message. Thus, we | 305 /// Mojom structs are always the root of any Mojom message. Thus, we |
269 /// provide convenience functions for serialization here. | 306 /// provide convenience functions for serialization here. |
270 pub trait MojomStruct: MojomPointer { | 307 pub trait MojomStruct: MojomPointer { |
271 /// Given a pre-allocated buffer, the struct serializes itself. | 308 /// Given a pre-allocated buffer, the struct serializes itself. |
272 fn serialize(self, buffer: &mut [u8]) -> Vec<UntypedHandle> { | 309 fn serialize(self, buffer: &mut [u8]) -> Vec<UntypedHandle> { |
(...skipping 15 matching lines...) Expand all Loading... |
288 /// Decode the type from a byte array and a set of handles. | 325 /// Decode the type from a byte array and a set of handles. |
289 fn deserialize(buffer: &[u8], handles: Vec<UntypedHandle>) -> Result<Self, V
alidationError> { | 326 fn deserialize(buffer: &[u8], handles: Vec<UntypedHandle>) -> Result<Self, V
alidationError> { |
290 let mut decoder = Decoder::new(buffer, handles); | 327 let mut decoder = Decoder::new(buffer, handles); |
291 Self::decode_new(&mut decoder, Default::default(), 0) | 328 Self::decode_new(&mut decoder, Default::default(), 0) |
292 } | 329 } |
293 } | 330 } |
294 | 331 |
295 /// Marks a MojomStruct as being capable of being sent across some | 332 /// Marks a MojomStruct as being capable of being sent across some |
296 /// Mojom interface. | 333 /// Mojom interface. |
297 pub trait MojomMessage: MojomStruct { | 334 pub trait MojomMessage: MojomStruct { |
| 335 fn min_version() -> u32; |
298 fn create_header() -> MessageHeader; | 336 fn create_header() -> MessageHeader; |
299 } | 337 } |
300 | 338 |
301 /// The trait for a "container" type intended to be used in MojomInterfaceRecv. | 339 /// The trait for a "container" type intended to be used in MojomInterfaceRecv. |
302 /// | 340 /// |
303 /// This trait contains the decode logic which decodes based on the message head
er | 341 /// This trait contains the decode logic which decodes based on the message head
er |
304 /// and returns itself: a union type which may contain any of the possible messa
ges | 342 /// and returns itself: a union type which may contain any of the possible messa
ges |
305 /// that may be sent across this interface. | 343 /// that may be sent across this interface. |
306 pub trait MojomMessageOption: Sized { | 344 pub trait MojomMessageOption: Sized { |
307 /// Decodes the actual payload of the message. | 345 /// Decodes the actual payload of the message. |
308 /// | 346 /// |
309 /// Implemented by a code generator. | 347 /// Implemented by a code generator. |
310 fn decode_payload(header: MessageHeader, buffer: &[u8], handles: Vec<Untyped
Handle>) -> Result<Self, ValidationError>; | 348 fn decode_payload(header: MessageHeader, buffer: &[u8], handles: Vec<Untyped
Handle>) -> Result<Self, ValidationError>; |
311 | 349 |
312 /// Decodes the message header and then the payload, returning a new | 350 /// Decodes the message header and then the payload, returning a new |
313 /// copy of itself. | 351 /// copy of itself and the request ID found in the header. |
314 fn decode_message(buffer: Vec<u8>, handles: Vec<UntypedHandle>) -> Result<Se
lf, ValidationError> { | 352 fn decode_message(buffer: Vec<u8>, handles: Vec<UntypedHandle>) -> Result<(u
64, Self), ValidationError> { |
315 let header = match MessageHeader::deserialize(&buffer[..], Vec::new()) { | 353 let header = try!(MessageHeader::deserialize(&buffer[..], Vec::new())); |
316 Ok(header) => header, | |
317 Err(err) => return Err(err), | |
318 }; | |
319 let payload_buffer = &buffer[header.serialized_size(&Default::default())
..]; | 354 let payload_buffer = &buffer[header.serialized_size(&Default::default())
..]; |
320 Self::decode_payload(header, payload_buffer, handles) | 355 let req_id = header.request_id; |
| 356 let ret = try!(Self::decode_payload(header, payload_buffer, handles)); |
| 357 Ok((req_id, ret)) |
321 } | 358 } |
322 } | 359 } |
323 | 360 |
324 // ********************************************** // | 361 // ********************************************** // |
325 // ****** IMPLEMENTATIONS FOR COMMON TYPES ****** // | 362 // ****** IMPLEMENTATIONS FOR COMMON TYPES ****** // |
326 // ********************************************** // | 363 // ********************************************** // |
327 | 364 |
328 macro_rules! impl_encodable_for_prim { | 365 macro_rules! impl_encodable_for_prim { |
329 ($($prim_type:ty),*) => { | 366 ($($prim_type:ty),*) => { |
330 $( | 367 $( |
(...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
851 impl_encodable_for_handle!(data_pipe::Consumer<T>); | 888 impl_encodable_for_handle!(data_pipe::Consumer<T>); |
852 } | 889 } |
853 | 890 |
854 impl<T> MojomEncodable for data_pipe::Producer<T> { | 891 impl<T> MojomEncodable for data_pipe::Producer<T> { |
855 impl_encodable_for_handle!(data_pipe::Producer<T>); | 892 impl_encodable_for_handle!(data_pipe::Producer<T>); |
856 } | 893 } |
857 | 894 |
858 impl MojomEncodable for wait_set::WaitSet { | 895 impl MojomEncodable for wait_set::WaitSet { |
859 impl_encodable_for_handle!(wait_set::WaitSet); | 896 impl_encodable_for_handle!(wait_set::WaitSet); |
860 } | 897 } |
OLD | NEW |