// Copyright 2015-2017 Parity Technologies (UK) Ltd. // This file is part of Parity. // Parity is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // Parity is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with Parity. If not, see . use std::sync::Arc; use std::path::Path; use ethcore::client::BlockChainClient; use hypervisor::Hypervisor; use ethsync::{SyncConfig, NetworkConfiguration, NetworkError, Params}; use ethcore::snapshot::SnapshotService; use light::Provider; #[cfg(not(feature="ipc"))] use self::no_ipc_deps::*; #[cfg(not(feature="ipc"))] use ethcore_logger::Config as LogConfig; #[cfg(feature="ipc")] use self::ipc_deps::*; #[cfg(feature="ipc")] pub mod service_urls { use std::path::PathBuf; pub const CLIENT: &'static str = "parity-chain.ipc"; pub const SNAPSHOT: &'static str = "parity-snapshot.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 const SYNC_CONTROL: &'static str = "parity-sync-control.ipc"; pub const LIGHT_PROVIDER: &'static str = "parity-light-provider.ipc"; #[cfg(feature="stratum")] pub const STRATUM_CONTROL: &'static str = "parity-stratum-control.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"))] mod no_ipc_deps { pub use ethsync::{EthSync, SyncProvider, ManageNetwork}; pub use ethcore::client::ChainNotify; } #[cfg(feature="ipc")] pub type SyncModules = ( GuardedSocket>, GuardedSocket>, GuardedSocket> ); #[cfg(not(feature="ipc"))] pub type SyncModules = (Arc, Arc, Arc); #[cfg(feature="ipc")] mod ipc_deps { pub use ethsync::remote::{SyncClient, NetworkManagerClient}; pub use ethsync::ServiceConfiguration; pub use ethcore::client::remote::ChainNotifyClient; pub use hypervisor::{SYNC_MODULE_ID, BootArgs, HYPERVISOR_IPC_URL}; pub use nanoipc::{GuardedSocket, NanoSocket, generic_client, fast_client}; pub use ipc::IpcSocket; pub use ipc::binary::serialize; pub use light::remote::LightProviderClient; } #[cfg(feature="ipc")] 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(_: &Path) -> Option { None } #[cfg(feature="ipc")] 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 let service_payload = serialize(&service_config).expect("Any binary-derived struct is serializable by definition"); // client service url and logging settings are passed in command line let mut cli_args = Vec::new(); cli_args.push("sync".to_owned()); if !log_settings.color { cli_args.push("--no-color".to_owned()); } if let Some(ref mode) = log_settings.mode { cli_args.push("-l".to_owned()); cli_args.push(mode.to_owned()); } if let Some(ref file) = log_settings.file { cli_args.push("--log-file".to_owned()); cli_args.push(file.to_owned()); } BootArgs::new().stdin(service_payload).cli(cli_args) } #[cfg(feature="ipc")] pub fn stratum( hypervisor_ref: &mut Option, config: &::ethcore::miner::StratumOptions ) { use ethcore_stratum; let mut hypervisor = hypervisor_ref.take().expect("There should be hypervisor for ipc configuration"); let args = BootArgs::new().stdin( serialize(ðcore_stratum::ServiceConfiguration { io_path: hypervisor.io_path.to_owned(), port: config.port, listen_addr: config.listen_addr.to_owned(), secret: config.secret, }).expect("Any binary-derived struct is serializable by definition") ).cli(vec!["stratum".to_owned()]); hypervisor = hypervisor.module(super::stratum::MODULE_ID, args); *hypervisor_ref = Some(hypervisor); } #[cfg(feature="ipc")] pub fn sync( hypervisor_ref: &mut Option, sync_cfg: SyncConfig, net_cfg: NetworkConfiguration, _client: Arc, _snapshot_service: Arc, _provider: Arc, log_settings: &LogConfig, ) -> Result { let mut hypervisor = hypervisor_ref.take().expect("There should be hypervisor for ipc configuration"); 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 = generic_client::>( &service_urls::with_base(&hypervisor.io_path, service_urls::SYNC)).unwrap(); let notify_client = generic_client::>( &service_urls::with_base(&hypervisor.io_path, service_urls::SYNC_NOTIFY)).unwrap(); let manage_client = generic_client::>( &service_urls::with_base(&hypervisor.io_path, service_urls::NETWORK_MANAGER)).unwrap(); let provider_client = generic_client::>( &service_urls::with_base(&hypervisor.io_path, service_urls::LIGHT_PROVIDER)).unwrap(); *hypervisor_ref = Some(hypervisor); Ok((sync_client, manage_client, notify_client)) } #[cfg(not(feature="ipc"))] pub fn sync( _hypervisor: &mut Option, sync_cfg: SyncConfig, net_cfg: NetworkConfiguration, client: Arc, snapshot_service: Arc, provider: Arc, _log_settings: &LogConfig, ) -> Result { let eth_sync = EthSync::new(Params { config: sync_cfg, chain: client, provider: provider, snapshot_service: snapshot_service, network_config: net_cfg, })?; Ok((eth_sync.clone() as Arc, eth_sync.clone() as Arc, eth_sync.clone() as Arc)) }