use async_std::net::{SocketAddr, ToSocketAddrs};
use embedded_nal_async::{AddrType, IpAddr};
#[derive(Debug)]
struct NotFound;
impl core::fmt::Display for NotFound {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "Not found")
}
}
impl std::error::Error for NotFound {}
#[derive(Debug)]
struct TooLong;
impl core::fmt::Display for TooLong {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "Name too long")
}
}
impl std::error::Error for TooLong {}
impl embedded_nal_async::Dns for crate::Stack {
type Error = std::io::Error;
async fn get_host_by_name(
&self,
hostname: &str,
addr_type: AddrType,
) -> Result<IpAddr, Self::Error> {
let accept_v4 = addr_type != AddrType::IPv6;
let accept_v6 = addr_type != AddrType::IPv4;
let fake_port = 1234;
for addr in (hostname, fake_port).to_socket_addrs().await? {
match addr {
SocketAddr::V4(v) if accept_v4 => {
return Ok(v.ip().octets().into());
}
SocketAddr::V6(v) if accept_v6 => {
return Ok(v.ip().octets().into());
}
_ => continue,
}
}
Err(Self::Error::new(std::io::ErrorKind::NotFound, NotFound))
}
async fn get_host_by_address(
&self,
addr: IpAddr,
result: &mut [u8],
) -> Result<usize, Self::Error> {
let fakesocketaddr =
std::net::SocketAddr::new(crate::conversion::IpAddr::from(addr).into(), 1234);
let (name, _service) =
async_std::task::spawn_blocking(move || dns_lookup::getnameinfo(&fakesocketaddr, 0))
.await?;
if name.parse::<std::net::IpAddr>().is_ok() {
return Err(Self::Error::new(std::io::ErrorKind::NotFound, NotFound));
}
if let Some(result) = result.get_mut(..name.len()) {
result.copy_from_slice(name.as_bytes());
Ok(result.len())
} else {
Err(Self::Error::new(std::io::ErrorKind::OutOfMemory, TooLong))
}
}
}