Bump version to 0.1.1 and enhance IP detection with timeout support

Bump version from 0.1.0 to 0.1.1

- Update IP detection logic to use DNS port (53) instead of HTTP port (80)
- Add new function `guess_local_ip_with_timeout` with configurable timeout
- Improve process port detection logic
- Add `list_all_ips` function to list all non-loopback IP addresses
- Update documentation and examples
- Add version.txt file
This commit is contained in:
2026-02-28 18:26:17 +01:00
parent dfa818fbb1
commit fa1c9e12ff
6 changed files with 97 additions and 34 deletions

2
Cargo.lock generated
View File

@@ -554,7 +554,7 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]] [[package]]
name = "pmoutils" name = "pmoutils"
version = "0.1.0" version = "0.1.1"
dependencies = [ dependencies = [
"get_if_addrs", "get_if_addrs",
"netstat2", "netstat2",

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "pmoutils" name = "pmoutils"
version = "0.1.0" version = "0.1.1"
edition = "2021" edition = "2021"
description = "Utilitaires système pour la gestion des adresses IP et des processus" description = "Utilitaires système pour la gestion des adresses IP et des processus"

View File

@@ -1,5 +1,6 @@
use get_if_addrs::get_if_addrs; use get_if_addrs::get_if_addrs;
use std::net::UdpSocket; use std::net::UdpSocket;
use std::time::Duration;
/// Devine l'adresse IP locale de la machine. /// Devine l'adresse IP locale de la machine.
/// ///
@@ -10,7 +11,7 @@ use std::net::UdpSocket;
/// # Fonctionnement /// # Fonctionnement
/// ///
/// 1. Crée un socket UDP lié à `0.0.0.0:0` (n'importe quelle interface, port aléatoire) /// 1. Crée un socket UDP lié à `0.0.0.0:0` (n'importe quelle interface, port aléatoire)
/// 2. Tente une connexion (non effective pour UDP) vers `8.8.8.8:80` /// 2. Tente une connexion (non effective pour UDP) vers `8.8.8.8:53` (port DNS standard)
/// 3. Récupère l'adresse IP locale du socket /// 3. Récupère l'adresse IP locale du socket
/// 4. En cas d'échec à n'importe quelle étape, retourne `127.0.0.1` /// 4. En cas d'échec à n'importe quelle étape, retourne `127.0.0.1`
/// ///
@@ -36,7 +37,44 @@ use std::net::UdpSocket;
pub fn guess_local_ip() -> String { pub fn guess_local_ip() -> String {
match UdpSocket::bind("0.0.0.0:0") { match UdpSocket::bind("0.0.0.0:0") {
Ok(socket) => { Ok(socket) => {
if socket.connect("8.8.8.8:80").is_ok() { if socket.connect("8.8.8.8:53").is_ok() {
if let Ok(local_addr) = socket.local_addr() {
return local_addr.ip().to_string();
}
}
"127.0.0.1".to_string()
}
Err(_) => "127.0.0.1".to_string(),
}
}
/// Devine l'adresse IP locale de la machine avec un timeout configurable.
///
/// Cette fonction est une version améliorée de [`guess_local_ip`] qui permet
/// de spécifier un timeout pour la connexion.
///
/// # Arguments
///
/// * `timeout` - Durée maximale d'attente pour la connexion
///
/// # Returns
///
/// Retourne l'adresse IP locale sous forme de `String`, ou `"127.0.0.1"` en cas d'échec.
///
/// # Examples
///
/// ```
/// use pmoutils::guess_local_ip_with_timeout;
/// use std::time::Duration;
///
/// let ip = guess_local_ip_with_timeout(Duration::from_secs(2));
/// println!("IP locale détectée: {}", ip);
/// ```
pub fn guess_local_ip_with_timeout(timeout: Duration) -> String {
match UdpSocket::bind("0.0.0.0:0") {
Ok(socket) => {
socket.set_read_timeout(Some(timeout)).ok();
if socket.connect("8.8.8.8:53").is_ok() {
if let Ok(local_addr) = socket.local_addr() { if let Ok(local_addr) = socket.local_addr() {
return local_addr.ip().to_string(); return local_addr.ip().to_string();
} }

View File

@@ -6,30 +6,31 @@
/// # Fonctions principales /// # Fonctions principales
/// ///
/// - [`guess_local_ip`] : Devine l'adresse IP locale utilisée pour les connexions sortantes /// - [`guess_local_ip`] : Devine l'adresse IP locale utilisée pour les connexions sortantes
/// - [`guess_local_ip_with_timeout`] : Version avec timeout configurable
/// - `list_all_ips` : Liste toutes les adresses IP non-loopback des interfaces réseau
/// ///
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// use pmoutils::guess_local_ip; /// use pmoutils::guess_local_ip;
/// use pmoutils::ip_utils::list_all_ips;
/// ///
/// let ip = guess_local_ip(); /// let ip = guess_local_ip();
/// println!("Adresse IP locale: {}", ip); /// println!("Adresse IP locale: {}", ip);
///
/// let ips = list_all_ips();
/// for (interface, addresses) in ips.iter() {
/// println!("Interface {}: {:?}", interface, addresses);
/// }
/// ``` /// ```
pub mod ip_utils; pub mod ip_utils;
pub use ip_utils::guess_local_ip; pub use ip_utils::{guess_local_ip, guess_local_ip_with_timeout};
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
#[test]
fn test_get_os_string_format() {
let os = get_os_string();
assert!(!os.is_empty());
assert!(os.contains("/"));
}
#[test] #[test]
fn test_get_os_string_contains_os_type() { fn test_get_os_string_contains_os_type() {
let os = get_os_string(); let os = get_os_string();
@@ -45,20 +46,51 @@ mod tests {
} }
} }
/// Utilitaires pour la gestion des processus et des ports réseau.
///
/// Ce module fournit des fonctions pour identifier les processus qui utilisent
/// des ports réseau spécifiques.
///
/// # Fonctions principales
///
/// - [`find_process_using_port`] : Trouve le processus qui écoute sur un port donné
/// - [`ProcessPortInfo`] : Structure contenant les informations d'un processus
/// - [`TransportProtocol`] : Énumération des protocoles TCP et UDP
///
/// # Examples
///
/// ```
/// use pmoutils::{find_process_using_port, TransportProtocol};
///
/// let info = find_process_using_port(TransportProtocol::Tcp, 8080);
///
/// if let Some(process_info) = info {
/// println!("PID: {}", process_info.pid);
/// println!("Nom: {}", process_info.process_name);
/// println!("Propriétaire: {}", process_info.owner);
/// }
/// ```
pub mod process; pub mod process;
pub use process::{find_process_using_port, ProcessPortInfo, TransportProtocol}; pub use process::{find_process_using_port, ProcessPortInfo, TransportProtocol};
/// Retourne une chaîne décrivant le système d'exploitation et sa version. /// Retourne une chaîne décrivant le système d'exploitation et sa version.
/// ///
/// Utilise la crate `os_info` pour obtenir de manière portable et fiable /// Utilise la crate `os_info` pour obtenir de manière portable et fiable
/// les informations sur le système d'exploitation courant. /// les informations sur le système d'exploitation courant.
/// ///
/// # Format /// # Format
///
/// - macOS: "macOS/15.1" ou "Mac OS/10.15.7" /// - macOS: "macOS/15.1" ou "Mac OS/10.15.7"
/// - Linux: "Linux/6.5.0" ou "Ubuntu/22.04" /// - Linux: "Linux/6.5.0" ou "Ubuntu/22.04"
/// - Windows: "Windows/10.0.19045" /// - Windows: "Windows/10.0.19045"
/// - Autre: "{OS}/Unknown" /// - Autre: "{OS}/Unknown"
/// ///
/// # Exemples /// # Returns
///
/// Une chaîne de caractères au format "Type/Version".
///
/// # Examples
/// ///
/// ``` /// ```
/// use pmoutils::get_os_string; /// use pmoutils::get_os_string;

View File

@@ -20,7 +20,7 @@ pub enum TransportProtocol {
/// Tente de trouver le processus qui écoute sur `port` pour le protocole donné. /// Tente de trouver le processus qui écoute sur `port` pour le protocole donné.
/// ///
/// Retourne `Some(ProcessPortInfo)` si un processus a pu être identifié, sinon `None`. /// Retourne `Some(ProcessPortInfo)` si un processus a pu être identifié, sinon `None`.
pub fn find_process_using_port(port: u16, protocol: TransportProtocol) -> Option<ProcessPortInfo> { pub fn find_process_using_port(protocol: TransportProtocol, port: u16) -> Option<ProcessPortInfo> {
let proto_flag = match protocol { let proto_flag = match protocol {
TransportProtocol::Tcp => ProtocolFlags::TCP, TransportProtocol::Tcp => ProtocolFlags::TCP,
TransportProtocol::Udp => ProtocolFlags::UDP, TransportProtocol::Udp => ProtocolFlags::UDP,
@@ -37,26 +37,18 @@ pub fn find_process_using_port(port: u16, protocol: TransportProtocol) -> Option
system.refresh_all(); system.refresh_all();
for socket in sockets { for socket in sockets {
match socket.protocol_socket_info { let port_match = match (&socket.protocol_socket_info, protocol) {
ProtocolSocketInfo::Tcp(ref tcp_info) (ProtocolSocketInfo::Tcp(tcp), TransportProtocol::Tcp) => tcp.local_port == port,
if matches!(protocol, TransportProtocol::Tcp) && tcp_info.local_port == port => (ProtocolSocketInfo::Udp(udp), TransportProtocol::Udp) => udp.local_port == port,
_ => false,
};
if port_match {
if let Some(info) =
build_process_info(&mut system, port, socket.associated_pids.first())
{ {
if let Some(info) = return Some(info);
build_process_info(&mut system, port, socket.associated_pids.first())
{
return Some(info);
}
} }
ProtocolSocketInfo::Udp(ref udp_info)
if matches!(protocol, TransportProtocol::Udp) && udp_info.local_port == port =>
{
if let Some(info) =
build_process_info(&mut system, port, socket.associated_pids.first())
{
return Some(info);
}
}
_ => continue,
} }
} }
@@ -68,7 +60,7 @@ fn build_process_info(
port: u16, port: u16,
pid_opt: Option<&u32>, pid_opt: Option<&u32>,
) -> Option<ProcessPortInfo> { ) -> Option<ProcessPortInfo> {
let pid = *pid_opt?; let pid = pid_opt.copied()?;
let process = system.process(Pid::from_u32(pid))?; let process = system.process(Pid::from_u32(pid))?;
let process_name = process.name().to_string(); let process_name = process.name().to_string();
@@ -133,7 +125,7 @@ mod tests {
#[test] #[test]
fn test_find_process_using_port_invalid() { fn test_find_process_using_port_invalid() {
let result = find_process_using_port(65535, TransportProtocol::Tcp); let result = find_process_using_port(TransportProtocol::Tcp, 65535);
assert!(result.is_none() || result.is_some()); assert!(result.is_none() || result.is_some());
} }

1
version.txt Normal file
View File

@@ -0,0 +1 @@
0.1.1