Configuration of bind address for resolver.

Allows configuration of the local address that is used by the resolver.
This is useful if the system has multiple active network connections
and it is desirable to specify which interface is used for name
resolution.
This commit is contained in:
Sebastian Urban
2020-11-04 00:07:30 +01:00
committed by Benjamin Fry
parent aeb39cca38
commit 6ef9b4ec4a
34 changed files with 526 additions and 98 deletions

View File

@@ -10,10 +10,12 @@ use std::net::SocketAddr;
use std::pin::Pin;
use std::task::{Context, Poll};
use async_std::task::spawn_blocking;
use async_trait::async_trait;
use futures_io::{AsyncRead, AsyncWrite};
use futures_util::future::FutureExt;
use pin_utils::pin_mut;
use socket2::{Domain, Protocol, Socket, Type};
use trust_dns_resolver::proto::tcp::{Connect, DnsTcpStream};
use trust_dns_resolver::proto::udp::UdpSocket;
@@ -71,8 +73,28 @@ impl DnsTcpStream for AsyncStdTcpStream {
#[async_trait]
impl Connect for AsyncStdTcpStream {
async fn connect(addr: SocketAddr) -> io::Result<Self> {
let stream = async_std::net::TcpStream::connect(addr).await?;
async fn connect_with_bind(
addr: SocketAddr,
bind_addr: Option<SocketAddr>,
) -> io::Result<Self> {
let stream = match bind_addr {
Some(bind_addr) => {
spawn_blocking(move || {
let domain = match bind_addr {
SocketAddr::V4(_) => Domain::IPV4,
SocketAddr::V6(_) => Domain::IPV6,
};
let socket = Socket::new(domain, Type::STREAM, Some(Protocol::TCP))?;
socket.bind(&bind_addr.into())?;
socket.connect(&addr.into())?;
let std_stream: std::net::TcpStream = socket.into();
let stream = async_std::net::TcpStream::from(std_stream);
Ok::<_, io::Error>(stream)
})
.await?
}
None => async_std::net::TcpStream::connect(addr).await?,
};
stream.set_nodelay(true)?;
Ok(AsyncStdTcpStream(stream))
}