use std::net::{TcpStream, ToSocketAddrs};
use std::sync::mpsc;
use std::thread;
use std::time::Duration;
use crate::event::AppEvent;
pub fn ping_host(alias: String, hostname: String, port: u16, tx: mpsc::Sender<AppEvent>) {
thread::spawn(move || {
ping_host_inner(&alias, &hostname, port, &tx);
});
}
fn ping_host_inner(alias: &str, hostname: &str, port: u16, tx: &mpsc::Sender<AppEvent>) {
let clean = hostname.trim_start_matches('[').trim_end_matches(']');
let addr_str = if clean.contains(':') {
format!("[{}]:{}", clean, port)
} else {
format!("{}:{}", hostname, port)
};
let (done_tx, done_rx) = mpsc::channel();
let addr_str_clone = addr_str.clone();
thread::spawn(move || {
let result = match addr_str_clone.to_socket_addrs() {
Ok(addrs) => addrs
.into_iter()
.any(|addr| TcpStream::connect_timeout(&addr, Duration::from_secs(3)).is_ok()),
Err(_) => false,
};
let _ = done_tx.send(result);
});
let reachable = done_rx
.recv_timeout(Duration::from_secs(5))
.unwrap_or(false);
let _ = tx.send(AppEvent::PingResult {
alias: alias.to_string(),
reachable,
});
}
pub fn ping_all(hosts: &[(String, String, u16)], tx: mpsc::Sender<AppEvent>) {
let hosts = hosts.to_vec();
thread::spawn(move || {
let max_concurrent: usize = 10;
let (slot_tx, slot_rx) = mpsc::channel();
for _ in 0..max_concurrent {
let _ = slot_tx.send(());
}
for (alias, hostname, port) in hosts {
let _ = slot_rx.recv(); let slot_tx = slot_tx.clone();
let tx = tx.clone();
thread::spawn(move || {
ping_host_inner(&alias, &hostname, port, &tx);
let _ = slot_tx.send(()); });
}
});
}