ajoute une fonction dans pmoutils pour checker les ports occupés

This commit is contained in:
2025-10-19 12:45:59 +02:00
parent d2fe0a1bf6
commit 756ae7f82c
6 changed files with 268 additions and 48 deletions

Binary file not shown.

190
Cargo.lock generated
View File

@@ -88,7 +88,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
]
[[package]]
@@ -115,7 +115,7 @@ checksum = "f548ad2c4031f2902e3edc1f29c29e835829437de49562d8eb5dc5584d3a1043"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
]
[[package]]
@@ -148,7 +148,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
]
[[package]]
@@ -159,7 +159,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
]
[[package]]
@@ -329,7 +329,7 @@ dependencies = [
"parking_lot",
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
"toml_edit 0.23.6",
]
@@ -395,7 +395,7 @@ dependencies = [
"indexmap",
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
"uuid",
]
@@ -474,7 +474,7 @@ checksum = "4f154e572231cb6ba2bd1176980827e3d5dc04cc183a75dea38109fbdd672d29"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
]
[[package]]
@@ -748,7 +748,7 @@ checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
]
[[package]]
@@ -768,7 +768,7 @@ checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
]
[[package]]
@@ -810,7 +810,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
]
[[package]]
@@ -866,7 +866,7 @@ checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
]
[[package]]
@@ -973,7 +973,7 @@ checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
]
[[package]]
@@ -1128,7 +1128,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
]
[[package]]
@@ -1186,7 +1186,7 @@ dependencies = [
"c_linked_list",
"get_if_addrs-sys",
"libc",
"winapi",
"winapi 0.2.8",
]
[[package]]
@@ -1493,7 +1493,7 @@ dependencies = [
"js-sys",
"log",
"wasm-bindgen",
"windows-core",
"windows-core 0.62.1",
]
[[package]]
@@ -1672,7 +1672,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
]
[[package]]
@@ -1865,7 +1865,7 @@ checksum = "ed9983e64b2358522f745c1251924e3ab7252d55637e80f6a0a3de642d6a9efc"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
]
[[package]]
@@ -2039,6 +2039,20 @@ dependencies = [
"tempfile",
]
[[package]]
name = "netstat2"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0faa3f4ad230fd2bf2a5dad71476ecbaeaed904b3c7e7e5b1f266c415c03761f"
dependencies = [
"bitflags 1.3.2",
"byteorder",
"libc",
"num-derive 0.3.3",
"num-traits",
"thiserror 1.0.69",
]
[[package]]
name = "new_debug_unreachable"
version = "1.0.6"
@@ -2061,6 +2075,15 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8"
[[package]]
name = "ntapi"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4"
dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "nu-ansi-term"
version = "0.50.1"
@@ -2086,6 +2109,17 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
[[package]]
name = "num-derive"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "num-derive"
version = "0.4.2"
@@ -2094,7 +2128,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
]
[[package]]
@@ -2183,7 +2217,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
]
[[package]]
@@ -2589,7 +2623,10 @@ name = "pmoutils"
version = "0.1.0"
dependencies = [
"get_if_addrs",
"netstat2",
"os_info",
"sysinfo",
"users",
]
[[package]]
@@ -2669,7 +2706,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b"
dependencies = [
"quote",
"syn",
"syn 2.0.106",
]
[[package]]
@@ -2827,7 +2864,7 @@ dependencies = [
"maybe-rayon",
"new_debug_unreachable",
"noop_proc_macro",
"num-derive",
"num-derive 0.4.2",
"num-traits",
"once_cell",
"paste",
@@ -3025,7 +3062,7 @@ dependencies = [
"proc-macro2",
"quote",
"rust-embed-utils",
"syn",
"syn 2.0.106",
"walkdir",
]
@@ -3198,7 +3235,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
]
[[package]]
@@ -3573,6 +3610,17 @@ dependencies = [
"symphonia-metadata",
]
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.106"
@@ -3601,7 +3649,22 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
]
[[package]]
name = "sysinfo"
version = "0.30.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a5b4ddaee55fb2bea2bf0e5000747e5f5c0de765e5a5ff87f4cd106439f4bb3"
dependencies = [
"cfg-if",
"core-foundation-sys",
"libc",
"ntapi",
"once_cell",
"rayon",
"windows",
]
[[package]]
@@ -3689,7 +3752,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
]
[[package]]
@@ -3700,7 +3763,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
]
[[package]]
@@ -3795,7 +3858,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
]
[[package]]
@@ -3985,7 +4048,7 @@ checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
]
[[package]]
@@ -4081,6 +4144,16 @@ dependencies = [
"serde",
]
[[package]]
name = "users"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032"
dependencies = [
"libc",
"log",
]
[[package]]
name = "utf8_iter"
version = "1.0.4"
@@ -4108,7 +4181,7 @@ dependencies = [
"proc-macro2",
"quote",
"regex",
"syn",
"syn 2.0.106",
]
[[package]]
@@ -4166,7 +4239,7 @@ checksum = "41b6d82be61465f97d42bd1d15bf20f3b0a3a0905018f38f9d6f6962055b0b5c"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
]
[[package]]
@@ -4253,7 +4326,7 @@ dependencies = [
"log",
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
"wasm-bindgen-shared",
]
@@ -4288,7 +4361,7 @@ checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@@ -4362,6 +4435,22 @@ version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.11"
@@ -4371,6 +4460,31 @@ dependencies = [
"windows-sys 0.61.1",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
dependencies = [
"windows-core 0.52.0",
"windows-targets",
]
[[package]]
name = "windows-core"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-core"
version = "0.62.1"
@@ -4392,7 +4506,7 @@ checksum = "edb307e42a74fb6de9bf3a02d9712678b22399c87e6fa869d6dfcd8c1b7754e0"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
]
[[package]]
@@ -4403,7 +4517,7 @@ checksum = "c0abd1ddbc6964ac14db11c7213d6532ef34bd9aa042c2e5935f59d7908b46a5"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
]
[[package]]
@@ -4635,7 +4749,7 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
"synstructure",
]
@@ -4656,7 +4770,7 @@ checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
]
[[package]]
@@ -4676,7 +4790,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
"synstructure",
]
@@ -4716,7 +4830,7 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.106",
]
[[package]]

View File

@@ -34,6 +34,7 @@ use crate::upnp_api::UpnpApiExt;
use pmocovers::Cache as CoverCache;
use pmoaudiocache::Cache as AudioCache;
use pmoutils::{find_process_using_port, TransportProtocol};
/// Registre de devices global et thread-safe.
///
@@ -423,14 +424,23 @@ impl UpnpServerExt for Server {
Err(e) => {
let kind = e.kind();
if kind == std::io::ErrorKind::AddrInUse {
error!(
"❌ SSDP initialization failed: port {} is already in use. \
Check which process listens on UDP:{} (e.g. `lsof -nP -i UDP:{}`): {}",
crate::ssdp::SSDP_PORT,
crate::ssdp::SSDP_PORT,
crate::ssdp::SSDP_PORT,
e,
);
let port = crate::ssdp::SSDP_PORT;
if let Some(process) =
find_process_using_port(port, TransportProtocol::Udp)
{
error!(
"❌ SSDP initialization failed: port {} is already in use by \
PID {} ({}) owned by {}: {}",
port, process.pid, process.process_name, process.owner, e
);
} else {
error!(
"❌ SSDP initialization failed: port {} is already in use. \
Unable to identify the blocking process automatically. \
Check manually with `lsof -nP -i UDP:{}`: {}",
port, port, e
);
}
} else {
error!("❌ SSDP initialization failed: {}", e);
}

View File

@@ -5,4 +5,7 @@ edition = "2024"
[dependencies]
get_if_addrs = "0.5.3"
os_info = "3.8"
os_info = "3.8"
netstat2 = "0.9"
sysinfo = "0.30"
users = "0.11"

View File

@@ -18,6 +18,8 @@
pub mod ip_utils;
pub use ip_utils::guess_local_ip;
pub mod process;
pub use process::{find_process_using_port, ProcessPortInfo, TransportProtocol};
/// Retourne une chaîne décrivant le système d'exploitation et sa version.
///
@@ -49,4 +51,4 @@ pub fn get_os_string() -> String {
} else {
format!("{}/Unknown", os_type)
}
}
}

91
pmoutils/src/process.rs Normal file
View File

@@ -0,0 +1,91 @@
use netstat2::{get_sockets_info, AddressFamilyFlags, ProtocolFlags, ProtocolSocketInfo};
use sysinfo::{Pid, System};
/// Informations sur un processus utilisant un port réseau.
#[derive(Debug, Clone)]
pub struct ProcessPortInfo {
pub pid: u32,
pub process_name: String,
pub owner: String,
pub port: u16,
}
/// Protocole de transport utilisé pour la recherche.
#[derive(Debug, Clone, Copy)]
pub enum TransportProtocol {
Tcp,
Udp,
}
/// 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`.
pub fn find_process_using_port(port: u16, protocol: TransportProtocol) -> Option<ProcessPortInfo> {
let proto_flag = match protocol {
TransportProtocol::Tcp => ProtocolFlags::TCP,
TransportProtocol::Udp => ProtocolFlags::UDP,
};
let sockets = get_sockets_info(
AddressFamilyFlags::IPV4 | AddressFamilyFlags::IPV6,
proto_flag,
)
.ok()?;
// Préparer l'inspection des processus.
let mut system = System::new_all();
system.refresh_all();
for socket in sockets {
match socket.protocol_socket_info {
ProtocolSocketInfo::Tcp(ref tcp_info)
if matches!(protocol, TransportProtocol::Tcp)
&& tcp_info.local_port == port =>
{
if let 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,
}
}
None
}
fn build_process_info(
system: &mut System,
port: u16,
pid_opt: Option<&u32>,
) -> Option<ProcessPortInfo> {
let pid = *pid_opt?;
let process = system.process(Pid::from_u32(pid))?;
let process_name = process.name().to_string();
let owner = process
.user_id()
.and_then(|uid| {
users::get_user_by_uid(**uid)
.map(|user| user.name().to_string_lossy().into_owned())
})
.unwrap_or_else(|| "unknown".to_string());
Some(ProcessPortInfo {
pid,
process_name,
owner,
port,
})
}