/
proc.go
129 lines (108 loc) · 2.68 KB
/
proc.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
package proc
import (
"net"
"sync"
"time"
)
var (
cacheInterval = time.Duration(60) * time.Second
cacheUpdated time.Time
mtx sync.RWMutex
connCache map[string]int
once sync.Once
)
func setup() {
loadConnCache(true)
}
func init() {
once.Do(setup)
}
// connCacheLoader runs a loop which updates the tcp connection count cache.
func connCacheLoader() {
for {
loadConnCache(false)
time.Sleep(cacheInterval)
}
}
// loadConnCache loads the tcp connection count cache.
func loadConnCache(force bool) {
mtx.Lock()
defer mtx.Unlock()
// If below cache interval just return
u := time.Now().Sub(cacheUpdated).Seconds()
if connCache != nil && force == false && u < cacheInterval.Seconds() {
return
}
conns, err := establishedTcpConns()
if err != nil {
return
}
connCache = conns
cacheUpdated = time.Now()
}
// numRemoteTcpConns returns the number of tcp establishes connections to a remote host.
// Host argument needs to be in the form host:port
func numRemoteTcpConns(host string) int {
mtx.RLock()
defer mtx.RUnlock()
// sanity check
if connCache == nil {
return 0
}
// split host port
hst, port, err := net.SplitHostPort(host)
if err != nil {
return 0
}
// Resolve the host
ips, err := net.LookupIP(hst)
if err != nil {
return 0
}
// Get an ipv4 addr
var addr string
for _, ip := range ips {
if i := ip.To4(); i != nil {
addr = i.String()
break
}
}
// Found an ipv4 addr?
if len(addr) == 0 {
return 0
}
rhost := net.JoinHostPort(addr, port)
return connCache[rhost]
}
// CachedNumRemoteTcpConns retrieves the number of established tcp connections for a remote host
// from the cache. Host argument should be of the form host:port
func CachedNumRemoteTcpConns(host string) int {
loadConnCache(false)
return numRemoteTcpConns(host)
}
// CachedRemoteTcpConns returns a map containing the number of tcp connections for all remote
// hosts connected to by this process.
func CachedRemoteTcpConns() map[string]int {
loadConnCache(false)
mtx.RLock()
defer mtx.RUnlock()
return connCache
}
// NumRemoteTcpConns forces a cache update and retrieves the number of established tcp connections
// for a remote host. Host argument should be of the form host:port
func NumRemoteTcpConns(host string) int {
loadConnCache(true)
return numRemoteTcpConns(host)
}
// RemoteTcpConns forces a cache update and returns a map containing the number of tcp connections
// for all remote hosts connected to by this process.
func RemoteTcpConns() map[string]int {
loadConnCache(true)
mtx.RLock()
defer mtx.RUnlock()
return connCache
}
// RunCacheLoader starts the cache loader in a background routine
func RunCacheLoader() {
go connCacheLoader()
}