Skip to content

Commit

Permalink
fix: change the code to use FluereError
Browse files Browse the repository at this point in the history
  • Loading branch information
SkuldNorniern committed Dec 10, 2024
1 parent fd7a81b commit 447343e
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 68 deletions.
61 changes: 29 additions & 32 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1,36 @@
use std::io;
use pcap;
use crate::net::NetError;
use std::{io, path::PathBuf};

#[derive(Debug)]
pub enum FluereError {
// IO related errors
IoError(io::Error),
// Network related errors
NetworkError(NetError),
// PCAP related errors
PcapError(pcap::Error),
// Parsing related errors
ParseError(String),
// Configuration related errors
ConfigError(String),
// Interface related errors
InterfaceError(String),
// Argument related errors
ArgumentError(String),
// Add new variants
FileNotFound(PathBuf),
ParameterMissing(String),
InvalidValue { field: String, value: String },
}

impl std::error::Error for FluereError {}

impl std::fmt::Display for FluereError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
FluereError::IoError(e) => write!(f, "IO error: {}", e),
FluereError::NetworkError(e) => write!(f, "Network error: {}", e),
FluereError::PcapError(e) => write!(f, "PCAP error: {}", e),
FluereError::ParseError(e) => write!(f, "Parse error: {}", e),
FluereError::ConfigError(e) => write!(f, "Configuration error: {}", e),
FluereError::InterfaceError(e) => write!(f, "Interface error: {}", e),
FluereError::ArgumentError(e) => write!(f, "Argument error: {}", e),
Self::IoError(e) => write!(f, "IO error: {}", e),
Self::NetworkError(e) => write!(f, "Network error: {}", e),
Self::PcapError(e) => write!(f, "PCAP error: {}", e),
Self::ParseError(e) => write!(f, "Parse error: {}", e),
Self::ConfigError(e) => write!(f, "Configuration error: {}", e),
Self::InterfaceError(e) => write!(f, "Interface error: {}", e),
Self::ArgumentError(e) => write!(f, "Argument error: {}", e),
Self::FileNotFound(path) => write!(f, "File not found: {}", path.display()),
Self::ParameterMissing(name) => write!(f, "Required parameter missing: {}", name),
Self::InvalidValue { field, value } => {
write!(f, "Invalid value '{}' for field '{}'", value, field)
}
}
}
}
Expand All @@ -55,21 +54,19 @@ impl From<NetError> for FluereError {
}
}

// Helper methods for creating errors
impl FluereError {
pub fn interface_not_found() -> Self {
FluereError::InterfaceError("Network interface not found".to_string())
}

pub fn argument_error<T: std::fmt::Display>(msg: T) -> Self {
FluereError::ArgumentError(msg.to_string())
impl From<std::num::ParseIntError> for FluereError {
fn from(error: std::num::ParseIntError) -> Self {
FluereError::ParseError(error.to_string())
}
}

pub fn config_error<T: std::fmt::Display>(msg: T) -> Self {
FluereError::ConfigError(msg.to_string())
}
// Add conversion for Option to Result
pub trait OptionExt<T> {
fn required(self, name: &str) -> Result<T, FluereError>;
}

pub fn parse_error<T: std::fmt::Display>(msg: T) -> Self {
FluereError::ParseError(msg.to_string())
impl<T> OptionExt<T> for Option<T> {
fn required(self, name: &str) -> Result<T, FluereError> {
self.ok_or_else(|| FluereError::ParameterMissing(name.to_string()))
}
}
}
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
mod error;
pub mod cli;
mod error;
pub mod logger;
pub mod net;
pub mod types;
Expand Down Expand Up @@ -74,7 +74,7 @@ pub fn setup_logging(verbose: u8) -> Result<(), FluereError> {
false,
);
let filter = get_log_level(verbose);

log::set_boxed_logger(Box::new(logger))
.map(|()| log::set_max_level(filter))
.map_err(|e| FluereError::ConfigError(format!("Failed to setup logger: {}", e)))
Expand Down
12 changes: 8 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,21 @@ async fn main() -> Result<(), FluereError> {
if let Some((mode_str, sub_args)) = args.subcommand() {
// Convert mode string to Mode enum using TryFrom
let mode = Mode::try_from(mode_str)?;

// Handle mode-specific arguments
let (params, verbosity) = fluere::cli::handle_mode(mode_str, sub_args).await;

let Ok((params, verbosity)) = fluere::cli::handle_mode(mode_str, sub_args).await else {
return Err(FluereError::ConfigError(
"Failed to handle mode".to_string(),
));
};

// Setup logging using library function
fluere::setup_logging(verbosity)?;
debug!("Fluere started");

// Execute the selected mode using library function
fluere::execute_mode(mode, params).await?;

Ok(())
} else {
process::exit(0);
Expand Down
60 changes: 49 additions & 11 deletions src/net/errors.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,56 @@
use snafu::prelude::*;
use std::{io, path::PathBuf};

#[derive(Debug, Snafu)]
#[snafu(visibility(pub))]
#[derive(Debug)]
pub enum NetError {
#[snafu(display("unexpected empty packet"))]
EmptyPacket,
#[snafu(display("unknown Protocol `{protocol}`"))]
UnknownProtocol { protocol: String },
#[snafu(display("unknown IP version `{version}`"))]
UnknownIPVersion { version: String },
}
#[derive(Debug, Snafu)]
#[snafu(visibility(pub))]
pub enum ParseError {
#[snafu(display("unexpected dscp `{dscp}`"))]
UnknownDSCP { dscp: u8 },
DeviceNotFound { name: String },
CaptureError { msg: String },
PacketParseError { msg: String },
PluginError { msg: String },
FileError { path: PathBuf },
InterfaceError { msg: String },
// Add new variants for parameter errors
ParameterError { name: String, msg: String },
IoError(io::Error),
ParseError { value: String, type_name: String },
}

impl std::fmt::Display for NetError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::EmptyPacket => write!(f, "Unexpected empty packet"),
Self::UnknownProtocol { protocol } => write!(f, "Unknown protocol `{}`", protocol),
Self::UnknownIPVersion { version } => write!(f, "Unknown IP version `{}`", version),
Self::UnknownDSCP { dscp } => write!(f, "Unexpected DSCP value `{}`", dscp),
Self::DeviceNotFound { name } => write!(f, "Network device not found: {}", name),
Self::CaptureError { msg } => write!(f, "Capture error: {}", msg),
Self::PacketParseError { msg } => write!(f, "Packet parse error: {}", msg),
Self::PluginError { msg } => write!(f, "Plugin error: {}", msg),
Self::FileError { path } => write!(f, "File operation error: {}", path.display()),
Self::InterfaceError { msg } => write!(f, "Interface error: {}", msg),
Self::ParameterError { name, msg } => write!(f, "Parameter '{}' error: {}", name, msg),
Self::IoError(e) => write!(f, "IO error: {}", e),
Self::ParseError { value, type_name } => {
write!(f, "Failed to parse '{}' as {}", value, type_name)
}
}
}
}

impl From<io::Error> for NetError {
fn from(error: io::Error) -> Self {
NetError::IoError(error)
}
}

impl From<std::num::ParseIntError> for NetError {
fn from(error: std::num::ParseIntError) -> Self {
NetError::ParseError {
value: error.to_string(),
type_name: "integer".to_string(),
}
}
}
7 changes: 5 additions & 2 deletions src/net/live_fluereflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@ struct FlowSummary {
// It takes the command line arguments as input, which specify the network interface to capture from and other parameters.
// The function runs indefinitely, capturing packets and updating the terminal user interface with the captured data.
pub async fn online_packet_capture(arg: Args) -> Result<(), FluereError> {
let csv_file = arg.files.csv.unwrap();
let csv_file = arg
.files
.csv
.ok_or_else(|| FluereError::ConfigError("CSV file not specified".to_string()))?;
let use_mac = arg.parameters.use_mac.unwrap();

Check failure on line 72 in src/net/live_fluereflow.rs

View workflow job for this annotation

GitHub Actions / clippy

used `unwrap()` on an `Option` value

error: used `unwrap()` on an `Option` value --> src/net/live_fluereflow.rs:72:19 | 72 | let use_mac = arg.parameters.use_mac.unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: if this value is `None`, it will panic = help: consider using `expect()` to provide a better panic message = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used
let interface_name = arg.interface.expect("interface not found");
let duration = arg.parameters.duration.unwrap();

Check failure on line 74 in src/net/live_fluereflow.rs

View workflow job for this annotation

GitHub Actions / clippy

used `unwrap()` on an `Option` value

error: used `unwrap()` on an `Option` value --> src/net/live_fluereflow.rs:74:20 | 74 | let duration = arg.parameters.duration.unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: if this value is `None`, it will panic = help: consider using `expect()` to provide a better panic message = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used
Expand Down Expand Up @@ -330,7 +333,7 @@ pub async fn online_packet_capture(arg: Args) -> Result<(), FluereError> {
println!("Export {} result: {:?}", file_path, result);
}*/
file_path = cur_time_file(csv_file.as_str(), file_dir, ".csv");
file = fs::File::create(file_path.as_ref()).unwrap();
file = fs::File::create(file_path.as_ref()).map_err(FluereError::IoError)?;
*last_export_guard = Instant::now();
*last_export_unix_time_guard = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
Expand Down
21 changes: 8 additions & 13 deletions src/net/offline_fluereflows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ use std::{
};

use crate::{
error::OptionExt,
net::{
flows::update_flow,
parser::{parse_fluereflow, parse_keys, parse_microseconds},
types::{Key, TcpFlags},
NetError,
},
types::{Args, UDFlowKey},
utils::fluere_exporter,
Expand All @@ -24,20 +24,15 @@ use pcap::Capture;
use tokio::task;

pub async fn fluereflow_fileparse(arg: Args) -> Result<(), FluereError> {
let _csv_file = arg.files.csv.unwrap();
let file_name = arg.files.file.unwrap();
let use_mac = arg.parameters.use_mac.unwrap();
let flow_timeout = arg.parameters.timeout.unwrap();
let _csv_file = arg.files.csv.required("csv file")?;
let file_name = arg.files.file.required("input file")?;
let use_mac = arg.parameters.use_mac.required("use_mac parameter")?;
let flow_timeout = arg.parameters.timeout.required("timeout parameter")?;

let mut cap = Capture::from_file(file_name.clone()).map_err(NetError::from)?;
let mut cap = Capture::from_file(file_name.clone())?;

let file_dir = "./output";
match fs::create_dir_all(<&str>::clone(&file_dir)) {
Ok(_) => {
debug!("Created directory: {}", file_dir)
}
Err(error) => panic!("Problem creating directory: {:?}", error),
};
fs::create_dir_all(file_dir)?;

let start = Instant::now();
let file_noext = format!(
Expand All @@ -48,7 +43,7 @@ pub async fn fluereflow_fileparse(arg: Args) -> Result<(), FluereError> {
.unwrap_or("output")
);
let output_file_path = format!("{}/{}", file_dir, file_noext);
let file = fs::File::create(output_file_path.clone()).unwrap();
let file = fs::File::create(&output_file_path)?;

let mut records: Vec<FluereRecord> = Vec::new();
let mut active_flow: HashMap<Key, FluereRecord> = HashMap::new();
Expand Down
5 changes: 2 additions & 3 deletions src/net/online_fluereflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ use crate::{
flows::update_flow,
parser::{parse_fluereflow, parse_keys, parse_microseconds},
types::{Key, TcpFlags},
CaptureDevice,
NetError,
CaptureDevice, NetError,
},
types::{Args, UDFlowKey},
utils::{cur_time_file, fluere_exporter},
Expand All @@ -31,7 +30,7 @@ use fluere_config::Config;
use fluere_plugin::PluginManager;
use fluereflow::FluereRecord;

use log::{debug, info, trace, error};
use log::{debug, error, info, trace};
use tokio::{task, task::JoinHandle};

// This function captures packets from a network interface and converts them into NetFlow data.
Expand Down
2 changes: 1 addition & 1 deletion src/utils/fluere_csv_exporter.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use fluereflow::FluereRecord;
use log::{debug, trace, error};
use log::{debug, error, trace};
use std::fs::File;

pub async fn fluere_exporter(records: Vec<FluereRecord>, file: File) -> Result<(), csv::Error> {
Expand Down

0 comments on commit 447343e

Please sign in to comment.