-
Notifications
You must be signed in to change notification settings - Fork 175
/
dns_cache.go
143 lines (118 loc) · 3.6 KB
/
dns_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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package herocache
import (
"net"
"github.com/rs/zerolog"
"github.com/onflow/flow-go/model/flow"
herocache "github.com/onflow/flow-go/module/mempool/herocache/backdata"
"github.com/onflow/flow-go/module/mempool/herocache/backdata/heropool"
"github.com/onflow/flow-go/module/mempool/stdmap"
)
type DNSCache struct {
ipCache *stdmap.Backend
txtCache *stdmap.Backend
}
func NewDNSCache(sizeLimit uint32, logger zerolog.Logger) *DNSCache {
return &DNSCache{
txtCache: stdmap.NewBackendWithBackData(
herocache.NewCache(sizeLimit, 8, heropool.LRUEjection, logger)),
ipCache: stdmap.NewBackendWithBackData(
herocache.NewCache(sizeLimit, 8, heropool.LRUEjection, logger)),
}
}
// PutDomainIp adds the given ip domain into the cache.
func (d *DNSCache) PutDomainIp(domain string, addresses []net.IPAddr, timestamp int64) bool {
i := ipEntity{
id: domainToIdentifier(domain),
domain: domain,
addresses: addresses,
timestamp: timestamp,
}
return d.ipCache.Add(i)
}
// PutTxtRecord adds the given txt record into the cache.
func (d *DNSCache) PutTxtRecord(domain string, record []string, timestamp int64) bool {
t := txtEntity{
id: domainToIdentifier(domain),
txt: domain,
record: record,
timestamp: timestamp,
}
return d.txtCache.Add(t)
}
// GetIpDomain returns the ip domain if exists in the cache.
// The second return value determines the timestamp of adding the
// domain to the cache.
// The boolean return value determines if domain exists in the cache.
func (d *DNSCache) GetDomainIp(domain string) ([]net.IPAddr, int64, bool) {
entity, ok := d.ipCache.ByID(domainToIdentifier(domain))
if !ok {
return nil, 0, false
}
i, ok := entity.(ipEntity)
if !ok {
return nil, 0, false
}
return i.addresses, i.timestamp, true
}
// GetTxtRecord returns the txt record if exists in the cache.
// The second return value determines the timestamp of adding the
// record to the cache.
// The boolean return value determines if record exists in the cache.
func (d *DNSCache) GetTxtRecord(domain string) ([]string, int64, bool) {
entity, ok := d.txtCache.ByID(domainToIdentifier(domain))
if !ok {
return nil, 0, false
}
t, ok := entity.(txtEntity)
if !ok {
return nil, 0, false
}
return t.record, t.timestamp, true
}
// RemoveIp removes an ip domain from cache.
func (d *DNSCache) RemoveIp(domain string) bool {
return d.ipCache.Rem(domainToIdentifier(domain))
}
// RemoveTxt removes a txt record from cache.
func (d *DNSCache) RemoveTxt(domain string) bool {
return d.txtCache.Rem(domainToIdentifier(domain))
}
// Size returns total domains maintained into this cache.
// The first returned value determines number of ip domains.
// The second returned value determines number of txt records.
func (d DNSCache) Size() (uint, uint) {
return d.ipCache.Size(), d.txtCache.Size()
}
// ipEntity is a dns cache entry for ip records.
type ipEntity struct {
// caching identifier to avoid cpu overhead
// per query.
id flow.Identifier
domain string
addresses []net.IPAddr
timestamp int64
}
func (i ipEntity) ID() flow.Identifier {
return i.id
}
func (i ipEntity) Checksum() flow.Identifier {
return domainToIdentifier(i.domain)
}
// txtEntity is a dns cache entry for txt records.
type txtEntity struct {
// caching identifier to avoid cpu overhead
// per query.
id flow.Identifier
txt string
record []string
timestamp int64
}
func (t txtEntity) ID() flow.Identifier {
return t.id
}
func (t txtEntity) Checksum() flow.Identifier {
return domainToIdentifier(t.txt)
}
func domainToIdentifier(domain string) flow.Identifier {
return flow.MakeID(domain)
}