Initial commit
This commit is contained in:
+214
@@ -0,0 +1,214 @@
|
||||
use std::fs::File;
|
||||
use std::net::Ipv4Addr;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
use std::str::FromStr;
|
||||
use std::string::ToString;
|
||||
use std::sync::mpsc;
|
||||
use std::sync::mpsc::Sender;
|
||||
use std::{io, thread};
|
||||
use std::io::BufRead;
|
||||
use std::time::{Duration, SystemTime};
|
||||
use ansi_term::Colour::{Green, Red};
|
||||
use clap::Parser;
|
||||
use log::{debug, error, log_enabled, info, Level};
|
||||
#[derive(Clone)]
|
||||
struct HistoricHost {
|
||||
pub name: String,
|
||||
pub address: Ipv4Addr,
|
||||
pub history: Vec<u128>,
|
||||
pub alive: bool
|
||||
}
|
||||
#[derive(Clone, Debug)]
|
||||
struct PingResult {
|
||||
pub address: Ipv4Addr,
|
||||
pub rtt: u128
|
||||
}
|
||||
|
||||
impl HistoricHost {
|
||||
pub fn dump_state(&self) {
|
||||
let working_history = self.history.clone();
|
||||
if working_history.len() == 0 {
|
||||
println!("No Results for {} yet.", self.name);
|
||||
return;
|
||||
}
|
||||
|
||||
let num_results = working_history.len();
|
||||
let mut running_total = 0;
|
||||
for result in working_history {
|
||||
running_total += result;
|
||||
}
|
||||
let average_ping_time = running_total.div_ceil(num_results as u128);
|
||||
println!("Counted {} results, total time {} with average {}",
|
||||
num_results, running_total, average_ping_time
|
||||
);
|
||||
}
|
||||
|
||||
pub fn get_ping_time_for(target: Ipv4Addr) -> (i32, Duration) {
|
||||
let start_time = SystemTime::now();
|
||||
let result = Command::new("/usr/bin/ping").arg(target.to_string())
|
||||
.arg("-c 1")
|
||||
.arg("-4")
|
||||
.arg("-w 10")
|
||||
.arg("-W 1")
|
||||
.output().unwrap().status.code().unwrap_or(255);
|
||||
let ping_duration = SystemTime::now().duration_since(start_time).unwrap_or(Duration::from_secs(600));
|
||||
(result, ping_duration)
|
||||
}
|
||||
|
||||
pub fn get_ping_time(&self) -> (i32, Duration) {
|
||||
HistoricHost::get_ping_time_for(self.address)
|
||||
}
|
||||
|
||||
pub fn ping(&mut self) {
|
||||
let (result, ping_duration) = self.get_ping_time();
|
||||
match result {
|
||||
0 => {
|
||||
self.history.push(ping_duration.as_millis())
|
||||
},
|
||||
1 => {
|
||||
println!("Error ping to {}", self.name);
|
||||
},
|
||||
_ => {
|
||||
println!("General Ping Error.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(version, about, long_about = None)]
|
||||
struct PPArgs {
|
||||
pub targets: Option<PathBuf>
|
||||
}
|
||||
|
||||
|
||||
// The output is wrapped in a Result to allow matching on errors.
|
||||
// Returns an Iterator to the Reader of the lines of the file.
|
||||
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
|
||||
where P: AsRef<Path>, {
|
||||
let file = File::open(filename)?;
|
||||
Ok(io::BufReader::new(file).lines())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
||||
env_logger::init();
|
||||
|
||||
let args = PPArgs::parse();
|
||||
|
||||
let targets = match args.targets {
|
||||
Some(file) => {
|
||||
println!("Loading hosts from {}", file.to_str().unwrap_or("no file."));
|
||||
let mut working = vec![];
|
||||
if let Ok(lines) = read_lines(file) {
|
||||
// Consumes the iterator, returns an (Optional) String
|
||||
for line in lines.map_while(Result::ok) {
|
||||
println!("{}", line);
|
||||
working.push(line.to_string())
|
||||
}
|
||||
}
|
||||
working.to_vec()
|
||||
}
|
||||
None => {
|
||||
println!("Default Hosts used.");
|
||||
vec!["127.0.0.1".to_string(), "1.1.1.1".to_string(), "8.8.8.8".to_string()]
|
||||
}
|
||||
};
|
||||
|
||||
let (sender, receiver) = mpsc::channel::<PingResult>();
|
||||
|
||||
// sender gets cloned and sent to each pinger
|
||||
|
||||
let mut hosts = vec![];
|
||||
|
||||
info!("Building hosts list...");
|
||||
// build hosts list...
|
||||
for target in targets {
|
||||
hosts.push(
|
||||
HistoricHost {
|
||||
name: target.to_string(),
|
||||
address: Ipv4Addr::from_str(&target).unwrap_or(Ipv4Addr::new(127,0,0,1)),
|
||||
history: vec![],
|
||||
alive: false
|
||||
}
|
||||
)
|
||||
}
|
||||
info!("Completed building with {} hosts.", hosts.len());
|
||||
|
||||
info!("Starting Manager Thread");
|
||||
// Manager Thread
|
||||
let my_hosts = hosts.clone();
|
||||
let _ = thread::spawn(move || {
|
||||
loop {
|
||||
println!("\x1b[2J --------------");
|
||||
for current_target in my_hosts.clone() {
|
||||
// debug!("[MT] Preparing to send off ping request to {}", current_target.address.to_string());
|
||||
let start_time = SystemTime::now();
|
||||
|
||||
let result = Command::new("/usr/bin/ping").arg(current_target.address.to_string())
|
||||
.arg("-c 1")
|
||||
.arg("-4")
|
||||
.arg("-w 10")
|
||||
.arg("-W 1")
|
||||
.output().unwrap().status.code().unwrap_or(255);
|
||||
let ping_duration = SystemTime::now().duration_since(start_time).unwrap_or(Duration::from_secs(600));
|
||||
let to_send = if result == 0 {
|
||||
PingResult { address: current_target.address, rtt: ping_duration.as_millis() }
|
||||
} else {
|
||||
PingResult { address: current_target.address, rtt: u128::MAX }
|
||||
};
|
||||
let my_sender = sender.clone();
|
||||
let _ = my_sender.send(to_send);
|
||||
}
|
||||
thread::sleep(Duration::from_secs(2));
|
||||
}
|
||||
});
|
||||
|
||||
info!("Manager Thread Started");
|
||||
|
||||
info!("Starting Data Thread");
|
||||
// Data Thread
|
||||
let _ = thread::spawn(move || {
|
||||
debug!("[DT] STARTING WITH {} HOSTS", hosts.len());
|
||||
loop {
|
||||
if let Ok(rx) = receiver.recv_timeout(Duration::from_micros(1000)) {
|
||||
let addr = rx.clone().address;
|
||||
let rtt = rx.clone().rtt;
|
||||
if rtt == u128::MAX {
|
||||
// error!("[DT] No reply from {}", addr);
|
||||
println!("{} not responding", Red.paint(addr.to_string()));
|
||||
|
||||
} else {
|
||||
// debug!("[DT] Recieved a ping result from {} with time of {}", addr, rtt);
|
||||
println!("{} responding.", Green.paint(addr.to_string()));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
info!("Data Thread Started");
|
||||
|
||||
info!("Keep Alive Thread Starting.");
|
||||
let _ = thread::spawn(move || {
|
||||
let mut counter = 0 ;
|
||||
loop {
|
||||
thread::sleep(Duration::from_millis(1000));
|
||||
counter += 1;
|
||||
if counter % 1000 == 0 {
|
||||
info!("Keep Alive Counter at {}", counter);
|
||||
}
|
||||
}
|
||||
}).join();
|
||||
|
||||
//
|
||||
// let _ = thread::spawn(move || {
|
||||
// loop {
|
||||
// println!("-- Status Start -- ");
|
||||
// for host in &hosts.clone() {
|
||||
// host.dump_state();
|
||||
// }
|
||||
// println!("-- Status Done -- ");
|
||||
// thread::sleep(Duration::from_secs(1));
|
||||
// }
|
||||
// }).join();
|
||||
}
|
||||
Reference in New Issue
Block a user