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,7 +194,14 @@ impl IpAddrs { | |||||||
|         None |         None | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     pub(super) fn split_by_preference(self) -> (IpAddrs, IpAddrs) { |     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(); | ||||||
|  |  | ||||||
|  |             (IpAddrs::new(preferred), IpAddrs::new(vec![])) | ||||||
|  |         } else { | ||||||
|             let preferring_v6 = self.iter |             let preferring_v6 = self.iter | ||||||
|                 .as_slice() |                 .as_slice() | ||||||
|                 .first() |                 .first() | ||||||
| @@ -206,6 +213,7 @@ impl IpAddrs { | |||||||
|  |  | ||||||
|             (IpAddrs::new(preferred), IpAddrs::new(fallback)) |             (IpAddrs::new(preferred), IpAddrs::new(fallback)) | ||||||
|         } |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     pub(super) fn is_empty(&self) -> bool { |     pub(super) fn is_empty(&self) -> bool { | ||||||
|         self.iter.as_slice().is_empty() |         self.iter.as_slice().is_empty() | ||||||
| @@ -325,14 +333,24 @@ mod tests { | |||||||
|         let v6_addr = (Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 80).into(); |         let v6_addr = (Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 80).into(); | ||||||
|  |  | ||||||
|         let (mut preferred, mut fallback) = |         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!(preferred.next().unwrap().is_ipv4()); | ||||||
|         assert!(fallback.next().unwrap().is_ipv6()); |         assert!(fallback.next().unwrap().is_ipv6()); | ||||||
|  |  | ||||||
|         let (mut preferred, mut fallback) = |         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!(preferred.next().unwrap().is_ipv6()); | ||||||
|         assert!(fallback.next().unwrap().is_ipv4()); |         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] |     #[test] | ||||||
|   | |||||||
| @@ -501,7 +501,7 @@ impl ConnectingTcp { | |||||||
|         reuse_address: bool, |         reuse_address: bool, | ||||||
|     ) -> ConnectingTcp { |     ) -> ConnectingTcp { | ||||||
|         if let Some(fallback_timeout) = fallback_timeout { |         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() { |             if fallback_addrs.is_empty() { | ||||||
|                 return ConnectingTcp { |                 return ConnectingTcp { | ||||||
|                     local_addr, |                     local_addr, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user