Skip to content

Commit 478d6a5

Browse files
committed
Merge #354: Drop Windows support for JSONRPC over UDS
7ce039c Make the jsonrpc module optional through a default feature (Antoine Poinsot) 767c38e jsonrpc: remove support for Windows (Antoine Poinsot) Pull request description: Based on #353, which provides a way to access `revaultd`'s commands through a library API, this drops the support of our greatly hacky JSONRPC server on UDS socket for Windows >10. This also makes the JSONRPC server an optional feature (activated by default). Fixes #339 Fixes #79 Fixes #27 ACKs for top commit: edouardparis: ACK 7ce039c Tree-SHA512: de1d7da33311da5b10e5e6cc23558cbdfaeccafddc74838c894076f25ba254559204782ad91ce66b85c10838e550e2071d57df88cbbbba5b10a85a1942da5c78
2 parents d7907a8 + 7ce039c commit 478d6a5

File tree

6 files changed

+19
-156
lines changed

6 files changed

+19
-156
lines changed

.github/workflows/main.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,9 @@ jobs:
3838
toolchain: ${{ matrix.toolchain }}
3939
override: true
4040
profile: minimal
41-
- name: Test on Rust ${{ matrix.toolchain }}
41+
- name: Test on Rust ${{ matrix.toolchain }} (only Windows)
42+
if: matrix.os == 'windows-latest'
43+
run: cargo test --verbose --no-default-features
44+
- name: Test on Rust ${{ matrix.toolchain }} (non Windows)
45+
if: matrix.os != 'windows-latest'
4246
run: cargo test --verbose --color always -- --nocapture

Cargo.lock

Lines changed: 1 addition & 74 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,16 @@ exclude = [".github/", ".cirrus.yml", "tests/", "test_data/", "contrib/", "pypr
1212
[[bin]]
1313
name = "revaultd"
1414
path = "src/bin/daemon.rs"
15+
required-features = ["jsonrpc_server"]
1516

1617
[[bin]]
1718
name = "revault-cli"
1819
path = "src/bin/cli.rs"
20+
required-features = ["jsonrpc_server"]
21+
22+
[features]
23+
default = ["jsonrpc_server"]
24+
jsonrpc_server = ["jsonrpc-core", "jsonrpc-derive", "mio"]
1925

2026
[dependencies]
2127
revault_tx = { git = "https://github.com/revault/revault_tx", features = ["use-serde"] }
@@ -54,9 +60,6 @@ rusqlite = { version = "0.26.3", features = ["bundled", "unlock_notify"] }
5460
libc = "0.2.80"
5561

5662
# For the JSONRPC server
57-
jsonrpc-core = "15.1"
58-
jsonrpc-derive = "15.1"
59-
[target.'cfg(not(windows))'.dependencies]
60-
mio = { version = "0.7", features = ["default", "os-poll", "os-util", "uds"] }
61-
[target.'cfg(windows)'.dependencies]
62-
uds_windows = "1.0"
63+
jsonrpc-core = { version = "15.1", optional = true }
64+
jsonrpc-derive = { version = "15.1", optional = true }
65+
mio = { version = "0.7", features = ["default", "os-poll", "os-util", "uds"], optional = true }

src/bin/cli.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,7 @@ use std::{
99

1010
use serde_json::Value as Json;
1111

12-
#[cfg(not(windows))]
1312
use std::os::unix::net::UnixStream;
14-
#[cfg(windows)]
15-
use uds_windows::UnixStream;
1613

1714
// Exits with error
1815
fn show_usage() {

src/jsonrpc/server.rs

Lines changed: 1 addition & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,8 @@ use std::{
1212
thread,
1313
};
1414

15-
#[cfg(not(windows))]
1615
pub use mio::net::UnixListener;
17-
#[cfg(not(windows))]
1816
use mio::{net::UnixStream, Events, Interest, Poll, Token};
19-
#[cfg(windows)]
20-
pub use uds_windows::UnixListener;
21-
#[cfg(windows)]
22-
use uds_windows::UnixStream;
2317

2418
use jsonrpc_core::{futures::Future, Call, MethodCall, Response};
2519

@@ -62,10 +56,6 @@ fn read_bytes_from_stream(stream: &mut dyn io::Read) -> Result<Option<Vec<u8>>,
6256
// done writing.
6357
if total_read == buf.len() {
6458
buf.resize(total_read * 2, 0);
65-
} else {
66-
// But on windows, we do as we'll never receive a WouldBlock..
67-
#[cfg(windows)]
68-
return Ok(Some(trimmed(buf, total_read)));
6959
}
7060
}
7161
Err(err) => {
@@ -131,7 +121,6 @@ fn write_byte_stream(stream: &mut UnixStream, resp: Vec<u8>) -> Result<Option<Ve
131121

132122
// Used to check if, when receiving an event for a token, we have an ongoing connection and stream
133123
// for it.
134-
#[cfg(not(windows))]
135124
type ConnectionMap = HashMap<Token, (UnixStream, Arc<RwLock<VecDeque<Vec<u8>>>>)>;
136125

137126
fn handle_single_request(
@@ -235,8 +224,7 @@ fn read_handle_request(
235224
Ok(())
236225
}
237226

238-
// For all but Windows, we use Mio.
239-
#[cfg(not(windows))]
227+
// Our main polling loop
240228
fn mio_loop(
241229
mut listener: UnixListener,
242230
jsonrpc_io: jsonrpc_core::MetaIoHandler<JsonRpcMetaData>,
@@ -375,52 +363,6 @@ fn mio_loop(
375363
}
376364
}
377365

378-
// For windows, we don't: Mio UDS support for Windows is not yet implemented.
379-
#[cfg(windows)]
380-
fn windows_loop(
381-
listener: UnixListener,
382-
jsonrpc_io: jsonrpc_core::MetaIoHandler<JsonRpcMetaData>,
383-
metadata: JsonRpcMetaData,
384-
) -> Result<(), io::Error> {
385-
for mut stream in listener.incoming() {
386-
let mut stream = stream?;
387-
388-
// Ok, so we got something to read (we don't respond to garbage)
389-
while let Some(bytes) = read_bytes_from_stream(&mut stream)? {
390-
// Is it actually readable?
391-
match String::from_utf8(bytes) {
392-
Ok(string) => {
393-
// If it is and wants a response, write it directly
394-
if let Some(resp) = jsonrpc_io.handle_request_sync(&string, metadata.clone()) {
395-
let mut resp = Some(resp.into_bytes());
396-
loop {
397-
resp = write_byte_stream(&mut stream, resp.unwrap())?;
398-
if resp.is_none() {
399-
break;
400-
}
401-
}
402-
}
403-
}
404-
Err(e) => {
405-
log::error!(
406-
"JSONRPC server: error interpreting request: '{}'",
407-
e.to_string()
408-
);
409-
}
410-
}
411-
}
412-
413-
// We can't loop until is_shutdown() as we block until we got a message.
414-
// So, to handle shutdown the cleanest way is to check if the above handler
415-
// just set shutdown.
416-
if metadata.is_shutdown() {
417-
break;
418-
}
419-
}
420-
421-
Ok(())
422-
}
423-
424366
// Tries to bind to the socket, if we are told it's already in use try to connect
425367
// to check there is actually someone listening and it's not a leftover from a
426368
// crash.
@@ -448,11 +390,8 @@ fn bind(socket_path: PathBuf) -> Result<UnixListener, io::Error> {
448390
/// Bind to the UDS at `socket_path`
449391
pub fn rpcserver_setup(socket_path: PathBuf) -> Result<UnixListener, io::Error> {
450392
// Create the socket with RW permissions only for the user
451-
// FIXME: find a workaround for Windows...
452-
#[cfg(unix)]
453393
let old_umask = unsafe { libc::umask(0o177) };
454394
let listener = bind(socket_path);
455-
#[cfg(unix)]
456395
unsafe {
457396
libc::umask(old_umask);
458397
}
@@ -470,10 +409,7 @@ pub fn rpcserver_loop(
470409
let metadata = JsonRpcMetaData::new(daemon_control);
471410

472411
log::info!("JSONRPC server started.");
473-
#[cfg(not(windows))]
474412
return mio_loop(listener, jsonrpc_io, metadata);
475-
#[cfg(windows)]
476-
return windows_loop(listener, jsonrpc_io, metadata);
477413
}
478414

479415
#[cfg(test)]
@@ -488,10 +424,7 @@ mod tests {
488424
time::Duration,
489425
};
490426

491-
#[cfg(not(windows))]
492427
use std::os::unix::net::UnixStream;
493-
#[cfg(windows)]
494-
use uds_windows::UnixStream;
495428

496429
// Redundant with functional tests but useful for testing the Windows loop
497430
// until the functional tests suite can run on it.
@@ -539,8 +472,6 @@ mod tests {
539472
)
540473
);
541474

542-
// TODO: support this for Windows..
543-
#[cfg(not(windows))]
544475
{
545476
// Write valid JSONRPC message with a half-written one afterward
546477
let msg = String::from(

src/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ pub mod commands;
66
mod communication;
77
pub mod config;
88
mod database;
9+
#[cfg(all(not(windows), feature = "jsonrpc_server"))]
910
mod jsonrpc;
1011
mod revaultd;
1112
mod sigfetcher;
@@ -150,8 +151,8 @@ impl DaemonControl {
150151
self.sigfetcher_conn.shutdown();
151152
}
152153

153-
// TODO: make it optional at compile time
154154
/// Start and bind the server to the configured UNIX socket
155+
#[cfg(all(not(windows), feature = "jsonrpc_server"))]
155156
pub fn rpc_server_setup(&self) -> Result<jsonrpc::server::UnixListener, io::Error> {
156157
let socket_file = self.revaultd.read().unwrap().rpc_socket_file();
157158
jsonrpc::server::rpcserver_setup(socket_file)
@@ -264,8 +265,8 @@ impl DaemonHandle {
264265
.expect("Joining sigfetcher thread");
265266
}
266267

267-
// TODO: make it optional at compilation time
268268
/// Start the JSONRPC server and listen for commands until we are stopped
269+
#[cfg(all(not(windows), feature = "jsonrpc_server"))]
269270
pub fn rpc_server(&self) -> Result<(), io::Error> {
270271
log::info!("Starting JSONRPC server");
271272

0 commit comments

Comments
 (0)