diff options
| author | ache <ache@ache.one> | 2026-08-06 06:55:55 +0200 |
|---|---|---|
| committer | ache <ache@ache.one> | 2026-08-06 06:55:55 +0200 |
| commit | 368f4c99ed22ca9c30e60f7cc86a77553d745117 (patch) | |
| tree | b03e763e74c4ff4895e70e056687c57bfe8ef3fd /src | |
| parent | Fix green background (diff) | |
Remove ttl and add main loop
Diffstat (limited to 'src')
| -rw-r--r-- | src/args.rs | 14 | ||||
| -rw-r--r-- | src/main.rs | 175 | ||||
| -rw-r--r-- | src/pinger.rs | 7 |
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 { |