MCPcopy
hub / github.com/AdguardTeam/dnsproxy / getWithSubnet

Method getWithSubnet

proxy/cache.go:255–307  ·  view source on GitHub ↗

getWithSubnet returns cached item for the req if it's found by n. expired is true if the item's TTL is expired. k is the resulting key for req. It's returned to avoid recalculating it afterwards. Note that a slow longest-prefix-match algorithm is used, so cache searches are performed up to mask+

(req *dns.Msg, n *net.IPNet)

Source from the content-addressed store, hash-verified

253// Note that a slow longest-prefix-match algorithm is used, so cache searches
254// are performed up to mask+1 times.
255func (c *cache) getWithSubnet(req *dns.Msg, n *net.IPNet) (ci *cacheItem, expired bool, k []byte) {
256 c.itemsWithSubnetLock.RLock()
257 defer c.itemsWithSubnetLock.RUnlock()
258
259 if !canLookUpInCache(c.itemsWithSubnet, req) {
260 return nil, false, nil
261 }
262
263 ecsIP := n.IP.Mask(n.Mask)
264 ipLen := len(ecsIP)
265 m, _ := n.Mask.Size()
266
267 k = msgToKeyWithSubnet(req, ecsIP, m)
268 data := c.itemsWithSubnet.Get(k)
269
270 // In order to reduce allocations we apply mask on bits level. As the key
271 // k has ecsIP in bytes slice representation, each iteration we can just
272 // clear one bit in the end of it by applying the bitmask.
273 for bitmask := ^byte(0); m >= 0 && data == nil; m-- {
274 // Set mask identification byte in the key.
275 k[keyMaskIndex] = byte(m)
276
277 // In case mask is zero, the key doesn't have IP in it.
278 if m == 0 {
279 k = slices.Delete(k, keyIPIndex, keyIPIndex+ipLen)
280 data = c.itemsWithSubnet.Get(k)
281
282 continue
283 }
284
285 // Shift or renew bitmask.
286 if m%8 == 0 {
287 bitmask = ^byte(0)
288 } else {
289 bitmask <<= 1
290 }
291
292 // Clear the last non-zero bit in the byte of the IP address.
293 k[keyIPIndex+m/8] &= bitmask
294
295 data = c.itemsWithSubnet.Get(k)
296 }
297
298 if data == nil {
299 return nil, false, k
300 }
301
302 if ci, expired = c.unpackItem(data, req); ci == nil {
303 c.itemsWithSubnet.Del(k)
304 }
305
306 return ci, expired, k
307}
308
309// canLookUpInCache returns true if these parameters could be used to make a
310// cache lookup.

Callers 4

replyFromCacheMethod · 0.80
TestCache_getWithSubnetFunction · 0.80

Calls 3

unpackItemMethod · 0.95
canLookUpInCacheFunction · 0.85
msgToKeyWithSubnetFunction · 0.85

Tested by 3

TestCache_getWithSubnetFunction · 0.64