diff --git a/ethcore/src/service.rs b/ethcore/src/service.rs index 5c6e2e93a..6d81f6b49 100644 --- a/ethcore/src/service.rs +++ b/ethcore/src/service.rs @@ -60,6 +60,7 @@ impl ClientService { config: ClientConfig, spec: &Spec, db_path: &Path, + ipc_path: &Path, miner: Arc, ) -> Result { @@ -86,7 +87,7 @@ impl ClientService { try!(io_service.register_handler(client_io)); let stop_guard = ::devtools::StopGuard::new(); - run_ipc(client.clone(), stop_guard.share()); + run_ipc(ipc_path, client.clone(), stop_guard.share()); Ok(ClientService { io_service: Arc::new(io_service), @@ -167,10 +168,13 @@ impl IoHandler for ClientIoHandler { } #[cfg(feature="ipc")] -fn run_ipc(client: Arc, stop: Arc) { +fn run_ipc(base_path: &Path, client: Arc, stop: Arc) { + let mut path = ::std::path::PathBuf::from(base_path); + path.push("parity-chain.ipc"); + let socket_addr = format!("ipc://{}", path.to_str().unwrap()); ::std::thread::spawn(move || { let mut worker = nanoipc::Worker::new(&(client as Arc)); - worker.add_reqrep("ipc:///tmp/parity-chain.ipc").expect("Ipc expected to initialize with no issues"); + worker.add_reqrep(&socket_addr).expect("Ipc expected to initialize with no issues"); while !stop.load(::std::sync::atomic::Ordering::Relaxed) { worker.poll(); @@ -179,7 +183,7 @@ fn run_ipc(client: Arc, stop: Arc) { } #[cfg(not(feature="ipc"))] -fn run_ipc(_client: Arc, _stop: Arc) { +fn run_ipc(_base_path: &Path, _client: Arc, _stop: Arc) { } #[cfg(test)] @@ -203,6 +207,7 @@ mod tests { ClientConfig::default(), &spec, &path, + &path, Arc::new(Miner::with_spec(&spec)), ); assert!(service.is_ok()); diff --git a/ipc/hypervisor/src/lib.rs b/ipc/hypervisor/src/lib.rs index 3e82908cd..b0e1564ab 100644 --- a/ipc/hypervisor/src/lib.rs +++ b/ipc/hypervisor/src/lib.rs @@ -26,7 +26,7 @@ extern crate semver; pub mod service; /// Default value for hypervisor ipc listener -pub const HYPERVISOR_IPC_URL: &'static str = "ipc:///tmp/parity-internal-hyper-status.ipc"; +pub const HYPERVISOR_IPC_URL: &'static str = "parity-internal-hyper-status.ipc"; use std::sync::{Arc,RwLock}; use service::{HypervisorService, IpcModuleId}; @@ -43,6 +43,7 @@ pub struct Hypervisor { ipc_worker: RwLock>, processes: RwLock>, modules: HashMap, + pub io_path: String, } /// Boot arguments for binary @@ -90,6 +91,11 @@ impl Hypervisor { self } + pub fn io_path(mut self, directory: &str) -> Hypervisor { + self.io_path = directory.to_owned(); + self + } + /// Starts with the specified address for the ipc listener and /// the specified list of modules in form of created service pub fn with_url(addr: &str) -> Hypervisor { @@ -101,6 +107,7 @@ impl Hypervisor { ipc_worker: RwLock::new(worker), processes: RwLock::new(HashMap::new()), modules: HashMap::new(), + io_path: "/tmp".to_owned(), } } diff --git a/ipc/nano/src/lib.rs b/ipc/nano/src/lib.rs index 58c2d22de..df2e34d04 100644 --- a/ipc/nano/src/lib.rs +++ b/ipc/nano/src/lib.rs @@ -97,6 +97,7 @@ pub fn init_client(socket_addr: &str) -> Result, SocketError SocketError::RequestLink })); + trace!(target: "ipc", "Created cleint for {}", socket_addr); Ok(GuardedSocket { client: Arc::new(S::init(socket)), _endpoint: endpoint, @@ -189,6 +190,8 @@ impl Worker where S: IpcInterface { self.rebuild_poll_request(); + trace!(target: "ipc", "Started duplex worker at {}", addr); + Ok(()) } @@ -200,6 +203,7 @@ impl Worker where S: IpcInterface { SocketError::DuplexLink })); + let endpoint = try!(socket.bind(addr).map_err(|e| { warn!(target: "ipc", "Failed to bind socket to address '{}': {:?}", addr, e); SocketError::DuplexLink @@ -209,6 +213,7 @@ impl Worker where S: IpcInterface { self.rebuild_poll_request(); + trace!(target: "ipc", "Started request-reply worker at {}", addr); Ok(()) } } diff --git a/parity/blockchain.rs b/parity/blockchain.rs index b0c5d95a7..06e03ae72 100644 --- a/parity/blockchain.rs +++ b/parity/blockchain.rs @@ -138,6 +138,7 @@ fn execute_import(cmd: ImportBlockchain) -> Result { client_config, &spec, Path::new(&client_path), + Path::new(&cmd.dirs.ipc_path()), Arc::new(Miner::with_spec(&spec)), ).map_err(|e| format!("Client service error: {:?}", e))); @@ -248,6 +249,7 @@ fn execute_export(cmd: ExportBlockchain) -> Result { client_config, &spec, Path::new(&client_path), + Path::new(&cmd.dirs.ipc_path()), Arc::new(Miner::with_spec(&spec)), ).map_err(|e| format!("Client service error: {:?}", e))); diff --git a/parity/configuration.rs b/parity/configuration.rs index 5b14660a9..5786b10de 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -540,6 +540,15 @@ impl Configuration { |e| warn!("Failed to create '{}' for geth mode: {}", &geth_path.to_str().unwrap(), e)); } + if cfg!(feature = "ipc") && !cfg!(feature = "windows") { + let mut path_buf = PathBuf::from(db_path.clone()); + path_buf.push("ipc"); + let ipc_path = path_buf.to_str().unwrap(); + ::std::fs::create_dir_all(ipc_path).unwrap_or_else( + |e| warn!("Failed to directory '{}' for ipc sockets: {}", ipc_path, e) + ); + } + Directories { keys: keys_path, db: db_path, diff --git a/parity/dir.rs b/parity/dir.rs index bb92e1277..f1f230163 100644 --- a/parity/dir.rs +++ b/parity/dir.rs @@ -66,6 +66,13 @@ impl Directories { dir.push("db"); dir } + + /// Get the ipc sockets path + pub fn ipc_path(&self) -> PathBuf { + let mut dir = Path::new(&self.db).to_path_buf(); + dir.push("ipc"); + dir + } } #[cfg(test)] diff --git a/parity/modules.rs b/parity/modules.rs index a41fc58b6..20f2567ce 100644 --- a/parity/modules.rs +++ b/parity/modules.rs @@ -23,12 +23,22 @@ use self::no_ipc_deps::*; #[cfg(feature="ipc")] use self::ipc_deps::*; use ethcore_logger::Config as LogConfig; +use std::path::Path; pub mod service_urls { - pub const CLIENT: &'static str = "ipc:///tmp/parity-chain.ipc"; - pub const SYNC: &'static str = "ipc:///tmp/parity-sync.ipc"; - pub const SYNC_NOTIFY: &'static str = "ipc:///tmp/parity-sync-notify.ipc"; - pub const NETWORK_MANAGER: &'static str = "ipc:///tmp/parity-manage-net.ipc"; + use std::path::PathBuf; + + pub const CLIENT: &'static str = "parity-chain.ipc"; + pub const SYNC: &'static str = "parity-sync.ipc"; + pub const SYNC_NOTIFY: &'static str = "parity-sync-notify.ipc"; + pub const NETWORK_MANAGER: &'static str = "parity-manage-net.ipc"; + + pub fn with_base(data_dir: &str, service_path: &str) -> String { + let mut path = PathBuf::from(data_dir); + path.push(service_path); + + format!("ipc://{}", path.to_str().unwrap()) + } } #[cfg(not(feature="ipc"))] @@ -51,27 +61,30 @@ pub type SyncModules = (Arc, Arc, Arc) mod ipc_deps { pub use ethsync::{SyncClient, NetworkManagerClient, ServiceConfiguration}; pub use ethcore::client::ChainNotifyClient; - pub use hypervisor::{SYNC_MODULE_ID, BootArgs}; + pub use hypervisor::{SYNC_MODULE_ID, BootArgs, HYPERVISOR_IPC_URL}; pub use nanoipc::{GuardedSocket, NanoSocket, init_client}; pub use ipc::IpcSocket; pub use ipc::binary::serialize; } #[cfg(feature="ipc")] -pub fn hypervisor() -> Option { - Some(Hypervisor::new()) +pub fn hypervisor(base_path: &Path) -> Option { + Some(Hypervisor + ::with_url(&service_urls::with_base(base_path.to_str().unwrap(), HYPERVISOR_IPC_URL)) + .io_path(base_path.to_str().unwrap())) } #[cfg(not(feature="ipc"))] -pub fn hypervisor() -> Option { +pub fn hypervisor(_: &Path) -> Option { None } #[cfg(feature="ipc")] -fn sync_arguments(sync_cfg: SyncConfig, net_cfg: NetworkConfiguration, log_settings: &LogConfig) -> BootArgs { +fn sync_arguments(io_path: &str, sync_cfg: SyncConfig, net_cfg: NetworkConfiguration, log_settings: &LogConfig) -> BootArgs { let service_config = ServiceConfiguration { sync: sync_cfg, net: net_cfg, + io_path: io_path.to_owned(), }; // initialisation payload is passed via stdin @@ -105,14 +118,18 @@ pub fn sync -> Result { let mut hypervisor = hypervisor_ref.take().expect("There should be hypervisor for ipc configuration"); - hypervisor = hypervisor.module(SYNC_MODULE_ID, sync_arguments(sync_cfg, net_cfg, log_settings)); + let args = sync_arguments(&hypervisor.io_path, sync_cfg, net_cfg, log_settings); + hypervisor = hypervisor.module(SYNC_MODULE_ID, args); hypervisor.start(); hypervisor.wait_for_startup(); - let sync_client = init_client::>(service_urls::SYNC).unwrap(); - let notify_client = init_client::>(service_urls::SYNC_NOTIFY).unwrap(); - let manage_client = init_client::>(service_urls::NETWORK_MANAGER).unwrap(); + let sync_client = init_client::>( + &service_urls::with_base(&hypervisor.io_path, service_urls::SYNC)).unwrap(); + let notify_client = init_client::>( + &service_urls::with_base(&hypervisor.io_path, service_urls::SYNC_NOTIFY)).unwrap(); + let manage_client = init_client::>( + &service_urls::with_base(&hypervisor.io_path, service_urls::NETWORK_MANAGER)).unwrap(); *hypervisor_ref = Some(hypervisor); Ok((sync_client, manage_client, notify_client)) diff --git a/parity/run.rs b/parity/run.rs index c659d4d25..91f8d5bfa 100644 --- a/parity/run.rs +++ b/parity/run.rs @@ -163,13 +163,14 @@ pub fn execute(cmd: RunCmd) -> Result<(), String> { } // create supervisor - let mut hypervisor = modules::hypervisor(); + let mut hypervisor = modules::hypervisor(Path::new(&cmd.dirs.ipc_path())); // create client service. let service = try!(ClientService::start( client_config, &spec, Path::new(&client_path), + Path::new(&cmd.dirs.ipc_path()), miner.clone(), ).map_err(|e| format!("Client service error: {:?}", e))); diff --git a/parity/snapshot.rs b/parity/snapshot.rs index 2a3c12567..c3e43e89f 100644 --- a/parity/snapshot.rs +++ b/parity/snapshot.rs @@ -95,6 +95,7 @@ impl SnapshotCommand { client_config, &spec, Path::new(&client_path), + Path::new(&self.dirs.ipc_path()), Arc::new(Miner::with_spec(&spec)) ).map_err(|e| format!("Client service error: {:?}", e))); diff --git a/parity/sync.rs b/parity/sync.rs index 447f3678c..382c1806d 100644 --- a/parity/sync.rs +++ b/parity/sync.rs @@ -86,18 +86,34 @@ pub fn main() { io::stdin().read_to_end(&mut buffer).expect("Failed to read initialisation payload"); let service_config = ipc::binary::deserialize::(&buffer).expect("Failed deserializing initialisation payload"); - let remote_client = nanoipc::init_client::>(service_urls::CLIENT).unwrap(); + let remote_client = nanoipc::init_client::>( + &service_urls::with_base(&service_config.io_path, service_urls::CLIENT), + ).unwrap(); remote_client.handshake().unwrap(); let stop = Arc::new(AtomicBool::new(false)); let sync = EthSync::new(service_config.sync, remote_client.service().clone(), service_config.net).unwrap(); - run_service(service_urls::SYNC, stop.clone(), sync.clone() as Arc); - run_service(service_urls::NETWORK_MANAGER, stop.clone(), sync.clone() as Arc); - run_service(service_urls::SYNC_NOTIFY, stop.clone(), sync.clone() as Arc); + run_service( + &service_urls::with_base(&service_config.io_path, service_urls::SYNC), + stop.clone(), + sync.clone() as Arc + ); + run_service( + &service_urls::with_base(&service_config.io_path, service_urls::NETWORK_MANAGER), + stop.clone(), + sync.clone() as Arc + ); + run_service( + &service_urls::with_base(&service_config.io_path, service_urls::SYNC_NOTIFY), + stop.clone(), + sync.clone() as Arc + ); - let hypervisor_client = nanoipc::init_client::>(HYPERVISOR_IPC_URL).unwrap(); + let hypervisor_client = nanoipc::init_client::>( + &service_urls::with_base(&service_config.io_path, HYPERVISOR_IPC_URL), + ).unwrap(); hypervisor_client.handshake().unwrap(); hypervisor_client.module_ready(SYNC_MODULE_ID); diff --git a/sync/src/api.rs b/sync/src/api.rs index f98387abd..1ded32367 100644 --- a/sync/src/api.rs +++ b/sync/src/api.rs @@ -306,4 +306,5 @@ impl From for NetworkConfiguration { pub struct ServiceConfiguration { pub sync: SyncConfig, pub net: NetworkConfiguration, + pub io_path: String, }