cleaned up a few things during PR review

This commit is contained in:
epi
2020-10-12 06:32:33 -05:00
parent fbffb57db3
commit f676f56d71
5 changed files with 59 additions and 25 deletions

View File

@@ -325,7 +325,12 @@ impl Configuration {
.map(|code| {
StatusCode::from_bytes(code.as_bytes())
.unwrap_or_else(|e| {
eprintln!("[!] Error encountered: {}", e); // todo normalize error output
eprintln!(
"{} {}: {}",
status_colorizer("ERROR"),
module_colorizer("Configuration::new"),
e
);
exit(1)
})
.as_u16()
@@ -347,7 +352,12 @@ impl Configuration {
.unwrap() // already known good
.map(|size| {
size.parse::<u64>().unwrap_or_else(|e| {
eprintln!("[!] Error encountered: {}", e); // todo normalize error output
eprintln!(
"{} {}: {}",
status_colorizer("ERROR"),
module_colorizer("Configuration::new"),
e
);
exit(1)
})
})

View File

@@ -1,4 +1,4 @@
use crate::config::PROGRESS_PRINTER;
use crate::config::{CONFIGURATION, PROGRESS_PRINTER};
use crate::reporter::{get_cached_file_handle, safe_file_write};
use console::{style, Color};
use env_logger::Builder;
@@ -39,7 +39,7 @@ pub fn initialize(verbosity: u8) {
//
// The workaround was to have a RwLock around the file and allow both the logger and the
// file handler to both write independent of each other.
let locked_file = get_cached_file_handle();
let locked_file = get_cached_file_handle(&CONFIGURATION.output);
builder
.format(move |_, record| {

View File

@@ -120,16 +120,18 @@ async fn get_targets() -> FeroxResult<Vec<String>> {
#[tokio::main]
async fn main() {
// setup logging based on the number of -v's used
logger::initialize(CONFIGURATION.verbosity);
// can't trace main until after logger is initialized
log::trace!("enter: main");
log::debug!("{:#?}", *CONFIGURATION);
let save_output = !CONFIGURATION.output.is_empty(); // was -o used?
let (tx_term, tx_file, term_handle, file_handle) =
reporter::initialize(&CONFIGURATION.output, save_output);
logger::initialize(CONFIGURATION.verbosity);
log::trace!("enter: main");
log::debug!("{:#?}", *CONFIGURATION);
// get targets from command line or stdin
let targets = match get_targets().await {
Ok(t) => t,
@@ -157,9 +159,10 @@ async fn main() {
// discard non-responsive targets
let live_targets = heuristics::connectivity_test(&targets).await;
// kick off a scan against any targets determined to be responsive
match scan(live_targets, tx_term.clone(), tx_file.clone()).await {
Ok(_) => {
log::info!("Done");
log::info!("All scans complete!");
}
Err(e) => log::error!("An error occurred: {}", e),
};
@@ -168,32 +171,37 @@ async fn main() {
drop(tx_term);
log::trace!("dropped terminal output handler's transmitter");
log::trace!("awaiting terminal output receiver");
log::trace!("awaiting terminal output handler's receiver");
// after dropping tx, we can await the future where rx lived
match term_handle.await {
Ok(_) => {}
Err(e) => {
log::error!("error awaiting terminal output's receiver: {}", e);
log::error!("error awaiting terminal output handler's receiver: {}", e);
}
}
log::trace!("done awaiting terminal output receiver");
log::trace!("done awaiting terminal output handler's receiver");
log::trace!("tx_file: {:?}", tx_file);
// the same drop/await process used on the terminal handler is repeated for the file handler
// we drop the file transmitter every time, because it's created no matter what
drop(tx_file);
log::trace!("dropped file output handler's transmitter");
if save_output {
log::trace!("awaiting file output receiver");
// but we only await if -o was specified
log::trace!("awaiting file output handler's receiver");
match file_handle.unwrap().await {
Ok(_) => {}
Err(e) => {
log::error!("error awaiting file output's receiver: {}", e);
log::error!("error awaiting file output handler's receiver: {}", e);
}
}
log::trace!("done awaiting file output receiver");
log::trace!("done awaiting file output handler's receiver");
}
PROGRESS_PRINTER.finish();
log::trace!("exit: main");
// clean-up function for the MultiProgress bar; must be called last in order to still see
// the final trace message above
PROGRESS_PRINTER.finish();
}

View File

@@ -9,7 +9,12 @@ use std::{fs, io};
use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender};
use tokio::task::JoinHandle;
/// Singleton buffered file behind an Arc/RwLock; used for file writes from two locations:
/// - [logger::initialize](../logger/fn.initialize.html) (specifically a closure on the global logger instance)
/// - `reporter::spawn_file_handler`
pub static mut LOCKED_FILE: Option<Arc<RwLock<io::BufWriter<fs::File>>>> = None;
/// An initializer Once variable used to create `LOCKED_FILE`
static INIT: Once = Once::new();
// Accessing a `static mut` is unsafe much of the time, but if we do so
@@ -18,18 +23,17 @@ static INIT: Once = Once::new();
//
// This function will only call `open_file` once, and will
// otherwise always return the value returned from the first invocation.
pub fn get_cached_file_handle() -> Option<Arc<RwLock<io::BufWriter<fs::File>>>> {
pub fn get_cached_file_handle(filename: &str) -> Option<Arc<RwLock<io::BufWriter<fs::File>>>> {
unsafe {
INIT.call_once(|| {
LOCKED_FILE = open_file(&CONFIGURATION.output);
LOCKED_FILE = open_file(&filename);
});
LOCKED_FILE.clone()
}
}
/// Creates all required output handlers (terminal, file) and returns
/// the transmitter side of an mpsc and the primary output handler's JoinHandle
/// to be awaited
/// the transmitter sides of each mpsc along with each receiver's future's JoinHandle to be awaited
///
/// Any other module that needs to write a Response to stdout or output results to a file should
/// be passed a clone of the appropriate returned transmitter
@@ -133,7 +137,7 @@ async fn spawn_terminal_reporter(
/// The consumer simply receives responses and writes them to the given output file if they meet
/// the given reporting criteria
async fn spawn_file_reporter(mut report_channel: UnboundedReceiver<String>, output_file: &str) {
let buffered_file = match get_cached_file_handle() {
let buffered_file = match get_cached_file_handle(&CONFIGURATION.output) {
Some(file) => file,
None => {
log::trace!("exit: spawn_file_reporter");
@@ -212,3 +216,15 @@ pub fn safe_file_write(contents: &str, locked_file: Arc<RwLock<io::BufWriter<fs:
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[should_panic]
/// asserts that an empty string for a filename returns None
fn reporter_get_cached_file_handle_without_filename_returns_none() {
let _used = get_cached_file_handle(&"").unwrap();
}
}

View File

@@ -279,7 +279,7 @@ async fn try_recursion(
Ok(_) => {}
Err(e) => {
log::error!(
"could not send {}/ to recursion handler: {}",
"Could not send {}/ to recursion handler: {}",
response.url(),
e
);