Separating RPC

This commit is contained in:
Tomasz Drwięga 2016-04-21 13:12:43 +02:00
parent 3c665f7640
commit 09b2d7b3a6
5 changed files with 213 additions and 129 deletions

54
parity/die.rs Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
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);
}

View File

@ -116,6 +116,7 @@ impl Hypervisor {
} }
} }
#[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use std::sync::atomic::{AtomicBool,Ordering}; use std::sync::atomic::{AtomicBool,Ordering};

View File

@ -20,6 +20,7 @@
#![cfg_attr(feature="dev", feature(plugin))] #![cfg_attr(feature="dev", feature(plugin))]
#![cfg_attr(feature="dev", plugin(clippy))] #![cfg_attr(feature="dev", plugin(clippy))]
#![cfg_attr(feature="dev", allow(useless_format))] #![cfg_attr(feature="dev", allow(useless_format))]
extern crate docopt; extern crate docopt;
extern crate num_cpus; extern crate num_cpus;
extern crate rustc_serialize; extern crate rustc_serialize;
@ -46,7 +47,8 @@ extern crate bincode;
#[macro_use] extern crate hyper; #[macro_use] extern crate hyper;
#[cfg(feature = "rpc")] #[cfg(feature = "rpc")]
extern crate ethcore_rpc as rpc; extern crate ethcore_rpc;
#[cfg(feature = "webapp")] #[cfg(feature = "webapp")]
extern crate ethcore_webapp as webapp; extern crate ethcore_webapp as webapp;
@ -54,9 +56,7 @@ use std::io::{BufRead, BufReader};
use std::fs::File; use std::fs::File;
use std::net::{SocketAddr, IpAddr}; use std::net::{SocketAddr, IpAddr};
use std::env; use std::env;
use std::process::exit;
use std::path::PathBuf; use std::path::PathBuf;
use env_logger::LogBuilder;
use ctrlc::CtrlC; use ctrlc::CtrlC;
use util::*; use util::*;
use util::panics::{MayPanic, ForwardPanic, PanicHandler}; use util::panics::{MayPanic, ForwardPanic, PanicHandler};
@ -70,24 +70,20 @@ use ethminer::{Miner, MinerService};
use docopt::Docopt; use docopt::Docopt;
use daemonize::Daemonize; use daemonize::Daemonize;
use number_prefix::{binary_prefix, Standalone, Prefixed}; use number_prefix::{binary_prefix, Standalone, Prefixed};
#[cfg(feature = "rpc")]
use rpc::Server as RpcServer;
#[cfg(feature = "webapp")] #[cfg(feature = "webapp")]
use webapp::Server as WebappServer; use webapp::Server as WebappServer;
#[macro_use]
mod die;
mod price_info; mod price_info;
mod upgrade; mod upgrade;
mod hypervisor; mod hypervisor;
mod setup_log;
mod rpc;
fn die_with_message(msg: &str) -> ! { use die::*;
println!("ERROR: {}", msg); use rpc::RpcServer;
exit(1);
}
#[macro_export]
macro_rules! die {
($($arg:tt)*) => (die_with_message(&format!("{}", format_args!($($arg)*))));
}
const USAGE: &'static str = r#" const USAGE: &'static str = r#"
Parity. Ethereum Client. Parity. Ethereum Client.
@ -281,78 +277,6 @@ struct Args {
flag_networkid: Option<String>, flag_networkid: Option<String>,
} }
fn setup_log(init: &Option<String>) -> Arc<RotatingLogger> {
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<Client>,
sync: Arc<EthSync>,
secret_store: Arc<AccountService>,
miner: Arc<Miner>,
url: &SocketAddr,
cors_domain: Option<String>,
apis: Vec<&str>,
logger: Arc<RotatingLogger>,
) -> 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")] #[cfg(feature = "webapp")]
fn setup_webapp_server( fn setup_webapp_server(
@ -364,7 +288,7 @@ fn setup_webapp_server(
auth: Option<(String, String)>, auth: Option<(String, String)>,
logger: Arc<RotatingLogger>, logger: Arc<RotatingLogger>,
) -> WebappServer { ) -> WebappServer {
use rpc::v1::*; use ethcore_rpc::v1::*;
let server = webapp::ServerBuilder::new(); let server = webapp::ServerBuilder::new();
server.add_delegate(Web3Client::new().to_delegate()); 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<Client>,
_sync: Arc<EthSync>,
_secret_store: Arc<AccountService>,
_miner: Arc<Miner>,
_url: &SocketAddr,
_cors_domain: Option<String>,
_apis: Vec<&str>,
_logger: Arc<RotatingLogger>,
) -> ! {
die!("Your Parity version has been compiled without JSON-RPC support.")
}
#[cfg(not(feature = "webapp"))] #[cfg(not(feature = "webapp"))]
struct WebappServer; struct WebappServer;
@ -704,7 +612,7 @@ impl Configuration {
let panic_handler = PanicHandler::new_in_arc(); let panic_handler = PanicHandler::new_in_arc();
// Setup logging // Setup logging
let logger = setup_log(&self.args.flag_logging); let logger = setup_log::setup_log(&self.args.flag_logging);
// Raise fdlimit // Raise fdlimit
unsafe { ::fdlimit::raise_fd_limit(); } 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 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()); 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(), service.client(),
sync.clone(), sync.clone(),
account_service.clone(), account_service.clone(),
@ -828,31 +736,7 @@ fn wait_for_exit(panic_handler: Arc<PanicHandler>, _rpc_server: Option<RpcServer
info!("Finishing work, please wait..."); info!("Finishing work, please wait...");
} }
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),
}
}
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() { fn main() {
Configuration::parse().execute(); Configuration::parse().execute();
} }

85
parity/rpc.rs Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
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<Client>,
_sync: Arc<EthSync>,
_secret_store: Arc<AccountService>,
_miner: Arc<Miner>,
_url: &SocketAddr,
_cors_domain: Option<String>,
_apis: Vec<&str>,
_logger: Arc<RotatingLogger>,
) -> ! {
die!("Your Parity version has been compiled without JSON-RPC support.")
}
#[cfg(feature = "rpc")]
pub fn setup_rpc_server(
client: Arc<Client>,
sync: Arc<EthSync>,
secret_store: Arc<AccountService>,
miner: Arc<Miner>,
url: &SocketAddr,
cors_domain: Option<String>,
apis: Vec<&str>,
logger: Arc<RotatingLogger>,
) -> 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,
}
}

60
parity/setup_log.rs Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
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<String>) -> Arc<RotatingLogger> {
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
}