From b68a09cb34a412c898f9fb36122e2a36087860f3 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Wed, 28 Feb 2024 13:56:30 -0800 Subject: [PATCH] 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 --- ipn/ipnlocal/local.go | 21 +++++++++------------ ipn/ipnlocal/local_test.go | 4 ---- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index 0fbc0a103..03d8b02d7 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -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() diff --git a/ipn/ipnlocal/local_test.go b/ipn/ipnlocal/local_test.go index 9d30cb77d..c2e6f1cbd 100644 --- a/ipn/ipnlocal/local_test.go +++ b/ipn/ipnlocal/local_test.go @@ -37,7 +37,6 @@ "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 @@ type legacyBackend interface { 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()