diff --git a/examples/mdns.rs b/examples/mdns.rs index cf40c4c..16b0436 100644 --- a/examples/mdns.rs +++ b/examples/mdns.rs @@ -7,11 +7,13 @@ fn main() { // Validate that building with options works with the public API let with_options = MulticastSocket::with_options( mdns_multicast_address, - multicast_socket::all_ipv4_interfaces().unwrap(), + multicast_socket::all_ipv4_interfaces() + .expect("could not fetch all interfaces for options"), multicast_socket::MulticastOptions { ..Default::default() }, - ); + ) + .expect("validate that we are starting with options"); drop(with_options); let socket = MulticastSocket::all_interfaces(mdns_multicast_address) diff --git a/src/unix.rs b/src/unix.rs index e9923de..f83eaaf 100644 --- a/src/unix.rs +++ b/src/unix.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use std::io; use std::mem; use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; @@ -102,13 +103,20 @@ pub fn all_ipv4_interfaces() -> io::Result> { .into_iter() .map(reverse_interface); - let ipv4_interfaces = interfaces - .filter_map(|i| match i.ip() { - std::net::IpAddr::V4(v4) if !i.is_loopback() => Some(v4), - _ => None, - }) - .collect(); - Ok(ipv4_interfaces) + // We have to filter the same interface if it has multiple ips + // https://stackoverflow.com/questions/49819010/ip-add-membership-fails-when-set-both-on-interface-and-its-subinterface-is-that + let mut collected_interfaces = HashMap::with_capacity(interfaces.len()); + for interface in interfaces { + if !collected_interfaces.contains_key(&interface.name) { + match interface.ip() { + std::net::IpAddr::V4(v4) if !interface.is_loopback() => { + collected_interfaces.insert(interface.name, v4); + } + _ => {} + } + } + } + Ok(collected_interfaces.into_iter().map(|(_, ip)| ip).collect()) } impl MulticastSocket { diff --git a/src/win.rs b/src/win.rs index a838b40..f85fb4c 100644 --- a/src/win.rs +++ b/src/win.rs @@ -171,13 +171,18 @@ fn create_on_interfaces( }) } -/// Defines a allocation size for the buffer -/// That seems like a pretty good number for most cases -/// If things break, we can allocate the buffer a vec and try to double on error -const MAX_AMOUNT_OF_INTERFACES: usize = 16; +/// The amount of ip's per interface we can support +/// This was an increase when I suddenly got 60 different IPs registered on my computer +/// Let's hope we can keep it like that (or increase it even further) +const PER_INTERFACE_IP_SUPPORT: usize = 5; fn build_address_table(interfaces: HashSet) -> io::Result> { - let mut buffer = [0; mem::size_of::() * MAX_AMOUNT_OF_INTERFACES]; + let mut buffer = vec![ + 0; + mem::size_of::() + * interfaces.len() + * PER_INTERFACE_IP_SUPPORT + ]; let mut adapter_info = buffer.as_mut_ptr() as iptypes::PIP_ADAPTER_INFO; let mut size = buffer.len() as u32; let r = unsafe { winapi::um::iphlpapi::GetAdaptersInfo(adapter_info, &mut size) };