// Copyright 2015, 2016 Ethcore (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 .
//! Parity sync service
extern crate ethcore_ipc_nano as nanoipc;
extern crate ethcore_ipc_hypervisor as hypervisor;
extern crate ethcore_ipc as ipc;
extern crate ctrlc;
#[macro_use] extern crate log;
extern crate ethsync;
extern crate rustc_serialize;
extern crate docopt;
extern crate ethcore;
extern crate ethcore_util as util;
use std::sync::Arc;
use hypervisor::{HypervisorServiceClient, SYNC_MODULE_ID, HYPERVISOR_IPC_URL};
use ctrlc::CtrlC;
use std::sync::atomic::{AtomicBool, Ordering};
use docopt::Docopt;
use ethcore::client::{RemoteClient, ChainNotify};
use ethsync::{SyncProvider, SyncConfig, EthSync, ManageNetwork, NetworkConfiguration};
use std::thread;
use util::numbers::{U256, H256};
use std::str::FromStr;
use nanoipc::IpcInterface;
use util::sha3::Hashable;
const USAGE: &'static str = "
Ethcore sync service
Usage:
sync [options]
Options:
--public-address IP Public address.
--boot-nodes LIST List of boot nodes.
--reserved-nodes LIST List of reserved peers,
--secret HEX Use node key hash
--udp-port UDP port
";
#[derive(Debug, RustcDecodable)]
struct Args {
arg_network_id: String,
arg_listen_address: String,
arg_nat_enabled: bool,
arg_discovery_enabled: bool,
arg_ideal_peers: u32,
arg_config_path: String,
arg_client_url: String,
arg_allow_non_reserved: bool,
flag_public_address: Option,
flag_secret: Option,
flag_boot_nodes: Vec,
flag_reserved_nodes: Vec,
flag_udp_port: Option,
}
impl Args {
pub fn into_config(self) -> (SyncConfig, NetworkConfiguration, String) {
let mut sync_config = SyncConfig::default();
sync_config.network_id = U256::from_str(&self.arg_network_id).unwrap();
let network_config = NetworkConfiguration {
udp_port: self.flag_udp_port,
nat_enabled: self.arg_nat_enabled,
boot_nodes: self.flag_boot_nodes,
listen_address: Some(self.arg_listen_address),
public_address: self.flag_public_address,
use_secret: self.flag_secret.as_ref().map(|s| H256::from_str(s).unwrap_or_else(|_| s.sha3())),
discovery_enabled: self.arg_discovery_enabled,
ideal_peers: self.arg_ideal_peers,
config_path: Some(self.arg_config_path),
reserved_nodes: self.flag_reserved_nodes,
allow_non_reserved: self.arg_allow_non_reserved,
};
(sync_config, network_config, self.arg_client_url)
}
}
fn run_service(addr: &str, stop_guard: Arc, service: Arc) where T: IpcInterface {
let socket_url = addr.to_owned();
std::thread::spawn(move || {
let mut worker = nanoipc::Worker::::new(&service);
worker.add_reqrep(&socket_url).unwrap();
while !stop_guard.load(Ordering::Relaxed) {
worker.poll();
}
});
}
fn main() {
let args: Args = Docopt::new(USAGE)
.and_then(|d| d.decode())
.unwrap_or_else(|e| e.exit());
let (sync_config, network_config, client_url) = args.into_config();
let remote_client = nanoipc::init_client::>(&client_url).unwrap();
remote_client.handshake().unwrap();
let stop = Arc::new(AtomicBool::new(false));
let sync = EthSync::new(sync_config, remote_client.service().clone(), network_config).unwrap();
run_service("ipc:///tmp/parity-sync.ipc", stop.clone(), sync.clone() as Arc);
run_service("ipc:///tmp/parity-manage-net.ipc", stop.clone(), sync.clone() as Arc);
run_service("ipc:///tmp/parity-sync-notify.ipc", stop.clone(), sync.clone() as Arc);
let hypervisor_client = nanoipc::init_client::>(HYPERVISOR_IPC_URL).unwrap();
hypervisor_client.handshake().unwrap();
hypervisor_client.module_ready(SYNC_MODULE_ID);
let terminate_stop = stop.clone();
CtrlC::set_handler(move || {
terminate_stop.store(true, Ordering::Relaxed);
});
while !stop.load(Ordering::Relaxed) {
thread::park_timeout(std::time::Duration::from_millis(1000));
}
}