Allow enabling/disabling analyzers from config file (#382)

Co-authored-by: Will Greenberg <willg@eff.org>
This commit is contained in:
Markus Unterwaditzer
2025-06-10 21:37:38 +02:00
committed by GitHub
parent fb2149f0c8
commit 86e08f9a85
8 changed files with 95 additions and 27 deletions

View File

@@ -8,7 +8,7 @@ use axum::{
};
use futures::TryStreamExt;
use log::{debug, error, info};
use rayhunter::analysis::analyzer::Harness;
use rayhunter::analysis::analyzer::{AnalyzerConfig, Harness};
use rayhunter::diag::{DataType, MessagesContainer};
use rayhunter::qmdl::QmdlReader;
use serde::Serialize;
@@ -35,8 +35,12 @@ pub struct AnalysisWriter {
// lets us simply append new rows to the end without parsing the entire JSON
// object beforehand.
impl AnalysisWriter {
pub async fn new(file: File, enable_dummy_analyzer: bool) -> Result<Self, std::io::Error> {
let mut harness = Harness::new_with_all_analyzers();
pub async fn new(
file: File,
enable_dummy_analyzer: bool,
analyzer_config: &AnalyzerConfig,
) -> Result<Self, std::io::Error> {
let mut harness = Harness::new_with_config(analyzer_config);
if enable_dummy_analyzer {
harness.add_analyzer(Box::new(TestAnalyzer { count: 0 }));
}
@@ -131,6 +135,7 @@ async fn perform_analysis(
name: &str,
qmdl_store_lock: Arc<RwLock<RecordingStore>>,
enable_dummy_analyzer: bool,
analyzer_config: &AnalyzerConfig,
) -> Result<(), String> {
info!("Opening QMDL and analysis file for {}...", name);
let (analysis_file, qmdl_file, entry_index) = {
@@ -150,9 +155,10 @@ async fn perform_analysis(
(analysis_file, qmdl_file, entry_index)
};
let mut analysis_writer = AnalysisWriter::new(analysis_file, enable_dummy_analyzer)
.await
.map_err(|e| format!("{:?}", e))?;
let mut analysis_writer =
AnalysisWriter::new(analysis_file, enable_dummy_analyzer, analyzer_config)
.await
.map_err(|e| format!("{:?}", e))?;
let file_size = qmdl_file
.metadata()
.await
@@ -196,6 +202,7 @@ pub fn run_analysis_thread(
qmdl_store_lock: Arc<RwLock<RecordingStore>>,
analysis_status_lock: Arc<RwLock<AnalysisStatus>>,
enable_dummy_analyzer: bool,
analyzer_config: AnalyzerConfig,
) {
task_tracker.spawn(async move {
loop {
@@ -204,9 +211,13 @@ pub fn run_analysis_thread(
let count = queued_len(analysis_status_lock.clone()).await;
for _ in 0..count {
let name = dequeue_to_running(analysis_status_lock.clone()).await;
if let Err(err) =
perform_analysis(&name, qmdl_store_lock.clone(), enable_dummy_analyzer)
.await
if let Err(err) = perform_analysis(
&name,
qmdl_store_lock.clone(),
enable_dummy_analyzer,
&analyzer_config,
)
.await
{
error!("failed to analyze {}: {}", name, err);
}

View File

@@ -2,7 +2,7 @@ use clap::Parser;
use futures::TryStreamExt;
use log::{info, warn};
use rayhunter::{
analysis::analyzer::{EventType, Harness},
analysis::analyzer::{AnalyzerConfig, EventType, Harness},
diag::DataType,
gsmtap_parser,
pcap::GsmtapPcapWriter,
@@ -33,7 +33,7 @@ struct Args {
}
async fn analyze_file(enable_dummy_analyzer: bool, qmdl_path: &str, show_skipped: bool) {
let mut harness = Harness::new_with_all_analyzers();
let mut harness = Harness::new_with_config(&AnalyzerConfig::default());
if enable_dummy_analyzer {
harness.add_analyzer(Box::new(dummy_analyzer::TestAnalyzer { count: 0 }));
}
@@ -141,7 +141,7 @@ async fn main() {
.unwrap();
info!("Analyzers:");
let mut harness = Harness::new_with_all_analyzers();
let mut harness = Harness::new_with_config(&AnalyzerConfig::default());
if args.enable_dummy_analyzer {
harness.add_analyzer(Box::new(dummy_analyzer::TestAnalyzer { count: 0 }));
}

View File

@@ -1,7 +1,9 @@
use crate::error::RayhunterError;
use serde::Deserialize;
use rayhunter::analysis::analyzer::AnalyzerConfig;
use crate::error::RayhunterError;
#[derive(Debug, Deserialize)]
#[serde(default)]
pub struct Config {
@@ -12,6 +14,7 @@ pub struct Config {
pub enable_dummy_analyzer: bool,
pub colorblind_mode: bool,
pub key_input_mode: u8,
pub analyzers: AnalyzerConfig,
}
impl Default for Config {
@@ -24,6 +27,7 @@ impl Default for Config {
enable_dummy_analyzer: false,
colorblind_mode: false,
key_input_mode: 1,
analyzers: AnalyzerConfig::default(),
}
}
}

View File

@@ -199,6 +199,7 @@ async fn main() -> Result<(), RayhunterError> {
qmdl_store_lock.clone(),
analysis_tx.clone(),
config.enable_dummy_analyzer,
config.analyzers.clone(),
);
info!("Starting UI");
display::update_ui(&task_tracker, &config, ui_shutdown_rx, ui_update_rx);
@@ -215,6 +216,7 @@ async fn main() -> Result<(), RayhunterError> {
qmdl_store_lock.clone(),
analysis_status_lock.clone(),
config.enable_dummy_analyzer,
config.analyzers.clone(),
);
run_ctrl_c_thread(
&task_tracker,

View File

@@ -8,6 +8,7 @@ use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
use futures::{StreamExt, TryStreamExt};
use log::{debug, error, info, warn};
use rayhunter::analysis::analyzer::AnalyzerConfig;
use rayhunter::diag::DataType;
use rayhunter::diag_device::DiagDevice;
use rayhunter::qmdl::QmdlWriter;
@@ -36,12 +37,13 @@ pub fn run_diag_read_thread(
qmdl_store_lock: Arc<RwLock<RecordingStore>>,
analysis_sender: Sender<AnalysisCtrlMessage>,
enable_dummy_analyzer: bool,
analyzer_config: AnalyzerConfig,
) {
task_tracker.spawn(async move {
let (initial_qmdl_file, initial_analysis_file) = qmdl_store_lock.write().await.new_entry().await.expect("failed creating QMDL file entry");
let mut maybe_qmdl_writer: Option<QmdlWriter<File>> = Some(QmdlWriter::new(initial_qmdl_file));
let mut diag_stream = pin!(dev.as_stream().into_stream());
let mut maybe_analysis_writer = Some(AnalysisWriter::new(initial_analysis_file, enable_dummy_analyzer).await
let mut maybe_analysis_writer = Some(AnalysisWriter::new(initial_analysis_file, enable_dummy_analyzer, &analyzer_config).await
.expect("failed to create analysis writer"));
loop {
tokio::select! {
@@ -63,7 +65,7 @@ pub fn run_diag_read_thread(
analysis_writer.close().await.expect("failed to close analysis writer");
}
maybe_analysis_writer = Some(AnalysisWriter::new(new_analysis_file, enable_dummy_analyzer).await
maybe_analysis_writer = Some(AnalysisWriter::new(new_analysis_file, enable_dummy_analyzer, &analyzer_config).await
.expect("failed to write to analysis file"));
if let Err(e) = ui_update_sender.send(display::DisplayState::Recording).await {