xref: /aosp_15_r20/external/libwebsockets/READMEs/README.async-dns.md (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
1*1c60b9acSAndroid Build Coastguard Worker# Asynchronous DNS
2*1c60b9acSAndroid Build Coastguard Worker
3*1c60b9acSAndroid Build Coastguard Worker## Introduction
4*1c60b9acSAndroid Build Coastguard Worker
5*1c60b9acSAndroid Build Coastguard WorkerLws now features optional asynchronous, ie, nonblocking recursive DNS
6*1c60b9acSAndroid Build Coastguard Workerresolution done on the event loop, enable `-DLWS_WITH_SYS_ASYNC_DNS=1`
7*1c60b9acSAndroid Build Coastguard Workerat cmake to build it in.
8*1c60b9acSAndroid Build Coastguard Worker
9*1c60b9acSAndroid Build Coastguard Worker## Description
10*1c60b9acSAndroid Build Coastguard Worker
11*1c60b9acSAndroid Build Coastguard WorkerThe default libc name resolution is via libc `getaddrinfo()`, which is
12*1c60b9acSAndroid Build Coastguard Workerblocking, possibly for quite long periods (seconds).  If you are
13*1c60b9acSAndroid Build Coastguard Workertaking care about latency, but want to create outgoing connections,
14*1c60b9acSAndroid Build Coastguard Workeryou can't tolerate this exception from the rule that everything in
15*1c60b9acSAndroid Build Coastguard Workerlws is nonblocking.
16*1c60b9acSAndroid Build Coastguard Worker
17*1c60b9acSAndroid Build Coastguard WorkerLws' asynchronous DNS resolver creates a caching name resolver
18*1c60b9acSAndroid Build Coastguard Workerthat directly queries the configured nameserver itself over UDP,
19*1c60b9acSAndroid Build Coastguard Workerfrom the event loop.
20*1c60b9acSAndroid Build Coastguard Worker
21*1c60b9acSAndroid Build Coastguard WorkerIt supports both ipv4 / A records and ipv6 / AAAA records (see later
22*1c60b9acSAndroid Build Coastguard Workerfor a description about how).  One server supported over UDP :53,
23*1c60b9acSAndroid Build Coastguard Workerand the nameserver is autodicovered on linux, windows, and freertos.
24*1c60b9acSAndroid Build Coastguard Worker
25*1c60b9acSAndroid Build Coastguard WorkerOther features
26*1c60b9acSAndroid Build Coastguard Worker
27*1c60b9acSAndroid Build Coastguard Worker - lws-style paranoid response parsing
28*1c60b9acSAndroid Build Coastguard Worker - random unique tid generation to increase difficulty of poisoning
29*1c60b9acSAndroid Build Coastguard Worker - it's really integrated with the lws event loop, it does not spawn
30*1c60b9acSAndroid Build Coastguard Worker   threads or use the libc resolver, and of course no blocking at all
31*1c60b9acSAndroid Build Coastguard Worker - platform-specific server address capturing (from /etc/resolv.conf
32*1c60b9acSAndroid Build Coastguard Worker   on linux, windows apis on windows)
33*1c60b9acSAndroid Build Coastguard Worker - LRU caching
34*1c60b9acSAndroid Build Coastguard Worker - piggybacking (multiple requests before the first completes go on
35*1c60b9acSAndroid Build Coastguard Worker    a list on the first request, not spawn multiple requests)
36*1c60b9acSAndroid Build Coastguard Worker - observes TTL in cache
37*1c60b9acSAndroid Build Coastguard Worker - TTL and timeout use `lws_sul` timers on the event loop
38*1c60b9acSAndroid Build Coastguard Worker - Uses CNAME resolution inside the same response if present, otherwise
39*1c60b9acSAndroid Build Coastguard Worker   recurses to resolve the CNAME (up to 3 deep)
40*1c60b9acSAndroid Build Coastguard Worker - ipv6 pieces only built if cmake `LWS_IPV6` enabled
41*1c60b9acSAndroid Build Coastguard Worker
42*1c60b9acSAndroid Build Coastguard Worker## Api
43*1c60b9acSAndroid Build Coastguard Worker
44*1c60b9acSAndroid Build Coastguard WorkerIf enabled at cmake, the async DNS implementation is used automatically
45*1c60b9acSAndroid Build Coastguard Workerfor lws client connections.  It's also possible to call it directly, see
46*1c60b9acSAndroid Build Coastguard Workerthe api-test-async-dns example for how.
47*1c60b9acSAndroid Build Coastguard Worker
48*1c60b9acSAndroid Build Coastguard WorkerThe Api follows that of `getaddrinfo()` but results are not created on
49*1c60b9acSAndroid Build Coastguard Workerthe heap.  Instead a single, const cached copy of the addrinfo struct
50*1c60b9acSAndroid Build Coastguard Workerchain is reference-counted, with `lws_async_dns_freeaddrinfo()` provided
51*1c60b9acSAndroid Build Coastguard Workerto deduct from the reference count.  Cached items with a nonzero
52*1c60b9acSAndroid Build Coastguard Workerreference count can't be destroyed from the cache, so it's safe to keep
53*1c60b9acSAndroid Build Coastguard Workera pointer to the results and iterate through them.
54*1c60b9acSAndroid Build Coastguard Worker
55*1c60b9acSAndroid Build Coastguard Worker## Dealing with IPv4 and IPv6
56*1c60b9acSAndroid Build Coastguard Worker
57*1c60b9acSAndroid Build Coastguard WorkerDNS is a very old standard that has some quirks... one of them is that
58*1c60b9acSAndroid Build Coastguard Workermultiple queries are not supported in one packet, even though the protocol
59*1c60b9acSAndroid Build Coastguard Workersuggests it is.  This creates problems on ipv6 enabled systems, where
60*1c60b9acSAndroid Build Coastguard Workerit may prefer to have AAAA results, but the server may only have A records.
61*1c60b9acSAndroid Build Coastguard Worker
62*1c60b9acSAndroid Build Coastguard WorkerTo square the circle, for ipv4 only systems (`LWS_IPV6=0`) the resolver
63*1c60b9acSAndroid Build Coastguard Workerrequests only A records.  For ipv6-capable systems, it always requests
64*1c60b9acSAndroid Build Coastguard Workerfirst A and then immediately afterwards AAAA records.
65*1c60b9acSAndroid Build Coastguard Worker
66*1c60b9acSAndroid Build Coastguard WorkerTo simplify the implementation, the tid b0 is used to differentiate
67*1c60b9acSAndroid Build Coastguard Workerbetween A (b0 = 0) and AAAA (b0 = 1) requests and responses using the
68*1c60b9acSAndroid Build Coastguard Workersame query body.
69*1c60b9acSAndroid Build Coastguard Worker
70*1c60b9acSAndroid Build Coastguard WorkerThe first response to come back is parsed, and a cache entry made...
71*1c60b9acSAndroid Build Coastguard Workerit leaves a note in the query about the address of the last `struct addrinfo`
72*1c60b9acSAndroid Build Coastguard Workerrecord.  When the second response comes, a second allocation is made,
73*1c60b9acSAndroid Build Coastguard Workerbut not added to the logical cache... instead it's chained on to the
74*1c60b9acSAndroid Build Coastguard Workerfirst cache entry and the `struct addrinfo` linked-list from the
75*1c60b9acSAndroid Build Coastguard Workerfirst cache entry is extended into the second one.  At the time the
76*1c60b9acSAndroid Build Coastguard Workersecond result arrives, the query is destroyed and the cached results
77*1c60b9acSAndroid Build Coastguard Workerprovided on the result callback.
78*1c60b9acSAndroid Build Coastguard Worker
79*1c60b9acSAndroid Build Coastguard Worker## Recursion
80*1c60b9acSAndroid Build Coastguard Worker
81*1c60b9acSAndroid Build Coastguard WorkerWhere CNAMEs are returned, DNS servers may take two approaches... if the
82*1c60b9acSAndroid Build Coastguard WorkerCNAME is also resolved by the same server and so it knows what it should
83*1c60b9acSAndroid Build Coastguard Workerresolve to, it may provide the CNAME resolution in the same response
84*1c60b9acSAndroid Build Coastguard Workerpacket.
85*1c60b9acSAndroid Build Coastguard Worker
86*1c60b9acSAndroid Build Coastguard WorkerIn the case the CNAME is actually resolved by a different name server,
87*1c60b9acSAndroid Build Coastguard Workerthe server with the CNAME does not have the information to hand to also
88*1c60b9acSAndroid Build Coastguard Workerresolve the CNAME in the same response.  So it just leaves it for the
89*1c60b9acSAndroid Build Coastguard Workerclient to sort out.
90*1c60b9acSAndroid Build Coastguard Worker
91*1c60b9acSAndroid Build Coastguard WorkerThe lws implementation can deal with both of these, first it "recurses"
92*1c60b9acSAndroid Build Coastguard Worker(it does not recurse on the process stack but uses its own manual stack)
93*1c60b9acSAndroid Build Coastguard Workerto look for results in the same packet that told it about the CNAME.  If
94*1c60b9acSAndroid Build Coastguard Workerthere are no results, it resets the query to look instead for the CNAME,
95*1c60b9acSAndroid Build Coastguard Workerand restarts it.  It allows this to happen for 3 CNAME deep.
96*1c60b9acSAndroid Build Coastguard Worker
97*1c60b9acSAndroid Build Coastguard WorkerAt the end, either way, the cached result is set using the original
98*1c60b9acSAndroid Build Coastguard Workerquery name and the results from the last CNAME in the chain.
99*1c60b9acSAndroid Build Coastguard Worker
100*1c60b9acSAndroid Build Coastguard Worker
101