Skip to content

Commit 1dd56ca

Browse files
committed
feat(client): change DNS Resolver to resolve to SocketAddrs
The DNS resolver part of `HttpConnector` used to require resolving to `IpAddr`s, and this changes it so that they resolve to `SocketAddr`s. The main benefit here is allowing for resolvers to set the IPv6 zone ID when resolving, but it also just more closely matches `std::net::ToSocketAddrs`. Closes #1937 BREAKING CHANGE: Custom resolvers used with `HttpConnector` must change to resolving to an iterator of `SocketAddr`s instead of `IpAddr`s.
1 parent a470446 commit 1dd56ca

File tree

2 files changed

+42
-39
lines changed

2 files changed

+42
-39
lines changed

src/client/connect/dns.rs

+32-32
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,21 @@
99
//! # Resolvers are `Service`s
1010
//!
1111
//! A resolver is just a
12-
//! `Service<Name, Response = impl Iterator<Item = IpAddr>>`.
12+
//! `Service<Name, Response = impl Iterator<Item = SocketAddr>>`.
1313
//!
1414
//! A simple resolver that ignores the name and always returns a specific
1515
//! address:
1616
//!
1717
//! ```rust,ignore
18-
//! use std::{convert::Infallible, iter, net::IpAddr};
18+
//! use std::{convert::Infallible, iter, net::SocketAddr};
1919
//!
2020
//! let resolver = tower::service_fn(|_name| async {
21-
//! Ok::<_, Infallible>(iter::once(IpAddr::from([127, 0, 0, 1])))
21+
//! Ok::<_, Infallible>(iter::once(SocketAddr::from(([127, 0, 0, 1], 8080))))
2222
//! });
2323
//! ```
2424
use std::error::Error;
2525
use std::future::Future;
26-
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
26+
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
2727
use std::pin::Pin;
2828
use std::str::FromStr;
2929
use std::task::{self, Poll};
@@ -48,12 +48,12 @@ pub struct GaiResolver {
4848

4949
/// An iterator of IP addresses returned from `getaddrinfo`.
5050
pub struct GaiAddrs {
51-
inner: IpAddrs,
51+
inner: SocketAddrs,
5252
}
5353

5454
/// A future to resolve a name returned by `GaiResolver`.
5555
pub struct GaiFuture {
56-
inner: JoinHandle<Result<IpAddrs, io::Error>>,
56+
inner: JoinHandle<Result<SocketAddrs, io::Error>>,
5757
}
5858

5959
impl Name {
@@ -121,7 +121,7 @@ impl Service<Name> for GaiResolver {
121121
debug!("resolving host={:?}", name.host);
122122
(&*name.host, 0)
123123
.to_socket_addrs()
124-
.map(|i| IpAddrs { iter: i })
124+
.map(|i| SocketAddrs { iter: i })
125125
});
126126

127127
GaiFuture { inner: blocking }
@@ -159,10 +159,10 @@ impl fmt::Debug for GaiFuture {
159159
}
160160

161161
impl Iterator for GaiAddrs {
162-
type Item = IpAddr;
162+
type Item = SocketAddr;
163163

164164
fn next(&mut self) -> Option<Self::Item> {
165-
self.inner.next().map(|sa| sa.ip())
165+
self.inner.next()
166166
}
167167
}
168168

@@ -172,47 +172,47 @@ impl fmt::Debug for GaiAddrs {
172172
}
173173
}
174174

175-
pub(super) struct IpAddrs {
175+
pub(super) struct SocketAddrs {
176176
iter: vec::IntoIter<SocketAddr>,
177177
}
178178

179-
impl IpAddrs {
179+
impl SocketAddrs {
180180
pub(super) fn new(addrs: Vec<SocketAddr>) -> Self {
181-
IpAddrs {
181+
SocketAddrs {
182182
iter: addrs.into_iter(),
183183
}
184184
}
185185

186-
pub(super) fn try_parse(host: &str, port: u16) -> Option<IpAddrs> {
186+
pub(super) fn try_parse(host: &str, port: u16) -> Option<SocketAddrs> {
187187
if let Ok(addr) = host.parse::<Ipv4Addr>() {
188188
let addr = SocketAddrV4::new(addr, port);
189-
return Some(IpAddrs {
189+
return Some(SocketAddrs {
190190
iter: vec![SocketAddr::V4(addr)].into_iter(),
191191
});
192192
}
193193
let host = host.trim_start_matches('[').trim_end_matches(']');
194194
if let Ok(addr) = host.parse::<Ipv6Addr>() {
195195
let addr = SocketAddrV6::new(addr, port, 0, 0);
196-
return Some(IpAddrs {
196+
return Some(SocketAddrs {
197197
iter: vec![SocketAddr::V6(addr)].into_iter(),
198198
});
199199
}
200200
None
201201
}
202202

203203
#[inline]
204-
fn filter(self, predicate: impl FnMut(&SocketAddr) -> bool) -> IpAddrs {
205-
IpAddrs::new(self.iter.filter(predicate).collect())
204+
fn filter(self, predicate: impl FnMut(&SocketAddr) -> bool) -> SocketAddrs {
205+
SocketAddrs::new(self.iter.filter(predicate).collect())
206206
}
207207

208208
pub(super) fn split_by_preference(
209209
self,
210210
local_addr_ipv4: Option<Ipv4Addr>,
211211
local_addr_ipv6: Option<Ipv6Addr>,
212-
) -> (IpAddrs, IpAddrs) {
212+
) -> (SocketAddrs, SocketAddrs) {
213213
match (local_addr_ipv4, local_addr_ipv6) {
214-
(Some(_), None) => (self.filter(SocketAddr::is_ipv4), IpAddrs::new(vec![])),
215-
(None, Some(_)) => (self.filter(SocketAddr::is_ipv6), IpAddrs::new(vec![])),
214+
(Some(_), None) => (self.filter(SocketAddr::is_ipv4), SocketAddrs::new(vec![])),
215+
(None, Some(_)) => (self.filter(SocketAddr::is_ipv6), SocketAddrs::new(vec![])),
216216
_ => {
217217
let preferring_v6 = self
218218
.iter
@@ -225,7 +225,7 @@ impl IpAddrs {
225225
.iter
226226
.partition::<Vec<_>, _>(|addr| addr.is_ipv6() == preferring_v6);
227227

228-
(IpAddrs::new(preferred), IpAddrs::new(fallback))
228+
(SocketAddrs::new(preferred), SocketAddrs::new(fallback))
229229
}
230230
}
231231
}
@@ -239,7 +239,7 @@ impl IpAddrs {
239239
}
240240
}
241241

242-
impl Iterator for IpAddrs {
242+
impl Iterator for SocketAddrs {
243243
type Item = SocketAddr;
244244
#[inline]
245245
fn next(&mut self) -> Option<SocketAddr> {
@@ -312,13 +312,13 @@ impl Future for TokioThreadpoolGaiFuture {
312312
*/
313313

314314
mod sealed {
315-
use super::{IpAddr, Name};
315+
use super::{SocketAddr, Name};
316316
use crate::common::{task, Future, Poll};
317317
use tower_service::Service;
318318

319319
// "Trait alias" for `Service<Name, Response = Addrs>`
320320
pub trait Resolve {
321-
type Addrs: Iterator<Item = IpAddr>;
321+
type Addrs: Iterator<Item = SocketAddr>;
322322
type Error: Into<Box<dyn std::error::Error + Send + Sync>>;
323323
type Future: Future<Output = Result<Self::Addrs, Self::Error>>;
324324

@@ -329,7 +329,7 @@ mod sealed {
329329
impl<S> Resolve for S
330330
where
331331
S: Service<Name>,
332-
S::Response: Iterator<Item = IpAddr>,
332+
S::Response: Iterator<Item = SocketAddr>,
333333
S::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
334334
{
335335
type Addrs = S::Response;
@@ -366,42 +366,42 @@ mod tests {
366366
let v4_addr = (ip_v4, 80).into();
367367
let v6_addr = (ip_v6, 80).into();
368368

369-
let (mut preferred, mut fallback) = IpAddrs {
369+
let (mut preferred, mut fallback) = SocketAddrs {
370370
iter: vec![v4_addr, v6_addr].into_iter(),
371371
}
372372
.split_by_preference(None, None);
373373
assert!(preferred.next().unwrap().is_ipv4());
374374
assert!(fallback.next().unwrap().is_ipv6());
375375

376-
let (mut preferred, mut fallback) = IpAddrs {
376+
let (mut preferred, mut fallback) = SocketAddrs {
377377
iter: vec![v6_addr, v4_addr].into_iter(),
378378
}
379379
.split_by_preference(None, None);
380380
assert!(preferred.next().unwrap().is_ipv6());
381381
assert!(fallback.next().unwrap().is_ipv4());
382382

383-
let (mut preferred, mut fallback) = IpAddrs {
383+
let (mut preferred, mut fallback) = SocketAddrs {
384384
iter: vec![v4_addr, v6_addr].into_iter(),
385385
}
386386
.split_by_preference(Some(ip_v4), Some(ip_v6));
387387
assert!(preferred.next().unwrap().is_ipv4());
388388
assert!(fallback.next().unwrap().is_ipv6());
389389

390-
let (mut preferred, mut fallback) = IpAddrs {
390+
let (mut preferred, mut fallback) = SocketAddrs {
391391
iter: vec![v6_addr, v4_addr].into_iter(),
392392
}
393393
.split_by_preference(Some(ip_v4), Some(ip_v6));
394394
assert!(preferred.next().unwrap().is_ipv6());
395395
assert!(fallback.next().unwrap().is_ipv4());
396396

397-
let (mut preferred, fallback) = IpAddrs {
397+
let (mut preferred, fallback) = SocketAddrs {
398398
iter: vec![v4_addr, v6_addr].into_iter(),
399399
}
400400
.split_by_preference(Some(ip_v4), None);
401401
assert!(preferred.next().unwrap().is_ipv4());
402402
assert!(fallback.is_empty());
403403

404-
let (mut preferred, fallback) = IpAddrs {
404+
let (mut preferred, fallback) = SocketAddrs {
405405
iter: vec![v4_addr, v6_addr].into_iter(),
406406
}
407407
.split_by_preference(None, Some(ip_v6));
@@ -422,7 +422,7 @@ mod tests {
422422
let dst = ::http::Uri::from_static("http://[::1]:8080/");
423423

424424
let mut addrs =
425-
IpAddrs::try_parse(dst.host().expect("host"), dst.port_u16().expect("port"))
425+
SocketAddrs::try_parse(dst.host().expect("host"), dst.port_u16().expect("port"))
426426
.expect("try_parse");
427427

428428
let expected = "[::1]:8080".parse::<SocketAddr>().expect("expected");

src/client/connect/http.rs

+10-7
Original file line numberDiff line numberDiff line change
@@ -321,14 +321,17 @@ where
321321

322322
// If the host is already an IP addr (v4 or v6),
323323
// skip resolving the dns and start connecting right away.
324-
let addrs = if let Some(addrs) = dns::IpAddrs::try_parse(host, port) {
324+
let addrs = if let Some(addrs) = dns::SocketAddrs::try_parse(host, port) {
325325
addrs
326326
} else {
327327
let addrs = resolve(&mut self.resolver, dns::Name::new(host.into()))
328328
.await
329329
.map_err(ConnectError::dns)?;
330-
let addrs = addrs.map(|addr| SocketAddr::new(addr, port)).collect();
331-
dns::IpAddrs::new(addrs)
330+
let addrs = addrs.map(|mut addr| {
331+
addr.set_port(port);
332+
addr
333+
}).collect();
334+
dns::SocketAddrs::new(addrs)
332335
};
333336

334337
let c = ConnectingTcp::new(addrs, config);
@@ -457,7 +460,7 @@ struct ConnectingTcp<'a> {
457460
}
458461

459462
impl<'a> ConnectingTcp<'a> {
460-
fn new(remote_addrs: dns::IpAddrs, config: &'a Config) -> Self {
463+
fn new(remote_addrs: dns::SocketAddrs, config: &'a Config) -> Self {
461464
if let Some(fallback_timeout) = config.happy_eyeballs_timeout {
462465
let (preferred_addrs, fallback_addrs) = remote_addrs
463466
.split_by_preference(config.local_address_ipv4, config.local_address_ipv6);
@@ -493,12 +496,12 @@ struct ConnectingTcpFallback {
493496
}
494497

495498
struct ConnectingTcpRemote {
496-
addrs: dns::IpAddrs,
499+
addrs: dns::SocketAddrs,
497500
connect_timeout: Option<Duration>,
498501
}
499502

500503
impl ConnectingTcpRemote {
501-
fn new(addrs: dns::IpAddrs, connect_timeout: Option<Duration>) -> Self {
504+
fn new(addrs: dns::SocketAddrs, connect_timeout: Option<Duration>) -> Self {
502505
let connect_timeout = connect_timeout.map(|t| t / (addrs.len() as u32));
503506

504507
Self {
@@ -920,7 +923,7 @@ mod tests {
920923
send_buffer_size: None,
921924
recv_buffer_size: None,
922925
};
923-
let connecting_tcp = ConnectingTcp::new(dns::IpAddrs::new(addrs), &cfg);
926+
let connecting_tcp = ConnectingTcp::new(dns::SocketAddrs::new(addrs), &cfg);
924927
let start = Instant::now();
925928
Ok::<_, ConnectError>((start, ConnectingTcp::connect(connecting_tcp).await?))
926929
})

0 commit comments

Comments
 (0)