Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support generic ping arguments. Closes #491 and #393 #499

Merged
merged 1 commit into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions gping.1
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
.SH NAME
gping \- Ping, but with a graph.
.SH SYNOPSIS
\fBgping\fR [\fB\-\-cmd\fR] [\fB\-n\fR|\fB\-\-watch\-interval\fR] [\fB\-b\fR|\fB\-\-buffer\fR] [\fB\-4 \fR] [\fB\-6 \fR] [\fB\-i\fR|\fB\-\-interface\fR] [\fB\-s\fR|\fB\-\-simple\-graphics\fR] [\fB\-\-vertical\-margin\fR] [\fB\-\-horizontal\-margin\fR] [\fB\-c\fR|\fB\-\-color\fR] [\fB\-\-clear\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fIHOSTS_OR_COMMANDS\fR]
\fBgping\fR [\fB\-\-cmd\fR] [\fB\-n\fR|\fB\-\-watch\-interval\fR] [\fB\-b\fR|\fB\-\-buffer\fR] [\fB\-4 \fR] [\fB\-6 \fR] [\fB\-i\fR|\fB\-\-interface\fR] [\fB\-s\fR|\fB\-\-simple\-graphics\fR] [\fB\-\-vertical\-margin\fR] [\fB\-\-horizontal\-margin\fR] [\fB\-c\fR|\fB\-\-color\fR] [\fB\-\-clear\fR] [\fB\-\-ping\-args\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fIHOSTS_OR_COMMANDS\fR]
.SH DESCRIPTION
Ping, but with a graph.
.SH OPTIONS
Expand All @@ -13,10 +13,10 @@ Ping, but with a graph.
Graph the execution time for a list of commands rather than pinging hosts
.TP
\fB\-n\fR, \fB\-\-watch\-interval\fR=\fIWATCH_INTERVAL\fR
Watch interval seconds (provide partial seconds like \*(Aq0.5\*(Aq). Default for ping is 0.2, default for cmd is 0.5.
Watch interval seconds (provide partial seconds like \*(Aq0.5\*(Aq). Default for ping is 0.2, default for cmd is 0.5
.TP
\fB\-b\fR, \fB\-\-buffer\fR=\fIBUFFER\fR [default: 30]
Determines the number of seconds to display in the graph.
Determines the number of seconds to display in the graph
.TP
\fB\-4\fR
Resolve ping targets to IPv4 address
Expand All @@ -28,7 +28,7 @@ Resolve ping targets to IPv6 address
Interface to use when pinging
.TP
\fB\-s\fR, \fB\-\-simple\-graphics\fR
Uses dot characters instead of braille

.TP
\fB\-\-vertical\-margin\fR=\fIVERTICAL_MARGIN\fR [default: 1]
Vertical margin around the graph (top and bottom)
Expand All @@ -51,10 +51,13 @@ following color names: \*(Aqblack\*(Aq, \*(Aqred\*(Aq, \*(Aqgreen\*(Aq, \*(Aqyel
\fB\-\-clear\fR
Clear the graph from the terminal after closing the program
.TP
\fB\-\-ping\-args\fR=\fIPING_ARGS\fR
Extra arguments to pass to `ping`. These are platform dependent
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.TP
[\fIHOSTS_OR_COMMANDS\fR]
Hosts or IPs to ping, or commands to run if \-\-cmd is provided. Can use cloud shorthands like aws:eu\-west\-1.
Hosts or IPs to ping, or commands to run if \-\-cmd is provided. Can use cloud shorthands like aws:eu\-west\-1
.SH AUTHORS
Tom Forbes <[email protected]>
87 changes: 40 additions & 47 deletions gping/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,29 +55,23 @@ build_env: {},{}"#,
);

#[derive(Parser, Debug)]
#[command(author, version=build::PKG_VERSION, name = "gping", about = "Ping, but with a graph.", long_version = VERSION_INFO)]
#[command(author, version=build::PKG_VERSION, name = "gping", about = "Ping, but with a graph.", long_version = VERSION_INFO
)]
struct Args {
#[arg(
long,
help = "Graph the execution time for a list of commands rather than pinging hosts"
)]
/// Graph the execution time for a list of commands rather than pinging hosts
#[arg(long)]
cmd: bool,
#[arg(
short = 'n',
long,
help = "Watch interval seconds (provide partial seconds like '0.5'). Default for ping is 0.2, default for cmd is 0.5."
)]

/// Watch interval seconds (provide partial seconds like '0.5'). Default for ping is 0.2, default for cmd is 0.5.
#[arg(short = 'n', long)]
watch_interval: Option<f32>,
#[arg(
help = "Hosts or IPs to ping, or commands to run if --cmd is provided. Can use cloud shorthands like aws:eu-west-1."
)]

/// Hosts or IPs to ping, or commands to run if --cmd is provided. Can use cloud shorthands like aws:eu-west-1.
#[arg(allow_hyphen_values = false)]
hosts_or_commands: Vec<String>,
#[arg(
short,
long,
default_value = "30",
help = "Determines the number of seconds to display in the graph."
)]

/// Determines the number of seconds to display in the graph.
#[arg(short, long, default_value = "30")]
buffer: u64,
/// Resolve ping targets to IPv4 address
#[arg(short = '4', conflicts_with = "ipv6")]
Expand All @@ -88,20 +82,19 @@ struct Args {
/// Interface to use when pinging.
#[arg(short = 'i', long)]
interface: Option<String>,
#[arg(short = 's', long, help = "Uses dot characters instead of braille")]

/// Uses dot characters instead of braille
#[arg(short = 's', long, help = "")]
simple_graphics: bool,
#[arg(
long,
help = "Vertical margin around the graph (top and bottom)",
default_value = "1"
)]

/// Vertical margin around the graph (top and bottom)
#[arg(long, default_value = "1")]
vertical_margin: u16,
#[arg(
long,
help = "Horizontal margin around the graph (left and right)",
default_value = "0"
)]

/// Horizontal margin around the graph (left and right)
#[arg(long, default_value = "0")]
horizontal_margin: u16,

#[arg(
name = "color",
short = 'c',
Expand All @@ -120,15 +113,14 @@ following color names: 'black', 'red', 'green', 'yellow', 'blue', 'magenta',
'light-blue', 'light-magenta', 'light-cyan', and 'white'"#
)]
color_codes_or_names: Vec<String>,
#[arg(
name = "clear",
long = "clear",
help = "\
Clear the graph from the terminal after closing the program\
",
action
)]

/// Clear the graph from the terminal after closing the program
#[arg(name = "clear", long = "clear", action)]
clear: bool,

/// Extra arguments to pass to `ping`. These are platform dependent.
#[arg(long, allow_hyphen_values = true, num_args = 0.., conflicts_with="cmd")]
ping_args: Option<Vec<String>>,
}

struct App {
Expand Down Expand Up @@ -302,17 +294,13 @@ fn start_cmd_thread(
}

fn start_ping_thread(
host: String,
options: PingOptions,
host_id: usize,
watch_interval: Option<f32>,
ping_tx: Sender<Event>,
kill_event: Arc<AtomicBool>,
interface: Option<String>,
) -> Result<JoinHandle<Result<()>>> {
let interval = Duration::from_millis((watch_interval.unwrap_or(0.2) * 1000.0) as u64);
let stream = ping(options)?;
// Pump ping messages into the queue
let ping_opts = PingOptions::new(host, interval, interface);
let stream = ping(ping_opts)?;
Ok(thread::spawn(move || -> Result<()> {
while !kill_event.load(Ordering::Acquire) {
match stream.recv() {
Expand Down Expand Up @@ -419,13 +407,18 @@ fn main() -> Result<()> {
);
threads.push(cmd_thread);
} else {
let interval =
Duration::from_millis((args.watch_interval.unwrap_or(0.2) * 1000.0) as u64);
let mut ping_opts = PingOptions::new(host_or_cmd, interval, args.interface.clone());
if let Some(ping_args) = &args.ping_args {
ping_opts = ping_opts.with_raw_arguments(ping_args.clone());
}

threads.push(start_ping_thread(
host_or_cmd,
ping_opts,
host_id,
args.watch_interval,
key_tx.clone(),
std::sync::Arc::clone(&killed),
args.interface.clone(),
)?);
}
}
Expand Down
3 changes: 3 additions & 0 deletions pinger/src/bsd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ impl Pinger for BSDPinger {
args.push("-I".into());
args.push(interface.clone());
}
if let Some(raw_args) = &self.options.raw_arguments {
args.extend(raw_args.iter().cloned());
}
args.push(self.options.target.to_string());
("ping", args)
}
Expand Down
15 changes: 15 additions & 0 deletions pinger/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,19 @@ pub struct PingOptions {
pub target: Target,
pub interval: Duration,
pub interface: Option<String>,
pub raw_arguments: Option<Vec<String>>,
}

impl PingOptions {
pub fn with_raw_arguments(mut self, raw_arguments: Vec<impl ToString>) -> Self {
self.raw_arguments = Some(
raw_arguments
.into_iter()
.map(|item| item.to_string())
.collect(),
);
self
}
}

impl PingOptions {
Expand All @@ -53,6 +66,7 @@ impl PingOptions {
target,
interval,
interface,
raw_arguments: None,
}
}
pub fn new(target: impl ToString, interval: Duration, interface: Option<String>) -> Self {
Expand Down Expand Up @@ -116,6 +130,7 @@ pub trait Pinger: Send + Sync {
fn start(&self) -> Result<mpsc::Receiver<PingResult>, PingCreationError> {
let (tx, rx) = mpsc::channel();
let (cmd, args) = self.ping_args();

let mut child = run_ping(cmd, args)?;
let stdout = child.stdout.take().expect("child did not have a stdout");

Expand Down
10 changes: 9 additions & 1 deletion pinger/src/linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,15 @@ impl Pinger for LinuxPinger {
"ping"
};

let args = vec![
let mut args = vec![
options.target.to_string(),
format!("-i{:.1}", options.interval.as_millis() as f32 / 1_000_f32),
];

if let Some(raw_args) = &options.raw_arguments {
args.extend(raw_args.iter().cloned());
}

(cmd, args)
}
LinuxPinger::IPTools(options) => {
Expand All @@ -94,6 +98,10 @@ impl Pinger for LinuxPinger {
args.push("-I".into());
args.push(interface.clone());
}
if let Some(raw_args) = &options.raw_arguments {
args.extend(raw_args.iter().cloned());
}

args.push(options.target.to_string());
(cmd, args)
}
Expand Down
4 changes: 4 additions & 0 deletions pinger/src/macos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ impl Pinger for MacOSPinger {
args.push(interface.clone());
}

if let Some(raw_args) = &self.options.raw_arguments {
args.extend(raw_args.iter().cloned());
}

(cmd, args)
}
}