blob: 55a4ed39fd7f58f243d260cfafc56c31bb285804 [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package netconfig implements a network configuration watcher.
package netconfig
// NOTE(p): This is also where we should put any code that changes
// network configuration.
import (
"net"
"sync"
"time"
)
var globalNotifier notifier
// NotifyChange returns a channel that will be closed when the network
// configuration changes from the time this function was invoked.
//
// This may provide false positivies, i.e., a network change
// will cause the channel to be closed but a channel closure
// may not imply a network change.
func NotifyChange() (<-chan struct{}, error) {
return globalNotifier.add()
}
// IPRoute represents a route in the kernel's routing table.
// Any route with a nil Gateway is a directly connected network.
type IPRoute struct {
Net net.IPNet
Gateway net.IP
PreferredSource net.IP
IfcIndex int
}
type notifier struct {
sync.Mutex
ch chan struct{}
timer *time.Timer
initErr error
inited bool
}
func (n *notifier) add() (<-chan struct{}, error) {
n.Lock()
defer n.Unlock()
if !n.inited {
n.ch = make(chan struct{})
n.initErr = n.initLocked()
n.inited = true
}
if n.initErr != nil {
return nil, n.initErr
}
return n.ch, nil
}
func (n *notifier) ding() {
// Changing networks usually spans many seconds and involves
// multiple network config changes. We add histeresis by
// setting an alarm when the first change is detected and
// not informing the client till the alarm goes off.
// NOTE(p): I chose 3 seconds because that covers all the
// events involved in moving from one wifi network to another.
n.Lock()
if n.timer == nil {
n.timer = time.AfterFunc(3*time.Second, n.resetChan)
}
n.Unlock()
}
func (n *notifier) resetChan() {
n.Lock()
close(n.ch)
n.ch = make(chan struct{})
n.timer = nil
n.Unlock()
}