commit
87c2d27a5a
@ -28,6 +28,7 @@ use std::ops::Deref;
|
||||
|
||||
const POLL_TIMEOUT: isize = 100;
|
||||
|
||||
/// Generic worker to handle service (binded) sockets
|
||||
pub struct Worker<S> where S: IpcInterface<S> {
|
||||
service: Arc<S>,
|
||||
sockets: Vec<(Socket, Endpoint)>,
|
||||
@ -35,6 +36,8 @@ pub struct Worker<S> where S: IpcInterface<S> {
|
||||
buf: Vec<u8>,
|
||||
}
|
||||
|
||||
/// struct for guarding `_endpoint` (so that it wont drop)
|
||||
/// derefs to client `S`
|
||||
pub struct GuardedSocket<S> where S: WithSocket<Socket> {
|
||||
client: Arc<S>,
|
||||
_endpoint: Endpoint,
|
||||
@ -48,6 +51,9 @@ impl<S> Deref for GuardedSocket<S> where S: WithSocket<Socket> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Spawns client <`S`> over specified address
|
||||
/// creates socket and connects endpoint to it
|
||||
/// for duplex (paired) connections with the service
|
||||
pub fn init_client<S>(socket_addr: &str) -> Result<GuardedSocket<S>, SocketError> where S: WithSocket<Socket> {
|
||||
let mut socket = try!(Socket::new(Protocol::Pair).map_err(|e| {
|
||||
warn!(target: "ipc", "Failed to create ipc socket: {:?}", e);
|
||||
@ -65,12 +71,15 @@ pub fn init_client<S>(socket_addr: &str) -> Result<GuardedSocket<S>, SocketError
|
||||
})
|
||||
}
|
||||
|
||||
/// Error occured while establising socket or endpoint
|
||||
#[derive(Debug)]
|
||||
pub enum SocketError {
|
||||
/// Error establising duplex (paired) socket and/or endpoint
|
||||
DuplexLink
|
||||
}
|
||||
|
||||
impl<S> Worker<S> where S: IpcInterface<S> {
|
||||
/// New worker over specified `service`
|
||||
pub fn new(service: Arc<S>) -> Worker<S> {
|
||||
Worker::<S> {
|
||||
service: service.clone(),
|
||||
@ -80,6 +89,7 @@ impl<S> Worker<S> where S: IpcInterface<S> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Polls all sockets, reads and dispatches method invocations
|
||||
pub fn poll(&mut self) {
|
||||
let mut request = PollRequest::new(&mut self.polls[..]);
|
||||
let _result_guard = Socket::poll(&mut request, POLL_TIMEOUT);
|
||||
@ -119,12 +129,15 @@ impl<S> Worker<S> where S: IpcInterface<S> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Stores nanomsg poll request for reuse
|
||||
fn rebuild_poll_request(&mut self) {
|
||||
self.polls = self.sockets.iter()
|
||||
.map(|&(ref socket, _)| socket.new_pollfd(PollInOut::In))
|
||||
.collect::<Vec<PollFd>>();
|
||||
}
|
||||
|
||||
/// Add exclusive socket for paired client
|
||||
/// Only one connection over this address is allowed
|
||||
pub fn add_duplex(&mut self, addr: &str) -> Result<(), SocketError> {
|
||||
let mut socket = try!(Socket::new(Protocol::Pair).map_err(|e| {
|
||||
warn!(target: "ipc", "Failed to create ipc socket: {:?}", e);
|
||||
|
@ -20,26 +20,35 @@ use std::io::{Read, Write};
|
||||
use std::marker::Sync;
|
||||
use semver::Version;
|
||||
|
||||
/// Handshake for client and server to negotiate api/protocol version
|
||||
pub struct Handshake {
|
||||
pub protocol_version: Version,
|
||||
pub api_version: Version,
|
||||
}
|
||||
|
||||
/// Allows to configure custom version and custom handshake response for
|
||||
/// ipc host
|
||||
pub trait IpcConfig {
|
||||
/// Current service api version
|
||||
/// Should be increased if any of the methods changes signature
|
||||
fn api_version() -> Version {
|
||||
Version::parse("1.0.0").unwrap()
|
||||
}
|
||||
|
||||
/// Current ipc protocol version
|
||||
/// Should be increased only if signature of system methods changes
|
||||
fn protocol_version() -> Version {
|
||||
Version::parse("1.0.0").unwrap()
|
||||
}
|
||||
|
||||
/// Default handshake requires exact versions match
|
||||
fn handshake(handshake: &Handshake) -> bool {
|
||||
handshake.protocol_version == Self::protocol_version() &&
|
||||
handshake.api_version == Self::api_version()
|
||||
}
|
||||
}
|
||||
|
||||
/// Error in dispatching or invoking methods via IPC
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
UnkownSystemCall,
|
||||
@ -48,6 +57,8 @@ pub enum Error {
|
||||
HandshakeFailed,
|
||||
}
|
||||
|
||||
/// Allows implementor to be attached to generic worker and dispatch rpc requests
|
||||
/// over IPC
|
||||
pub trait IpcInterface<T>: IpcConfig {
|
||||
/// reads the message from io, dispatches the call and returns serialized result
|
||||
fn dispatch<R>(&self, r: &mut R) -> Vec<u8> where R: Read;
|
||||
@ -79,11 +90,11 @@ pub fn invoke<W>(method_num: u16, params: &Option<Vec<u8>>, w: &mut W) where W:
|
||||
}
|
||||
}
|
||||
|
||||
/// IpcSocket
|
||||
/// IpcSocket, read/write generalization
|
||||
pub trait IpcSocket: Read + Write + Sync {
|
||||
}
|
||||
|
||||
|
||||
/// Basically something that needs only socket to be spawned
|
||||
pub trait WithSocket<S: IpcSocket> {
|
||||
fn init(socket: S) -> Self;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user