diff --git a/ipc/codegen/src/codegen.rs b/ipc/codegen/src/codegen.rs index 08944196f..63f225100 100644 --- a/ipc/codegen/src/codegen.rs +++ b/ipc/codegen/src/codegen.rs @@ -13,7 +13,6 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . - use aster; use syntax::ast::{ @@ -61,10 +60,24 @@ pub fn expand_ipc_implementation( }; push_client(cx, &builder, &item, &dispatches, push); + push_handshake_struct(cx, push); push(Annotatable::Item(impl_item)) } +fn push_handshake_struct(cx: &ExtCtxt, push: &mut FnMut(Annotatable)) { + let handshake_item = quote_item!(cx, + #[derive(Serialize, Deserialize)] + pub struct BinHandshake { + api_version: String, + protocol_version: String, + _reserved: Vec, + } + ).unwrap(); + + push(Annotatable::Item(handshake_item)); +} + fn field_name(builder: &aster::AstBuilder, arg: &Arg) -> ast::Ident { match arg.pat.node { PatKind::Ident(_, ref ident, _) => builder.id(ident.node), @@ -548,6 +561,14 @@ fn implement_interface( let dispatch_arms = implement_dispatch_arms(cx, builder, &dispatch_table, false); let dispatch_arms_buffered = implement_dispatch_arms(cx, builder, &dispatch_table, true); + let handshake_arm = quote_arm!(&cx, 0 => { + let handshake_payload = ::bincode::serde::deserialize_from::<_, BinHandshake>(r, ::bincode::SizeLimit::Infinite).unwrap(); + ::bincode::serde::serialize::(&Self::handshake(&::ipc::Handshake { + api_version: ::semver::Version::parse(&handshake_payload.api_version).unwrap(), + protocol_version: ::semver::Version::parse(&handshake_payload.protocol_version).unwrap(), + }), ::bincode::SizeLimit::Infinite).unwrap() + }); + Ok((quote_item!(cx, impl $impl_generics ::ipc::IpcInterface<$ty> for $ty $where_clause { fn dispatch(&self, r: &mut R) -> Vec @@ -561,6 +582,9 @@ fn implement_interface( } // method_num is a 16-bit little-endian unsigned number match method_num[1] as u16 + (method_num[0] as u16)*256 { + // handshake + $handshake_arm + // user methods $dispatch_arms _ => vec![] } diff --git a/ipc/rpc/src/interface.rs b/ipc/rpc/src/interface.rs index 060da36a9..5b5a30b27 100644 --- a/ipc/rpc/src/interface.rs +++ b/ipc/rpc/src/interface.rs @@ -22,9 +22,8 @@ use std::sync::atomic::*; use semver::Version; pub struct Handshake { - protocol_version: Version, - api_version: Version, - reserved: [u8; 64], + pub protocol_version: Version, + pub api_version: Version, } pub trait IpcConfig { @@ -34,13 +33,22 @@ pub trait IpcConfig { fn protocol_version() -> Version { Version::parse("1.0.0").unwrap() } + fn handshake(handshake: &Handshake) -> bool { + handshake.protocol_version == Self::protocol_version() && + handshake.api_version == Self::api_version() + } +} + +pub enum Error { + UnkownSystemCall, + ClientUnsupported, } pub trait IpcInterface where T: IpcConfig { /// reads the message from io, dispatches the call and returns serialized result fn dispatch(&self, r: &mut R) -> Vec where R: Read; - /// deserialize the payload from buffer, dispatches invoke and returns serialized result + /// deserializes the payload from buffer, dispatches invoke and returns serialized result /// (for non-blocking io) fn dispatch_buf(&self, method_num: u16, buf: &[u8]) -> Vec; } diff --git a/ipc/rpc/src/lib.rs b/ipc/rpc/src/lib.rs index a0d718871..f0083e66e 100644 --- a/ipc/rpc/src/lib.rs +++ b/ipc/rpc/src/lib.rs @@ -20,4 +20,4 @@ extern crate ethcore_devtools as devtools; extern crate semver; pub mod interface; -pub use interface::{IpcInterface, IpcSocket, invoke, IpcConfig}; +pub use interface::{IpcInterface, IpcSocket, invoke, IpcConfig, Handshake, Error}; diff --git a/ipc/tests/service.rs.in b/ipc/tests/service.rs.in index 14de716da..f48596e6c 100644 --- a/ipc/tests/service.rs.in +++ b/ipc/tests/service.rs.in @@ -16,6 +16,7 @@ use std::sync::RwLock; use std::ops::*; +use ipc::IpcConfig; pub struct Service { pub commits: RwLock,