/
ip_resolver.go
121 lines (105 loc) · 2.43 KB
/
ip_resolver.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
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package helper // import "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator/helper"
import (
"net"
"sync"
"time"
)
// cacheEntry keeps information about host and expiration time
type cacheEntry struct {
hostname string
expireTime time.Time
}
const (
defaultInvalidationInterval time.Duration = 5 * time.Minute
)
type IPResolver struct {
cache map[string]cacheEntry
mutex sync.RWMutex
done chan bool
stopped bool
invalidationInterval time.Duration
}
// Create new resolver
func NewIPResolver() *IPResolver {
r := &IPResolver{
cache: make(map[string]cacheEntry),
stopped: false,
done: make(chan bool),
invalidationInterval: defaultInvalidationInterval,
}
r.start()
return r
}
// Stop cache invalidation
func (r *IPResolver) Stop() {
r.mutex.Lock()
if r.stopped {
r.mutex.Unlock()
return
}
r.stopped = true
r.mutex.Unlock()
r.done <- true
}
// start runs cache invalidation every 5 minutes
func (r *IPResolver) start() {
ticker := time.NewTicker(r.invalidationInterval)
go func() {
for {
select {
case <-r.done:
ticker.Stop()
return
case <-ticker.C:
r.mutex.Lock()
r.invalidateCache()
r.mutex.Unlock()
}
}
}()
}
// invalidateCache removes not longer valid entries from cache
func (r *IPResolver) invalidateCache() {
now := time.Now()
for key, entry := range r.cache {
if entry.expireTime.Before(now) {
delete(r.cache, key)
}
}
}
// GetHostFromIp returns hostname for given ip
// It is taken from cache if exists,
// otherwise lookup is performed and result is put into cache
func (r *IPResolver) GetHostFromIP(ip string) (host string) {
r.mutex.RLock()
entry, ok := r.cache[ip]
if ok {
host = entry.hostname
defer r.mutex.RUnlock()
return host
}
r.mutex.RUnlock()
host = r.lookupIPAddr(ip)
r.mutex.Lock()
r.cache[ip] = cacheEntry{
hostname: host,
expireTime: time.Now().Add(5 * time.Minute),
}
r.mutex.Unlock()
return host
}
// lookupIPAddr resturns hostname based on ip address
func (r *IPResolver) lookupIPAddr(ip string) (host string) {
res, err := net.LookupAddr(ip)
if err != nil || len(res) == 0 {
return ip
}
host = res[0]
// Trim one trailing '.'.
if last := len(host) - 1; last >= 0 && host[last] == '.' {
host = host[:last]
}
return host
}