git.delta.rocks / remowt / refs/commits / 6d9cf16dada2

difftreelog

source

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		rpc.add_direct(Address::Plugin(id), child_port(stdout, stdin), Rtt(0));43		self.children.lock().expect("not poisoned").push(child);44		Ok(())45	}46}4748impl PluginHost for Host {49	async fn load_plugin(&self, id: u16, name: String) -> Result<(), Error> {50		// TODO: Right now loads plugin next to the binary...51		// But with our CA addressed schema, the plugins should be located in content-addressed subdir...52		// Maybe it should just be scrapped in favor of load_plugin_path.53		if name.is_empty() || name == "." || name == ".." || name.contains(['/', '\0']) {54			return Err(Error::BadName);55		}56		let exe = std::env::current_exe().map_err(|e| Error::Spawn(e.to_string()))?;57		let dir = exe58			.parent()59			.ok_or_else(|| Error::Spawn("primary agent has no parent directory".to_owned()))?;60		self.spawn(id, dir.join(&name))61	}6263	async fn load_plugin_path(&self, id: u16, path: String) -> Result<(), Error> {64		if path.is_empty() || path.contains('\0') {65			return Err(Error::BadName);66		}67		self.spawn(id, path)68	}69}