1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
use rand::{distributions::Alphanumeric, thread_rng, Rng}; use std::{ffi::OsStr, process::Stdio, time::Duration}; use tokio::{ io::{AsyncBufReadExt, BufReader}, process::{Child, Command}, time::timeout, }; pub struct Engine { pub token: String, command: Command, child: Option<Child>, } impl Engine { pub fn new<I, S>(program: &str, args: I) -> Self where I: IntoIterator<Item = S>, S: AsRef<OsStr>, { let secret: String = thread_rng().sample_iter(&Alphanumeric).take(8).collect(); let token = format!("token:{}", secret); let mut command = Command::new(program); command .arg("--enable-rpc=true") .arg(format!("--rpc-secret={}", secret)) .args(args) .stdin(Stdio::null()) .stderr(Stdio::null()) .stdout(Stdio::piped()); Engine { token, command, child: None, } } pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Self { self.command.arg(arg); self } pub async fn start(&mut self) { let mut child = self.command.spawn().unwrap(); let output = child.stdout.take().unwrap(); let reader = BufReader::new(output); let mut lines = reader.lines(); let mut result = false; timeout(Duration::from_secs(10), async { while let Some(line) = lines.next_line().await.unwrap() { if line.contains("[ERROR]") { panic!(); }; if line.contains("IPv4 RPC: listening on TCP port 6800") { result = true; break; } } }) .await .unwrap(); if result == false { panic!(); } self.child = Some(child); } pub fn stop(&mut self) { if let Some(child) = &mut self.child { child.kill().unwrap(); } } }