// 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 <http://www.gnu.org/licenses/>. //! Parity micro-service helpers use nanoipc; use ipc; use std; use std::sync::Arc; use hypervisor::HypervisorServiceClient; use hypervisor::service::IpcModuleId; use ctrlc::CtrlC; use std::sync::atomic::{AtomicBool, Ordering}; use nanoipc::{IpcInterface, GuardedSocket, NanoSocket}; use ipc::WithSocket; use ethcore_logger::{Config as LogConfig, setup_log}; use docopt::Docopt; #[derive(Debug)] pub enum BootError { ReadArgs(std::io::Error), DecodeArgs(ipc::binary::BinaryError), DependencyConnect(nanoipc::SocketError), } pub fn host_service<T: ?Sized + Send + Sync + 'static>(addr: &str, stop_guard: Arc<AtomicBool>, service: Arc<T>) where T: IpcInterface { let socket_url = addr.to_owned(); std::thread::spawn(move || { let mut worker = nanoipc::Worker::<T>::new(&service); worker.add_reqrep(&socket_url).unwrap(); while !stop_guard.load(Ordering::SeqCst) { worker.poll(); } }); } pub fn payload<B: ipc::BinaryConvertable>() -> Result<B, BootError> { use std::io; use std::io::Read; let mut buffer = Vec::new(); io::stdin().read_to_end(&mut buffer).map_err(BootError::ReadArgs)?; ipc::binary::deserialize::<B>(&buffer).map_err(BootError::DecodeArgs) } pub fn register(hv_url: &str, control_url: &str, module_id: IpcModuleId) -> GuardedSocket<HypervisorServiceClient<NanoSocket>>{ let hypervisor_client = nanoipc::fast_client::<HypervisorServiceClient<_>>(hv_url).unwrap(); hypervisor_client.handshake().unwrap(); hypervisor_client.module_ready(module_id, control_url.to_owned()); hypervisor_client } pub fn dependency<C: WithSocket<NanoSocket>>(url: &str) -> Result<GuardedSocket<C>, BootError> { nanoipc::generic_client::<C>(url).map_err(BootError::DependencyConnect) } pub fn main_thread() -> Arc<AtomicBool> { let stop = Arc::new(AtomicBool::new(false)); let ctrc_stop = stop.clone(); CtrlC::set_handler(move || { ctrc_stop.store(true, Ordering::Relaxed); }); stop } pub fn setup_cli_logger(svc_name: &str) { let usage = format!(" Ethcore {} service Usage: parity {} [options] Options: -l --logging LOGGING Specify the logging level. Must conform to the same format as RUST_LOG. --log-file FILENAME Specify a filename into which logging should be directed. --no-color Don't use terminal color codes in output. ", svc_name, svc_name); #[derive(Debug, RustcDecodable)] struct Args { flag_logging: Option<String>, flag_log_file: Option<String>, flag_no_color: bool, } impl Args { pub fn log_settings(&self) -> LogConfig { LogConfig { color: self.flag_no_color || cfg!(windows), mode: self.flag_logging.clone(), file: self.flag_log_file.clone(), } } } let args: Args = Docopt::new(usage) .and_then(|d| d.decode()) .unwrap_or_else(|e| e.exit()); setup_log(&args.log_settings()).expect("Log initialization failure"); }