diff --git a/parity/die.rs b/parity/die.rs new file mode 100644 index 000000000..602e2cdee --- /dev/null +++ b/parity/die.rs @@ -0,0 +1,54 @@ +// 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 . + +use std; +use ethcore; +use util::UtilError; +use std::process::exit; + +#[macro_export] +macro_rules! die { + ($($arg:tt)*) => (die_with_message(&format!("{}", format_args!($($arg)*)))); +} + +pub fn die_with_error(e: ethcore::error::Error) -> ! { + use ethcore::error::Error; + + match e { + Error::Util(UtilError::StdIo(e)) => die_with_io_error(e), + _ => die!("{:?}", e), + } +} + +pub fn die_with_io_error(e: std::io::Error) -> ! { + match e.kind() { + std::io::ErrorKind::PermissionDenied => { + die!("No permissions to bind to specified port.") + }, + std::io::ErrorKind::AddrInUse => { + die!("Specified address is already in use. Please make sure that nothing is listening on the same port or try using a different one.") + }, + std::io::ErrorKind::AddrNotAvailable => { + die!("Could not use specified interface or given address is invalid.") + }, + _ => die!("{:?}", e), + } +} + +pub fn die_with_message(msg: &str) -> ! { + println!("ERROR: {}", msg); + exit(1); +} diff --git a/parity/hypervisor/mod.rs b/parity/hypervisor/mod.rs index bbc95b150..1776aa023 100644 --- a/parity/hypervisor/mod.rs +++ b/parity/hypervisor/mod.rs @@ -116,6 +116,7 @@ impl Hypervisor { } } +#[cfg(test)] mod tests { use super::*; use std::sync::atomic::{AtomicBool,Ordering}; diff --git a/parity/main.rs b/parity/main.rs index dff7ceaeb..612719ce2 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -20,6 +20,7 @@ #![cfg_attr(feature="dev", feature(plugin))] #![cfg_attr(feature="dev", plugin(clippy))] #![cfg_attr(feature="dev", allow(useless_format))] + extern crate docopt; extern crate num_cpus; extern crate rustc_serialize; @@ -46,7 +47,8 @@ extern crate bincode; #[macro_use] extern crate hyper; #[cfg(feature = "rpc")] -extern crate ethcore_rpc as rpc; +extern crate ethcore_rpc; + #[cfg(feature = "webapp")] extern crate ethcore_webapp as webapp; @@ -54,9 +56,7 @@ use std::io::{BufRead, BufReader}; use std::fs::File; use std::net::{SocketAddr, IpAddr}; use std::env; -use std::process::exit; use std::path::PathBuf; -use env_logger::LogBuilder; use ctrlc::CtrlC; use util::*; use util::panics::{MayPanic, ForwardPanic, PanicHandler}; @@ -70,24 +70,20 @@ use ethminer::{Miner, MinerService}; use docopt::Docopt; use daemonize::Daemonize; use number_prefix::{binary_prefix, Standalone, Prefixed}; -#[cfg(feature = "rpc")] -use rpc::Server as RpcServer; + #[cfg(feature = "webapp")] use webapp::Server as WebappServer; +#[macro_use] +mod die; mod price_info; mod upgrade; mod hypervisor; +mod setup_log; +mod rpc; -fn die_with_message(msg: &str) -> ! { - println!("ERROR: {}", msg); - exit(1); -} - -#[macro_export] -macro_rules! die { - ($($arg:tt)*) => (die_with_message(&format!("{}", format_args!($($arg)*)))); -} +use die::*; +use rpc::RpcServer; const USAGE: &'static str = r#" Parity. Ethereum Client. @@ -281,78 +277,6 @@ struct Args { flag_networkid: Option, } -fn setup_log(init: &Option) -> Arc { - use rlog::*; - - let mut levels = String::new(); - let mut builder = LogBuilder::new(); - builder.filter(None, LogLevelFilter::Info); - - if env::var("RUST_LOG").is_ok() { - let lvl = &env::var("RUST_LOG").unwrap(); - levels.push_str(&lvl); - levels.push_str(","); - builder.parse(lvl); - } - - if let Some(ref s) = *init { - levels.push_str(s); - builder.parse(s); - } - - let logs = Arc::new(RotatingLogger::new(levels)); - let log2 = logs.clone(); - let format = move |record: &LogRecord| { - let timestamp = time::strftime("%Y-%m-%d %H:%M:%S %Z", &time::now()).unwrap(); - let format = if max_log_level() <= LogLevelFilter::Info { - format!("{}{}", timestamp, record.args()) - } else { - format!("{}{}:{}: {}", timestamp, record.level(), record.target(), record.args()) - }; - log2.append(format.clone()); - format - }; - builder.format(format); - builder.init().unwrap(); - logs -} - -#[cfg(feature = "rpc")] -fn setup_rpc_server( - client: Arc, - sync: Arc, - secret_store: Arc, - miner: Arc, - url: &SocketAddr, - cors_domain: Option, - apis: Vec<&str>, - logger: Arc, -) -> RpcServer { - use rpc::v1::*; - - let server = rpc::RpcServer::new(); - for api in apis.into_iter() { - match api { - "web3" => server.add_delegate(Web3Client::new().to_delegate()), - "net" => server.add_delegate(NetClient::new(&sync).to_delegate()), - "eth" => { - server.add_delegate(EthClient::new(&client, &sync, &secret_store, &miner).to_delegate()); - server.add_delegate(EthFilterClient::new(&client, &miner).to_delegate()); - }, - "personal" => server.add_delegate(PersonalClient::new(&secret_store).to_delegate()), - "ethcore" => server.add_delegate(EthcoreClient::new(&miner, logger.clone()).to_delegate()), - _ => { - die!("{}: Invalid API name to be enabled.", api); - }, - } - } - let start_result = server.start_http(url, cors_domain); - match start_result { - Err(rpc::RpcServerError::IoError(err)) => die_with_io_error(err), - Err(e) => die!("{:?}", e), - Ok(server) => server, - } -} #[cfg(feature = "webapp")] fn setup_webapp_server( @@ -364,7 +288,7 @@ fn setup_webapp_server( auth: Option<(String, String)>, logger: Arc, ) -> WebappServer { - use rpc::v1::*; + use ethcore_rpc::v1::*; let server = webapp::ServerBuilder::new(); server.add_delegate(Web3Client::new().to_delegate()); @@ -389,22 +313,6 @@ fn setup_webapp_server( } -#[cfg(not(feature = "rpc"))] -struct RpcServer; - -#[cfg(not(feature = "rpc"))] -fn setup_rpc_server( - _client: Arc, - _sync: Arc, - _secret_store: Arc, - _miner: Arc, - _url: &SocketAddr, - _cors_domain: Option, - _apis: Vec<&str>, - _logger: Arc, -) -> ! { - die!("Your Parity version has been compiled without JSON-RPC support.") -} #[cfg(not(feature = "webapp"))] struct WebappServer; @@ -704,7 +612,7 @@ impl Configuration { let panic_handler = PanicHandler::new_in_arc(); // Setup logging - let logger = setup_log(&self.args.flag_logging); + let logger = setup_log::setup_log(&self.args.flag_logging); // Raise fdlimit unsafe { ::fdlimit::raise_fd_limit(); } @@ -749,7 +657,7 @@ impl Configuration { let addr = SocketAddr::from_str(&url).unwrap_or_else(|_| die!("{}: Invalid JSONRPC listen host/port given.", url)); let cors_domain = self.args.flag_jsonrpc_cors.clone().or(self.args.flag_rpccorsdomain.clone()); - Some(setup_rpc_server( + Some(rpc::setup_rpc_server( service.client(), sync.clone(), account_service.clone(), @@ -828,31 +736,7 @@ fn wait_for_exit(panic_handler: Arc, _rpc_server: Option ! { - use ethcore::error::Error; - - match e { - Error::Util(UtilError::StdIo(e)) => die_with_io_error(e), - _ => die!("{:?}", e), - } -} -fn die_with_io_error(e: std::io::Error) -> ! { - match e.kind() { - std::io::ErrorKind::PermissionDenied => { - die!("No permissions to bind to specified port.") - }, - std::io::ErrorKind::AddrInUse => { - die!("Specified address is already in use. Please make sure that nothing is listening on the same port or try using a different one.") - }, - std::io::ErrorKind::AddrNotAvailable => { - die!("Could not use specified interface or given address is invalid.") - }, - _ => die!("{:?}", e), - } -} - fn main() { - Configuration::parse().execute(); } diff --git a/parity/rpc.rs b/parity/rpc.rs new file mode 100644 index 000000000..b5a2eadb5 --- /dev/null +++ b/parity/rpc.rs @@ -0,0 +1,85 @@ +// 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 . + + +use std::sync::Arc; +use std::net::SocketAddr; +use ethcore::client::Client; +use ethsync::EthSync; +use ethminer::Miner; +use util::RotatingLogger; +use util::keys::store::{AccountService}; +use die::*; + +#[cfg(feature = "rpc")] +pub use ethcore_rpc::Server as RpcServer; +#[cfg(feature = "rpc")] +use ethcore_rpc::{RpcServerError, RpcServer as Server}; + +#[cfg(not(feature = "rpc"))] +pub struct RpcServer; + +#[cfg(not(feature = "rpc"))] +pub fn setup_rpc_server( + _client: Arc, + _sync: Arc, + _secret_store: Arc, + _miner: Arc, + _url: &SocketAddr, + _cors_domain: Option, + _apis: Vec<&str>, + _logger: Arc, +) -> ! { + die!("Your Parity version has been compiled without JSON-RPC support.") +} + +#[cfg(feature = "rpc")] +pub fn setup_rpc_server( + client: Arc, + sync: Arc, + secret_store: Arc, + miner: Arc, + url: &SocketAddr, + cors_domain: Option, + apis: Vec<&str>, + logger: Arc, +) -> RpcServer { + use ethcore_rpc::v1::*; + + let server = Server::new(); + for api in apis.into_iter() { + match api { + "web3" => server.add_delegate(Web3Client::new().to_delegate()), + "net" => server.add_delegate(NetClient::new(&sync).to_delegate()), + "eth" => { + server.add_delegate(EthClient::new(&client, &sync, &secret_store, &miner).to_delegate()); + server.add_delegate(EthFilterClient::new(&client, &miner).to_delegate()); + }, + "personal" => server.add_delegate(PersonalClient::new(&secret_store).to_delegate()), + "ethcore" => server.add_delegate(EthcoreClient::new(&miner, logger.clone()).to_delegate()), + _ => { + die!("{}: Invalid API name to be enabled.", api); + }, + } + } + let start_result = server.start_http(url, cors_domain); + match start_result { + Err(RpcServerError::IoError(err)) => die_with_io_error(err), + Err(e) => die!("{:?}", e), + Ok(server) => server, + } +} + diff --git a/parity/setup_log.rs b/parity/setup_log.rs new file mode 100644 index 000000000..13ae41c40 --- /dev/null +++ b/parity/setup_log.rs @@ -0,0 +1,60 @@ +// 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 . + + +use std::env; +use std::sync::Arc; +use time; +use env_logger::LogBuilder; +use util::{RotatingLogger}; + +/// Sets up the logger +pub fn setup_log(init: &Option) -> Arc { + use rlog::*; + + let mut levels = String::new(); + let mut builder = LogBuilder::new(); + builder.filter(None, LogLevelFilter::Info); + + if env::var("RUST_LOG").is_ok() { + let lvl = &env::var("RUST_LOG").unwrap(); + levels.push_str(&lvl); + levels.push_str(","); + builder.parse(lvl); + } + + if let Some(ref s) = *init { + levels.push_str(s); + builder.parse(s); + } + + let logs = Arc::new(RotatingLogger::new(levels)); + let log2 = logs.clone(); + let format = move |record: &LogRecord| { + let timestamp = time::strftime("%Y-%m-%d %H:%M:%S %Z", &time::now()).unwrap(); + let format = if max_log_level() <= LogLevelFilter::Info { + format!("{}{}", timestamp, record.args()) + } else { + format!("{}{}:{}: {}", timestamp, record.level(), record.target(), record.args()) + }; + log2.append(format.clone()); + format + }; + builder.format(format); + builder.init().unwrap(); + logs +} +