From 690701841709637df076ca34e0f74a131642c93f Mon Sep 17 00:00:00 2001 From: Demi Obenour Date: Tue, 16 Jun 2020 10:14:12 +0000 Subject: [PATCH] Add IPC support (#6348) This is useful for both security and performance reasons. IPC is faster than TCP, and it is subject to OS access controls. --- Cargo.lock | 80 +++++++++++++++++++++++++++++- client/cli/src/commands/mod.rs | 6 +++ client/cli/src/commands/run_cmd.rs | 8 +++ client/cli/src/config.rs | 8 +++ client/rpc-servers/Cargo.toml | 1 + client/rpc-servers/src/lib.rs | 19 +++++++ client/service/src/config.rs | 2 + client/service/src/lib.rs | 11 ++++ client/service/test/src/lib.rs | 1 + utils/browser/src/lib.rs | 1 + 10 files changed, 136 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 83c98c65c6cb0..8948337d584a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2383,6 +2383,20 @@ dependencies = [ "unicase", ] +[[package]] +name = "jsonrpc-ipc-server" +version = "14.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dedccd693325d833963b549e959137f30a7a0ea650cde92feda81dc0c1393cb5" +dependencies = [ + "jsonrpc-core", + "jsonrpc-server-utils", + "log", + "parity-tokio-ipc", + "parking_lot 0.10.2", + "tokio-service", +] + [[package]] name = "jsonrpc-pubsub" version = "14.2.0" @@ -3092,7 +3106,7 @@ dependencies = [ "kernel32-sys", "libc", "log", - "miow", + "miow 0.2.1", "net2", "slab", "winapi 0.2.8", @@ -3110,6 +3124,18 @@ dependencies = [ "slab", ] +[[package]] +name = "mio-named-pipes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5e374eff525ce1c5b7687c4cef63943e7686524a387933ad27ca7ec43779cb3" +dependencies = [ + "log", + "mio", + "miow 0.3.5", + "winapi 0.3.8", +] + [[package]] name = "mio-uds" version = "0.6.7" @@ -3133,6 +3159,16 @@ dependencies = [ "ws2_32-sys", ] +[[package]] +name = "miow" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07b88fb9795d4d36d62a012dfbf49a8f5cf12751f36d31a9dbe66d528e58979e" +dependencies = [ + "socket2", + "winapi 0.3.8", +] + [[package]] name = "more-asserts" version = "0.2.1" @@ -4734,6 +4770,25 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa9777aa91b8ad9dd5aaa04a9b6bcb02c7f1deb952fca5a66034d5e63afc5c6f" +[[package]] +name = "parity-tokio-ipc" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e57fea504fea33f9fbb5f49f378359030e7e026a6ab849bb9e8f0787376f1bf" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.29", + "libc", + "log", + "mio-named-pipes", + "miow 0.3.5", + "rand 0.7.3", + "tokio 0.1.22", + "tokio-named-pipes", + "tokio-uds", + "winapi 0.3.8", +] + [[package]] name = "parity-util-mem" version = "0.6.1" @@ -6580,6 +6635,7 @@ version = "2.0.0-rc3" dependencies = [ "jsonrpc-core", "jsonrpc-http-server", + "jsonrpc-ipc-server", "jsonrpc-pubsub", "jsonrpc-ws-server", "log", @@ -8655,6 +8711,19 @@ dependencies = [ "syn 1.0.17", ] +[[package]] +name = "tokio-named-pipes" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d282d483052288b2308ba5ee795f5673b159c9bdf63c385a05609da782a5eae" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.29", + "mio", + "mio-named-pipes", + "tokio 0.1.22", +] + [[package]] name = "tokio-reactor" version = "0.1.12" @@ -8686,6 +8755,15 @@ dependencies = [ "webpki", ] +[[package]] +name = "tokio-service" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162" +dependencies = [ + "futures 0.1.29", +] + [[package]] name = "tokio-sync" version = "0.1.8" diff --git a/client/cli/src/commands/mod.rs b/client/cli/src/commands/mod.rs index 6931a8715c4fd..04cce66bef80d 100644 --- a/client/cli/src/commands/mod.rs +++ b/client/cli/src/commands/mod.rs @@ -285,6 +285,12 @@ macro_rules! substrate_cli_subcommands { } } + fn rpc_ipc(&self) -> $crate::Result<::std::option::Option<::std::string::String>> { + match self { + $($enum::$variant(cmd) => cmd.rpc_ipc()),* + } + } + fn rpc_http(&self) -> $crate::Result<::std::option::Option<::std::net::SocketAddr>> { match self { $($enum::$variant(cmd) => cmd.rpc_http()),* diff --git a/client/cli/src/commands/run_cmd.rs b/client/cli/src/commands/run_cmd.rs index 82d40e6a73f07..16bae1ea963b0 100644 --- a/client/cli/src/commands/run_cmd.rs +++ b/client/cli/src/commands/run_cmd.rs @@ -122,6 +122,10 @@ pub struct RunCmd { #[structopt(long = "prometheus-external")] pub prometheus_external: bool, + /// Specify IPC RPC server path + #[structopt(long = "ipc-path", value_name = "PATH")] + pub ipc_path: Option, + /// Specify HTTP RPC server TCP port. #[structopt(long = "rpc-port", value_name = "PORT")] pub rpc_port: Option, @@ -434,6 +438,10 @@ impl CliConfiguration for RunCmd { Ok(Some(SocketAddr::new(interface, self.rpc_port.unwrap_or(9933)))) } + fn rpc_ipc(&self) -> Result> { + Ok(self.ipc_path.clone()) + } + fn rpc_ws(&self) -> Result> { let interface = rpc_interface( self.ws_external, diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index d121546c193a0..2c3cfe84199d2 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -264,6 +264,13 @@ pub trait CliConfiguration: Sized { Ok(Default::default()) } + /// Get the RPC IPC path (`None` if disabled). + /// + /// By default this is `None`. + fn rpc_ipc(&self) -> Result> { + Ok(Default::default()) + } + /// Get the RPC websocket address (`None` if disabled). /// /// By default this is `None`. @@ -451,6 +458,7 @@ pub trait CliConfiguration: Sized { execution_strategies: self.execution_strategies(is_dev, is_validator)?, rpc_http: self.rpc_http()?, rpc_ws: self.rpc_ws()?, + rpc_ipc: self.rpc_ipc()?, rpc_methods: self.rpc_methods()?, rpc_ws_max_connections: self.rpc_ws_max_connections()?, rpc_cors: self.rpc_cors(is_dev)?, diff --git a/client/rpc-servers/Cargo.toml b/client/rpc-servers/Cargo.toml index 9ea70f1794591..b1ec04f5e4aa4 100644 --- a/client/rpc-servers/Cargo.toml +++ b/client/rpc-servers/Cargo.toml @@ -22,3 +22,4 @@ sp-runtime = { version = "2.0.0-rc3", path = "../../primitives/runtime" } [target.'cfg(not(target_os = "unknown"))'.dependencies] http = { package = "jsonrpc-http-server", version = "14.2.0" } ws = { package = "jsonrpc-ws-server", version = "14.2.0" } +ipc = { version = "14.2.0", package = "jsonrpc-ipc-server" } diff --git a/client/rpc-servers/src/lib.rs b/client/rpc-servers/src/lib.rs index 6fe4586b6ee5e..1e476262acea8 100644 --- a/client/rpc-servers/src/lib.rs +++ b/client/rpc-servers/src/lib.rs @@ -62,6 +62,8 @@ pub fn rpc_handler( mod inner { use super::*; + /// Type alias for ipc server + pub type IpcServer = ipc::Server; /// Type alias for http server pub type HttpServer = http::Server; /// Type alias for ws server @@ -89,6 +91,23 @@ mod inner { .start_http(addr) } + /// Start IPC server listening on given path. + /// + /// **Note**: Only available if `not(target_os = "unknown")`. + pub fn start_ipc( + addr: &str, + io: RpcHandler, + ) -> io::Result { + let builder = ipc::ServerBuilder::new(io); + #[cfg(target_os = "unix")] + builder.set_security_attributes({ + let security_attributes = ipc::SecurityAttributes::empty(); + security_attributes.set_mode(0o600)?; + security_attributes + }); + builder.start(addr) + } + /// Start WS server listening on given address. /// /// **Note**: Only available if `not(target_os = "unknown")`. diff --git a/client/service/src/config.rs b/client/service/src/config.rs index 2d4dc9dc2e90a..b79831d57bba3 100644 --- a/client/service/src/config.rs +++ b/client/service/src/config.rs @@ -67,6 +67,8 @@ pub struct Configuration { pub rpc_http: Option, /// RPC over Websockets binding address. `None` if disabled. pub rpc_ws: Option, + /// RPC over IPC binding path. `None` if disabled. + pub rpc_ipc: Option, /// Maximum number of connections for WebSockets RPC server. `None` if default. pub rpc_ws_max_connections: Option, /// CORS settings for HTTP & WS servers. `None` if all origins are allowed. diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index fc0567e268260..6e230b253da24 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -510,6 +510,16 @@ mod waiting { } } + pub struct IpcServer(pub Option); + impl Drop for IpcServer { + fn drop(&mut self) { + if let Some(server) = self.0.take() { + server.close_handle().close(); + let _ = server.wait(); + } + } + } + pub struct WsServer(pub Option); impl Drop for WsServer { fn drop(&mut self) { @@ -555,6 +565,7 @@ fn start_rpc_servers sc_rpc_server::RpcHandler