Skip to content

Commit e3dbdd3

Browse files
committed
hickory: add ToSocketAddrs impl
And tokio utils to run it
1 parent 6cdede6 commit e3dbdd3

File tree

3 files changed

+61
-20
lines changed

3 files changed

+61
-20
lines changed

src/implementors/hickory.rs

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
1-
use crate::{traits::AsyncToSocketAddrs, util::SocketAddrsFromIpAddrs};
2-
use hickory_resolver::{IntoName, Resolver};
3-
use std::{io, net::SocketAddr, str::FromStr};
1+
use crate::{
2+
traits::AsyncToSocketAddrs,
3+
util::{self, SocketAddrsFromIpAddrs},
4+
};
5+
use hickory_resolver::{IntoName, Resolver, lookup_ip::LookupIpIntoIter};
6+
use std::{
7+
io,
8+
net::{SocketAddr, ToSocketAddrs},
9+
str::FromStr,
10+
};
411

512
/// Perform async DNS resolution using hickory-dns
6-
#[derive(Debug)]
13+
#[derive(Debug, Clone)]
714
pub struct HickoryToSocketAddrs<T: IntoName + Send + 'static> {
815
host: T,
916
port: u16,
@@ -14,6 +21,23 @@ impl<H: IntoName + Send + 'static> HickoryToSocketAddrs<H> {
1421
pub fn new(host: H, port: u16) -> Self {
1522
Self { host, port }
1623
}
24+
25+
async fn lookup(self) -> io::Result<SocketAddrsFromIpAddrs<LookupIpIntoIter>> {
26+
if !util::inside_tokio() {
27+
return Err(io::Error::other(
28+
"hickory-dns is only supported in a tokio context",
29+
));
30+
}
31+
32+
Ok(SocketAddrsFromIpAddrs(
33+
Resolver::builder_tokio()?
34+
.build()
35+
.lookup_ip(self.host)
36+
.await?
37+
.into_iter(),
38+
self.port,
39+
))
40+
}
1741
}
1842

1943
impl FromStr for HickoryToSocketAddrs<String> {
@@ -30,27 +54,20 @@ impl FromStr for HickoryToSocketAddrs<String> {
3054
}
3155
}
3256

57+
impl<T: IntoName + Clone + Send + 'static> ToSocketAddrs for HickoryToSocketAddrs<T> {
58+
type Iter = SocketAddrsFromIpAddrs<LookupIpIntoIter>;
59+
60+
fn to_socket_addrs(&self) -> io::Result<Self::Iter> {
61+
util::block_on_tokio(self.clone().lookup())
62+
}
63+
}
64+
3365
impl<T: IntoName + Send + 'static> AsyncToSocketAddrs for HickoryToSocketAddrs<T> {
3466
fn to_socket_addrs(
3567
self,
3668
) -> impl Future<Output = io::Result<impl Iterator<Item = SocketAddr> + Send + 'static>>
3769
+ Send
3870
+ 'static {
39-
async move {
40-
if tokio::runtime::Handle::try_current().is_err() {
41-
return Err(io::Error::other(
42-
"hickory-dns is only supported in a tokio context",
43-
));
44-
}
45-
46-
Ok(SocketAddrsFromIpAddrs(
47-
Resolver::builder_tokio()?
48-
.build()
49-
.lookup_ip(self.host)
50-
.await?
51-
.into_iter(),
52-
self.port,
53-
))
54-
}
71+
self.lookup()
5572
}
5673
}

src/util/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,8 @@ pub use io::*;
1313

1414
mod runtime;
1515
pub use runtime::*;
16+
17+
#[cfg(feature = "tokio")]
18+
mod tokio;
19+
#[cfg(feature = "tokio")]
20+
pub use tokio::*;

src/util/tokio.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
use std::{future::Future, io};
2+
use tokio::runtime::Handle;
3+
4+
/// Check whether we're in a tokio context or not
5+
pub fn inside_tokio() -> bool {
6+
Handle::try_current().is_ok()
7+
}
8+
9+
/// Block on the given future in a tokio context, creating a new one if required
10+
pub fn block_on_tokio<T>(fut: impl Future<Output = io::Result<T>>) -> io::Result<T> {
11+
if let Ok(handle) = Handle::try_current() {
12+
handle.block_on(fut)
13+
} else {
14+
tokio::runtime::Builder::new_current_thread()
15+
.enable_all()
16+
.build()?
17+
.block_on(fut)
18+
}
19+
}

0 commit comments

Comments
 (0)