pub(crate) mod discover;
pub(crate) mod scan;
use zond_engine::export::Redaction;
use zond_engine::{ScanEvent, ScanReport, ScanSession, ScanTask, ZondConfig};
use crate::error::Error;
use crate::exit::Outcome;
use crate::input;
use crate::render::Renderer;
use crate::settings;
fn engine_settings(profile: Option<&str>) -> Result<settings::EngineSettings, Error> {
let (settings, warnings) = settings::engine(profile)?;
for warning in warnings {
tracing::warn!("{warning}");
}
Ok(settings)
}
fn redaction(config: &ZondConfig) -> Redaction {
if config.redact {
Redaction::Standard
} else {
Redaction::None
}
}
async fn drive(
session: ScanSession,
task: ScanTask,
renderer: &mut dyn Renderer,
) -> Result<Outcome, Error> {
let (hosts, mut events, handle) = session.into_parts();
let mut stops = input::watch(&handle);
let mut announced = false;
loop {
tokio::select! {
event = events.recv() => {
let Some(event) = event else { break };
if let ScanEvent::HostUpdated(ip) = event
&& let Some(host) = hosts.get(&ip)
&& host.is_alive()
{
renderer.host_found(&host)?;
}
}
_ = stops.recv() => {
if announced {
return Ok(Outcome::Interrupted);
}
announced = true;
renderer.interrupted()?;
}
}
}
let report = task.join().await?;
renderer.finished(&report)?;
Ok(outcome(&report, handle.should_stop()))
}
fn outcome(report: &ScanReport, stopped: bool) -> Outcome {
if stopped {
Outcome::Interrupted
} else if report.is_partial() {
Outcome::Partial
} else {
Outcome::Complete
}
}