socket-api feature: make the daemon core embeddable in-process

Gate the unix-socket server, systemd activation, and the socket-serving
run() behind a new default socket-api feature, with required-features on
the binary. The core modules (daemon, store, transfer, discovery, meta)
stay feature-free, so platforms without a daemon model (iOS — redoal
ADR-0012) can embed Daemon directly via
cargo check -p varde-daemon --no-default-features.

Also cfg-gate the abstract-socket branch of sd_notify to Linux: abstract
socket names don't exist elsewhere, and this was the one spot keeping
varde-daemon from compiling on macOS at all.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-16 12:41:01 +02:00
parent 258fa072aa
commit 8c98c00549
3 changed files with 22 additions and 4 deletions
+6 -1
View File
@@ -10,6 +10,7 @@ rust-version.workspace = true
[[bin]] [[bin]]
name = "varde-daemon" name = "varde-daemon"
path = "src/main.rs" path = "src/main.rs"
required-features = ["socket-api"]
[dependencies] [dependencies]
varde-proto = { workspace = true } varde-proto = { workspace = true }
@@ -42,8 +43,12 @@ tracing-subscriber = { workspace = true }
[features] [features]
# Metered-connection detection via NetworkManager over D-Bus. On by # Metered-connection detection via NetworkManager over D-Bus. On by
# default; disable for systems without D-Bus (they run as unmetered). # default; disable for systems without D-Bus (they run as unmetered).
default = ["metered"] default = ["metered", "socket-api"]
metered = ["dep:zbus"] metered = ["dep:zbus"]
# The unix-socket API server, systemd socket activation, and signal
# handling. On by default; disable to embed the daemon core in-process
# on platforms without a daemon model (iOS — ADR-0012 in redoal).
socket-api = []
[dev-dependencies] [dev-dependencies]
tempfile = "3" tempfile = "3"
+3
View File
@@ -9,16 +9,19 @@ pub mod discovery;
pub mod dscp; pub mod dscp;
pub mod meta; pub mod meta;
pub mod metered; pub mod metered;
#[cfg(feature = "socket-api")]
pub mod server; pub mod server;
pub mod shaped; pub mod shaped;
pub mod store; pub mod store;
pub mod transfer; pub mod transfer;
#[cfg(feature = "socket-api")]
use anyhow::Result; use anyhow::Result;
/// Run a daemon with the given config until the future is dropped or the /// Run a daemon with the given config until the future is dropped or the
/// listener fails. The socket is bound before the accept loop starts, so /// listener fails. The socket is bound before the accept loop starts, so
/// once this future has been polled the socket path exists. /// once this future has been polled the socket path exists.
#[cfg(feature = "socket-api")]
pub async fn run(config: config::Config) -> Result<()> { pub async fn run(config: config::Config) -> Result<()> {
let socket_path = config.socket_path.clone(); let socket_path = config.socket_path.clone();
let daemon = daemon::Daemon::open(config).await?; let daemon = daemon::Daemon::open(config).await?;
+10
View File
@@ -49,9 +49,19 @@ pub fn notify_ready() {
let socket = std::os::unix::net::UnixDatagram::unbound()?; let socket = std::os::unix::net::UnixDatagram::unbound()?;
let bytes = path.as_encoded_bytes(); let bytes = path.as_encoded_bytes();
if let Some(name) = bytes.strip_prefix(b"@") { if let Some(name) = bytes.strip_prefix(b"@") {
// Abstract socket names are Linux-only, like systemd itself;
// elsewhere an @-prefixed NOTIFY_SOCKET can only be ignored.
#[cfg(target_os = "linux")]
{
use std::os::linux::net::SocketAddrExt; use std::os::linux::net::SocketAddrExt;
let addr = std::os::unix::net::SocketAddr::from_abstract_name(name)?; let addr = std::os::unix::net::SocketAddr::from_abstract_name(name)?;
socket.send_to_addr(b"READY=1", &addr)?; socket.send_to_addr(b"READY=1", &addr)?;
}
#[cfg(not(target_os = "linux"))]
{
let _ = name;
debug!("abstract NOTIFY_SOCKET unsupported on this platform");
}
} else { } else {
socket.send_to(b"READY=1", &path)?; socket.send_to(b"READY=1", &path)?;
} }