Skip to content

Commit

Permalink
Rewrite the pinger library
Browse files Browse the repository at this point in the history
  • Loading branch information
orf committed Dec 15, 2024
1 parent 8abb126 commit b9edbf8
Show file tree
Hide file tree
Showing 12 changed files with 318 additions and 283 deletions.
40 changes: 40 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions gping/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crossterm::{
};
use dns_lookup::lookup_host;
use itertools::{Itertools, MinMaxResult};
use pinger::{ping_with_interval, PingResult};
use pinger::{ping, PingOptions, PingResult};
use std::io;
use std::io::BufWriter;
use std::iter;
Expand Down Expand Up @@ -310,7 +310,8 @@ fn start_ping_thread(
) -> Result<JoinHandle<Result<()>>> {
let interval = Duration::from_millis((watch_interval.unwrap_or(0.2) * 1000.0) as u64);
// Pump ping messages into the queue
let stream = ping_with_interval(host, interval, interface)?;
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
6 changes: 4 additions & 2 deletions pinger/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ repository = "https://github.com/orf/pinger/"

[dependencies]
anyhow = "1.0.94"
thiserror = "2.0.6"
thiserror = "2.0.7"
rand = "0.8.5"
lazy-regex = "3.1.0"
lazy-regex = "3.3.0"
derive-new = "0.7.0"
which = "7.0.0"

[target.'cfg(windows)'.dependencies]
winping = "0.10.1"
Expand Down
6 changes: 4 additions & 2 deletions pinger/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ A full example of using the library can be found in the `examples/` directory, b
interface is quite simple:

```rust
use pinger::ping;
use std::time::Duration;
use pinger::{ping, PingOptions};

fn ping_google() {
let stream = ping("google.com", None).expect("Error pinging");
let options = PingOptions::new("google.com", Duration::from_secs(1), None);
let stream = ping(options).expect("Error pinging");
for message in stream {
match message {
pinger::PingResult::Pong(duration, _) => {
Expand Down
5 changes: 3 additions & 2 deletions pinger/examples/simple-ping.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use pinger::ping_with_interval;
use pinger::{ping, PingOptions};

pub fn main() {
let target = "tomforb.es".to_string();
let interval = std::time::Duration::from_secs(1);
let stream = ping_with_interval(target, interval, None).expect("Error pinging");
let options = PingOptions::new(target, interval, None);
let stream = ping(options).expect("Error pinging");
for message in stream {
match message {
pinger::PingResult::Pong(duration, line) => {
Expand Down
53 changes: 24 additions & 29 deletions pinger/src/bsd.rs
Original file line number Diff line number Diff line change
@@ -1,49 +1,44 @@
use crate::{Parser, PingResult, Pinger};
use crate::{extract_regex, PingDetectionError, PingOptions, PingResult, Pinger};
use lazy_regex::*;
use std::time::Duration;

pub static RE: Lazy<Regex> = lazy_regex!(r"time=(?:(?P<ms>[0-9]+).(?P<ns>[0-9]+)\s+ms)");

pub struct BSDPinger {
interval: Duration,
interface: Option<String>,
options: PingOptions,
}

pub(crate) fn parse_bsd(line: String) -> Option<PingResult> {
if line.starts_with("PING ") {
return None;
}
if line.starts_with("Request timeout") {
return Some(PingResult::Timeout(line));
}
extract_regex(&RE, line)
}

impl Pinger for BSDPinger {
type Parser = BSDParser;
fn from_options(options: PingOptions) -> Result<Self, PingDetectionError>
where
Self: Sized,
{
Ok(Self { options })
}

fn new(interval: Duration, interface: Option<String>) -> Self {
Self {
interface,
interval,
}
fn parse_fn(&self) -> fn(String) -> Option<PingResult> {
parse_bsd
}

fn ping_args(&self, target: String) -> (&str, Vec<String>) {
fn ping_args(&self) -> (&str, Vec<String>) {
let mut args = vec![format!(
"-i{:.1}",
self.interval.as_millis() as f32 / 1_000_f32
self.options.interval.as_millis() as f32 / 1_000_f32
)];
if let Some(interface) = &self.interface {
if let Some(interface) = &self.options.interface {
args.push("-I".into());
args.push(interface.clone());
}
args.push(target);
args.push(self.options.target.clone());
("ping", args)
}
}

#[derive(Default)]
pub struct BSDParser {}

impl Parser for BSDParser {
fn parse(&self, line: String) -> Option<PingResult> {
if line.starts_with("PING ") {
return None;
}
if line.starts_with("Request timeout") {
return Some(PingResult::Timeout(line));
}
self.extract_regex(&RE, line)
}
}
38 changes: 17 additions & 21 deletions pinger/src/fake.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,36 @@
use crate::{Parser, PingResult, Pinger};
use crate::{PingDetectionError, PingOptions, PingResult, Pinger};
use rand::prelude::*;
use std::sync::mpsc;
use std::sync::mpsc::Receiver;
use std::thread;
use std::time::Duration;

pub struct FakePinger {
interval: Duration,
options: PingOptions,
}

impl Pinger for FakePinger {
type Parser = FakeParser;
fn from_options(options: PingOptions) -> Result<Self, PingDetectionError>
where
Self: Sized,
{
Ok(Self { options })
}

fn new(interval: Duration, _interface: Option<String>) -> Self {
Self { interval }
fn parse_fn(&self) -> fn(String) -> Option<PingResult> {
unimplemented!("parse for FakeParser not implemented")
}

fn start(&self, _target: String) -> anyhow::Result<Receiver<PingResult>> {
fn ping_args(&self) -> (&str, Vec<String>) {
unimplemented!("ping_args not implemented for FakePinger")
}

fn start(&self) -> anyhow::Result<Receiver<PingResult>> {
let (tx, rx) = mpsc::channel();
let sleep_time = self.interval;
let sleep_time = self.options.interval;

thread::spawn(move || {
let mut random = rand::thread_rng();
let mut random = thread_rng();
loop {
let fake_seconds = random.gen_range(50..150);
let ping_result = PingResult::Pong(
Expand All @@ -38,17 +47,4 @@ impl Pinger for FakePinger {

Ok(rx)
}

fn ping_args(&self, _target: String) -> (&str, Vec<String>) {
unimplemented!("ping_args not implemented for FakePinger")
}
}

#[derive(Default)]
pub struct FakeParser {}

impl Parser for FakeParser {
fn parse(&self, _line: String) -> Option<PingResult> {
unimplemented!("parse for FakeParser not implemented")
}
}
Loading

0 comments on commit b9edbf8

Please sign in to comment.