ptp: use ip_mreq instead of ip_mreqn for macOS

To join a multicast the macOS still uses the interface address
from the ip_mreq instead of the ip_mreqn unlike other Linux systems.

So add a new conditional block for macOS to use ip_mreq for IP_ADD_MEMBERSHIP
and ip_mreqn for IP_MULTICAST_IF

This is similar to the fix in the glib for multicast join/leave
operation on macOS
https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4333

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7851>
This commit is contained in:
Taruntej Kanakamalla 2024-11-07 15:44:25 +05:30 committed by GStreamer Marge Bot
parent e57bd3b0dc
commit 36d8243397
2 changed files with 75 additions and 8 deletions

View file

@ -376,6 +376,15 @@ pub mod unix {
pub imr_ifindex: c_int,
}
// macOS uses ip_mreq instead of ip_mreqn in its latest version of the MAC Kernel for IP_ADD_MEMBERSHIP
#[cfg(target_os = "macos")]
#[repr(C)]
#[derive(Copy, Clone)]
pub struct ip_mreq {
pub imr_multiaddr: in_addr,
pub imr_address: in_addr,
}
#[cfg(any(target_os = "solaris", target_os = "illumos"))]
#[repr(C)]
pub struct ifaddrs {

View file

@ -376,7 +376,7 @@ mod imp {
addr: &Ipv4Addr,
iface: &InterfaceInfo,
) -> Result<(), Error> {
#[cfg(not(any(target_os = "solaris", target_os = "illumos")))]
#[cfg(not(any(target_os = "solaris", target_os = "illumos", target_os = "macos")))]
{
let mreqn = ip_mreqn {
imr_multiaddr: in_addr {
@ -408,12 +408,7 @@ mod imp {
}
}
#[cfg(not(any(
target_os = "openbsd",
target_os = "dragonfly",
target_os = "netbsd",
target_os = "macos"
)))]
#[cfg(not(any(target_os = "openbsd", target_os = "dragonfly", target_os = "netbsd")))]
{
let mreqn = ip_mreqn {
imr_multiaddr: in_addr {
@ -445,7 +440,7 @@ mod imp {
}
}
}
#[cfg(any(target_os = "openbsd", target_os = "dragonfly", target_os = "macos"))]
#[cfg(any(target_os = "openbsd", target_os = "dragonfly"))]
{
let addr = in_addr {
s_addr: u32::from_ne_bytes(iface.ip_addr.octets()),
@ -534,6 +529,69 @@ mod imp {
Ok(())
}
#[cfg(target_os = "macos")]
{
let mreq = ip_mreq {
imr_multiaddr: in_addr {
s_addr: u32::from_ne_bytes(addr.octets()),
},
imr_address: in_addr {
s_addr: u32::from_ne_bytes(iface.ip_addr.octets()),
},
};
let mreqn = ip_mreqn {
imr_multiaddr: in_addr {
s_addr: u32::from_ne_bytes(Ipv4Addr::UNSPECIFIED.octets()),
},
imr_address: in_addr {
s_addr: u32::from_ne_bytes(Ipv4Addr::UNSPECIFIED.octets()),
},
imr_ifindex: iface.index as _,
};
// SAFETY: Requires a valid ip_mreq struct to be passed together with its size for checking
// validity. On errors a negative integer is returned.
unsafe {
if setsockopt(
socket.as_raw_fd(),
IPPROTO_IP,
IP_ADD_MEMBERSHIP,
&mreq as *const _ as *const _,
mem::size_of_val(&mreq) as _,
) < 0
{
bail!(
source: io::Error::last_os_error(),
"Failed joining multicast group for interface {}",
iface.name,
);
}
}
// SAFETY: Requires a valid ip_mreqn struct to be passed together
// with its size for checking which of the two it is. On errors a negative
// integer is returned.
unsafe {
if setsockopt(
socket.as_raw_fd(),
IPPROTO_IP,
IP_MULTICAST_IF,
&mreqn as *const _ as *const _,
mem::size_of_val(&mreqn) as _,
) < 0
{
bail!(
source: io::Error::last_os_error(),
"Failed joining multicast group for interface {}",
iface.name,
);
}
}
Ok(())
}
}
/// Allow multiple sockets to bind to the same address / port.