Implement Pluggable Name-resolution (#148)
This defines a new trait `Resolver`, which turns an address into a Vec<SocketAddr>. It also provides an implementation of Resolver for `Fn(&str)` so it's easy to define simple resolvers with a closure. Fixes #82 Co-authored-by: Ulrik <ulrikm@spotify.com>
This commit is contained in:
@@ -4,7 +4,6 @@ use std::io::{
|
||||
};
|
||||
use std::net::SocketAddr;
|
||||
use std::net::TcpStream;
|
||||
use std::net::ToSocketAddrs;
|
||||
use std::time::Duration;
|
||||
use std::time::Instant;
|
||||
|
||||
@@ -386,15 +385,17 @@ pub(crate) fn connect_host(unit: &Unit, hostname: &str, port: u16) -> Result<Tcp
|
||||
} else {
|
||||
unit.deadline
|
||||
};
|
||||
|
||||
// TODO: Find a way to apply deadline to DNS lookup.
|
||||
let sock_addrs: Vec<SocketAddr> = match unit.req.proxy {
|
||||
|
||||
let netloc = match unit.req.proxy {
|
||||
Some(ref proxy) => format!("{}:{}", proxy.server, proxy.port),
|
||||
None => format!("{}:{}", hostname, port),
|
||||
}
|
||||
.to_socket_addrs()
|
||||
.map_err(|e| Error::DnsFailed(format!("{}", e)))?
|
||||
.collect();
|
||||
};
|
||||
|
||||
// TODO: Find a way to apply deadline to DNS lookup.
|
||||
let sock_addrs = unit
|
||||
.resolver()
|
||||
.resolve(&netloc)
|
||||
.map_err(|e| Error::DnsFailed(format!("{}", e)))?;
|
||||
|
||||
if sock_addrs.is_empty() {
|
||||
return Err(Error::DnsFailed(format!("No ip address for {}", hostname)));
|
||||
@@ -419,6 +420,7 @@ pub(crate) fn connect_host(unit: &Unit, hostname: &str, port: u16) -> Result<Tcp
|
||||
// connect with a configured timeout.
|
||||
let stream = if Some(Proto::SOCKS5) == proto {
|
||||
connect_socks5(
|
||||
&unit,
|
||||
unit.req.proxy.to_owned().unwrap(),
|
||||
deadline,
|
||||
sock_addr,
|
||||
@@ -496,11 +498,15 @@ pub(crate) fn connect_host(unit: &Unit, hostname: &str, port: u16) -> Result<Tcp
|
||||
}
|
||||
|
||||
#[cfg(feature = "socks-proxy")]
|
||||
fn socks5_local_nslookup(hostname: &str, port: u16) -> Result<TargetAddr, std::io::Error> {
|
||||
let addrs: Vec<SocketAddr> = format!("{}:{}", hostname, port)
|
||||
.to_socket_addrs()
|
||||
.map_err(|e| std::io::Error::new(ErrorKind::NotFound, format!("DNS failure: {}.", e)))?
|
||||
.collect();
|
||||
fn socks5_local_nslookup(
|
||||
unit: &Unit,
|
||||
hostname: &str,
|
||||
port: u16,
|
||||
) -> Result<TargetAddr, std::io::Error> {
|
||||
let addrs: Vec<SocketAddr> = unit
|
||||
.resolver()
|
||||
.resolve(&format!("{}:{}", hostname, port))
|
||||
.map_err(|e| std::io::Error::new(ErrorKind::NotFound, format!("DNS failure: {}.", e)))?;
|
||||
|
||||
if addrs.is_empty() {
|
||||
return Err(std::io::Error::new(
|
||||
@@ -522,6 +528,7 @@ fn socks5_local_nslookup(hostname: &str, port: u16) -> Result<TargetAddr, std::i
|
||||
|
||||
#[cfg(feature = "socks-proxy")]
|
||||
fn connect_socks5(
|
||||
unit: &Unit,
|
||||
proxy: Proxy,
|
||||
deadline: Option<Instant>,
|
||||
proxy_addr: SocketAddr,
|
||||
@@ -533,7 +540,7 @@ fn connect_socks5(
|
||||
use std::str::FromStr;
|
||||
|
||||
let host_addr = if Ipv4Addr::from_str(host).is_ok() || Ipv6Addr::from_str(host).is_ok() {
|
||||
match socks5_local_nslookup(host, port) {
|
||||
match socks5_local_nslookup(unit, host, port) {
|
||||
Ok(addr) => addr,
|
||||
Err(err) => return Err(err),
|
||||
}
|
||||
@@ -625,6 +632,7 @@ fn get_socks5_stream(
|
||||
|
||||
#[cfg(not(feature = "socks-proxy"))]
|
||||
fn connect_socks5(
|
||||
_unit: &Unit,
|
||||
_proxy: Proxy,
|
||||
_deadline: Option<Instant>,
|
||||
_proxy_addr: SocketAddr,
|
||||
|
||||
Reference in New Issue
Block a user