git.delta.rocks / fleet / refs/commits / 087938500f2e

difftreelog

source

remowt/crates/remowt-plugin/src/host.rs2.1 KiBsourcehistory
1use std::ffi::OsStr;2use std::process::Stdio;3use std::sync::Mutex;45use bifrostlink::{Rpc, Rtt, WeakRpc};6use tokio::process::{Child, Command};78use remowt_link_shared::plugin::{Error, PluginEndpoints, PluginHost};9use remowt_link_shared::port::child_port;10use remowt_link_shared::{Address, BifConfig};1112pub fn serve(rpc: &mut Rpc<BifConfig>) {13	let host = Host {14		me: rpc.me(),15		rpc: rpc.clone().downgrade(),16		children: Mutex::new(Vec::new()),17	};18	PluginEndpoints(host).register_endpoints(rpc);19}2021struct Host {22	me: Address,23	rpc: WeakRpc<BifConfig>,24	children: Mutex<Vec<Child>>,25}2627impl Host {28	fn spawn(&self, id: u16, path: impl AsRef<OsStr>) -> Result<(), Error> {29		let rpc = self.rpc.clone().upgrade().ok_or(Error::Gone)?;3031		let mut child = Command::new(path)32			.arg(id.to_string())33			.arg(serde_json::to_string(&self.me).expect("address serializes"))34			.stdin(Stdio::piped())35			.stdout(Stdio::piped())36			.kill_on_drop(true)37			.spawn()38			.map_err(|e| Error::Spawn(e.to_string()))?;39		let stdin = child.stdin.take().expect("stdin piped");40		let stdout = child.stdout.take().expect("stdout piped");4142		let addr = Address::Plugin(id);43		rpc.add_direct(addr, child_port(stdout, stdin), Rtt(0));44		self.children.lock().expect("not poisoned").push(child);45		Ok(())46	}47}4849impl PluginHost for Host {50	async fn load_plugin(&self, id: u16, name: String) -> Result<(), Error> {51		// TODO: Right now loads plugin next to the binary...52		// But with our CA addressed schema, the plugins should be located in content-addressed subdir...53		// Maybe it should just be scrapped in favor of load_plugin_path.54		if name.is_empty() || name == "." || name == ".." || name.contains(['/', '\0']) {55			return Err(Error::BadName);56		}57		let exe = std::env::current_exe().map_err(|e| Error::Spawn(e.to_string()))?;58		let dir = exe59			.parent()60			.ok_or_else(|| Error::Spawn("primary agent has no parent directory".to_owned()))?;61		self.spawn(id, dir.join(&name))62	}6364	async fn load_plugin_path(&self, id: u16, path: String) -> Result<(), Error> {65		if path.is_empty() || path.contains('\0') {66			return Err(Error::BadName);67		}68		self.spawn(id, path)69	}70}