use std::fs::File; use std::io; use std::io::BufRead; use std::net::Ipv4Addr; use std::path::{Path, PathBuf}; use std::str::FromStr; use std::sync::mpsc; use std::time::{Duration, SystemTime}; use clap::Parser; use crate::manager::Manager; use crate::ping_result::PingResult; use crate::state::State; use crate::target_state::TargetState; mod manager; mod state; mod target_state; mod ping_result; mod ping_request; const SECONDS_BETWEEN_DISPLAY: u32 = 1; const SECONDS_BETWEEN_PING: u32 = 2; fn read_lines

(filename: P) -> io::Result>> where P: AsRef, { let file = File::open(filename)?; Ok(io::BufReader::new(file).lines()) } fn build_targets_from_file(filename: Option) -> Vec{ let mut targets = vec![Ipv4Addr::new(127, 0, 0, 1), Ipv4Addr::new(172, 24, 10, 1), Ipv4Addr::new(1,1,1,1), Ipv4Addr::new(8,8,8,8), Ipv4Addr::new(216,121,247,231), Ipv4Addr::new(216,234,202,122), Ipv4Addr::new(24,143,184,98), ]; if let Some(file) = filename { println!("File is {:?}", file.to_str()); if let Ok(lines) = read_lines(file) { targets.clear(); // Consumes the iterator, returns an (Optional) String for line in lines.map_while(Result::ok) { targets.push( Ipv4Addr::from_str(&*line).unwrap() ); } } // targets = vec![]; }; targets } /// Simple program to greet a person #[derive(Parser, Debug)] #[command(version, about, long_about = None)] pub struct AppSettings { /// File of list of hosts #[arg(short, long)] ping_host_file: Option, } fn main() { // Get App Settings let settings = AppSettings::parse(); // channel to send requests to ping let (ping_response_sender, ping_response_listener) = mpsc::channel::(); let file_to_read = settings.ping_host_file; let targets = build_targets_from_file(file_to_read); let mut state = State::default(); for current in &targets { state.add_target(*current); } println!("Setting up requests for {} hosts.", targets.len()); Manager::spawn_manager_thread(state.targets_ipv4().clone(), ping_response_sender.clone()); let mut display_loop_start = SystemTime::now(); let mut duration_since_last_loop = SystemTime::now().duration_since(display_loop_start).unwrap(); loop { if let Ok(response) = ping_response_listener.recv_timeout(Duration::from_millis(100)) { for (index, current_state) in state.targets.clone().iter().enumerate() { if current_state.target == response.target { let last_alive_change = if response.success == current_state.alive { current_state.last_alive_change } else { SystemTime::now() }; let new_state = TargetState { target: current_state.target, alive: response.success, last_rtt: response.rtt, last_alive_change, }; state.targets[index] = new_state.clone(); } } } duration_since_last_loop = SystemTime::now() .duration_since(display_loop_start) .expect("unable to figure out how long ago we displayed stuff"); if duration_since_last_loop.as_secs() > SECONDS_BETWEEN_DISPLAY as u64 { println!("DISPLAY LOOP"); println!("Host \t\t | Alive \t | RTT \t\t"); for current_result in state.targets.clone() { let time_since_last_change = SystemTime::now().duration_since(current_result.last_alive_change).unwrap(); let target_string = if current_result.target.clone().to_string().len() > 8 { format!("{}", current_result.target) } else { format!("{}\t", current_result.target) }; println!("{}\t | {} \t | {}\t | Changed {}s ago", target_string, current_result.alive, current_result.last_rtt,time_since_last_change.as_secs() ); } display_loop_start = SystemTime::now(); } } }