use core::net::IpAddr;
use core::net::Ipv4Addr;
use super::op::OpImpl;
use crate::stack::constants::MAX_HOST_NAME_LEN;
use crate::transfer::Xfer;
use crate::StackError;
#[derive(Debug)]
pub struct DnsOp {
host: heapless::String<MAX_HOST_NAME_LEN>, count: u32,
initialized: bool,
}
impl DnsOp {
pub fn new(host: &str, timeout: u32) -> Result<Self, StackError> {
let host_string =
heapless::String::try_from(host).map_err(|_| StackError::InvalidParameters)?;
Ok(Self {
host: host_string,
count: timeout,
initialized: false,
})
}
}
impl<X: Xfer> OpImpl<X> for DnsOp {
type Output = IpAddr;
type Error = StackError;
fn poll_impl(
&mut self,
manager: &mut crate::manager::Manager<X>,
callbacks: &mut crate::stack::socket_callbacks::SocketCallbacks,
) -> Result<Option<Self::Output>, Self::Error> {
if !self.initialized {
if callbacks.dns_resolved_addr.is_none() {
callbacks.dns_resolved_addr = Some(None);
}
manager.send_gethostbyname(&self.host)?;
self.initialized = true;
}
if let Some(result) = &mut callbacks.dns_resolved_addr {
if let Some(ip) = result.take() {
callbacks.dns_resolved_addr = None;
return if ip == Ipv4Addr::new(0, 0, 0, 0) {
Err(StackError::DnsFailed)
} else {
Ok(Some(IpAddr::V4(ip)))
};
}
}
if self.count == 0 {
return Err(StackError::DnsTimeout);
}
self.count -= 1;
Ok(None)
}
}