aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/args.rs14
-rw-r--r--src/main.rs175
-rw-r--r--src/pinger.rs7
3 files changed, 110 insertions, 86 deletions
diff --git a/src/args.rs b/src/args.rs
index fb5d6c1..7004791 100644
--- a/src/args.rs
+++ b/src/args.rs
@@ -17,9 +17,9 @@ pub struct Args {
#[arg(short = 'I', value_name = "interface")]
pub interface: Option<String>,
- /// number of seconds to wait between 2 pings
- #[arg(short = 'i', value_name = "seconds")]
- pub seconds: Option<f32>,
+ /// number of milliseconds to wait between 2 pings
+ #[arg(short = 'i', value_name = "milliseconds")]
+ pub interval: Option<u32>,
/// the Time-to-live
#[arg(short = 't', long = "ttl", value_name = "TTL")]
@@ -29,12 +29,12 @@ pub struct Args {
#[arg(short = 's', long = "stats", action = ArgAction::SetTrue)]
pub stats: bool,
- /// Print the Help line
- #[arg(short = 'H', action = ArgAction::Help, required = false)]
- pub help: Option<bool>,
+ /// Print the legende line
+ #[arg(short = 'l', long = "legende", action = ArgAction::SetTrue)]
+ pub legende: bool,
/// Print the remainder line
- #[arg(short = 'l', long = "remainder", action = ArgAction::SetTrue)]
+ #[arg(short = 'r', long = "remainder", action = ArgAction::SetTrue)]
pub remainder: bool,
/// Target IP address
diff --git a/src/main.rs b/src/main.rs
index a5996d4..675634d 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -17,6 +17,87 @@ use print::{print_legende_line, print_ping_line, print_stats};
use state::State;
use stats::compute_stats;
+fn main_loop(args : &Args, states: &mut Vec<State>, target: &IpAddr, tx: &mpsc::Sender<PingResult>, rx: &mut mpsc::Receiver<PingResult>, packet_id: &mut u32) {
+
+ let current_time = State::current_time_ms();
+ for state in states.iter_mut() {
+ if let State::NotYetReceived { time_sent } = state {
+ // TODO: 2000ms Should be a configurable variable
+ if current_time - *time_sent > 2000 {
+ // 2s = 2000ms
+ *state = State::Lost;
+ }
+ }
+ }
+
+ // Send the ping
+ states.push(State::NotYetReceived {
+ time_sent: current_time,
+ });
+ spawn_ping(*target, tx.clone(), *packet_id, args.ttl.unwrap_or(64));
+ *packet_id += 1;
+
+ // The update state loop
+ loop {
+ match rx.try_recv() {
+ // Update the state of the received packet
+ Ok(result) => {
+ if args.beep {
+ print!("\x07"); // Rust doesn't support \a ?!
+ }
+ match result {
+ PingResult::Ping { rtt, id } => {
+ if (id as usize) < states.len() {
+ states[id as usize] = State::Received { rtt };
+ }
+ }
+ PingResult::NoPingErr { id } => {
+ states[id as usize] = State::SendError;
+ }
+ }
+ }
+ Err(TryRecvError::Disconnected) => {
+ eprintln!("Critical error, pinger thread killed");
+ std::process::exit(2);
+ }
+ Err(TryRecvError::Empty) => {
+ // No more ping to read
+ break;
+ }
+ }
+ }
+
+ // Put the cursor back up
+ if !std::process::Command::new("tput")
+ .arg("rc")
+ .status()
+ .map(|s| s.success())
+ .unwrap_or(false)
+ {
+ println!("Process failed too");
+ std::process::exit(1);
+ }
+
+ // Prints lines based on the state of each ping
+ print_ping_line(&states);
+
+ // Print stats
+ if args.stats {
+ if let Some(stats) = compute_stats(&states) {
+ print_stats(&stats);
+ }
+ // Print stats of the last 30 pings
+ let first_index = if (states.len() as i32) - 30 > 0 {
+ states.len() - 30
+ } else {
+ 0
+ };
+ if let Some(stats) = compute_stats(&states[first_index..]) {
+ print_stats(&stats);
+ }
+ }
+}
+
#[tokio::main]
async fn main() {
let args = Args::parse();
@@ -36,7 +117,14 @@ async fn main() {
let mut states: Vec<State> = Vec::new();
let mut packet_id: u32 = 0;
- print_legende_line();
+ if args.legende {
+ print_legende_line();
+ }
+
+ if args.remainder {
+ // TODO: Not yet implemented
+ // print_remainder_line
+ }
// Save the current cursor position
if !std::process::Command::new("tput")
@@ -49,83 +137,18 @@ async fn main() {
std::process::exit(1);
}
- // Should be quit with Ctrl + C
- loop {
- let current_time = State::current_time_ms();
- for state in states.iter_mut() {
- if let State::NotYetReceived { time_sent } = state {
- // TODO: 2000ms Should be a configurable variable
- if current_time - *time_sent > 2000 {
- // 2s = 2000ms
- *state = State::Lost;
- }
- }
- }
-
- // Send the ping
- states.push(State::NotYetReceived {
- time_sent: current_time,
- });
- spawn_ping(target, tx.clone(), packet_id);
- packet_id += 1;
- // The update state loop
- loop {
- match rx.try_recv() {
- // Update the state of the received packet
- Ok(result) => match result {
- PingResult::Ping { rtt, id } => {
- if (id as usize) < states.len() {
- states[id as usize] = State::Received { rtt };
- }
- }
- PingResult::NoPingErr { id } => {
- states[id as usize] = State::SendError;
- }
- },
- Err(TryRecvError::Disconnected) => {
- eprintln!("Critical error, pinger thread killed");
- std::process::exit(2);
- }
- Err(TryRecvError::Empty) => {
- // No more ping to read
- break;
- }
- }
- }
-
- // Put the cursor back up
- if !std::process::Command::new("tput")
- .arg("rc")
- .status()
- .map(|s| s.success())
- .unwrap_or(false)
- {
- println!("Process failed too");
- std::process::exit(1);
- }
-
- // Prints lines based on the state of each ping
- print_ping_line(&states);
-
- // Print stats
- if args.stats {
- if let Some(stats) = compute_stats(&states) {
- print_stats(&stats);
- }
- // Print stats of the last 30 pings
- let first_index = if (states.len() as i32) - 30 > 0 {
- states.len() - 30
- } else {
- 0
- };
- if let Some(stats) = compute_stats(&states[first_index..]) {
- print_stats(&stats);
+ let wait_time = args.interval.unwrap_or(1000);
+ match args.count {
+ Some(c) => {
+ for _ in 1..c {
+ main_loop(&args, &mut states, &target, &tx, &mut rx, &mut packet_id);
+ sleep(tokio::time::Duration::from_millis(wait_time as u64)).await;
}
+ },
+ None => loop {
+ main_loop(&args, &mut states, &target, &tx, &mut rx, &mut packet_id);
+ sleep(tokio::time::Duration::from_millis(wait_time as u64)).await;
}
-
- // Sleep for 1 second before the next ping
- // FEAT: Should be configurable via CLI
- sleep(tokio::time::Duration::from_millis(1000)).await;
}
}
diff --git a/src/pinger.rs b/src/pinger.rs
index 12cad5d..2170ead 100644
--- a/src/pinger.rs
+++ b/src/pinger.rs
@@ -8,19 +8,20 @@ pub enum PingResult {
Ping { rtt: u64, id: u32 },
}
-pub fn spawn_ping(target: IpAddr, tx: Sender<PingResult>, id: u32) {
+pub fn spawn_ping(target: IpAddr, tx: Sender<PingResult>, id: u32, ttl: u32) {
task::spawn_blocking(move || {
- let result = do_ping(target, id);
+ let result = do_ping(target, id, ttl);
let _ = tx.try_send(result);
});
}
-fn do_ping(target: IpAddr, id: u32) -> PingResult {
+fn do_ping(target: IpAddr, id: u32, ttl: u32) -> PingResult {
let payload: [u8; 24] = [0u8; 24];
let result = ping::new(target)
.timeout(Duration::from_secs(3))
.payload(&payload)
+ .ttl(ttl)
.send();
match result {