-
Notifications
You must be signed in to change notification settings - Fork 0
/
cache.go
106 lines (89 loc) · 1.77 KB
/
cache.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package main
import (
"sync"
"time"
"github.com/golang/groupcache/lru"
"github.com/miekg/dns"
"go.papla.net/goutil/log"
"go.papla.net/yuanxiao/source"
)
type Cache struct {
lru *lru.Cache
timeout time.Duration
sync.Mutex
}
type cacheEntry struct {
ans *source.Answer
ts time.Time
}
func NewCache(size int, to time.Duration) *Cache {
switch size {
case 0:
return &Cache{}
case -1:
return &Cache{
lru: lru.New(0),
timeout: to,
}
default:
return &Cache{
lru: lru.New(size),
timeout: to,
}
}
}
func (c *Cache) Put(key string, a *source.Answer) {
if c.lru == nil {
return
}
c.Lock()
defer c.Unlock()
e := &cacheEntry{}
e.ts = time.Now()
e.ans = a
c.lru.Add(key, e)
}
func (c *Cache) Get(key string) (*source.Answer, bool) {
if c.lru == nil {
return nil, false
}
c.Lock()
defer c.Unlock()
value, ok := c.lru.Get(key)
if !ok {
log.Debugf("cache miss for key: %s", key)
return nil, false
}
entry := value.(*cacheEntry)
elapse := time.Since(entry.ts)
if elapse > c.timeout {
return nil, false
}
delta := uint32(elapse.Seconds())
newans := &source.Answer{}
if newans.An, ok = checkTTL(entry.ans.An, delta); !ok {
return nil, false
}
if newans.Ns, ok = checkTTL(entry.ans.Ns, delta); !ok {
return nil, false
}
if newans.Ex, ok = checkTTL(entry.ans.Ex, delta); !ok {
return nil, false
}
newans.Auth = entry.ans.Auth
newans.Rcode = entry.ans.Rcode
return newans, true
}
func checkTTL(sec []dns.RR, elapse uint32) ([]dns.RR, bool) {
var newsec []dns.RR
for _, rr := range sec {
if rr.Header().Ttl <= elapse {
log.Debugf("ttl expire: %s, elapse: %d", rr, elapse)
return nil, false
}
newrr := dns.Copy(rr)
newrr.Header().Ttl -= elapse
newsec = append(newsec, newrr)
}
return newsec, true
}