ipn{,/ipnlocal}: add ipn.NotifyInitial* flags to WatchIPNBus

To simplify clients getting the initial state when they subscribe.

Change-Id: I2490a5ab2411253717c74265a46a98012b80db82
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
pull/6586/head
Brad Fitzpatrick 1 year ago committed by Brad Fitzpatrick
parent 197a4f1ae8
commit 8dd1418774

@ -133,6 +133,7 @@ var debugCmd = &ffcli.Command{
FlagSet: (func() *flag.FlagSet {
fs := newFlagSet("watch-ipn")
fs.BoolVar(&watchIPNArgs.netmap, "netmap", true, "include netmap in messages")
fs.BoolVar(&watchIPNArgs.initial, "initial", false, "include initial status")
return fs
})(),
},
@ -318,11 +319,16 @@ func runPrefs(ctx context.Context, args []string) error {
}
var watchIPNArgs struct {
netmap bool
netmap bool
initial bool
}
func runWatchIPN(ctx context.Context, args []string) error {
watcher, err := localClient.WatchIPNBus(ctx, 0)
var mask ipn.NotifyWatchOpt
if watchIPNArgs.initial {
mask = ipn.NotifyInitialState | ipn.NotifyInitialPrefs | ipn.NotifyInitialNetMap
}
watcher, err := localClient.WatchIPNBus(ctx, mask)
if err != nil {
return err
}

@ -61,6 +61,10 @@ const (
// client either regularly or when they change, without having to ask for
// each one via RequestEngineStatus.
NotifyWatchEngineUpdates NotifyWatchOpt = 1 << iota
NotifyInitialState // if set, the first Notify message (sent immediately) will contain the current State + BrowseToURL
NotifyInitialPrefs // if set, the first Notify message (sent immediately) will contain the current Prefs
NotifyInitialNetMap // if set, the first Notify message (sent immediately) will contain the current NetMap
)
// Notify is a communication from a backend (e.g. tailscaled) to a frontend

@ -59,6 +59,7 @@ import (
"tailscale.com/types/netmap"
"tailscale.com/types/persist"
"tailscale.com/types/preftype"
"tailscale.com/types/ptr"
"tailscale.com/types/views"
"tailscale.com/util/deephash"
"tailscale.com/util/dnsname"
@ -534,6 +535,10 @@ func stripKeysFromPrefs(p ipn.PrefsView) ipn.PrefsView {
func (b *LocalBackend) Prefs() ipn.PrefsView {
b.mu.Lock()
defer b.mu.Unlock()
return b.prefsLocked()
}
func (b *LocalBackend) prefsLocked() ipn.PrefsView {
return stripKeysFromPrefs(b.pm.CurrentPrefs())
}
@ -1736,15 +1741,41 @@ func (b *LocalBackend) readPoller() {
func (b *LocalBackend) WatchNotifications(ctx context.Context, mask ipn.NotifyWatchOpt, fn func(roNotify *ipn.Notify) (keepGoing bool)) {
ch := make(chan *ipn.Notify, 128)
var ini *ipn.Notify
b.mu.Lock()
const initialBits = ipn.NotifyInitialState | ipn.NotifyInitialPrefs | ipn.NotifyInitialNetMap
if mask&initialBits != 0 {
ini = &ipn.Notify{}
if mask&ipn.NotifyInitialState != 0 {
ini.State = ptr.To(b.state)
if b.state == ipn.NeedsLogin {
ini.BrowseToURL = ptr.To(b.authURLSticky)
}
}
if mask&ipn.NotifyInitialPrefs != 0 {
ini.Prefs = ptr.To(b.prefsLocked())
}
if mask&ipn.NotifyInitialNetMap != 0 {
ini.NetMap = b.netMap
}
}
handle := b.notifyWatchers.Add(ch)
b.mu.Unlock()
defer func() {
b.mu.Lock()
delete(b.notifyWatchers, handle)
b.mu.Unlock()
}()
if ini != nil {
if !fn(ini) {
return
}
}
// The GUI clients want to know when peers become active or inactive.
// They've historically got this information by polling for it, which is
// wasteful. As a step towards making it efficient, they now set this

Loading…
Cancel
Save