Index: mojo/public/rust/src/bindings/mojom.rs |
diff --git a/mojo/public/rust/src/bindings/mojom.rs b/mojo/public/rust/src/bindings/mojom.rs |
index e0dbf9b9776b2ae719dc691bb5f2bbddac76e2f5..8401bb7ddbe3b94fa39acf702b9da000a08369e3 100644 |
--- a/mojo/public/rust/src/bindings/mojom.rs |
+++ b/mojo/public/rust/src/bindings/mojom.rs |
@@ -15,7 +15,7 @@ use std::panic; |
use std::ptr; |
use std::vec::Vec; |
-use system::{CastHandle, Handle, UntypedHandle}; |
+use system::{MojoResult, CastHandle, Handle, UntypedHandle}; |
use system::data_pipe; |
use system::message_pipe; |
use system::shared_buffer; |
@@ -204,7 +204,7 @@ pub trait MojomInterface: MojomEncodable { |
fn service_name() -> &'static str; |
/// Get the version for this interface. |
- fn version() -> u32; |
+ fn version(&self) -> u32; |
/// Access the underlying message pipe for this interface. |
fn pipe(&self) -> &message_pipe::MessageEndpoint; |
@@ -213,6 +213,16 @@ pub trait MojomInterface: MojomEncodable { |
fn unwrap(self) -> message_pipe::MessageEndpoint; |
} |
+/// An error that may occur when sending data over a Mojom interface. |
+#[derive(Debug)] |
+pub enum MojomSendError { |
+ /// Failed to write to the underlying message pipe. |
+ FailedWrite(MojoResult), |
+ |
+ /// The version is too old to write the attempted message. |
+ OldVersion(u32, u32), |
+} |
+ |
/// Whatever implements this trait is considered to be a Mojom |
/// interface that may send messages of some generic type. |
/// |
@@ -220,11 +230,13 @@ pub trait MojomInterface: MojomEncodable { |
/// a tighter trait bound than MojomMessage that limits the types |
/// available for sending to those that are valid messages available |
/// to the interface. |
+/// |
+/// TODO(mknyszek): Add sending control messages |
pub trait MojomInterfaceSend<R: MojomMessage>: MojomInterface { |
/// Creates a message. |
- fn create_request(&self, payload: R) -> (Vec<u8>, Vec<UntypedHandle>) { |
- let header = R::create_header(); |
- // TODO(mknyszek): Calculate and set an actual request id |
+ fn create_request(&self, req_id: u64, payload: R) -> (Vec<u8>, Vec<UntypedHandle>) { |
+ let mut header = R::create_header(); |
+ header.request_id = req_id; |
let header_size = header.compute_size(Default::default()); |
let size = header_size + payload.compute_size(Default::default()); |
let mut buffer: Vec<u8> = Vec::with_capacity(size); |
@@ -238,13 +250,30 @@ pub trait MojomInterfaceSend<R: MojomMessage>: MojomInterface { |
(buffer, handles) |
} |
- /// Creates and sends a message. |
- fn send_request(&self, payload: R) { |
- let (buffer, handles) = self.create_request(payload); |
- self.pipe().write(&buffer, handles, mpflags!(Write::None)); |
+ /// Creates and sends a message, and returns its request ID. |
+ fn send_request(&self, req_id: u64, payload: R) -> Result<(), MojomSendError> { |
+ if self.version() < R::min_version() { |
+ return Err(MojomSendError::OldVersion(self.version(), R::min_version())); |
+ } |
+ let (buffer, handles) = self.create_request(req_id, payload); |
+ match self.pipe().write(&buffer, handles, mpflags!(Write::None)) { |
+ MojoResult::Okay => Ok(()), |
+ err => Err(MojomSendError::FailedWrite(err)), |
+ } |
} |
} |
+/// An error that may occur when attempting to recieve a message over a |
+/// Mojom interface. |
+#[derive(Debug)] |
+pub enum MojomRecvError { |
+ /// Failed to read from the underlying message pipe. |
+ FailedRead(MojoResult), |
+ |
+ /// Failed to validate the buffer during decode. |
+ FailedValidation(ValidationError), |
+} |
+ |
/// Whatever implements this trait is considered to be a Mojom |
/// interface that may recieve messages for some interface. |
/// |
@@ -252,14 +281,22 @@ pub trait MojomInterfaceSend<R: MojomMessage>: MojomInterface { |
/// which can contain any of the potential messages that may be recieved. |
/// This way, we can return that type and let the user multiplex over |
/// what message was received. |
+/// |
+/// TODO(mknyszek): Add responding to control messages |
pub trait MojomInterfaceRecv: MojomInterface { |
type Container: MojomMessageOption; |
/// Tries to read a message from a pipe and decodes it. |
- fn recv_response(&self) -> Result<Self::Container, ValidationError> { |
- // TODO(mknyszek): Actually handle errors with reading |
- let (buffer, handles) = self.pipe().read(mpflags!(Read::None)).unwrap(); |
- Self::Container::decode_message(buffer, handles) |
+ fn recv_response(&self) -> Result<(u64, Self::Container), MojomRecvError> { |
+ match self.pipe().read(mpflags!(Read::None)) { |
+ Ok((buffer, handles)) => { |
+ match Self::Container::decode_message(buffer, handles) { |
+ Ok((req_id, val)) => Ok((req_id, val)), |
+ Err(err) => Err(MojomRecvError::FailedValidation(err)), |
+ } |
+ }, |
+ Err(err) => Err(MojomRecvError::FailedRead(err)), |
+ } |
} |
} |
@@ -295,6 +332,7 @@ pub trait MojomStruct: MojomPointer { |
/// Marks a MojomStruct as being capable of being sent across some |
/// Mojom interface. |
pub trait MojomMessage: MojomStruct { |
+ fn min_version() -> u32; |
fn create_header() -> MessageHeader; |
} |
@@ -310,14 +348,13 @@ pub trait MojomMessageOption: Sized { |
fn decode_payload(header: MessageHeader, buffer: &[u8], handles: Vec<UntypedHandle>) -> Result<Self, ValidationError>; |
/// Decodes the message header and then the payload, returning a new |
- /// copy of itself. |
- fn decode_message(buffer: Vec<u8>, handles: Vec<UntypedHandle>) -> Result<Self, ValidationError> { |
- let header = match MessageHeader::deserialize(&buffer[..], Vec::new()) { |
- Ok(header) => header, |
- Err(err) => return Err(err), |
- }; |
+ /// copy of itself and the request ID found in the header. |
+ fn decode_message(buffer: Vec<u8>, handles: Vec<UntypedHandle>) -> Result<(u64, Self), ValidationError> { |
+ let header = try!(MessageHeader::deserialize(&buffer[..], Vec::new())); |
let payload_buffer = &buffer[header.serialized_size(&Default::default())..]; |
- Self::decode_payload(header, payload_buffer, handles) |
+ let req_id = header.request_id; |
+ let ret = try!(Self::decode_payload(header, payload_buffer, handles)); |
+ Ok((req_id, ret)) |
} |
} |