feat(client): filter remote IP addresses by family of given local IP address
It is not possible to connect to an IPv4 address from an IPv6 address or vice-versa so don't waste time trying. If no remote addresses match then a "missing connect error" will now occur.
This commit is contained in:
		
				
					committed by
					
						 Sean McArthur
						Sean McArthur
					
				
			
			
				
	
			
			
			
						parent
						
							71d088d3d0
						
					
				
				
					commit
					131962c86a
				
			| @@ -194,17 +194,25 @@ impl IpAddrs { | ||||
|         None | ||||
|     } | ||||
|  | ||||
|     pub(super) fn split_by_preference(self) -> (IpAddrs, IpAddrs) { | ||||
|         let preferring_v6 = self.iter | ||||
|             .as_slice() | ||||
|             .first() | ||||
|             .map(SocketAddr::is_ipv6) | ||||
|             .unwrap_or(false); | ||||
|     pub(super) fn split_by_preference(self, local_addr: Option<IpAddr>) -> (IpAddrs, IpAddrs) { | ||||
|         if let Some(local_addr) = local_addr { | ||||
|             let preferred = self.iter | ||||
|                 .filter(|addr| addr.is_ipv6() == local_addr.is_ipv6()) | ||||
|                 .collect(); | ||||
|  | ||||
|         let (preferred, fallback) = self.iter | ||||
|             .partition::<Vec<_>, _>(|addr| addr.is_ipv6() == preferring_v6); | ||||
|             (IpAddrs::new(preferred), IpAddrs::new(vec![])) | ||||
|         } else { | ||||
|             let preferring_v6 = self.iter | ||||
|                 .as_slice() | ||||
|                 .first() | ||||
|                 .map(SocketAddr::is_ipv6) | ||||
|                 .unwrap_or(false); | ||||
|  | ||||
|         (IpAddrs::new(preferred), IpAddrs::new(fallback)) | ||||
|             let (preferred, fallback) = self.iter | ||||
|                 .partition::<Vec<_>, _>(|addr| addr.is_ipv6() == preferring_v6); | ||||
|  | ||||
|             (IpAddrs::new(preferred), IpAddrs::new(fallback)) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub(super) fn is_empty(&self) -> bool { | ||||
| @@ -325,14 +333,24 @@ mod tests { | ||||
|         let v6_addr = (Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 80).into(); | ||||
|  | ||||
|         let (mut preferred, mut fallback) = | ||||
|             IpAddrs { iter: vec![v4_addr, v6_addr].into_iter() }.split_by_preference(); | ||||
|             IpAddrs { iter: vec![v4_addr, v6_addr].into_iter() }.split_by_preference(None); | ||||
|         assert!(preferred.next().unwrap().is_ipv4()); | ||||
|         assert!(fallback.next().unwrap().is_ipv6()); | ||||
|  | ||||
|         let (mut preferred, mut fallback) = | ||||
|             IpAddrs { iter: vec![v6_addr, v4_addr].into_iter() }.split_by_preference(); | ||||
|             IpAddrs { iter: vec![v6_addr, v4_addr].into_iter() }.split_by_preference(None); | ||||
|         assert!(preferred.next().unwrap().is_ipv6()); | ||||
|         assert!(fallback.next().unwrap().is_ipv4()); | ||||
|  | ||||
|         let (mut preferred, fallback) = | ||||
|             IpAddrs { iter: vec![v4_addr, v6_addr].into_iter() }.split_by_preference(Some(v4_addr.ip())); | ||||
|         assert!(preferred.next().unwrap().is_ipv4()); | ||||
|         assert!(fallback.is_empty()); | ||||
|  | ||||
|         let (mut preferred, fallback) = | ||||
|             IpAddrs { iter: vec![v4_addr, v6_addr].into_iter() }.split_by_preference(Some(v6_addr.ip())); | ||||
|         assert!(preferred.next().unwrap().is_ipv6()); | ||||
|         assert!(fallback.is_empty()); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|   | ||||
| @@ -501,7 +501,7 @@ impl ConnectingTcp { | ||||
|         reuse_address: bool, | ||||
|     ) -> ConnectingTcp { | ||||
|         if let Some(fallback_timeout) = fallback_timeout { | ||||
|             let (preferred_addrs, fallback_addrs) = remote_addrs.split_by_preference(); | ||||
|             let (preferred_addrs, fallback_addrs) = remote_addrs.split_by_preference(local_addr); | ||||
|             if fallback_addrs.is_empty() { | ||||
|                 return ConnectingTcp { | ||||
|                     local_addr, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user