mirror of
https://github.com/netbirdio/netbird.git
synced 2024-12-02 04:53:51 +01:00
83 lines
2.1 KiB
Go
83 lines
2.1 KiB
Go
|
//go:build !ios && !android
|
||
|
|
||
|
package networkmonitor
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"errors"
|
||
|
"net"
|
||
|
"net/netip"
|
||
|
"runtime/debug"
|
||
|
|
||
|
"github.com/cenkalti/backoff/v4"
|
||
|
log "github.com/sirupsen/logrus"
|
||
|
|
||
|
"github.com/netbirdio/netbird/client/internal/routemanager"
|
||
|
)
|
||
|
|
||
|
// Start begins watching for network changes and calls the callback function and stops when a change is detected.
|
||
|
func (nw *NetworkWatcher) Start(ctx context.Context, callback func()) {
|
||
|
if nw.cancel != nil {
|
||
|
log.Warn("Network monitor: already running, stopping previous watcher")
|
||
|
nw.Stop()
|
||
|
}
|
||
|
|
||
|
if ctx.Err() != nil {
|
||
|
log.Info("Network monitor: not starting, context is already cancelled")
|
||
|
return
|
||
|
}
|
||
|
|
||
|
ctx, nw.cancel = context.WithCancel(ctx)
|
||
|
defer nw.Stop()
|
||
|
|
||
|
var nexthop4, nexthop6 netip.Addr
|
||
|
var intf4, intf6 *net.Interface
|
||
|
|
||
|
operation := func() error {
|
||
|
var errv4, errv6 error
|
||
|
nexthop4, intf4, errv4 = routemanager.GetNextHop(netip.IPv4Unspecified())
|
||
|
nexthop6, intf6, errv6 = routemanager.GetNextHop(netip.IPv6Unspecified())
|
||
|
|
||
|
if errv4 != nil && errv6 != nil {
|
||
|
return errors.New("failed to get default next hops")
|
||
|
}
|
||
|
|
||
|
if errv4 == nil {
|
||
|
log.Debugf("Network monitor: IPv4 default route: %s, interface: %s", nexthop4, intf4.Name)
|
||
|
}
|
||
|
if errv6 == nil {
|
||
|
log.Debugf("Network monitor: IPv6 default route: %s, interface: %s", nexthop6, intf6.Name)
|
||
|
}
|
||
|
|
||
|
// continue if either route was found
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
expBackOff := backoff.WithContext(backoff.NewExponentialBackOff(), ctx)
|
||
|
|
||
|
if err := backoff.Retry(operation, expBackOff); err != nil {
|
||
|
log.Errorf("Network monitor: failed to get default next hops: %v", err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// recover in case sys ops panic
|
||
|
defer func() {
|
||
|
if r := recover(); r != nil {
|
||
|
log.Errorf("Network monitor: panic occurred: %v, stack trace: %s", r, string(debug.Stack()))
|
||
|
}
|
||
|
}()
|
||
|
|
||
|
if err := checkChange(ctx, nexthop4, intf4, nexthop6, intf6, callback); err != nil && !errors.Is(err, context.Canceled) {
|
||
|
log.Errorf("Network monitor: failed to start: %v", err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Stop stops the network monitor.
|
||
|
func (nw *NetworkWatcher) Stop() {
|
||
|
if nw.cancel != nil {
|
||
|
nw.cancel()
|
||
|
nw.cancel = nil
|
||
|
log.Info("Network monitor: stopped")
|
||
|
}
|
||
|
}
|