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