daemon: allow TCP sockets as well as unix
This commit is contained in:
parent
d57f605d42
commit
7cfb07241c
4 changed files with 53 additions and 11 deletions
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
env,
|
env,
|
||||||
|
net::SocketAddr,
|
||||||
sync::{Arc, LazyLock},
|
sync::{Arc, LazyLock},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -35,6 +36,12 @@ pub struct DaemonCmd {
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
#[arg(conflicts_with = "stdin")]
|
#[arg(conflicts_with = "stdin")]
|
||||||
pub socket: Option<PathBuf>,
|
pub socket: Option<PathBuf>,
|
||||||
|
|
||||||
|
/// Use a TCP port instead of a Unix socket or stdin. e.g.: 0.0.0.0:42420
|
||||||
|
#[arg(long)]
|
||||||
|
#[arg(conflicts_with = "socket")]
|
||||||
|
#[arg(conflicts_with = "stdin")]
|
||||||
|
pub tcp: Option<SocketAddr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, clap::Subcommand)]
|
#[derive(Debug, Clone, PartialEq, clap::Subcommand)]
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
use std::{
|
use std::{
|
||||||
|
borrow::Cow,
|
||||||
env, io,
|
env, io,
|
||||||
|
net::SocketAddr,
|
||||||
os::fd::{AsFd, BorrowedFd, IntoRawFd, OwnedFd, RawFd},
|
os::fd::{AsFd, BorrowedFd, IntoRawFd, OwnedFd, RawFd},
|
||||||
process::{Command, Stdio},
|
process::{Command, Stdio},
|
||||||
sync::{
|
sync::{
|
||||||
|
|
@ -11,7 +13,12 @@ use std::{
|
||||||
|
|
||||||
use iddqd::{BiHashMap, IdOrdMap};
|
use iddqd::{BiHashMap, IdOrdMap};
|
||||||
|
|
||||||
use mio::{Events, Interest, Poll, Token, event::Event, net::UnixListener, unix::SourceFd};
|
use mio::{
|
||||||
|
Events, Interest, Poll, Token,
|
||||||
|
event::Event,
|
||||||
|
net::{TcpListener, UnixListener},
|
||||||
|
unix::SourceFd,
|
||||||
|
};
|
||||||
|
|
||||||
use rustix::{
|
use rustix::{
|
||||||
buffer::spare_capacity,
|
buffer::spare_capacity,
|
||||||
|
|
@ -56,14 +63,6 @@ pub static TMPDIR: LazyLock<&'static Path> = LazyLock::new(|| {
|
||||||
Box::leak(dir)
|
Box::leak(dir)
|
||||||
});
|
});
|
||||||
|
|
||||||
pub static NIXOS_REBUILD: LazyLock<&'static Path> = LazyLock::new(|| {
|
|
||||||
which::which("nixos-rebuild")
|
|
||||||
.inspect_err(|e| error!("couldn't find `nixos-rebuild` in PATH: {e}"))
|
|
||||||
.map(PathBuf::into_boxed_path)
|
|
||||||
.map(|boxed| &*Box::leak(boxed))
|
|
||||||
.unwrap_or(Path::new("/run/current-system/sw/bin/nixos-rebuild"))
|
|
||||||
});
|
|
||||||
|
|
||||||
pub static NIX: LazyLock<&'static Path> = LazyLock::new(|| {
|
pub static NIX: LazyLock<&'static Path> = LazyLock::new(|| {
|
||||||
which::which("nix")
|
which::which("nix")
|
||||||
.inspect_err(|e| error!("couldn't find `nix` in PATH: {e}"))
|
.inspect_err(|e| error!("couldn't find `nix` in PATH: {e}"))
|
||||||
|
|
@ -243,7 +242,11 @@ impl Daemon {
|
||||||
.insert_unique(FdInfo::new(fd.as_raw_fd(), kind))
|
.insert_unique(FdInfo::new(fd.as_raw_fd(), kind))
|
||||||
.unwrap_or_else(|e| unreachable!("{e}"));
|
.unwrap_or_else(|e| unreachable!("{e}"));
|
||||||
|
|
||||||
debug!("opened daemon to {:?} file descriptor {fd:?}", name);
|
if let Some(name) = &name {
|
||||||
|
info!("opened daemon to {}", name.to_string_lossy());
|
||||||
|
} else {
|
||||||
|
debug!("opened daemon to {name:?} (fd {fd:?})");
|
||||||
|
}
|
||||||
|
|
||||||
let path = name
|
let path = name
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
|
@ -260,6 +263,24 @@ impl Daemon {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_tcp_socket_addr(config_path: Arc<Path>, addr: SocketAddr) -> Result<Self, IoError> {
|
||||||
|
let listener = TcpListener::bind(addr.clone())
|
||||||
|
.inspect_err(|e| error!("failed to bind to '{addr}': {e}"))?;
|
||||||
|
|
||||||
|
let listener_owned_fd = OwnedFd::from(listener);
|
||||||
|
// FIXME: should we KEEP_ALIVE?
|
||||||
|
rustix::net::sockopt::set_socket_keepalive(&listener_owned_fd, true).unwrap();
|
||||||
|
|
||||||
|
let name = OsString::from(addr.to_string()).into_boxed_os_str();
|
||||||
|
|
||||||
|
Ok(Self::new(
|
||||||
|
config_path,
|
||||||
|
listener_owned_fd,
|
||||||
|
FdKind::Socket,
|
||||||
|
Some(name),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn from_unix_socket_path(config_path: Arc<Path>, path: &Path) -> Result<Self, IoError> {
|
pub fn from_unix_socket_path(config_path: Arc<Path>, path: &Path) -> Result<Self, IoError> {
|
||||||
// We unconditionally unlink() `path` before binding, but completely ignore the result.
|
// We unconditionally unlink() `path` before binding, but completely ignore the result.
|
||||||
let _ = rustix::fs::unlink(path);
|
let _ = rustix::fs::unlink(path);
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,7 @@ impl<'a> Display for FdInfoDisplay<'a> {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"{} fd {} ({})",
|
"{} fd {} ({})",
|
||||||
self.inner.kind.name_str(),
|
self.inner.kind,
|
||||||
self.inner.fd,
|
self.inner.fd,
|
||||||
self.inner.name().to_string_lossy(),
|
self.inner.name().to_string_lossy(),
|
||||||
)?;
|
)?;
|
||||||
|
|
@ -136,6 +136,19 @@ impl FdKind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for FdKind {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> FmtResult {
|
||||||
|
use FdKind::*;
|
||||||
|
let name = self.name_str();
|
||||||
|
match self {
|
||||||
|
ChildStdout(pid) | ChildStderr(pid) | Pid(pid) => write!(f, "{name} for {pid}")?,
|
||||||
|
_ => write!(f, "{name}")?,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy)]
|
#[derive(Copy)]
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct TokenFd {
|
pub struct TokenFd {
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,7 @@ pub fn do_daemon(args: Arc<Args>, daemon_args: DaemonCmd) -> Result<(), BoxDynEr
|
||||||
|
|
||||||
let mut daemon = match daemon_args {
|
let mut daemon = match daemon_args {
|
||||||
DaemonCmd { stdin: true, .. } => Daemon::from_stdin(config_file),
|
DaemonCmd { stdin: true, .. } => Daemon::from_stdin(config_file),
|
||||||
|
DaemonCmd { tcp: Some(tcp), .. } => Daemon::from_tcp_socket_addr(config_file, tcp)?,
|
||||||
DaemonCmd { socket: None, .. } => Daemon::open_default_socket(config_file)?,
|
DaemonCmd { socket: None, .. } => Daemon::open_default_socket(config_file)?,
|
||||||
DaemonCmd {
|
DaemonCmd {
|
||||||
socket: Some(socket),
|
socket: Some(socket),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue