diff --git a/examples/get_all.rs b/examples/get_all.rs index baaac31..295f95d 100644 --- a/examples/get_all.rs +++ b/examples/get_all.rs @@ -1,4 +1,5 @@ fn main() { + // Retrieve all listeners if let Ok(listeners) = listeners::get_all() { for l in listeners { println!("{l}"); diff --git a/examples/get_ports_by_pid.rs b/examples/get_ports_by_pid.rs new file mode 100644 index 0000000..bdd5768 --- /dev/null +++ b/examples/get_ports_by_pid.rs @@ -0,0 +1,16 @@ +use std::env::args; + +fn main() { + let pid = args() + .nth(1) + .expect("Expected CLI argument: PID") + .parse() + .expect("PID must be an unsigned integer on at most 32 bits"); + + // Retrieve ports listened to by a process given its PID + if let Ok(ports) = listeners::get_ports_by_pid(pid) { + for p in ports { + println!("{p}"); + } + } +} diff --git a/examples/get_ports_by_process_name.rs b/examples/get_ports_by_process_name.rs new file mode 100644 index 0000000..77b9f80 --- /dev/null +++ b/examples/get_ports_by_process_name.rs @@ -0,0 +1,12 @@ +use std::env::args; + +fn main() { + let process_name = args().nth(1).expect("Expected CLI argument: process name"); + + // Retrieve ports listened to by a process given its name + if let Ok(ports) = listeners::get_ports_by_process_name(&process_name) { + for p in ports { + println!("{p}"); + } + } +} diff --git a/examples/get_processes_by_port.rs b/examples/get_processes_by_port.rs new file mode 100644 index 0000000..00568f8 --- /dev/null +++ b/examples/get_processes_by_port.rs @@ -0,0 +1,16 @@ +use std::env::args; + +fn main() { + let port = args() + .nth(1) + .expect("Expected CLI argument: port") + .parse() + .expect("Port must be an unsigned integer on at most 16 bits"); + + // Retrieve PID and name of processes listening on a given port + if let Ok(processes) = listeners::get_processes_by_port(port) { + for p in processes { + println!("{p}"); + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 5785978..c3ade05 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,20 +26,16 @@ pub struct Process { pub name: String, } -/// Returns the list of all processes listening on a TCP port. +/// Returns all the listeners. /// /// # Errors /// -/// This function returns an error if it fails to get the list of processes for the current platform. +/// This function returns an error if it fails to retrieve listeners for the current platform. /// /// # Example /// /// ``` rust -/// if let Ok(listeners) = listeners::get_all() { -/// for l in listeners { -/// println!("{l}"); -/// } -/// } +#[doc = include_str!("../examples/get_all.rs")] /// ``` /// /// Output: @@ -55,6 +51,86 @@ pub fn get_all() -> Result> { platform::get_all() } +/// Returns the list of processes listening on a given TCP port. +/// +/// # Errors +/// +/// This function returns an error if it fails to retrieve listeners for the current platform. +/// +/// # Example +/// +/// ``` rust +#[doc = include_str!("../examples/get_processes_by_port.rs")] +/// ``` +/// +/// Output: +/// ``` text +/// PID: 160 Process name: mysqld +/// ``` +pub fn get_processes_by_port(port: u16) -> Result> { + platform::get_all().map(|listeners| { + listeners + .into_iter() + .filter(|listener| listener.socket.port() == port) + .map(|listener| listener.process) + .collect() + }) +} + +/// Returns the list of ports listened to by a process given its PID. +/// +/// # Errors +/// +/// This function returns an error if it fails to retrieve listeners for the current platform. +/// +/// # Example +/// +/// ``` rust +#[doc = include_str!("../examples/get_ports_by_pid.rs")] +/// ``` +/// +/// Output: +/// ``` text +/// 3306 +/// 33060 +/// ``` +pub fn get_ports_by_pid(pid: u32) -> Result> { + platform::get_all().map(|listeners| { + listeners + .into_iter() + .filter(|listener| listener.process.pid == pid) + .map(|listener| listener.socket.port()) + .collect() + }) +} + +/// Returns the list of ports listened to by a process given its name. +/// +/// # Errors +/// +/// This function returns an error if it fails to retrieve listeners for the current platform. +/// +/// # Example +/// +/// ``` rust +#[doc = include_str!("../examples/get_ports_by_process_name.rs")] +/// ``` +/// +/// Output: +/// ``` text +/// 3306 +/// 33060 +/// ``` +pub fn get_ports_by_process_name(name: &str) -> Result> { + platform::get_all().map(|listeners| { + listeners + .into_iter() + .filter(|listener| listener.process.name == name) + .map(|listener| listener.socket.port()) + .collect() + }) +} + impl Listener { fn new(pid: u32, name: String, socket: SocketAddr) -> Self { let process = Process::new(pid, name); @@ -80,10 +156,6 @@ impl Display for Listener { impl Display for Process { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "PID: {:<10} Process name: {:<25}", - self.pid, self.name - ) + write!(f, "PID: {:<10} Process name: {:<25}", self.pid, self.name) } }