diff --git a/Cargo.lock b/Cargo.lock index 5902aa786..811bb6cbc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4369,12 +4369,14 @@ dependencies = [ "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-network 1.12.0", "ethcore-network-devp2p 1.12.0", + "ethkey 0.3.0", "jsonrpc-core 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-http-server 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-pubsub 10.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "panic_hook 0.1.0", "parity-whisper 0.1.0", + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/whisper/README.md b/whisper/README.md index dc449568a..b64c0244f 100644 --- a/whisper/README.md +++ b/whisper/README.md @@ -14,8 +14,11 @@ Usage: Options: --whisper-pool-size SIZE Specify Whisper pool size [default: 10]. - -p, --port PORT Specify which RPC port to use [default: 8545]. - -a, --address ADDRESS Specify which address to use [default: 127.0.0.1]. + -p, --port PORT Specify which P2P port to use [default: random]. + -a, --address ADDRESS Specify which P2P address to use [default: 127.0.0.1]. + -s, --secret KEYFILE Specify which file contains the key to generate the enode. + -P, --rpc-port PORT Specify which RPC port to use [default: 8545]. + -A, --rpc-address ADDRESS Specify which RPC address to use [default: 127.0.0.1]. -l, --log LEVEL Specify the logging level. Must conform to the same format as RUST_LOG [default: Error]. -h, --help Display this message and exit. ``` diff --git a/whisper/cli/Cargo.toml b/whisper/cli/Cargo.toml index 4d123c09a..5ed38e47d 100644 --- a/whisper/cli/Cargo.toml +++ b/whisper/cli/Cargo.toml @@ -18,6 +18,8 @@ panic_hook = { path = "../../util/panic-hook" } parity-whisper = { path = "../" } serde = "1.0" serde_derive = "1.0" +ethkey = { path = "../../accounts/ethkey" } +rustc-hex = "2.0" [[bin]] name = "whisper" diff --git a/whisper/cli/src/main.rs b/whisper/cli/src/main.rs index 9ef2304b4..41d9e80e4 100644 --- a/whisper/cli/src/main.rs +++ b/whisper/cli/src/main.rs @@ -33,6 +33,8 @@ extern crate serde; extern crate jsonrpc_core; extern crate jsonrpc_pubsub; extern crate jsonrpc_http_server; +extern crate ethkey; +extern crate rustc_hex; #[macro_use] extern crate log as rlog; @@ -45,6 +47,10 @@ use std::{fmt, io, process, env, sync::Arc}; use jsonrpc_core::{Metadata, MetaIoHandler}; use jsonrpc_pubsub::{PubSubMetadata, Session}; use jsonrpc_http_server::{AccessControlAllowOrigin, DomainsValidation}; +use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr}; +use std::str::FromStr; +use ethkey::Secret; +use rustc_hex::FromHex; const POOL_UNIT: usize = 1024 * 1024; const USAGE: &'static str = r#" @@ -57,8 +63,11 @@ Usage: Options: --whisper-pool-size SIZE Specify Whisper pool size [default: 10]. - -p, --port PORT Specify which RPC port to use [default: 8545]. - -a, --address ADDRESS Specify which address to use [default: 127.0.0.1]. + -p, --port PORT Specify which P2P port to use [default: random]. + -a, --address ADDRESS Specify which P2P address to use [default: 127.0.0.1]. + -s, --secret KEYFILE Specify which file contains the key to generate the enode. + -P, --rpc-port PORT Specify which RPC port to use [default: 8545]. + -A, --rpc-address ADDRESS Specify which RPC address to use [default: 127.0.0.1]. -l, --log LEVEL Specify the logging level. Must conform to the same format as RUST_LOG [default: Error]. -h, --help Display this message and exit. "#; @@ -79,7 +88,10 @@ struct Args { flag_whisper_pool_size: usize, flag_port: String, flag_address: String, + flag_rpc_port: String, + flag_rpc_address: String, flag_log: String, + flag_secret: String, } struct WhisperPoolHandle { @@ -131,6 +143,8 @@ enum Error { JsonRpc(jsonrpc_core::Error), Network(net::Error), SockAddr(std::net::AddrParseError), + FromHex(rustc_hex::FromHexError), + ParseInt(std::num::ParseIntError), } impl From for Error { @@ -163,6 +177,18 @@ impl From for Error { } } +impl From for Error { + fn from(err: rustc_hex::FromHexError) -> Self { + Error::FromHex(err) + } +} + +impl From for Error { + fn from(err: std::num::ParseIntError) -> Self { + Error::ParseInt(err) + } +} + impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { @@ -171,6 +197,8 @@ impl fmt::Display for Error { Error::Io(ref e) => write!(f, "{}", e), Error::JsonRpc(ref e) => write!(f, "{:?}", e), Error::Network(ref e) => write!(f, "{}", e), + Error::ParseInt(ref e) => write!(f, "Invalid port: {}", e), + Error::FromHex(ref e) => write!(f, "Error deciphering key: {}", e), } } } @@ -196,7 +224,7 @@ fn execute(command: I) -> Result<(), Error> where I: IntoIterator, // Parse arguments let args: Args = Docopt::new(USAGE).and_then(|d| d.argv(command).deserialize())?; let pool_size = args.flag_whisper_pool_size * POOL_UNIT; - let url = format!("{}:{}", args.flag_address, args.flag_port); + let rpc_url = format!("{}:{}", args.flag_rpc_address, args.flag_rpc_port); initialize_logger(args.flag_log); info!(target: "whisper-cli", "start"); @@ -207,8 +235,29 @@ fn execute(command: I) -> Result<(), Error> where I: IntoIterator, // Whisper protocol network handler let whisper_network_handler = Arc::new(whisper::net::Network::new(pool_size, manager.clone())); + let network_config = { + let mut cfg = net::NetworkConfiguration::new(); + let port = match args.flag_port.as_str() { + "random" => 0 as u16, + port => port.parse::()?, + + }; + let addr = Ipv4Addr::from_str(&args.flag_address[..])?; + cfg.listen_address = Some(SocketAddr::V4(SocketAddrV4::new(addr, port))); + cfg.use_secret = match args.flag_secret.as_str() { + "" => None, + fname => { + let key_text = std::fs::read_to_string(fname)?; + let key : Vec = FromHex::from_hex(key_text.as_str())?; + Secret::from_slice(key.as_slice()) + } + }; + cfg.nat_enabled = false; + cfg + }; + // Create network service - let network = devp2p::NetworkService::new(net::NetworkConfiguration::new_local(), None)?; + let network = devp2p::NetworkService::new(network_config, None)?; // Start network service network.start().map_err(|(err, _)| err)?; @@ -233,7 +282,7 @@ fn execute(command: I) -> Result<(), Error> where I: IntoIterator, let server = jsonrpc_http_server::ServerBuilder::new(io) .cors(DomainsValidation::AllowOnly(vec![AccessControlAllowOrigin::Null])) - .start_http(&url.parse()?)?; + .start_http(&rpc_url.parse()?)?; server.wait();