Skip to content

Commit 10408ea

Browse files
committed
feat(client): allow both IPv6 and IPv4 local addresses
Closes: #2169 BREAKING CHANGE: `HttpConnector::set_local_address(&mut self, addr: Option<IpAddr>)` signature has been changed to `HttpConnector::set_local_address(&mut self, addr_ipv4: Option<Ipv4Addr>, addr_ipv6: Option<Ipv6Addr>)`
1 parent f329ae0 commit 10408ea

File tree

3 files changed

+190
-58
lines changed

3 files changed

+190
-58
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ net2 = { version = "0.2.32", optional = true }
4444
futures-util = { version = "0.3", default-features = false, features = ["alloc"] }
4545
matches = "0.1"
4646
num_cpus = "1.0"
47+
pnet = "0.25.0"
4748
pretty_env_logger = "0.4"
4849
spmc = "0.3"
4950
serde = "1.0"

src/client/connect/dns.rs

Lines changed: 49 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -194,27 +194,33 @@ impl IpAddrs {
194194
None
195195
}
196196

197-
pub(super) fn split_by_preference(self, local_addr: Option<IpAddr>) -> (IpAddrs, IpAddrs) {
198-
if let Some(local_addr) = local_addr {
199-
let preferred = self
200-
.iter
201-
.filter(|addr| addr.is_ipv6() == local_addr.is_ipv6())
202-
.collect();
203-
204-
(IpAddrs::new(preferred), IpAddrs::new(vec![]))
205-
} else {
206-
let preferring_v6 = self
207-
.iter
208-
.as_slice()
209-
.first()
210-
.map(SocketAddr::is_ipv6)
211-
.unwrap_or(false);
212-
213-
let (preferred, fallback) = self
214-
.iter
215-
.partition::<Vec<_>, _>(|addr| addr.is_ipv6() == preferring_v6);
216-
217-
(IpAddrs::new(preferred), IpAddrs::new(fallback))
197+
#[inline]
198+
fn filter(self, predicate: impl FnMut(&SocketAddr) -> bool) -> IpAddrs {
199+
IpAddrs::new(self.iter.filter(predicate).collect())
200+
}
201+
202+
pub(super) fn split_by_preference(
203+
self,
204+
local_addr_ipv4: Option<Ipv4Addr>,
205+
local_addr_ipv6: Option<Ipv6Addr>,
206+
) -> (IpAddrs, IpAddrs) {
207+
match (local_addr_ipv4, local_addr_ipv6) {
208+
(Some(_), None) => (self.filter(SocketAddr::is_ipv4), IpAddrs::new(vec![])),
209+
(None, Some(_)) => (self.filter(SocketAddr::is_ipv6), IpAddrs::new(vec![])),
210+
_ => {
211+
let preferring_v6 = self
212+
.iter
213+
.as_slice()
214+
.first()
215+
.map(SocketAddr::is_ipv6)
216+
.unwrap_or(false);
217+
218+
let (preferred, fallback) = self
219+
.iter
220+
.partition::<Vec<_>, _>(|addr| addr.is_ipv6() == preferring_v6);
221+
222+
(IpAddrs::new(preferred), IpAddrs::new(fallback))
223+
}
218224
}
219225
}
220226

@@ -349,34 +355,50 @@ mod tests {
349355

350356
#[test]
351357
fn test_ip_addrs_split_by_preference() {
352-
let v4_addr = (Ipv4Addr::new(127, 0, 0, 1), 80).into();
353-
let v6_addr = (Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 80).into();
358+
let ip_v4 = Ipv4Addr::new(127, 0, 0, 1);
359+
let ip_v6 = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
360+
let v4_addr = (ip_v4, 80).into();
361+
let v6_addr = (ip_v6, 80).into();
362+
363+
let (mut preferred, mut fallback) = IpAddrs {
364+
iter: vec![v4_addr, v6_addr].into_iter(),
365+
}
366+
.split_by_preference(None, None);
367+
assert!(preferred.next().unwrap().is_ipv4());
368+
assert!(fallback.next().unwrap().is_ipv6());
369+
370+
let (mut preferred, mut fallback) = IpAddrs {
371+
iter: vec![v6_addr, v4_addr].into_iter(),
372+
}
373+
.split_by_preference(None, None);
374+
assert!(preferred.next().unwrap().is_ipv6());
375+
assert!(fallback.next().unwrap().is_ipv4());
354376

355377
let (mut preferred, mut fallback) = IpAddrs {
356378
iter: vec![v4_addr, v6_addr].into_iter(),
357379
}
358-
.split_by_preference(None);
380+
.split_by_preference(Some(ip_v4), Some(ip_v6));
359381
assert!(preferred.next().unwrap().is_ipv4());
360382
assert!(fallback.next().unwrap().is_ipv6());
361383

362384
let (mut preferred, mut fallback) = IpAddrs {
363385
iter: vec![v6_addr, v4_addr].into_iter(),
364386
}
365-
.split_by_preference(None);
387+
.split_by_preference(Some(ip_v4), Some(ip_v6));
366388
assert!(preferred.next().unwrap().is_ipv6());
367389
assert!(fallback.next().unwrap().is_ipv4());
368390

369391
let (mut preferred, fallback) = IpAddrs {
370392
iter: vec![v4_addr, v6_addr].into_iter(),
371393
}
372-
.split_by_preference(Some(v4_addr.ip()));
394+
.split_by_preference(Some(ip_v4), None);
373395
assert!(preferred.next().unwrap().is_ipv4());
374396
assert!(fallback.is_empty());
375397

376398
let (mut preferred, fallback) = IpAddrs {
377399
iter: vec![v4_addr, v6_addr].into_iter(),
378400
}
379-
.split_by_preference(Some(v6_addr.ip()));
401+
.split_by_preference(None, Some(ip_v6));
380402
assert!(preferred.next().unwrap().is_ipv6());
381403
assert!(fallback.is_empty());
382404
}

0 commit comments

Comments
 (0)