Skip to content

Commit d9b29b6

Browse files
committed
all: imp style, imp tests
1 parent 8b03cab commit d9b29b6

File tree

9 files changed

+158
-143
lines changed

9 files changed

+158
-143
lines changed

internal/cmd/args.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -439,8 +439,8 @@ func parseCmdLineOptions(conf *configuration) (err error) {
439439
timeoutIdx: &conf.Timeout,
440440
cacheMinTTLIdx: &conf.CacheMinTTL,
441441
cacheMaxTTLIdx: &conf.CacheMaxTTL,
442-
cacheOptimisticAnswerTTLIdx: &conf.CacheOptimisticAnswerTTL,
443-
cacheOptimisticMaxAgeIdx: &conf.CacheOptimisticMaxAge,
442+
cacheOptimisticAnswerTTLIdx: &conf.OptimisticAnswerTTL,
443+
cacheOptimisticMaxAgeIdx: &conf.OptimisticMaxAge,
444444
cacheSizeBytesIdx: &conf.CacheSizeBytes,
445445
ratelimitIdx: &conf.Ratelimit,
446446
ratelimitSubnetLenIPv4Idx: &conf.RatelimitSubnetLenIPv4,

internal/cmd/config.go

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -107,13 +107,13 @@ type configuration struct {
107107
// greater.
108108
CacheMaxTTL uint32 `yaml:"cache-max-ttl"`
109109

110-
// CacheOptimisticAnswerTTL is the default TTL for expired cached responses
110+
// OptimisticAnswerTTL is the default TTL for expired cached responses
111111
// in seconds.
112-
CacheOptimisticAnswerTTL timeutil.Duration `yaml:"optimistic-answers-ttl"`
112+
OptimisticAnswerTTL timeutil.Duration `yaml:"optimistic-answers-ttl"`
113113

114-
// CacheOptimisticMaxAge is the maximum time entries remain in the cache
114+
// OptimisticMaxAge is the maximum time entries remain in the cache
115115
// when cache is optimistic.
116-
CacheOptimisticMaxAge timeutil.Duration `yaml:"optimistic-max-age"`
116+
OptimisticMaxAge timeutil.Duration `yaml:"optimistic-max-age"`
117117

118118
// CacheSizeBytes is the cache size in bytes. Default is 64k.
119119
CacheSizeBytes int `yaml:"cache-size"`
@@ -206,16 +206,16 @@ type configuration struct {
206206
// no options have been parsed, it returns a suitable exit code and an error.
207207
func parseConfig() (conf *configuration, exitCode int, err error) {
208208
conf = &configuration{
209-
HTTPSServerName: "dnsproxy",
210-
UpstreamMode: string(proxy.UpstreamModeLoadBalance),
211-
CacheSizeBytes: 64 * 1024,
212-
Timeout: timeutil.Duration(10 * time.Second),
213-
CacheOptimisticAnswerTTL: timeutil.Duration(30 * time.Second),
214-
CacheOptimisticMaxAge: timeutil.Duration(12 * time.Hour),
215-
RatelimitSubnetLenIPv4: 24,
216-
RatelimitSubnetLenIPv6: 56,
217-
HostsFileEnabled: true,
218-
PendingRequestsEnabled: true,
209+
HTTPSServerName: "dnsproxy",
210+
UpstreamMode: string(proxy.UpstreamModeLoadBalance),
211+
CacheSizeBytes: 64 * 1024,
212+
Timeout: timeutil.Duration(10 * time.Second),
213+
OptimisticAnswerTTL: timeutil.Duration(30 * time.Second),
214+
OptimisticMaxAge: timeutil.Duration(12 * time.Hour),
215+
RatelimitSubnetLenIPv4: 24,
216+
RatelimitSubnetLenIPv6: 56,
217+
HostsFileEnabled: true,
218+
PendingRequestsEnabled: true,
219219
}
220220

221221
err = parseCmdLineOptions(conf)

internal/cmd/proxy.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ func createProxyConfig(
6363
CacheSizeBytes: conf.CacheSizeBytes,
6464
CacheMinTTL: conf.CacheMinTTL,
6565
CacheMaxTTL: conf.CacheMaxTTL,
66-
CacheOptimisticAnswerTTL: uint32(time.Duration(conf.CacheOptimisticAnswerTTL).Seconds()),
67-
CacheOptimisticMaxAge: uint32(time.Duration(conf.CacheOptimisticMaxAge).Seconds()),
66+
CacheOptimisticAnswerTTL: time.Duration(conf.OptimisticAnswerTTL),
67+
CacheOptimisticMaxAge: time.Duration(conf.OptimisticMaxAge),
6868
CacheOptimistic: conf.CacheOptimistic,
6969
RefuseAny: conf.RefuseAny,
7070
HTTP3: conf.HTTP3,

proxy/cache.go

Lines changed: 57 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -40,21 +40,20 @@ type cache struct {
4040
// those again.
4141
optimistic bool
4242

43-
// optimisticTTL is the default TTL for expired cached responses in seconds.
44-
optimisticTTL uint32
43+
// optimisticTTL is the default TTL for expired cached responses.
44+
optimisticTTL time.Duration
4545

4646
// optimisticMaxAge is the maximum time entries remain in the cache when
4747
// cache is optimistic.
48-
optimisticMaxAge uint32
48+
optimisticMaxAge time.Duration
4949
}
5050

5151
// cacheItem is a single cache entry. It's a helper type to aggregate the
5252
// item-specific logic.
5353
type cacheItem struct {
54-
createdTime time.Time
55-
m *dns.Msg
56-
u string
57-
ttl uint32
54+
m *dns.Msg
55+
u string
56+
ttl uint32
5857
}
5958

6059
// respToItem converts the pair of the response and upstream resolved the one
@@ -71,10 +70,9 @@ func (c *cache) respToItem(m *dns.Msg, u upstream.Upstream, l *slog.Logger) (ite
7170
}
7271

7372
return &cacheItem{
74-
m: m,
75-
u: upsAddr,
76-
ttl: ttl,
77-
createdTime: time.Now(),
73+
m: m,
74+
u: upsAddr,
75+
ttl: ttl,
7876
}
7977
}
8078

@@ -85,12 +83,9 @@ const (
8583
// expTimeSz is the exact length of byte slice capable to store the
8684
// expiration time the response. It's essentially the size of a uint32.
8785
expTimeSz = 4
88-
// createdTimeSz is the exact length of byte slice capable to store the
89-
// creation time. It's essentially the size of a uint32.
90-
createdTimeSz = 4
9186

9287
// minPackedLen is the minimum length of the packed cacheItem.
93-
minPackedLen = expTimeSz + createdTimeSz + packedMsgLenSz
88+
minPackedLen = expTimeSz + packedMsgLenSz
9489
)
9590

9691
// pack converts the ci into bytes slice.
@@ -102,11 +97,8 @@ func (ci *cacheItem) pack() (packed []byte) {
10297
// Put expiration time.
10398
binary.BigEndian.PutUint32(packed, uint32(time.Now().Unix())+ci.ttl)
10499

105-
// Put creation time.
106-
binary.BigEndian.PutUint32(packed[expTimeSz:], uint32(ci.createdTime.Unix()))
107-
108100
// Put the length of the packed message.
109-
binary.BigEndian.PutUint16(packed[expTimeSz+createdTimeSz:], uint16(pmLen))
101+
binary.BigEndian.PutUint16(packed[expTimeSz:], uint16(pmLen))
110102

111103
// Put the packed message itself.
112104
packed = append(packed, pm...)
@@ -119,25 +111,26 @@ func (ci *cacheItem) pack() (packed []byte) {
119111

120112
// unpackItem converts the data into cacheItem using req as a request message.
121113
// expired is true if the item exists but expired. The expired cached items are
122-
// only returned if c is optimistic. req must not be nil.
114+
// only returned if c is optimistic and optimistic max age is not exceeded. req
115+
// must not be nil.
123116
func (c *cache) unpackItem(data []byte, req *dns.Msg) (ci *cacheItem, expired bool) {
124117
if len(data) < minPackedLen {
125118
return nil, false
126119
}
127120

128121
b := bytes.NewBuffer(data)
129-
expire := int64(binary.BigEndian.Uint32(b.Next(expTimeSz)))
130-
createdTime := time.Unix(int64(binary.BigEndian.Uint32(b.Next(createdTimeSz))), 0)
131-
now := time.Now().Unix()
122+
expire := time.Unix(int64(binary.BigEndian.Uint32(b.Next(expTimeSz))), 0)
123+
now := time.Now()
132124
var ttl uint32
133-
if expired = expire <= now; expired {
134-
if !c.optimistic {
125+
if expired = now.After(expire); expired {
126+
optimisticExpire := expire.Add(c.optimisticMaxAge)
127+
if !c.optimistic || now.After(optimisticExpire) {
135128
return nil, expired
136129
}
137130

138-
ttl = c.optimisticTTL
131+
ttl = uint32(c.optimisticTTL.Seconds())
139132
} else {
140-
ttl = uint32(expire - now)
133+
ttl = uint32(expire.Unix() - now.Unix())
141134
}
142135

143136
l := int(binary.BigEndian.Uint16(b.Next(packedMsgLenSz)))
@@ -165,9 +158,8 @@ func (c *cache) unpackItem(data []byte, req *dns.Msg) (ci *cacheItem, expired bo
165158
filterMsg(res, m, req.AuthenticatedData, doBit, ttl)
166159

167160
return &cacheItem{
168-
m: res,
169-
u: string(b.Next(b.Len())),
170-
createdTime: createdTime,
161+
m: res,
162+
u: string(b.Next(b.Len())),
171163
}, expired
172164
}
173165

@@ -181,35 +173,50 @@ func (p *Proxy) initCache() {
181173

182174
size := p.CacheSizeBytes
183175
p.logger.Info("cache enabled", "size", size)
184-
p.cache = newCache(
185-
size,
186-
p.CacheOptimisticAnswerTTL,
187-
p.CacheOptimisticMaxAge,
188-
p.EnableEDNSClientSubnet,
189-
p.CacheOptimistic,
190-
)
176+
p.cache = newCache(&cacheConfig{
177+
size: size,
178+
optimisticTTL: p.CacheOptimisticAnswerTTL,
179+
optimisticMaxAge: p.CacheOptimisticMaxAge,
180+
withECS: p.EnableEDNSClientSubnet,
181+
optimistic: p.CacheOptimistic,
182+
})
191183
p.shortFlighter = newOptimisticResolver(p)
192184
}
193185

186+
// cacheConfig is the configuration structure for [cache].
187+
type cacheConfig struct {
188+
// size is the cache size in bytes.
189+
size int
190+
191+
// optimisticTTL is the default TTL for expired cached responses when
192+
// optimistic is enabled.
193+
optimisticTTL time.Duration
194+
195+
// optimisticMaxAge is the maximum time entries remain in the cache when
196+
// cache is optimistic.
197+
optimisticMaxAge time.Duration
198+
199+
// withECS enables EDNS Client Subnet support for cache.
200+
withECS bool
201+
202+
// optimistic defines if the cache should return expired items and resolve
203+
// those again.
204+
optimistic bool
205+
}
206+
194207
// newCache returns a properly initialized cache. logger must not be nil.
195-
func newCache(
196-
size int,
197-
optimisticTTL,
198-
optimisticMaxAge uint32,
199-
withECS,
200-
optimistic bool,
201-
) (c *cache) {
208+
func newCache(conf *cacheConfig) (c *cache) {
202209
c = &cache{
203210
itemsLock: &sync.RWMutex{},
204211
itemsWithSubnetLock: &sync.RWMutex{},
205-
items: createCache(size),
206-
optimistic: optimistic,
207-
optimisticTTL: optimisticTTL,
208-
optimisticMaxAge: optimisticMaxAge,
212+
items: createCache(conf.size),
213+
optimistic: conf.optimistic,
214+
optimisticTTL: conf.optimisticTTL,
215+
optimisticMaxAge: conf.optimisticMaxAge,
209216
}
210217

211-
if withECS {
212-
c.itemsWithSubnet = createCache(size)
218+
if conf.withECS {
219+
c.itemsWithSubnet = createCache(conf.size)
213220
}
214221

215222
return c
@@ -236,21 +243,9 @@ func (c *cache) get(req *dns.Msg) (ci *cacheItem, expired bool, key []byte) {
236243
c.items.Del(key)
237244
}
238245

239-
if c.isOptimisticExpired(ci) {
240-
c.items.Del(key)
241-
242-
return nil, false, key
243-
}
244-
245246
return ci, expired, key
246247
}
247248

248-
// isOptimisticExpired returns true if cache is optimistic and expired item
249-
// should be deleted explicitly. ci must not be nil.
250-
func (c *cache) isOptimisticExpired(ci *cacheItem) (expired bool) {
251-
return c.optimistic && uint32(time.Since(ci.createdTime).Seconds()) > ci.ttl+c.optimisticMaxAge
252-
}
253-
254249
// getWithSubnet returns cached item for the req if it's found by n. expired
255250
// is true if the item's TTL is expired. k is the resulting key for req. It's
256251
// returned to avoid recalculating it afterwards.

0 commit comments

Comments
 (0)