Fix SSDP multicast on macOS Sequoia+
Corrige les problèmes de multicast SSDP sur macOS Sequoia+ en ajustant les interfaces multicast et en utilisant Terminal.app pour l'exécution des binaires en debug et release. - Dans le Makefile : modifie les cibles 'run' et 'run-release' pour lancer l'application via Terminal.app, nécessaire pour le multicast sur macOS Sequoia+ - Dans pmoupnp/src/ssdp/client.rs : améliore la gestion des interfaces multicast en rejoignant le groupe sur toutes les interfaces non loopback et en configurant explicitement l'interface de sortie - Dans pmoupnp/src/ssdp/server.rs : corrige la configuration multicast du serveur en maintenant l'interface de sortie correcte et en désactivant le multicast loopback
This commit is contained in:
@@ -75,27 +75,42 @@ impl SsdpClient {
|
||||
let bind_addr: SocketAddr = "0.0.0.0:0".parse().unwrap();
|
||||
socket2.bind(&bind_addr.into())?;
|
||||
|
||||
// Le client SSDP n'a pas besoin de join_multicast_v4 :
|
||||
// il envoie des M-SEARCH et reçoit des réponses unicast.
|
||||
// Le join est seulement utile pour recevoir les NOTIFY multicast,
|
||||
// ce dont le SsdpServer s'occupe.
|
||||
//
|
||||
// On configure uniquement l'interface de sortie multicast sur
|
||||
// l'IP principale pour que send_to vers 239.255.255.250 fonctionne.
|
||||
// Sur macOS, join_multicast_v4 sur des interfaces bridge/VM écrase
|
||||
// IP_MULTICAST_IF et provoque EHOSTUNREACH (errno 65).
|
||||
let socket: UdpSocket = socket2.into();
|
||||
socket.set_read_timeout(Some(Duration::from_secs(1)))?;
|
||||
socket.set_multicast_loop_v4(true)?; // utile en dev local
|
||||
|
||||
let multicast_addr = SSDP_MULTICAST_ADDR.parse().unwrap();
|
||||
for iface in get_if_addrs::get_if_addrs()? {
|
||||
if let std::net::IpAddr::V4(ipv4) = iface.ip() {
|
||||
if !ipv4.is_loopback() {
|
||||
match socket.join_multicast_v4(&multicast_addr, &ipv4) {
|
||||
Ok(()) => {
|
||||
debug!("SSDP: joined {} on {}", SSDP_MULTICAST_ADDR, ipv4);
|
||||
}
|
||||
Err(e) => {
|
||||
warn!(
|
||||
"SSDP: failed to join {} on {}: {}",
|
||||
SSDP_MULTICAST_ADDR, ipv4, e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sur macOS, chaque join_multicast_v4 écrase IP_MULTICAST_IF.
|
||||
// On remet explicitement l'interface de sortie sur l'IP principale
|
||||
// pour que send_to vers 239.255.255.250 utilise la bonne interface.
|
||||
let local_ip: std::net::Ipv4Addr = pmoutils::guess_local_ip()
|
||||
.parse()
|
||||
.unwrap_or("127.0.0.1".parse().unwrap());
|
||||
.unwrap_or("0.0.0.0".parse().unwrap());
|
||||
let socket2 = Socket::from(socket);
|
||||
socket2.set_multicast_if_v4(&local_ip)?;
|
||||
debug!(
|
||||
"SSDP client: multicast outgoing interface set to {}",
|
||||
local_ip
|
||||
);
|
||||
|
||||
let socket: UdpSocket = socket2.into();
|
||||
socket.set_read_timeout(Some(Duration::from_secs(1)))?;
|
||||
socket.set_multicast_loop_v4(true)?; // utile en dev local
|
||||
|
||||
info!("✅ SSDP client ready on {}", addr);
|
||||
|
||||
|
||||
@@ -74,30 +74,33 @@ impl SsdpServer {
|
||||
let bind_addr: SocketAddr = format!("0.0.0.0:{}", SSDP_PORT).parse().unwrap();
|
||||
socket2.bind(&bind_addr.into())?;
|
||||
|
||||
// Configurer l'interface de sortie multicast sur l'IP principale.
|
||||
// Sur macOS, sans cela le kernel peut router les paquets multicast
|
||||
// via une interface bridge/VM qui n'a pas de route, causant
|
||||
// EHOSTUNREACH (errno 65).
|
||||
let local_ip: std::net::Ipv4Addr = pmoutils::guess_local_ip()
|
||||
.parse()
|
||||
.unwrap_or("127.0.0.1".parse().unwrap());
|
||||
socket2.set_multicast_if_v4(&local_ip)?;
|
||||
debug!(
|
||||
"SSDP server: multicast outgoing interface set to {}",
|
||||
local_ip
|
||||
);
|
||||
|
||||
// Convertir en UdpSocket standard
|
||||
let socket: UdpSocket = socket2.into();
|
||||
let mut socket: UdpSocket = socket2.into();
|
||||
|
||||
// Rejoindre le groupe multicast via INADDR_ANY (l'OS choisit l'interface)
|
||||
// Rejoindre le groupe multicast
|
||||
socket.join_multicast_v4(
|
||||
&SSDP_MULTICAST_ADDR.parse().unwrap(),
|
||||
&"0.0.0.0".parse().unwrap(),
|
||||
)?;
|
||||
|
||||
// Sur macOS, join_multicast_v4 peut positionner IP_MULTICAST_IF
|
||||
// sur une interface bridge/VM. On remet explicitement l'interface
|
||||
// de sortie sur l'IP principale.
|
||||
let local_ip: std::net::Ipv4Addr = pmoutils::guess_local_ip()
|
||||
.parse()
|
||||
.unwrap_or("0.0.0.0".parse().unwrap());
|
||||
{
|
||||
let socket2 = Socket::from(socket);
|
||||
socket2.set_multicast_if_v4(&local_ip)?;
|
||||
debug!(
|
||||
"SSDP server: multicast outgoing interface set to {}",
|
||||
local_ip
|
||||
);
|
||||
socket = socket2.into();
|
||||
}
|
||||
|
||||
socket.set_read_timeout(Some(Duration::from_secs(1)))?;
|
||||
socket.set_multicast_loop_v4(true)?; // utile en dev local
|
||||
socket.set_multicast_loop_v4(false)?;
|
||||
|
||||
let socket = Arc::new(socket);
|
||||
self.socket = Some(socket.clone());
|
||||
|
||||
Reference in New Issue
Block a user