@@ -14,11 +14,7 @@ import (
1414 "github.com/jedisct1/dlog"
1515)
1616
17- const (
18- defaultNetworkMonitorInterval = 5 * time .Second
19- maxNetworkMonitorBackoff = 30 * time .Second
20- offlineNetworkFingerprint = "offline"
21- )
17+ const defaultNetworkMonitorInterval = 60 * time .Second
2218
2319type networkInterfaceSnapshot struct {
2420 Name string
@@ -29,35 +25,17 @@ type networkInterfaceSnapshot struct {
2925 Addrs []* net.IPNet
3026}
3127
32- type networkMonitorProbeState struct {
33- address string
34- retryAt time.Time
35- backoff time.Duration
36- }
37-
3828type networkMonitor struct {
3929 epochValue atomic.Uint64
4030 sampling atomic.Bool
4131 initialized bool
4232 lastInterfaces string
43- lastRoutes string
44- probes [2 ]networkMonitorProbeState
45- now func () time.Time
4633 interfaces func () ([]networkInterfaceSnapshot , error )
47- probe func (string ) (net.IP , error )
4834 onChange func ()
4935}
5036
5137func newNetworkMonitor () * networkMonitor {
52- return & networkMonitor {
53- probes : [2 ]networkMonitorProbeState {
54- {address : "192.0.2.1:9" },
55- {address : "[2001:db8::1]:9" },
56- },
57- now : time .Now ,
58- interfaces : snapshotNetworkInterfaces ,
59- probe : probeNetworkMonitorLocalIP ,
60- }
38+ return & networkMonitor {interfaces : snapshotNetworkInterfaces }
6139}
6240
6341func (monitor * networkMonitor ) epoch () uint64 {
@@ -120,27 +98,13 @@ func (monitor *networkMonitor) check() {
12098
12199func (monitor * networkMonitor ) sample (notify bool ) {
122100 interfaces , err := monitor .interfaces ()
123- interfacesChanged := false
124- if err == nil {
125- interfaceFingerprint := buildNetworkInterfaceFingerprint (interfaces )
126- interfacesChanged = monitor .lastInterfaces != "" && monitor .lastInterfaces != interfaceFingerprint
127- monitor .lastInterfaces = interfaceFingerprint
128- if interfacesChanged {
129- for i := range monitor .probes {
130- monitor .probes [i ].retryAt = time.Time {}
131- monitor .probes [i ].backoff = 0
132- }
133- if notify {
134- monitor .notifyNetworkChange ()
135- }
136- }
101+ if err != nil {
102+ return
137103 }
138-
139- localIPs := monitor .discoverLocalIPs (monitor .now ())
140- routeFingerprint := buildNetworkFingerprint (localIPs )
141- routesChanged := monitor .lastRoutes != "" && monitor .lastRoutes != routeFingerprint
142- monitor .lastRoutes = routeFingerprint
143- if notify && routesChanged && ! interfacesChanged {
104+ fingerprint := buildNetworkInterfaceFingerprint (interfaces )
105+ changed := monitor .lastInterfaces != "" && monitor .lastInterfaces != fingerprint
106+ monitor .lastInterfaces = fingerprint
107+ if changed && notify {
144108 monitor .notifyNetworkChange ()
145109 }
146110}
@@ -153,53 +117,6 @@ func (monitor *networkMonitor) notifyNetworkChange() {
153117 }
154118}
155119
156- func (monitor * networkMonitor ) discoverLocalIPs (now time.Time ) []net.IP {
157- localIPs := make ([]net.IP , 0 , len (monitor .probes ))
158- seen := make (map [string ]struct {}, len (monitor .probes ))
159- for i := range monitor .probes {
160- state := & monitor .probes [i ]
161- if ! state .retryAt .IsZero () && now .Before (state .retryAt ) {
162- continue
163- }
164- ip , err := monitor .probe (state .address )
165- if err != nil {
166- if state .backoff == 0 {
167- state .backoff = defaultNetworkMonitorInterval
168- } else {
169- state .backoff = min (state .backoff * 2 , maxNetworkMonitorBackoff )
170- }
171- state .retryAt = now .Add (state .backoff )
172- continue
173- }
174- state .retryAt = time.Time {}
175- state .backoff = 0
176- if ip == nil || ip .IsUnspecified () {
177- continue
178- }
179- ip = append (net .IP (nil ), ip ... )
180- key := ip .String ()
181- if _ , ok := seen [key ]; ok {
182- continue
183- }
184- seen [key ] = struct {}{}
185- localIPs = append (localIPs , ip )
186- }
187- return localIPs
188- }
189-
190- func probeNetworkMonitorLocalIP (address string ) (net.IP , error ) {
191- conn , err := net .DialTimeout ("udp" , address , time .Second )
192- if err != nil {
193- return nil , err
194- }
195- defer conn .Close ()
196- localAddr , ok := conn .LocalAddr ().(* net.UDPAddr )
197- if ! ok || localAddr .IP == nil || localAddr .IP .IsUnspecified () {
198- return nil , net .InvalidAddrError ("missing local IP" )
199- }
200- return append (net .IP (nil ), localAddr .IP ... ), nil
201- }
202-
203120func snapshotNetworkInterfaces () ([]networkInterfaceSnapshot , error ) {
204121 interfaces , err := net .Interfaces ()
205122 if err != nil {
@@ -299,24 +216,6 @@ func buildNetworkInterfaceFingerprint(interfaces []networkInterfaceSnapshot) str
299216 return hashNetworkFingerprint (parts )
300217}
301218
302- func buildNetworkFingerprint (localIPs []net.IP ) string {
303- if len (localIPs ) == 0 {
304- return offlineNetworkFingerprint
305- }
306- parts := make ([]string , 0 , len (localIPs ))
307- for _ , ip := range localIPs {
308- if ip == nil || ip .IsUnspecified () {
309- continue
310- }
311- ip = append (net .IP (nil ), ip ... )
312- parts = append (parts , "ip=" + ip .String ())
313- }
314- if len (parts ) == 0 {
315- return offlineNetworkFingerprint
316- }
317- return hashNetworkFingerprint (parts )
318- }
319-
320219func hashNetworkFingerprint (parts []string ) string {
321220 sort .Strings (parts )
322221 h := sha256 .New ()
0 commit comments