Skip to content

Commit b384346

Browse files
Adam GibsonAdam Gibson
Adam Gibson
authored and
Adam Gibson
committed
Server start now uses config in UI
1 parent 7ed8e0e commit b384346

File tree

1 file changed

+71
-28
lines changed

1 file changed

+71
-28
lines changed

src/bin/gui.rs

+71-28
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,43 @@
44

55
use eframe::egui::{self, Color32, Pos2, RichText, Vec2, Window};
66
use tokio::runtime::Runtime;
7-
use std::process::Stdio;
7+
use std::process::{Stdio, Command, Child};
88
use std::sync::{Arc, Mutex, RwLock};
99
use std::thread;
1010
use tokio::time::Duration;
1111
use rfd::FileDialog;
1212
use autct::autctactions::{request_audit_verify, request_echo};
1313
use autct::config::AutctConfig;
14+
use std::io;
15+
16+
struct ProcessGuard {
17+
child: Child,
18+
}
19+
20+
impl ProcessGuard {
21+
fn new(command: &str, args: &[&str]) -> io::Result<Self> {
22+
let child = Command::new(command)
23+
.args(args)
24+
.stderr(Stdio::null())
25+
.stdout(Stdio::null())
26+
.spawn()?;
27+
Ok(Self { child })
28+
}
29+
}
30+
31+
// kills subprocess (here autct) on shutdown.
32+
// while this can cause substantial delays, we otherwise
33+
// would need to sync a previously running process
34+
// with current config, which is a bunch more mess.
35+
impl Drop for ProcessGuard {
36+
fn drop(&mut self) {
37+
println!("drop is getting called now");
38+
// TODO is it even possible to
39+
// handle the case where kill fails to kill?
40+
let _ = self.child.kill();
41+
}
42+
}
43+
1444

1545
struct Wrapper {
1646
wrapped_app: Arc<RwLock<AutctVerifierApp>>,
@@ -40,6 +70,7 @@ struct AutctVerifierApp {
4070
last_verif_result: Option<String>,
4171
verif_runtime: Arc<Runtime>,
4272
server_state: Arc<Mutex<ServerState>>,
73+
autct_process_guard: Option<ProcessGuard>,
4374
}
4475

4576
#[derive(Debug)]
@@ -71,18 +102,20 @@ async fn main() -> eframe::Result {
71102
// println-s here for now to sanity check the monitoring echo RPC
72103
// calls are behaving as expected:
73104
if !app_for_reading.autctcfg.is_none() {
74-
println!("autctcfg was not none in the monitoring thread");
105+
//println!("autctcfg was not none in the monitoring thread");
75106
let rt = Runtime::new().unwrap();
76107
let res = rt.block_on(
77108
request_echo(&app_for_reading.autctcfg.as_ref().unwrap()));
78-
println!("Request echo method returned");
109+
//println!("Request echo method returned");
79110
match res {
80111
Ok(_) => {println!("Echo successful");
81112
let mut state = app_for_reading
82113
.server_state.lock().unwrap();
83114
*state = ServerState::Ready;
84115
break;},
85-
Err(_) => {println!("Echo call returned an error");}
116+
Err(_) => {
117+
//println!("Echo call returned an error");
118+
}
86119
} // end match
87120
} // end autctcfg none check
88121
else {
@@ -112,20 +145,25 @@ impl AutctVerifierApp {
112145
}
113146
}
114147

115-
fn check_cfg_data(&self) -> Result<AutctConfig, CustomError> {
116-
println!("Starting check cfg data");
148+
fn check_cfg_data(&self, servermode: bool) -> Result<AutctConfig, CustomError> {
149+
// If servermode is true, we only care about the keyset
150+
// and network settings. Otherwise, we check all.
117151
let mut cfg = self.autctcfg
118152
.clone().ok_or_else(|| CustomError("Failed to load config".to_string()))?;
153+
if !servermode {
119154
cfg.proof_file_str = Some(self.proof_file
120155
.lock().unwrap().clone().ok_or_else(
121156
|| CustomError("Failed to load proof file location".to_string()))?);
157+
}
122158
let keyset_str = self.keyset_file
123159
.lock().unwrap().clone().ok_or_else(
124160
|| CustomError("Failed to load keyset file location".to_string()))?;
125161
cfg.keysets = Some("mycontext".to_owned() + ":" + &keyset_str);
162+
if !servermode {
126163
cfg.user_string = Some(self.sigmessage
127164
.clone().ok_or_else(
128165
|| CustomError("Failed to load signature message".to_string()))?);
166+
}
129167
cfg.bc_network = Some(self.network.clone());
130168
println!("Finishing check cfg data ok");
131169
Ok(cfg)
@@ -153,32 +191,36 @@ impl AutctVerifierApp {
153191
}
154192

155193
/// Starts the verification server in the background
156-
/// by calling std::process:Command
157-
fn start_server(&self) {
194+
/// by calling std::process:Command; we use a wrapper
195+
/// `ProcessGuard` object so that the background process
196+
/// can be automatically killed on drop.
197+
fn start_server(&mut self) {
158198
let server_state = Arc::clone(
159199
&self.server_state);
160-
let keyset = self.autctcfg.clone().unwrap().keysets.unwrap();
161-
let network = self.autctcfg.clone().unwrap().bc_network.unwrap();
162-
// Spawn a new thread to run the process
163-
thread::spawn(move || {
164-
165-
let mut state = server_state.lock().unwrap();
166-
*state = ServerState::NotStarted;
167-
168-
169-
// Expected to take a while
170-
// TODO: expect just crashes; ideally want to show a prompt
171-
// that server startup failed with advice on how to fix it:
172-
std::process::Command::new(
173-
"./autct").arg("-k").arg(keyset).arg("-n").arg(
174-
network)
175-
.stderr(Stdio::null())
176-
.stdout(Stdio::null())
177-
.spawn().expect("Failed to start autct process in background.");
200+
// read in the current config settings in the UI before
201+
// passing them as arguments to the autct server.
202+
let newcfg = self.check_cfg_data(
203+
true);
204+
if newcfg.is_err() {
205+
self.show_verif_modal = true;
206+
} else {
207+
self.autctcfg = Some(newcfg.unwrap());
208+
let keyset = self.autctcfg.clone().unwrap().keysets.unwrap();
209+
let network = self.autctcfg.clone().unwrap().bc_network.unwrap();
210+
println!("Starting process with keyset: {}, network: {}", keyset, network);
211+
// TODO a failure to start is silent here; the user's
212+
// only feedback is that the dot won't turn green.
213+
self.autct_process_guard = Some(ProcessGuard::new(
214+
"./autct", &[
215+
"-M", "serve",
216+
"-k", &keyset,
217+
"-n", &network]).expect(
218+
"Failed to start child autct process"));
178219
// Running means the server is processing the data
179220
// but not yet serving on the port:
221+
let mut state = server_state.lock().unwrap();
180222
*state = ServerState::Running;
181-
});
223+
}
182224
}
183225

184226
fn update_dot(&mut self, ctx: &egui::Context,
@@ -230,6 +272,7 @@ impl Default for AutctVerifierApp {
230272
last_verif_result: None,
231273
verif_runtime: Arc::new(Runtime::new().unwrap()),
232274
server_state: Arc::new(Mutex::new(ServerState::NotStarted)),
275+
autct_process_guard: None,
233276
}
234277
}
235278
}
@@ -268,7 +311,7 @@ impl eframe::App for Wrapper {
268311
egui::Button::new(RichText::new(
269312
"VERIFY").size(30.0).strong())).clicked() {
270313
let newcfg =
271-
state.check_cfg_data();
314+
state.check_cfg_data(false);
272315
if newcfg.is_err() {
273316
state.show_verif_modal = true;
274317
} else {

0 commit comments

Comments
 (0)