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::{
|
||||
env,
|
||||
net::SocketAddr,
|
||||
sync::{Arc, LazyLock},
|
||||
};
|
||||
|
||||
|
|
@ -35,6 +36,12 @@ pub struct DaemonCmd {
|
|||
#[arg(long)]
|
||||
#[arg(conflicts_with = "stdin")]
|
||||
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)]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
use std::{
|
||||
borrow::Cow,
|
||||
env, io,
|
||||
net::SocketAddr,
|
||||
os::fd::{AsFd, BorrowedFd, IntoRawFd, OwnedFd, RawFd},
|
||||
process::{Command, Stdio},
|
||||
sync::{
|
||||
|
|
@ -11,7 +13,12 @@ use std::{
|
|||
|
||||
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::{
|
||||
buffer::spare_capacity,
|
||||
|
|
@ -56,14 +63,6 @@ pub static TMPDIR: LazyLock<&'static Path> = LazyLock::new(|| {
|
|||
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(|| {
|
||||
which::which("nix")
|
||||
.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))
|
||||
.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
|
||||
.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> {
|
||||
// We unconditionally unlink() `path` before binding, but completely ignore the result.
|
||||
let _ = rustix::fs::unlink(path);
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ impl<'a> Display for FdInfoDisplay<'a> {
|
|||
write!(
|
||||
f,
|
||||
"{} fd {} ({})",
|
||||
self.inner.kind.name_str(),
|
||||
self.inner.kind,
|
||||
self.inner.fd,
|
||||
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(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
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 {
|
||||
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: Some(socket),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue