ipn/ipnlocal: make active IPN sessions keyed by sessionID

We used a HandleSet before when we didn't have a unique handle. But a
sessionID is a unique handle, so use that instead. Then that replaces
the other map we had.

And now we'll have a way to look up an IPN session by sessionID for
later.

Updates tailscale/corp#17859

Change-Id: I5f647f367563ec8783c643e49f93817b341d9064
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick 2024-02-28 13:56:30 -08:00 committed by Brad Fitzpatrick
parent 2d5d6f5403
commit b68a09cb34
2 changed files with 9 additions and 16 deletions

View File

@ -252,8 +252,8 @@ type LocalBackend struct {
peerAPIListeners []*peerAPIListener
loginFlags controlclient.LoginFlags
fileWaiters set.HandleSet[context.CancelFunc] // of wake-up funcs
notifyWatchers set.HandleSet[*watchSession]
lastStatusTime time.Time // status.AsOf value of the last processed status update
notifyWatchers map[string]*watchSession // by session ID
lastStatusTime time.Time // status.AsOf value of the last processed status update
// directFileRoot, if non-empty, means to write received files
// directly to this directory, without staging them in an
// intermediate buffered directory for "pick-up" later. If
@ -278,9 +278,8 @@ type LocalBackend struct {
capForcedNetfilter string
// ServeConfig fields. (also guarded by mu)
lastServeConfJSON mem.RO // last JSON that was parsed into serveConfig
serveConfig ipn.ServeConfigView // or !Valid if none
activeWatchSessions set.Set[string] // of WatchIPN SessionID
lastServeConfJSON mem.RO // last JSON that was parsed into serveConfig
serveConfig ipn.ServeConfigView // or !Valid if none
webClient webClient
webClientListeners map[netip.AddrPort]*localListener // listeners for local web client traffic
@ -382,7 +381,6 @@ func NewLocalBackend(logf logger.Logf, logID logid.PublicID, sys *tsd.System, lo
gotPortPollRes: make(chan struct{}),
loginFlags: loginFlags,
clock: clock,
activeWatchSessions: make(set.Set[string]),
selfUpdateProgress: make([]ipnstate.UpdateProgress, 0),
lastSelfUpdateState: ipnstate.UpdateFinished,
}
@ -2266,7 +2264,6 @@ func (b *LocalBackend) WatchNotifications(ctx context.Context, mask ipn.NotifyWa
var ini *ipn.Notify
b.mu.Lock()
b.activeWatchSessions.Add(sessionID)
const initialBits = ipn.NotifyInitialState | ipn.NotifyInitialPrefs | ipn.NotifyInitialNetMap | ipn.NotifyInitialTailFSShares
if mask&initialBits != 0 {
@ -2297,13 +2294,12 @@ func (b *LocalBackend) WatchNotifications(ctx context.Context, mask ipn.NotifyWa
}
}
handle := b.notifyWatchers.Add(&watchSession{ch, sessionID})
mak.Set(&b.notifyWatchers, sessionID, &watchSession{ch, sessionID})
b.mu.Unlock()
defer func() {
b.mu.Lock()
delete(b.notifyWatchers, handle)
delete(b.activeWatchSessions, sessionID)
delete(b.notifyWatchers, sessionID)
b.mu.Unlock()
}()
@ -4768,8 +4764,9 @@ func (b *LocalBackend) reloadServeConfigLocked(prefs ipn.PrefsView) {
}
// remove inactive sessions
maps.DeleteFunc(conf.Foreground, func(s string, sc *ipn.ServeConfig) bool {
return !b.activeWatchSessions.Contains(s)
maps.DeleteFunc(conf.Foreground, func(sessionID string, sc *ipn.ServeConfig) bool {
_, ok := b.notifyWatchers[sessionID]
return !ok
})
b.serveConfig = conf.View()

View File

@ -37,7 +37,6 @@ import (
"tailscale.com/util/dnsname"
"tailscale.com/util/mak"
"tailscale.com/util/must"
"tailscale.com/util/set"
"tailscale.com/util/syspolicy"
"tailscale.com/wgengine"
"tailscale.com/wgengine/filter"
@ -765,9 +764,6 @@ var _ legacyBackend = (*LocalBackend)(nil)
func TestWatchNotificationsCallbacks(t *testing.T) {
b := new(LocalBackend)
// activeWatchSessions is typically set in NewLocalBackend
// so WatchNotifications expects it to be non-empty.
b.activeWatchSessions = make(set.Set[string])
n := new(ipn.Notify)
b.WatchNotifications(context.Background(), 0, func() {
b.mu.Lock()