Browse Source

ipn, ipn/ipnlocal: add Foreground field to ServeConfig

This PR adds a new field to the ServeConfig which maps
WatchIPNBus session ids to foreground serve configs.

The PR also adds a DeleteForegroundSession method to ensure the config
gets cleaned up on sessions ending.

Note this field is not currently used but will be in follow up work.

Updates #8489

Signed-off-by: Marwan Sulaiman <[email protected]>
Marwan Sulaiman 2 năm trước cách đây
mục cha
commit
45eeef244e
5 tập tin đã thay đổi với 41 bổ sung0 xóa
  1. 7 0
      ipn/ipn_clone.go
  2. 7 0
      ipn/ipn_view.go
  3. 2 0
      ipn/ipnlocal/local.go
  4. 17 0
      ipn/ipnlocal/serve.go
  5. 8 0
      ipn/serve.go

+ 7 - 0
ipn/ipn_clone.go

@@ -76,6 +76,12 @@ func (src *ServeConfig) Clone() *ServeConfig {
 		}
 	}
 	dst.AllowFunnel = maps.Clone(src.AllowFunnel)
+	if dst.Foreground != nil {
+		dst.Foreground = map[string]*ServeConfig{}
+		for k, v := range src.Foreground {
+			dst.Foreground[k] = v.Clone()
+		}
+	}
 	return dst
 }
 
@@ -84,6 +90,7 @@ var _ServeConfigCloneNeedsRegeneration = ServeConfig(struct {
 	TCP         map[uint16]*TCPPortHandler
 	Web         map[HostPort]*WebServerConfig
 	AllowFunnel map[HostPort]bool
+	Foreground  map[string]*ServeConfig
 }{})
 
 // Clone makes a deep copy of TCPPortHandler.

+ 7 - 0
ipn/ipn_view.go

@@ -177,11 +177,18 @@ func (v ServeConfigView) AllowFunnel() views.Map[HostPort, bool] {
 	return views.MapOf(v.ж.AllowFunnel)
 }
 
+func (v ServeConfigView) Foreground() views.MapFn[string, *ServeConfig, ServeConfigView] {
+	return views.MapFnOf(v.ж.Foreground, func(t *ServeConfig) ServeConfigView {
+		return t.View()
+	})
+}
+
 // A compilation failure here means this code must be regenerated, with the command at the top of this file.
 var _ServeConfigViewNeedsRegeneration = ServeConfig(struct {
 	TCP         map[uint16]*TCPPortHandler
 	Web         map[HostPort]*WebServerConfig
 	AllowFunnel map[HostPort]bool
+	Foreground  map[string]*ServeConfig
 }{})
 
 // View returns a readonly view of TCPPortHandler.

+ 2 - 0
ipn/ipnlocal/local.go

@@ -2014,6 +2014,8 @@ func (b *LocalBackend) WatchNotifications(ctx context.Context, mask ipn.NotifyWa
 		go b.pollRequestEngineStatus(ctx)
 	}
 
+	defer b.DeleteForegroundSession(sessionID) // TODO(marwan-at-work): check err
+
 	for {
 		select {
 		case <-ctx.Done():

+ 17 - 0
ipn/ipnlocal/serve.go

@@ -218,7 +218,10 @@ func (b *LocalBackend) updateServeTCPPortNetMapAddrListenersLocked(ports []uint1
 func (b *LocalBackend) SetServeConfig(config *ipn.ServeConfig) error {
 	b.mu.Lock()
 	defer b.mu.Unlock()
+	return b.setServeConfigLocked(config)
+}
 
+func (b *LocalBackend) setServeConfigLocked(config *ipn.ServeConfig) error {
 	prefs := b.pm.CurrentPrefs()
 	if config.IsFunnelOn() && prefs.ShieldsUp() {
 		return errors.New("Unable to turn on Funnel while shields-up is enabled")
@@ -258,6 +261,20 @@ func (b *LocalBackend) ServeConfig() ipn.ServeConfigView {
 	return b.serveConfig
 }
 
+// DeleteForegroundSession deletes a ServeConfig's foreground session
+// in the LocalBackend if it exists. It also ensures check, delete, and
+// set operations happen within the same mutex lock to avoid any races.
+func (b *LocalBackend) DeleteForegroundSession(sessionID string) error {
+	b.mu.Lock()
+	defer b.mu.Unlock()
+	if !b.serveConfig.Valid() || !b.serveConfig.Foreground().Has(sessionID) {
+		return nil
+	}
+	sc := b.serveConfig.AsStruct()
+	delete(sc.Foreground, sessionID)
+	return b.setServeConfigLocked(sc)
+}
+
 // StreamServe opens a stream to write any incoming connections made
 // to the given HostPort out to the listening io.Writer.
 //

+ 8 - 0
ipn/serve.go

@@ -37,6 +37,14 @@ type ServeConfig struct {
 	// AllowFunnel is the set of SNI:port values for which funnel
 	// traffic is allowed, from trusted ingress peers.
 	AllowFunnel map[HostPort]bool `json:",omitempty"`
+
+	// Foreground is a map of an IPN Bus session id to a
+	// foreground serve config. Note that only TCP and Web
+	// are used inside the Foreground map.
+	//
+	// TODO(marwan-at-work): this is not currently
+	// used. Remove the TODO in the follow up PR.
+	Foreground map[string]*ServeConfig `json:",omitempty"`
 }
 
 // HostPort is an SNI name and port number, joined by a colon.