Skip to content

Commit

Permalink
Detect network interface change and restart the service when detected
Browse files Browse the repository at this point in the history
  • Loading branch information
rs committed Nov 23, 2019
1 parent 3337730 commit 50b3d2e
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 0 deletions.
80 changes: 80 additions & 0 deletions netstatus/netstatus.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package netstatus

import (
"context"
"net"
"reflect"
"sync"
"time"
)

type Change struct{}

var handlers struct {
sync.Mutex
c []chan<- Change
}

var cancel context.CancelFunc
var lastInterfaces []net.Interface

// Notify sends a Change to c any time the network interfaces status change.
func Notify(c chan<- Change) {
handlers.Lock()
defer handlers.Unlock()
if handlers.c == nil {
go startChecker()
}
handlers.c = append(handlers.c, c)
}

// Stop unsubscribes from network interfaces change notification.
func Stop(c chan<- Change) {
handlers.Lock()
defer handlers.Unlock()
var newC = make([]chan<- Change, 0, len(handlers.c)-1)
for _, ch := range handlers.c {
if ch != c {
newC = append(newC, c)
}
}
handlers.c = newC
if len(handlers.c) == 0 && cancel != nil {
cancel()
cancel = nil
}
}

func broadcast(c Change) {
handlers.Lock()
defer handlers.Unlock()
for _, ch := range handlers.c {
ch <- c
}
}

func startChecker() {
tick := time.NewTicker(30 * time.Second)
defer tick.Stop()
var ctx context.Context
ctx, cancel = context.WithCancel(context.Background())
defer cancel()
changed() // init
for {
select {
case <-tick.C:
if changed() {
broadcast(Change{})
}
case <-ctx.Done():
break
}
}
}

func changed() bool {
interfaces, _ := net.Interfaces()
changed := !reflect.DeepEqual(lastInterfaces, interfaces)
lastInterfaces = interfaces
return changed
}
16 changes: 16 additions & 0 deletions service.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (

cflag "github.com/nextdns/nextdns/flag"
"github.com/nextdns/nextdns/mdns"
"github.com/nextdns/nextdns/netstatus"
"github.com/nextdns/nextdns/proxy"
"github.com/nextdns/nextdns/resolver"
"github.com/nextdns/nextdns/resolver/endpoint"
Expand Down Expand Up @@ -54,6 +55,11 @@ func (p *proxySvc) Start(s service.Service) (err error) {
return nil
}

func (p *proxySvc) Restart() error {
p.Stop(nil)
return p.Start(nil)
}

func (p *proxySvc) Stop(s service.Service) error {
if p.stop != nil {
p.stop()
Expand Down Expand Up @@ -213,6 +219,16 @@ func svc(cmd string) error {
if *reportClientInfo {
setupClientReporting(p, conf)
}
go func() {
netChange := make(chan netstatus.Change)
netstatus.Notify(netChange)
for range netChange {
_ = log.Info("Network change detected, restarting")
if err := p.Restart(); err != nil {
_ = log.Errorf("Restart failed: %v", err)
}
}
}()
return s.Run()
default:
panic("unknown cmd: " + cmd)
Expand Down

0 comments on commit 50b3d2e

Please sign in to comment.