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
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