From f3f2bdd4767d2ffbd5a63cde6bbcce0f048b7ab1 Mon Sep 17 00:00:00 2001 From: Antoine Poinsot Date: Tue, 17 Nov 2020 12:15:18 +0100 Subject: [PATCH] jsonrpc: uds support for Windows I could not find a way to get mio 0.7 running with Windows' uds. So, until https://github.com/tokio-rs/mio/issues/880 (https://github.com/deprecrated/mio-uds/issues/7) is implemented in Mio we use a simple blocking event loop for Windows. That's fine, it's just for the RPC. We could potentially see some load on a server, but it'd be on UNIX so Everything Is Fine :tm:. Signed-off-by: Antoine Poinsot --- Cargo.lock | 121 ++++++++++++++++++++++++++++++++++++++++++--- Cargo.toml | 3 ++ src/jsonrpc/mod.rs | 58 +++++++++++++++------- src/main.rs | 9 ++-- 4 files changed, 161 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 71d6276d..ed9858db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -133,7 +133,7 @@ dependencies = [ "num-integer", "num-traits", "time", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -179,7 +179,7 @@ checksum = "8e93d7f5705de3e49895a2b5e0b8855a1c27f080192ae9c32a6432d50741a57a" dependencies = [ "libc", "redox_users", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -210,6 +210,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + [[package]] name = "futures" version = "0.1.30" @@ -308,6 +314,16 @@ dependencies = [ "syn", ] +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -364,7 +380,7 @@ dependencies = [ "log", "miow", "ntapi", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -374,7 +390,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07b88fb9795d4d36d62a012dfbf49a8f5cf12751f36d31a9dbe66d528e58979e" dependencies = [ "socket2", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -383,7 +399,7 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -438,6 +454,43 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +dependencies = [ + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "rdrand", + "winapi 0.3.9", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + [[package]] name = "redox_syscall" version = "0.1.57" @@ -455,6 +508,15 @@ dependencies = [ "rust-argon2", ] +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "revault_tx" version = "0.0.1" @@ -484,6 +546,7 @@ dependencies = [ "serde", "serde_json", "toml", + "uds_windows", ] [[package]] @@ -583,7 +646,7 @@ dependencies = [ "cfg-if", "libc", "redox_syscall", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -597,6 +660,16 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "tempdir" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" +dependencies = [ + "rand", + "remove_dir_all", +] + [[package]] name = "time" version = "0.1.44" @@ -605,7 +678,7 @@ checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" dependencies = [ "libc", "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -617,6 +690,18 @@ dependencies = [ "serde", ] +[[package]] +name = "uds_windows" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f0497369defbdcde081067715cc9bf9313b695cb9157f45fee823977d4fbb55" +dependencies = [ + "kernel32-sys", + "tempdir", + "winapi 0.2.8", + "ws2_32-sys", +] + [[package]] name = "unicode-xid" version = "0.2.1" @@ -641,6 +726,12 @@ version = "0.10.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + [[package]] name = "winapi" version = "0.3.9" @@ -651,6 +742,12 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -662,3 +759,13 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] diff --git a/Cargo.toml b/Cargo.toml index f1f73653..ebae50f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,4 +36,7 @@ rusqlite = { version = "0.24.1", features = ["bundled"] } # For the JSONRPC API jsonrpc-core = "15.1.0" jsonrpc-derive = "15.1.0" +[target.'cfg(not(windows))'.dependencies] mio = { version = "0.7.5", features = ["default", "os-poll", "os-util", "uds"] } +[target.'cfg(windows)'.dependencies] +uds_windows = "0.1.5" diff --git a/src/jsonrpc/mod.rs b/src/jsonrpc/mod.rs index 934cb5d3..1987cf1f 100644 --- a/src/jsonrpc/mod.rs +++ b/src/jsonrpc/mod.rs @@ -8,12 +8,13 @@ use std::{ time::Duration, }; +#[cfg(not(windows))] use mio::{ net::{UnixListener, UnixStream}, Events, Interest, Poll, Token, }; - -const JSONRPC_SERVER: Token = Token(0); +#[cfg(windows)] +use uds_windows::{UnixListener, UnixStream}; pub struct RpcImpl; impl RpcApi for RpcImpl { @@ -23,17 +24,6 @@ impl RpcApi for RpcImpl { } } -/// Set up the poller used to listen on the Unix Domain Socket for JSONRPC messages -pub fn jsonrpcapi_setup(socket_path: PathBuf) -> Result<(Poll, UnixListener), io::Error> { - // FIXME: permissions! (umask before binding ?) - let mut listener = UnixListener::bind(&socket_path)?; - let poll = Poll::new()?; - poll.registry() - .register(&mut listener, JSONRPC_SERVER, Interest::READABLE)?; - - Ok((poll, listener)) -} - // Remove trailing newlines from utf-8 byte stream fn trimmed(mut vec: Vec, bytes_read: usize) -> Vec { vec.truncate(bytes_read); @@ -109,11 +99,19 @@ fn handle_byte_stream( Ok(()) } -/// The main event loop for the JSONRPC interface -pub fn jsonrpcapi_loop(mut poller: Poll, listener: UnixListener) -> Result<(), io::Error> { +// For all but Windows, we use Mio. +#[cfg(not(windows))] +fn mio_loop( + mut listener: UnixListener, + jsonrpc_io: jsonrpc_core::IoHandler, +) -> Result<(), io::Error> { + const JSONRPC_SERVER: Token = Token(0); + let mut poller = Poll::new()?; let mut events = Events::with_capacity(16); - let mut jsonrpc_io = jsonrpc_core::IoHandler::new(); - jsonrpc_io.extend_with(RpcImpl.to_delegate()); + + poller + .registry() + .register(&mut listener, JSONRPC_SERVER, Interest::READABLE)?; loop { poller.poll(&mut events, Some(Duration::from_millis(100)))?; @@ -146,3 +144,29 @@ pub fn jsonrpcapi_loop(mut poller: Poll, listener: UnixListener) -> Result<(), i } } } + +// For windows, we don't: Mio UDS support for Windows is not yet implemented. +#[cfg(windows)] +fn windows_loop( + listener: UnixListener, + jsonrpc_io: jsonrpc_core::IoHandler, +) -> Result<(), io::Error> { + for stream in listener.incoming() { + handle_byte_stream(&jsonrpc_io, stream?)?; + } + + Ok(()) +} + +/// The main event loop for the JSONRPC interface, polling the UDS at `socket_path` +pub fn jsonrpcapi_loop(socket_path: PathBuf) -> Result<(), io::Error> { + // FIXME: permissions! (umask before binding ?) + let listener = UnixListener::bind(&socket_path)?; + let mut jsonrpc_io = jsonrpc_core::IoHandler::new(); + jsonrpc_io.extend_with(RpcImpl.to_delegate()); + + #[cfg(not(windows))] + return mio_loop(listener, jsonrpc_io); + #[cfg(windows)] + return windows_loop(listener, jsonrpc_io); +} diff --git a/src/main.rs b/src/main.rs index 1298b2a1..e971be12 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,7 @@ use crate::{ bitcoind::actions::{bitcoind_main_loop, setup_bitcoind}, config::Config, database::actions::setup_db, - jsonrpc::{jsonrpcapi_loop, jsonrpcapi_setup}, + jsonrpc::jsonrpcapi_loop, revaultd::RevaultD, }; @@ -46,12 +46,9 @@ fn daemon_main(mut revaultd: RevaultD) { revaultd.bitcoind_config.network ); - let (poller, listener) = jsonrpcapi_setup(revaultd.rpc_socket_file()).unwrap_or_else(|e| { - log::error!("Error setting up the JSONRPC server: {}", e.to_string()); - process::exit(1) - }); + let socket_path = revaultd.rpc_socket_file(); let _jsonrpc_thread = thread::spawn(move || { - jsonrpcapi_loop(poller, listener).unwrap_or_else(|e| { + jsonrpcapi_loop(socket_path).unwrap_or_else(|e| { log::error!("Error in JSONRPC server event loop: {}", e.to_string()); process::exit(1) })