1use super::colors::colorize;
19use std::io::{BufRead, Result};
20use std::process::Command;
21use std::sync::{Arc, Mutex};
22use std::thread;
23use std::time::Duration;
24
25type Ping = (f32, String);
26
27fn parse_ping(output: Result<String>) -> Option<Ping> {
28 let output = output.ok()?;
29 if output.contains("time=") {
30 let mut ping_output = output.split("=").last().unwrap().split(" ");
31 let ping: f32 = ping_output.next().unwrap().parse().unwrap();
32 let unit = ping_output.next().unwrap();
33 Some((ping, unit.to_string()))
34 } else {
35 None
36 }
37}
38
39pub struct PingManager {
40 ping: Arc<Mutex<Option<Ping>>>,
41 host: String,
42}
43
44impl PingManager {
45 pub fn new(host: String) -> PingManager {
46 let ping_manager = PingManager {
47 host,
48 ping: Arc::new(Mutex::new(None)),
49 };
50 ping_manager.start();
51 ping_manager
52 }
53
54 fn start(self: &PingManager) -> () {
55 let ping = self.ping.clone();
57 let host = self.host.clone();
58
59 let _child = thread::spawn(move || {
60 let mut child = Command::new("ping")
61 .arg("-i 1")
62 .arg(host)
63 .stdout(std::process::Stdio::piped())
64 .spawn()
65 .expect("Failed to execute child!");
66
67 let child_stdout = child.stdout.as_mut().unwrap();
68
69 let reader = std::io::BufReader::new(child_stdout);
70 for line in reader.lines() {
71 *ping.lock().unwrap() = parse_ping(line);
72 }
73 });
74 }
75
76 pub fn wait(self: &PingManager) -> () {
77 for _ in 0..20 {
79 if self.ping.lock().unwrap().is_some() {
80 break;
81 }
82 thread::sleep(Duration::from_millis(10));
83 }
84 }
85
86 pub fn current(self: &PingManager) -> String {
87 match self.ping.lock().unwrap().as_ref() {
89 None => "N/A".to_string(),
90 Some(ping) => colorize(format!(" {} {}", ping.0, ping.1), ping.0, 30.0, 100.0),
91 }
92 }
93}