diff --git a/Cargo.lock b/Cargo.lock index 9dabf278..963131ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3071,6 +3071,7 @@ name = "gst-plugin-threadshare" version = "0.14.0-alpha.1" dependencies = [ "async-task", + "bitflags 2.6.0", "cc", "cfg-if", "clap", diff --git a/generic/threadshare/Cargo.toml b/generic/threadshare/Cargo.toml index 9bff3dfe..f6beb487 100644 --- a/generic/threadshare/Cargo.toml +++ b/generic/threadshare/Cargo.toml @@ -26,9 +26,12 @@ rustix = { version = "0.38.2", default-features = false, features = ["std", "fs" slab = "0.4.7" socket2 = {features = ["all"], version = "0.5"} waker-fn = "1.1" -getifaddrs = "0.1" +bitflags = "2.6.0" libc = "0.2" windows-sys = "0.59.0" +[target.'cfg(not(target_os = "android"))'.dependencies] +getifaddrs = "0.1" + # Used by examples clap = { version = "4", features = ["derive"], optional = true } diff --git a/generic/threadshare/src/net.rs b/generic/threadshare/src/net.rs index 51028122..12274cfc 100644 --- a/generic/threadshare/src/net.rs +++ b/generic/threadshare/src/net.rs @@ -8,6 +8,60 @@ // // SPDX-License-Identifier: MPL-2.0 +//FIXME: Remove this when https://github.com/mmastrac/getifaddrs/issues/5 is fixed in the `getifaddrs` crate +#[cfg(target_os = "android")] +pub mod getifaddrs { + use bitflags::bitflags; + + bitflags! { + /// Flags representing the status and capabilities of a network interface. + /// + /// These flags provide information about the current state and features of a network interface. + #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub struct InterfaceFlags: u32 { + /// The interface is up and running. + const UP = 0x1; + /// The interface is in a running state. + const RUNNING = 0x2; + /// The interface supports broadcast. + const BROADCAST = 0x4; + /// The interface is a loopback interface. + const LOOPBACK = 0x8; + /// The interface is a point-to-point link. + const POINTTOPOINT = 0x10; + /// The interface supports multicast. + const MULTICAST = 0x20; + } + } + + /// Represents a network interface. + /// + /// This struct contains information about a network interface, including its name, + /// IP address, netmask, flags, and index. + #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub struct Interface { + /// The name of the interface. + pub name: String, + /// The description of the interface (Windows-specific). + #[cfg(windows)] + pub description: String, + /// The IP address associated with the interface. + pub address: std::net::IpAddr, + // TODO: This may be implementable for Windows. + #[cfg(not(windows))] + /// The associated address of the interface. For broadcast interfaces, this + /// is the broadcast address. For point-to-point interfaces, this is the + /// peer address. + pub associated_address: Option, + /// The netmask of the interface, if available. + pub netmask: Option, + /// The flags indicating the interface's properties and state. + pub flags: InterfaceFlags, + /// The index of the interface, if available. + pub index: Option, + } +} + use getifaddrs::Interface; #[cfg(unix)] diff --git a/generic/threadshare/src/udpsink/imp.rs b/generic/threadshare/src/udpsink/imp.rs index dae1a2c0..77ca26e2 100644 --- a/generic/threadshare/src/udpsink/imp.rs +++ b/generic/threadshare/src/udpsink/imp.rs @@ -39,6 +39,10 @@ use std::net::{IpAddr, SocketAddr, UdpSocket}; use std::sync::{Arc, Mutex}; use std::time::Duration; +//FIXME: Remove this when https://github.com/mmastrac/getifaddrs/issues/5 is fixed in the `getifaddrs` crate +#[cfg(target_os = "android")] +use net::getifaddrs; + const DEFAULT_HOST: Option<&str> = Some("127.0.0.1"); const DEFAULT_PORT: i32 = 5004; const DEFAULT_SYNC: bool = true; @@ -159,42 +163,46 @@ impl UdpSinkPadHandler { // So we first get all the interfaces and then apply filter // for name and description (Friendly Name) of each interface. - let ifaces = getifaddrs::getifaddrs().map_err(|err| { - gst::error_msg!( - gst::ResourceError::OpenRead, - ["Failed to find interface {}: {}", multicast_iface, err] - ) - })?; + //FIXME: Remove this when https://github.com/mmastrac/getifaddrs/issues/5 is fixed in the `getifaddrs` crate + #[cfg(not(target_os = "android"))] + { + let ifaces = getifaddrs::getifaddrs().map_err(|err| { + gst::error_msg!( + gst::ResourceError::OpenRead, + ["Failed to find interface {}: {}", multicast_iface, err] + ) + })?; - let iface_filter = ifaces.filter(|i| { - let ip_ver = if i.address.is_ipv4() { "IPv4" } else { "IPv6" }; + let iface_filter = ifaces.filter(|i| { + let ip_ver = if i.address.is_ipv4() { "IPv4" } else { "IPv6" }; - if &i.name == multicast_iface { - gst::debug!( - CAT, - imp = imp, - "Found interface: {}, version: {ip_ver}", - i.name, - ); - true - } else { - #[cfg(windows)] - if &i.description == multicast_iface { + if &i.name == multicast_iface { gst::debug!( CAT, imp = imp, "Found interface: {}, version: {ip_ver}", - i.description, + i.name, ); - return true; + true + } else { + #[cfg(windows)] + if &i.description == multicast_iface { + gst::debug!( + CAT, + imp = imp, + "Found interface: {}, version: {ip_ver}", + i.description, + ); + return true; + } + + gst::trace!(CAT, imp = imp, "skipping interface {}", i.name); + false } + }); - gst::trace!(CAT, imp = imp, "skipping interface {}", i.name); - false - } - }); - - inner.multicast_ifaces = iface_filter.collect(); + inner.multicast_ifaces = iface_filter.collect(); + } } for addr in inner.clients.iter() { diff --git a/generic/threadshare/src/udpsrc/imp.rs b/generic/threadshare/src/udpsrc/imp.rs index 14a71393..146c98a2 100644 --- a/generic/threadshare/src/udpsrc/imp.rs +++ b/generic/threadshare/src/udpsrc/imp.rs @@ -40,6 +40,10 @@ use crate::socket::{wrap_socket, GioSocketWrapper, Socket, SocketError, SocketRe use futures::channel::mpsc::{channel, Receiver, Sender}; use futures::pin_mut; +//FIXME: Remove this when https://github.com/mmastrac/getifaddrs/issues/5 is fixed in the `getifaddrs` crate +#[cfg(target_os = "android")] +use net::getifaddrs; + const DEFAULT_ADDRESS: Option<&str> = Some("0.0.0.0"); const DEFAULT_PORT: i32 = 5004; const DEFAULT_REUSE: bool = true; @@ -378,42 +382,46 @@ impl TaskImpl for UdpSrcTask { let multi_ifaces: Vec = multicast_iface.split(',').map(|s| s.to_string()).collect(); - let iter = getifaddrs::getifaddrs().map_err(|err| { - gst::error_msg!( - gst::ResourceError::OpenRead, - ["Failed to get interfaces: {}", err] - ) - })?; + //FIXME: Remove this when https://github.com/mmastrac/getifaddrs/issues/5 is fixed in the `getifaddrs` crate + #[cfg(not(target_os = "android"))] + { + let iter = getifaddrs::getifaddrs().map_err(|err| { + gst::error_msg!( + gst::ResourceError::OpenRead, + ["Failed to get interfaces: {}", err] + ) + })?; - iter.for_each(|iface| { - let ip_ver = if iface.address.is_ipv4() { - "IPv4" - } else { - "IPv6" - }; - - for m in &multi_ifaces { - if &iface.name == m { - self.multicast_ifaces.push(iface.clone()); - gst::debug!( - CAT, - obj = self.element, - "Interface {m} available, version: {ip_ver}" - ); + iter.for_each(|iface| { + let ip_ver = if iface.address.is_ipv4() { + "IPv4" } else { - // check if name matches the interface description (Friendly name) on Windows - #[cfg(windows)] - if &iface.description == m { + "IPv6" + }; + + for m in &multi_ifaces { + if &iface.name == m { self.multicast_ifaces.push(iface.clone()); gst::debug!( CAT, obj = self.element, "Interface {m} available, version: {ip_ver}" ); + } else { + // check if name matches the interface description (Friendly name) on Windows + #[cfg(windows)] + if &iface.description == m { + self.multicast_ifaces.push(iface.clone()); + gst::debug!( + CAT, + obj = self.element, + "Interface {m} available, version: {ip_ver}" + ); + } } } - } - }); + }); + } } if self.multicast_ifaces.is_empty() {