1use std::process::Stdio;23use bifrostlink::declarative::endpoints;4use bifrostlink::Config;5use serde::{Deserialize, Serialize};6use std::result::Result;7use tokio::process::Command;89pub struct NixDaemon;1011#[derive(Serialize, Deserialize, Debug, thiserror::Error)]12pub enum Error {13 #[error("nix daemon unavailable: {0}")]14 DaemonUnavailable(String),15 #[error("tunnel socket unavailable: {0}")]16 Tunnel(String),17}1819#[endpoints(ns = 4)]20impl NixDaemon {21 #[endpoints(id = 2)]22 async fn serve_store(&self, store: String, socket: String) -> Result<(), Error> {23 let mut child = Command::new("nix-daemon")24 .arg("--stdio")25 .arg("--store")26 .arg(&store)27 .stdin(Stdio::piped())28 .stdout(Stdio::piped())29 .spawn()30 .map_err(|e| Error::DaemonUnavailable(e.to_string()))?;31 let tunnel = tokio::net::UnixStream::connect(&socket)32 .await33 .map_err(|e| Error::Tunnel(e.to_string()))?;34 let mut stdin = child.stdin.take().expect("piped");35 let mut stdout = child.stdout.take().expect("piped");36 tokio::spawn(async move {37 let mut tunnel = tunnel;38 let (mut tr, mut tw) = tunnel.split();39 let _ = tokio::join!(40 tokio::io::copy(&mut tr, &mut stdin),41 tokio::io::copy(&mut stdout, &mut tw),42 );43 let _ = child.wait().await;44 });45 Ok(())46 }47}