🔗Async DNS
net/dns.nim implements an in-loop DNS resolver (RFC 1035). Name resolution runs entirely on the powpow event loop — no blocking getaddrinfo, no worker threads, no --threads:on requirement. tcp.connect uses it automatically, so outbound connects never stall the loop on DNS.
Status: implemented (see plans/async_dns.md for the design and the follow-up work).
🔗How it works
- One non-blocking UDP socket owned by the loop; inbound datagrams are matched to queries by randomized query id.
- Sends A + AAAA queries with A-fallback; retries across nameservers with
timeout/attemptstaken fromresolv.conf(defaults 5s / 2). - Reads
/etc/hosts(IP + aliases, cached) and/etc/resolv.conf(nameserverentries). On macOS the stub127.0.0.1resolv.conf works (mDNSResponder handles it). Falls back to8.8.8.8/1.1.1.1. - TTL-based positive cache plus a short (30s) negative cache for NXDOMAIN.
- Numeric IP literals resolve inline with zero DNS I/O.
🔗Resolving an address
resolveAddrAsync(loop, "example.com", port = 443, SOCK_STREAM,
proc(addrs: seq[Sockaddr_storage]; err: string) =
if err.len > 0:
echo "resolution failed: ", err
else:
echo "resolved to ", addrs.len, " address(es)"))The callback fires with a sequence of Sockaddr_storage results (IPv4 and IPv6), or a non-empty err. The callback runs on the loop.
DnsCallback = proc(addrs: seq[Sockaddr_storage]; err: string) {.closure.}
🔗Configuring the resolver
configureDns(loop, timeoutMs = 3000, attempts = 3) # retry policy
setDnsServers(loop, [("8.8.8.8", 53), ("1.1.1.1", 53)]) # override servers
closeDns(loop) # free the resolver🔗Integration with TCP connect
tcp.connect resolves the hostname on the loop before opening the socket, and reports DNS failure through its onError callback:
connect(loop, "api.example.com", 443,
onConnect = proc(conn: Connection) = echo "connected",
onData = proc(conn: Connection, data: openArray[byte]) = discard,
onError = proc(err: string) = echo "connect/DNS failed: ", err)🔗Not yet implemented (roadmap)
- TCP fallback for truncated responses
- Search domains /
ndotsfromresolv.conf - IPv6 nameservers with scope IDs
- UDP
sendTosync cache fast-path
See plans/roadmap.md.
🔗API reference
Full signatures: DNS API.