use netstat2::{AddressFamilyFlags, ProtocolFlags, ProtocolSocketInfo}; use sysinfo::{System, SystemExt, Pid, PidExt, ProcessExt}; use serde::{Serialize, Deserialize}; use crate::errors::*; #[derive(Clone, Serialize, Deserialize, Eq, PartialEq, Hash)] pub struct Client { pub pid: u32, pub exe: String, } fn get_associated_pids(local_port: u16) -> Result, netstat2::error::Error> { let sockets_iter = netstat2::iterate_sockets_info( AddressFamilyFlags::IPV4, ProtocolFlags::TCP )?; for item in sockets_iter { let sock_info = item?; let proto_info = match sock_info.protocol_socket_info { ProtocolSocketInfo::Tcp(tcp_info) => tcp_info, ProtocolSocketInfo::Udp(_) => {continue;} }; if proto_info.local_port == local_port && proto_info.remote_port == 12345 && proto_info.local_addr == std::net::Ipv4Addr::LOCALHOST && proto_info.remote_addr == std::net::Ipv4Addr::LOCALHOST { return Ok(sock_info.associated_pids) } } Ok(vec![]) } // Theoretically, on some systems, multiple processes can share a socket pub fn get_clients(local_port: u16) -> Result>, ClientInfoError> { let mut clients = Vec::new(); let mut sys = System::new(); for p in get_associated_pids(local_port)? { let pid = Pid::from_u32(p); sys.refresh_process(pid); let proc = sys.process(pid) .ok_or(ClientInfoError::PidNotFound)?; let client = Client { pid: p, exe: proc.exe().to_string_lossy().into_owned(), }; clients.push(Some(client)); } if clients.is_empty() { clients.push(None); } Ok(clients) }