axnet/smoltcp_impl/
dns.rs1use alloc::vec::Vec;
2use axerrno::{AxError, AxResult, ax_err_type};
3use core::net::IpAddr;
4
5use smoltcp::iface::SocketHandle;
6use smoltcp::socket::dns::{self, GetQueryResultError, StartQueryError};
7use smoltcp::wire::DnsQueryType;
8
9use super::addr::into_core_ipaddr;
10use super::{ETH0, SOCKET_SET, SocketSetWrapper};
11
12struct DnsSocket {
14 handle: Option<SocketHandle>,
15}
16
17impl DnsSocket {
18 #[allow(clippy::new_without_default)]
19 pub fn new() -> Self {
21 let socket = SocketSetWrapper::new_dns_socket();
22 let handle = Some(SOCKET_SET.add(socket));
23 Self { handle }
24 }
25
26 #[allow(dead_code)]
27 pub fn update_servers(self, servers: &[smoltcp::wire::IpAddress]) {
29 SOCKET_SET.with_socket_mut::<dns::Socket, _, _>(self.handle.unwrap(), |socket| {
30 socket.update_servers(servers)
31 });
32 }
33
34 pub fn query(&self, name: &str, query_type: DnsQueryType) -> AxResult<Vec<IpAddr>> {
36 let handle = self.handle.ok_or_else(|| ax_err_type!(InvalidInput))?;
38 let iface = Ð0.iface;
39 let query_handle = SOCKET_SET
40 .with_socket_mut::<dns::Socket, _, _>(handle, |socket| {
41 socket.start_query(iface.lock().context(), name, query_type)
42 })
43 .map_err(|e| match e {
44 StartQueryError::NoFreeSlot => {
45 ax_err_type!(ResourceBusy, "socket query() failed: no free slot")
46 }
47 StartQueryError::InvalidName => {
48 ax_err_type!(InvalidInput, "socket query() failed: invalid name")
49 }
50 StartQueryError::NameTooLong => {
51 ax_err_type!(InvalidInput, "socket query() failed: too long name")
52 }
53 })?;
54 loop {
55 SOCKET_SET.poll_interfaces();
56 match SOCKET_SET.with_socket_mut::<dns::Socket, _, _>(handle, |socket| {
57 socket.get_query_result(query_handle).map_err(|e| match e {
58 GetQueryResultError::Pending => AxError::WouldBlock,
59 GetQueryResultError::Failed => {
60 ax_err_type!(ConnectionRefused, "socket query() failed")
61 }
62 })
63 }) {
64 Ok(n) => {
65 let mut res = Vec::with_capacity(n.capacity());
66 for ip in n {
67 res.push(into_core_ipaddr(ip))
68 }
69 return Ok(res);
70 }
71 Err(AxError::WouldBlock) => axtask::yield_now(),
72 Err(e) => return Err(e),
73 }
74 }
75 }
76}
77
78impl Drop for DnsSocket {
79 fn drop(&mut self) {
80 if let Some(handle) = self.handle {
81 SOCKET_SET.remove(handle);
82 }
83 }
84}
85
86pub fn dns_query(name: &str) -> AxResult<alloc::vec::Vec<IpAddr>> {
88 let socket = DnsSocket::new();
89 socket.query(name, DnsQueryType::A)
90}