feat: Améliorations et corrections dans la gestion des devices UPnP
- Correction des erreurs dans la génération des éléments XML pour les conteneurs - Amélioration de la gestion des caches (cover et audio) dans ParadiseStreaming - Optimisation des annonces SSDP avec des messages plus clairs - Ajout de logs de debug pour faciliter le débogage - Correction de la gestion des notifications GENA pour le ContentDirectory - Amélioration de la documentation et des commentaires dans les fichiers modifiés
This commit is contained in:
@@ -83,7 +83,6 @@ impl SsdpServer {
|
||||
&"0.0.0.0".parse().unwrap(),
|
||||
)?;
|
||||
|
||||
socket.set_read_timeout(Some(Duration::from_secs(1)))?;
|
||||
socket.set_multicast_loop_v4(false)?;
|
||||
|
||||
let socket = Arc::new(socket);
|
||||
@@ -118,8 +117,11 @@ impl SsdpServer {
|
||||
|
||||
// Envoyer alive pour tous les NTs
|
||||
if let Some(ref socket) = self.socket {
|
||||
for nt in device.get_notification_types() {
|
||||
self.send_alive(socket, &device, nt);
|
||||
let nts = device.get_notification_types();
|
||||
for nt in nts.iter() {
|
||||
Self::send_alive(socket, &device, nt, false);
|
||||
// Petit délai pour éviter de saturer le buffer UDP sur macOS
|
||||
std::thread::sleep(Duration::from_millis(5));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -146,7 +148,7 @@ impl SsdpServer {
|
||||
}
|
||||
|
||||
/// Envoie un NOTIFY alive
|
||||
fn send_alive(&self, socket: &UdpSocket, device: &SsdpDevice, nt: &str) {
|
||||
fn send_alive(socket: &UdpSocket, device: &SsdpDevice, nt: &str, is_periodic: bool) {
|
||||
let usn = if nt.starts_with("uuid:") {
|
||||
format!("{}", nt)
|
||||
} else {
|
||||
@@ -172,13 +174,18 @@ impl SsdpServer {
|
||||
|
||||
match socket.send_to(msg.as_bytes(), addr) {
|
||||
Ok(_) => {
|
||||
info!("✅ NOTIFY alive: {} (NT={})", usn, nt);
|
||||
let label = if is_periodic { " (periodic)" } else { "" };
|
||||
info!("✅ NOTIFY alive{}: {} (NT={})", label, usn, nt);
|
||||
debug!(
|
||||
"📣 NOTIFY alive payload\n<details>\n\n```\n{}\n```\n</details>\n",
|
||||
msg
|
||||
"📣 NOTIFY alive{} payload\n<details>\n\n```\n{}\n```\n</details>\n",
|
||||
label, msg
|
||||
);
|
||||
}
|
||||
Err(e) => warn!("❌ Failed to send NOTIFY alive for {}: {}", usn, e),
|
||||
|
||||
Err(e) => {
|
||||
let label = if is_periodic { "periodic " } else { "" };
|
||||
warn!("❌ Failed to send {}NOTIFY alive for {}: {}", label, usn, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,53 +233,20 @@ impl SsdpServer {
|
||||
debug!("⏰ SSDP periodic announcement tick");
|
||||
std::thread::sleep(period);
|
||||
|
||||
let devices = devices.read().unwrap();
|
||||
for device in devices.values() {
|
||||
// Clone la liste des devices pour libérer le lock rapidement
|
||||
let devices_snapshot: Vec<SsdpDevice> = {
|
||||
let devices = devices.read().unwrap();
|
||||
devices.values().cloned().collect()
|
||||
};
|
||||
for device in &devices_snapshot {
|
||||
for nt in device.get_notification_types() {
|
||||
Self::send_alive_static(&socket, device, nt);
|
||||
Self::send_alive(&socket, device, nt, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Version statique de send_alive pour les threads
|
||||
fn send_alive_static(socket: &UdpSocket, device: &SsdpDevice, nt: &str) {
|
||||
let usn = if nt.starts_with("uuid:") {
|
||||
format!("{}", nt)
|
||||
} else {
|
||||
format!("uuid:{}::{}", device.uuid, nt)
|
||||
};
|
||||
|
||||
let msg = format!(
|
||||
"NOTIFY * HTTP/1.1\r\n\
|
||||
HOST: {}:{}\r\n\
|
||||
CACHE-CONTROL: max-age={}\r\n\
|
||||
LOCATION: {}\r\n\
|
||||
NT: {}\r\n\
|
||||
NTS: ssdp:alive\r\n\
|
||||
SERVER: {}\r\n\
|
||||
USN: {}\r\n\
|
||||
\r\n",
|
||||
SSDP_MULTICAST_ADDR, SSDP_PORT, MAX_AGE, device.location, nt, device.server, usn
|
||||
);
|
||||
|
||||
let addr: SocketAddr = format!("{}:{}", SSDP_MULTICAST_ADDR, SSDP_PORT)
|
||||
.parse()
|
||||
.unwrap();
|
||||
|
||||
match socket.send_to(msg.as_bytes(), addr) {
|
||||
Ok(_) => {
|
||||
info!("✅ NOTIFY alive (periodic): {} (NT={})", usn, nt);
|
||||
debug!(
|
||||
"📣 NOTIFY alive (periodic) payload\n<details>\n\n```\n{}\n```\n</details>\n",
|
||||
msg
|
||||
);
|
||||
}
|
||||
Err(e) => warn!("❌ Failed to send periodic NOTIFY alive for {}: {}", usn, e),
|
||||
}
|
||||
}
|
||||
|
||||
/// Démarre l'écoute des M-SEARCH
|
||||
fn start_msearch_listener(&self, socket: Arc<UdpSocket>) {
|
||||
let devices = Arc::clone(&self.devices);
|
||||
@@ -289,17 +263,17 @@ impl SsdpServer {
|
||||
src, data
|
||||
);
|
||||
if let Some(st) = Self::parse_st(&data) {
|
||||
let devices = devices.read().unwrap();
|
||||
for device in devices.values() {
|
||||
// Clone la liste des devices pour libérer le lock rapidement
|
||||
let devices_snapshot: Vec<SsdpDevice> = {
|
||||
let devices = devices.read().unwrap();
|
||||
devices.values().cloned().collect()
|
||||
};
|
||||
for device in &devices_snapshot {
|
||||
Self::handle_msearch(&socket, &src, &st, device);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) if e.kind() == std::io::ErrorKind::WouldBlock => {
|
||||
// Timeout, continuer
|
||||
continue;
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("❌ SSDP read error: {}", e);
|
||||
}
|
||||
|
||||
@@ -250,19 +250,26 @@ impl UpnpServerExt for Server {
|
||||
}
|
||||
|
||||
// Enregistrer les URLs dans le serveur web
|
||||
tracing::warn!("🔍 DEBUG: About to register_urls for device {}", di.udn());
|
||||
di.register_urls(self).await?;
|
||||
tracing::warn!("🔍 DEBUG: register_urls completed for device {}", di.udn());
|
||||
|
||||
// Ajouter au registre pour l'introspection
|
||||
tracing::warn!("🔍 DEBUG: Adding to DEVICE_REGISTRY...");
|
||||
DEVICE_REGISTRY
|
||||
.write()
|
||||
.unwrap()
|
||||
.register(di.clone())
|
||||
.map_err(|e| DeviceError::UrlRegistrationError(e))?;
|
||||
tracing::warn!("🔍 DEBUG: Added to DEVICE_REGISTRY");
|
||||
|
||||
// Annoncer via SSDP (si initialisé)
|
||||
tracing::warn!("🔍 DEBUG: Checking SSDP...");
|
||||
if self.ssdp_enabled() {
|
||||
tracing::warn!("🔍 DEBUG: SSDP enabled, getting lock...");
|
||||
let ssdp_opt = SSDP_SERVER.read().unwrap();
|
||||
if let Some(ref ssdp) = *ssdp_opt {
|
||||
tracing::warn!("🔍 DEBUG: SSDP server exists, announcing...");
|
||||
use crate::config_ext::UpnpConfigExt;
|
||||
let config = pmoconfig::get_config();
|
||||
let manufacturer = config
|
||||
@@ -271,8 +278,10 @@ impl UpnpServerExt for Server {
|
||||
let ssdp_device = di.to_ssdp_device(&manufacturer, "1.0");
|
||||
ssdp.add_device(ssdp_device);
|
||||
info!("✅ SSDP announcement for {}", di.udn());
|
||||
tracing::warn!("🔍 DEBUG: SSDP announcement complete");
|
||||
}
|
||||
}
|
||||
tracing::warn!("🔍 DEBUG: Returning device instance");
|
||||
|
||||
Ok(di)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user