corrige un bug de détection des servers online #38

Merged
eric merged 1 commits from push-vnqkompntkws into main 2026-01-04 09:13:12 +01:00
3 changed files with 60 additions and 15 deletions

View File

@@ -12,7 +12,8 @@ pub struct UpnpDiscoveryManager {
}
impl UpnpDiscoveryManager {
pub fn new(device_registry: Arc<RwLock<DeviceRegistry>>,
pub fn new(
device_registry: Arc<RwLock<DeviceRegistry>>,
udn_cache: Arc<Mutex<UDNRegistry>>,
) -> Self {
Self {
@@ -42,10 +43,15 @@ impl UpnpDiscoveryManager {
if let Some(udn) = extract_udn_from_usn(&usn) {
if alive {
// Check cache
if UDNRegistry::should_fetch(self.udn_cache.clone(), &udn, max_age as u64) {
// ✅ Fetch + parse
if let Ok(info) = ParsedDeviceDescription::new(&udn, &location, &server_header,5) {
// Check if we should fetch the full device description
let should_fetch =
UDNRegistry::should_fetch(self.udn_cache.clone(), &udn, max_age as u64);
if should_fetch {
// Fetch + parse the device description
if let Ok(info) =
ParsedDeviceDescription::new(&udn, &location, &server_header, 5)
{
if let Some(renderer_info) = info.build_renderer() {
if let Ok(mut reg) = self.device_registry.write() {
reg.push_renderer(&renderer_info, max_age);
@@ -56,6 +62,13 @@ impl UpnpDiscoveryManager {
}
}
}
} else {
// Even if we don't fetch, we MUST update last_seen to prevent timeout
// This is critical: SSDP Alive messages arrive more frequently than max_age/2,
// and we need to acknowledge them to keep the device online
if let Ok(mut reg) = self.device_registry.write() {
reg.refresh_device_presence(&udn, max_age);
}
}
} else {
if let Ok(mut reg) = self.device_registry.write() {
@@ -64,11 +77,8 @@ impl UpnpDiscoveryManager {
}
}
}
}
fn extract_udn_from_usn(usn: &str) -> Option<String> {
let lower = usn.trim().to_ascii_lowercase();
if let Some(idx) = lower.find("uuid:") {

View File

@@ -130,46 +130,46 @@ impl MusicRenderer {
}
/// Returns the protocol.
fn protocol(&self) -> RendererProtocol {
pub fn protocol(&self) -> RendererProtocol {
self.info.protocol()
}
fn is_upnp(&self) -> bool {
pub fn is_upnp(&self) -> bool {
match &*self.backend.lock().expect("Backend mutex poisoned") {
MusicRendererBackend::Upnp(_) => true,
_ => false,
}
}
fn is_openhome(&self) -> bool {
pub fn is_openhome(&self) -> bool {
match &*self.backend.lock().expect("Backend mutex poisoned") {
MusicRendererBackend::OpenHome(_) => true,
_ => false,
}
}
fn is_linkplay(&self) -> bool {
pub fn is_linkplay(&self) -> bool {
match &*self.backend.lock().expect("Backend mutex poisoned") {
MusicRendererBackend::LinkPlay(_) => true,
_ => false,
}
}
fn is_arylictcp(&self) -> bool {
pub fn is_arylictcp(&self) -> bool {
match &*self.backend.lock().expect("Backend mutex poisoned") {
MusicRendererBackend::ArylicTcp(_) => true,
_ => false,
}
}
fn is_chromecast(&self) -> bool {
pub fn is_chromecast(&self) -> bool {
match &*self.backend.lock().expect("Backend mutex poisoned") {
MusicRendererBackend::Chromecast(_) => true,
_ => false,
}
}
fn is_hybridupnparylic(&self) -> bool {
pub fn is_hybridupnparylic(&self) -> bool {
match &*self.backend.lock().expect("Backend mutex poisoned") {
MusicRendererBackend::HybridUpnpArylic { .. } => true,
_ => false,

View File

@@ -257,6 +257,41 @@ impl DeviceRegistry {
}
}
/// Updates the last_seen timestamp for a device without fetching its full description.
///
/// This is critical for keeping devices online when SSDP Alive messages arrive
/// more frequently than the UDN cache refresh interval (max_age/2).
pub fn refresh_device_presence(&mut self, udn: &str, max_age: u32) {
let lookup = udn.to_ascii_lowercase();
if let Some(id) = self.udn_index.get(&lookup) {
if let Some(device) = self.devices.get(id) {
let was_online = device.is_online();
device.has_been_seen_now(max_age);
// If device was offline and came back online, broadcast Online event
if !was_online {
if device.is_a_music_renderer() {
if let Ok(renderer) = device.as_music_renderer() {
self.renderer_bus.broadcast(RendererEvent::Online {
id: id.clone(),
info: renderer.info().basic_info(),
});
}
}
if device.is_a_music_server() {
if let Ok(server) = device.as_music_server() {
self.server_bus.broadcast(MediaServerEvent::Online {
server_id: id.clone(),
info: server.basic_info(),
});
}
}
}
}
}
}
pub fn device_says_byebye(&mut self, udn: &str) {
let lookup = udn.to_ascii_lowercase();