replyFromCache tries to get the response from general or subnet cache. In case the cache is present in d, it's used first. Returns true on success.
(d *DNSContext)
| 17 | // replyFromCache tries to get the response from general or subnet cache. In |
| 18 | // case the cache is present in d, it's used first. Returns true on success. |
| 19 | func (p *Proxy) replyFromCache(d *DNSContext) (hit bool) { |
| 20 | dctxCache := p.cacheForContext(d) |
| 21 | |
| 22 | var ci *cacheItem |
| 23 | var cacheSource string |
| 24 | var expired bool |
| 25 | var key []byte |
| 26 | |
| 27 | // TODO(d.kolyshev): Use EnableEDNSClientSubnet from dctxCache. |
| 28 | if p.Config.EnableEDNSClientSubnet && d.ReqECS != nil { |
| 29 | ci, expired, key = dctxCache.getWithSubnet(d.Req, d.ReqECS) |
| 30 | cacheSource = "subnet cache" |
| 31 | } else { |
| 32 | ci, expired, key = dctxCache.get(d.Req) |
| 33 | cacheSource = "general cache" |
| 34 | } |
| 35 | |
| 36 | if hit = ci != nil; !hit { |
| 37 | return hit |
| 38 | } |
| 39 | |
| 40 | d.Res = ci.m |
| 41 | d.queryStatistics = cachedQueryStatistics(ci.u) |
| 42 | |
| 43 | p.logger.Debug( |
| 44 | "replying from cache", |
| 45 | "source", cacheSource, |
| 46 | "ecs_enabled", p.Config.EnableEDNSClientSubnet, |
| 47 | ) |
| 48 | |
| 49 | if dctxCache.optimistic && expired { |
| 50 | // Build a reduced clone of the current context to avoid data race. |
| 51 | minCtxClone := &DNSContext{ |
| 52 | // It is only read inside the optimistic resolver. |
| 53 | CustomUpstreamConfig: d.CustomUpstreamConfig, |
| 54 | ReqECS: cloneIPNet(d.ReqECS), |
| 55 | IsPrivateClient: d.IsPrivateClient, |
| 56 | } |
| 57 | if d.Req != nil { |
| 58 | minCtxClone.Req = d.Req.Copy() |
| 59 | } |
| 60 | |
| 61 | go p.shortFlighter.resolveOnce(minCtxClone, key, p.logger) |
| 62 | } |
| 63 | |
| 64 | return hit |
| 65 | } |
| 66 | |
| 67 | // cloneIPNet returns a deep clone of n. |
| 68 | func cloneIPNet(n *net.IPNet) (clone *net.IPNet) { |
no test coverage detected