get.pme.sh/pnats@v0.0.0-20240304004023-26bb5a137ed0/server/reload.go (about)

     1  // Copyright 2017-2023 The NATS Authors
     2  // Licensed under the Apache License, Version 2.0 (the "License");
     3  // you may not use this file except in compliance with the License.
     4  // You may obtain a copy of the License at
     5  //
     6  // http://www.apache.org/licenses/LICENSE-2.0
     7  //
     8  // Unless required by applicable law or agreed to in writing, software
     9  // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package server
    15  
    16  import (
    17  	"crypto/tls"
    18  	"errors"
    19  	"fmt"
    20  	"net/url"
    21  	"reflect"
    22  	"sort"
    23  	"strings"
    24  	"sync/atomic"
    25  	"time"
    26  
    27  	"github.com/klauspost/compress/s2"
    28  
    29  	"github.com/nats-io/jwt/v2"
    30  	"github.com/nats-io/nuid"
    31  )
    32  
    33  // FlagSnapshot captures the server options as specified by CLI flags at
    34  // startup. This should not be modified once the server has started.
    35  var FlagSnapshot *Options
    36  
    37  type reloadContext struct {
    38  	oldClusterPerms *RoutePermissions
    39  }
    40  
    41  // option is a hot-swappable configuration setting.
    42  type option interface {
    43  	// Apply the server option.
    44  	Apply(server *Server)
    45  
    46  	// IsLoggingChange indicates if this option requires reloading the logger.
    47  	IsLoggingChange() bool
    48  
    49  	// IsTraceLevelChange indicates if this option requires reloading cached trace level.
    50  	// Clients store trace level separately.
    51  	IsTraceLevelChange() bool
    52  
    53  	// IsAuthChange indicates if this option requires reloading authorization.
    54  	IsAuthChange() bool
    55  
    56  	// IsTLSChange indicates if this option requires reloading TLS.
    57  	IsTLSChange() bool
    58  
    59  	// IsClusterPermsChange indicates if this option requires reloading
    60  	// cluster permissions.
    61  	IsClusterPermsChange() bool
    62  
    63  	// IsClusterPoolSizeOrAccountsChange indicates if this option requires
    64  	// special handling for changes in cluster's pool size or accounts list.
    65  	IsClusterPoolSizeOrAccountsChange() bool
    66  
    67  	// IsJetStreamChange inidicates a change in the servers config for JetStream.
    68  	// Account changes will be handled separately in reloadAuthorization.
    69  	IsJetStreamChange() bool
    70  
    71  	// Indicates a change in the server that requires publishing the server's statz
    72  	IsStatszChange() bool
    73  }
    74  
    75  // noopOption is a base struct that provides default no-op behaviors.
    76  type noopOption struct{}
    77  
    78  func (n noopOption) IsLoggingChange() bool {
    79  	return false
    80  }
    81  
    82  func (n noopOption) IsTraceLevelChange() bool {
    83  	return false
    84  }
    85  
    86  func (n noopOption) IsAuthChange() bool {
    87  	return false
    88  }
    89  
    90  func (n noopOption) IsTLSChange() bool {
    91  	return false
    92  }
    93  
    94  func (n noopOption) IsClusterPermsChange() bool {
    95  	return false
    96  }
    97  
    98  func (n noopOption) IsClusterPoolSizeOrAccountsChange() bool {
    99  	return false
   100  }
   101  
   102  func (n noopOption) IsJetStreamChange() bool {
   103  	return false
   104  }
   105  
   106  func (n noopOption) IsStatszChange() bool {
   107  	return false
   108  }
   109  
   110  // loggingOption is a base struct that provides default option behaviors for
   111  // logging-related options.
   112  type loggingOption struct {
   113  	noopOption
   114  }
   115  
   116  func (l loggingOption) IsLoggingChange() bool {
   117  	return true
   118  }
   119  
   120  // traceLevelOption is a base struct that provides default option behaviors for
   121  // tracelevel-related options.
   122  type traceLevelOption struct {
   123  	loggingOption
   124  }
   125  
   126  func (l traceLevelOption) IsTraceLevelChange() bool {
   127  	return true
   128  }
   129  
   130  // traceOption implements the option interface for the `trace` setting.
   131  type traceOption struct {
   132  	traceLevelOption
   133  	newValue bool
   134  }
   135  
   136  // Apply is a no-op because logging will be reloaded after options are applied.
   137  func (t *traceOption) Apply(server *Server) {
   138  	server.Noticef("Reloaded: trace = %v", t.newValue)
   139  }
   140  
   141  // traceOption implements the option interface for the `trace` setting.
   142  type traceVerboseOption struct {
   143  	traceLevelOption
   144  	newValue bool
   145  }
   146  
   147  // Apply is a no-op because logging will be reloaded after options are applied.
   148  func (t *traceVerboseOption) Apply(server *Server) {
   149  	server.Noticef("Reloaded: trace_verbose = %v", t.newValue)
   150  }
   151  
   152  // debugOption implements the option interface for the `debug` setting.
   153  type debugOption struct {
   154  	loggingOption
   155  	newValue bool
   156  }
   157  
   158  // Apply is mostly a no-op because logging will be reloaded after options are applied.
   159  // However we will kick the raft nodes if they exist to reload.
   160  func (d *debugOption) Apply(server *Server) {
   161  	server.Noticef("Reloaded: debug = %v", d.newValue)
   162  	server.reloadDebugRaftNodes(d.newValue)
   163  }
   164  
   165  // logtimeOption implements the option interface for the `logtime` setting.
   166  type logtimeOption struct {
   167  	loggingOption
   168  	newValue bool
   169  }
   170  
   171  // Apply is a no-op because logging will be reloaded after options are applied.
   172  func (l *logtimeOption) Apply(server *Server) {
   173  	server.Noticef("Reloaded: logtime = %v", l.newValue)
   174  }
   175  
   176  // logtimeUTCOption implements the option interface for the `logtime_utc` setting.
   177  type logtimeUTCOption struct {
   178  	loggingOption
   179  	newValue bool
   180  }
   181  
   182  // Apply is a no-op because logging will be reloaded after options are applied.
   183  func (l *logtimeUTCOption) Apply(server *Server) {
   184  	server.Noticef("Reloaded: logtime_utc = %v", l.newValue)
   185  }
   186  
   187  // logfileOption implements the option interface for the `log_file` setting.
   188  type logfileOption struct {
   189  	loggingOption
   190  	newValue string
   191  }
   192  
   193  // Apply is a no-op because logging will be reloaded after options are applied.
   194  func (l *logfileOption) Apply(server *Server) {
   195  	server.Noticef("Reloaded: log_file = %v", l.newValue)
   196  }
   197  
   198  // syslogOption implements the option interface for the `syslog` setting.
   199  type syslogOption struct {
   200  	loggingOption
   201  	newValue bool
   202  }
   203  
   204  // Apply is a no-op because logging will be reloaded after options are applied.
   205  func (s *syslogOption) Apply(server *Server) {
   206  	server.Noticef("Reloaded: syslog = %v", s.newValue)
   207  }
   208  
   209  // remoteSyslogOption implements the option interface for the `remote_syslog`
   210  // setting.
   211  type remoteSyslogOption struct {
   212  	loggingOption
   213  	newValue string
   214  }
   215  
   216  // Apply is a no-op because logging will be reloaded after options are applied.
   217  func (r *remoteSyslogOption) Apply(server *Server) {
   218  	server.Noticef("Reloaded: remote_syslog = %v", r.newValue)
   219  }
   220  
   221  // tlsOption implements the option interface for the `tls` setting.
   222  type tlsOption struct {
   223  	noopOption
   224  	newValue *tls.Config
   225  }
   226  
   227  // Apply the tls change.
   228  func (t *tlsOption) Apply(server *Server) {
   229  	server.mu.Lock()
   230  	tlsRequired := t.newValue != nil
   231  	server.info.TLSRequired = tlsRequired && !server.getOpts().AllowNonTLS
   232  	message := "disabled"
   233  	if tlsRequired {
   234  		server.info.TLSVerify = (t.newValue.ClientAuth == tls.RequireAndVerifyClientCert)
   235  		message = "enabled"
   236  	}
   237  	server.mu.Unlock()
   238  	server.Noticef("Reloaded: tls = %s", message)
   239  }
   240  
   241  func (t *tlsOption) IsTLSChange() bool {
   242  	return true
   243  }
   244  
   245  // tlsTimeoutOption implements the option interface for the tls `timeout`
   246  // setting.
   247  type tlsTimeoutOption struct {
   248  	noopOption
   249  	newValue float64
   250  }
   251  
   252  // Apply is a no-op because the timeout will be reloaded after options are
   253  // applied.
   254  func (t *tlsTimeoutOption) Apply(server *Server) {
   255  	server.Noticef("Reloaded: tls timeout = %v", t.newValue)
   256  }
   257  
   258  // tlsPinnedCertOption implements the option interface for the tls `pinned_certs` setting.
   259  type tlsPinnedCertOption struct {
   260  	noopOption
   261  	newValue PinnedCertSet
   262  }
   263  
   264  // Apply is a no-op because the pinned certs will be reloaded after options are  applied.
   265  func (t *tlsPinnedCertOption) Apply(server *Server) {
   266  	server.Noticef("Reloaded: %d pinned_certs", len(t.newValue))
   267  }
   268  
   269  // tlsHandshakeFirst implements the option interface for the tls `handshake first` setting.
   270  type tlsHandshakeFirst struct {
   271  	noopOption
   272  	newValue bool
   273  }
   274  
   275  // Apply is a no-op because the timeout will be reloaded after options are applied.
   276  func (t *tlsHandshakeFirst) Apply(server *Server) {
   277  	server.Noticef("Reloaded: Client TLS handshake first: %v", t.newValue)
   278  }
   279  
   280  // tlsHandshakeFirstFallback implements the option interface for the tls `handshake first fallback delay` setting.
   281  type tlsHandshakeFirstFallback struct {
   282  	noopOption
   283  	newValue time.Duration
   284  }
   285  
   286  // Apply is a no-op because the timeout will be reloaded after options are applied.
   287  func (t *tlsHandshakeFirstFallback) Apply(server *Server) {
   288  	server.Noticef("Reloaded: Client TLS handshake first fallback delay: %v", t.newValue)
   289  }
   290  
   291  // authOption is a base struct that provides default option behaviors.
   292  type authOption struct {
   293  	noopOption
   294  }
   295  
   296  func (o authOption) IsAuthChange() bool {
   297  	return true
   298  }
   299  
   300  // usernameOption implements the option interface for the `username` setting.
   301  type usernameOption struct {
   302  	authOption
   303  }
   304  
   305  // Apply is a no-op because authorization will be reloaded after options are
   306  // applied.
   307  func (u *usernameOption) Apply(server *Server) {
   308  	server.Noticef("Reloaded: authorization username")
   309  }
   310  
   311  // passwordOption implements the option interface for the `password` setting.
   312  type passwordOption struct {
   313  	authOption
   314  }
   315  
   316  // Apply is a no-op because authorization will be reloaded after options are
   317  // applied.
   318  func (p *passwordOption) Apply(server *Server) {
   319  	server.Noticef("Reloaded: authorization password")
   320  }
   321  
   322  // authorizationOption implements the option interface for the `token`
   323  // authorization setting.
   324  type authorizationOption struct {
   325  	authOption
   326  }
   327  
   328  // Apply is a no-op because authorization will be reloaded after options are
   329  // applied.
   330  func (a *authorizationOption) Apply(server *Server) {
   331  	server.Noticef("Reloaded: authorization token")
   332  }
   333  
   334  // authTimeoutOption implements the option interface for the authorization
   335  // `timeout` setting.
   336  type authTimeoutOption struct {
   337  	noopOption // Not authOption because this is a no-op; will be reloaded with options.
   338  	newValue   float64
   339  }
   340  
   341  // Apply is a no-op because the timeout will be reloaded after options are
   342  // applied.
   343  func (a *authTimeoutOption) Apply(server *Server) {
   344  	server.Noticef("Reloaded: authorization timeout = %v", a.newValue)
   345  }
   346  
   347  // tagsOption implements the option interface for the `tags` setting.
   348  type tagsOption struct {
   349  	noopOption // Not authOption because this is a no-op; will be reloaded with options.
   350  }
   351  
   352  func (u *tagsOption) Apply(server *Server) {
   353  	server.Noticef("Reloaded: tags")
   354  }
   355  
   356  func (u *tagsOption) IsStatszChange() bool {
   357  	return true
   358  }
   359  
   360  // usersOption implements the option interface for the authorization `users`
   361  // setting.
   362  type usersOption struct {
   363  	authOption
   364  }
   365  
   366  func (u *usersOption) Apply(server *Server) {
   367  	server.Noticef("Reloaded: authorization users")
   368  }
   369  
   370  // nkeysOption implements the option interface for the authorization `users`
   371  // setting.
   372  type nkeysOption struct {
   373  	authOption
   374  }
   375  
   376  func (u *nkeysOption) Apply(server *Server) {
   377  	server.Noticef("Reloaded: authorization nkey users")
   378  }
   379  
   380  // clusterOption implements the option interface for the `cluster` setting.
   381  type clusterOption struct {
   382  	authOption
   383  	newValue        ClusterOpts
   384  	permsChanged    bool
   385  	accsAdded       []string
   386  	accsRemoved     []string
   387  	poolSizeChanged bool
   388  	compressChanged bool
   389  }
   390  
   391  // Apply the cluster change.
   392  func (c *clusterOption) Apply(s *Server) {
   393  	// TODO: support enabling/disabling clustering.
   394  	s.mu.Lock()
   395  	tlsRequired := c.newValue.TLSConfig != nil
   396  	s.routeInfo.TLSRequired = tlsRequired
   397  	s.routeInfo.TLSVerify = tlsRequired
   398  	s.routeInfo.AuthRequired = c.newValue.Username != ""
   399  	if c.newValue.NoAdvertise {
   400  		s.routeInfo.ClientConnectURLs = nil
   401  		s.routeInfo.WSConnectURLs = nil
   402  	} else {
   403  		s.routeInfo.ClientConnectURLs = s.clientConnectURLs
   404  		s.routeInfo.WSConnectURLs = s.websocket.connectURLs
   405  	}
   406  	s.setRouteInfoHostPortAndIP()
   407  	var routes []*client
   408  	if c.compressChanged {
   409  		co := &s.getOpts().Cluster.Compression
   410  		newMode := co.Mode
   411  		s.forEachRoute(func(r *client) {
   412  			r.mu.Lock()
   413  			// Skip routes that are "not supported" (because they will never do
   414  			// compression) or the routes that have already the new compression
   415  			// mode.
   416  			if r.route.compression == CompressionNotSupported || r.route.compression == newMode {
   417  				r.mu.Unlock()
   418  				return
   419  			}
   420  			// We need to close the route if it had compression "off" or the new
   421  			// mode is compression "off", or if the new mode is "accept", because
   422  			// these require negotiation.
   423  			if r.route.compression == CompressionOff || newMode == CompressionOff || newMode == CompressionAccept {
   424  				routes = append(routes, r)
   425  			} else if newMode == CompressionS2Auto {
   426  				// If the mode is "s2_auto", we need to check if there is really
   427  				// need to change, and at any rate, we want to save the actual
   428  				// compression level here, not s2_auto.
   429  				r.updateS2AutoCompressionLevel(co, &r.route.compression)
   430  			} else {
   431  				// Simply change the compression writer
   432  				r.out.cw = s2.NewWriter(nil, s2WriterOptions(newMode)...)
   433  				r.route.compression = newMode
   434  			}
   435  			r.mu.Unlock()
   436  		})
   437  	}
   438  	s.mu.Unlock()
   439  	if c.newValue.Name != "" && c.newValue.Name != s.ClusterName() {
   440  		s.setClusterName(c.newValue.Name)
   441  	}
   442  	for _, r := range routes {
   443  		r.closeConnection(ClientClosed)
   444  	}
   445  	s.Noticef("Reloaded: cluster")
   446  	if tlsRequired && c.newValue.TLSConfig.InsecureSkipVerify {
   447  		s.Warnf(clusterTLSInsecureWarning)
   448  	}
   449  }
   450  
   451  func (c *clusterOption) IsClusterPermsChange() bool {
   452  	return c.permsChanged
   453  }
   454  
   455  func (c *clusterOption) IsClusterPoolSizeOrAccountsChange() bool {
   456  	return c.poolSizeChanged || len(c.accsAdded) > 0 || len(c.accsRemoved) > 0
   457  }
   458  
   459  func (c *clusterOption) diffPoolAndAccounts(old *ClusterOpts) {
   460  	c.poolSizeChanged = c.newValue.PoolSize != old.PoolSize
   461  addLoop:
   462  	for _, na := range c.newValue.PinnedAccounts {
   463  		for _, oa := range old.PinnedAccounts {
   464  			if na == oa {
   465  				continue addLoop
   466  			}
   467  		}
   468  		c.accsAdded = append(c.accsAdded, na)
   469  	}
   470  removeLoop:
   471  	for _, oa := range old.PinnedAccounts {
   472  		for _, na := range c.newValue.PinnedAccounts {
   473  			if oa == na {
   474  				continue removeLoop
   475  			}
   476  		}
   477  		c.accsRemoved = append(c.accsRemoved, oa)
   478  	}
   479  }
   480  
   481  // routesOption implements the option interface for the cluster `routes`
   482  // setting.
   483  type routesOption struct {
   484  	noopOption
   485  	add    []*url.URL
   486  	remove []*url.URL
   487  }
   488  
   489  // Apply the route changes by adding and removing the necessary routes.
   490  func (r *routesOption) Apply(server *Server) {
   491  	server.mu.Lock()
   492  	routes := make([]*client, server.numRoutes())
   493  	i := 0
   494  	server.forEachRoute(func(r *client) {
   495  		routes[i] = r
   496  		i++
   497  	})
   498  	// If there was a change, notify monitoring code that it should
   499  	// update the route URLs if /varz endpoint is inspected.
   500  	if len(r.add)+len(r.remove) > 0 {
   501  		server.varzUpdateRouteURLs = true
   502  	}
   503  	server.mu.Unlock()
   504  
   505  	// Remove routes.
   506  	for _, remove := range r.remove {
   507  		for _, client := range routes {
   508  			var url *url.URL
   509  			client.mu.Lock()
   510  			if client.route != nil {
   511  				url = client.route.url
   512  			}
   513  			client.mu.Unlock()
   514  			if url != nil && urlsAreEqual(url, remove) {
   515  				// Do not attempt to reconnect when route is removed.
   516  				client.setNoReconnect()
   517  				client.closeConnection(RouteRemoved)
   518  				server.Noticef("Removed route %v", remove)
   519  			}
   520  		}
   521  	}
   522  
   523  	// Add routes.
   524  	server.mu.Lock()
   525  	server.solicitRoutes(r.add, server.getOpts().Cluster.PinnedAccounts)
   526  	server.mu.Unlock()
   527  
   528  	server.Noticef("Reloaded: cluster routes")
   529  }
   530  
   531  // maxConnOption implements the option interface for the `max_connections`
   532  // setting.
   533  type maxConnOption struct {
   534  	noopOption
   535  	newValue int
   536  }
   537  
   538  // Apply the max connections change by closing random connections til we are
   539  // below the limit if necessary.
   540  func (m *maxConnOption) Apply(server *Server) {
   541  	server.mu.Lock()
   542  	var (
   543  		clients = make([]*client, len(server.clients))
   544  		i       = 0
   545  	)
   546  	// Map iteration is random, which allows us to close random connections.
   547  	for _, client := range server.clients {
   548  		clients[i] = client
   549  		i++
   550  	}
   551  	server.mu.Unlock()
   552  
   553  	if m.newValue > 0 && len(clients) > m.newValue {
   554  		// Close connections til we are within the limit.
   555  		var (
   556  			numClose = len(clients) - m.newValue
   557  			closed   = 0
   558  		)
   559  		for _, client := range clients {
   560  			client.maxConnExceeded()
   561  			closed++
   562  			if closed >= numClose {
   563  				break
   564  			}
   565  		}
   566  		server.Noticef("Closed %d connections to fall within max_connections", closed)
   567  	}
   568  	server.Noticef("Reloaded: max_connections = %v", m.newValue)
   569  }
   570  
   571  // pidFileOption implements the option interface for the `pid_file` setting.
   572  type pidFileOption struct {
   573  	noopOption
   574  	newValue string
   575  }
   576  
   577  // Apply the setting by logging the pid to the new file.
   578  func (p *pidFileOption) Apply(server *Server) {
   579  	if p.newValue == "" {
   580  		return
   581  	}
   582  	if err := server.logPid(); err != nil {
   583  		server.Errorf("Failed to write pidfile: %v", err)
   584  	}
   585  	server.Noticef("Reloaded: pid_file = %v", p.newValue)
   586  }
   587  
   588  // portsFileDirOption implements the option interface for the `portFileDir` setting.
   589  type portsFileDirOption struct {
   590  	noopOption
   591  	oldValue string
   592  	newValue string
   593  }
   594  
   595  func (p *portsFileDirOption) Apply(server *Server) {
   596  	server.deletePortsFile(p.oldValue)
   597  	server.logPorts()
   598  	server.Noticef("Reloaded: ports_file_dir = %v", p.newValue)
   599  }
   600  
   601  // maxControlLineOption implements the option interface for the
   602  // `max_control_line` setting.
   603  type maxControlLineOption struct {
   604  	noopOption
   605  	newValue int32
   606  }
   607  
   608  // Apply the setting by updating each client.
   609  func (m *maxControlLineOption) Apply(server *Server) {
   610  	mcl := int32(m.newValue)
   611  	server.mu.Lock()
   612  	for _, client := range server.clients {
   613  		atomic.StoreInt32(&client.mcl, mcl)
   614  	}
   615  	server.mu.Unlock()
   616  	server.Noticef("Reloaded: max_control_line = %d", mcl)
   617  }
   618  
   619  // maxPayloadOption implements the option interface for the `max_payload`
   620  // setting.
   621  type maxPayloadOption struct {
   622  	noopOption
   623  	newValue int32
   624  }
   625  
   626  // Apply the setting by updating the server info and each client.
   627  func (m *maxPayloadOption) Apply(server *Server) {
   628  	server.mu.Lock()
   629  	server.info.MaxPayload = m.newValue
   630  	for _, client := range server.clients {
   631  		atomic.StoreInt32(&client.mpay, int32(m.newValue))
   632  	}
   633  	server.mu.Unlock()
   634  	server.Noticef("Reloaded: max_payload = %d", m.newValue)
   635  }
   636  
   637  // pingIntervalOption implements the option interface for the `ping_interval`
   638  // setting.
   639  type pingIntervalOption struct {
   640  	noopOption
   641  	newValue time.Duration
   642  }
   643  
   644  // Apply is a no-op because the ping interval will be reloaded after options
   645  // are applied.
   646  func (p *pingIntervalOption) Apply(server *Server) {
   647  	server.Noticef("Reloaded: ping_interval = %s", p.newValue)
   648  }
   649  
   650  // maxPingsOutOption implements the option interface for the `ping_max`
   651  // setting.
   652  type maxPingsOutOption struct {
   653  	noopOption
   654  	newValue int
   655  }
   656  
   657  // Apply is a no-op because the ping interval will be reloaded after options
   658  // are applied.
   659  func (m *maxPingsOutOption) Apply(server *Server) {
   660  	server.Noticef("Reloaded: ping_max = %d", m.newValue)
   661  }
   662  
   663  // writeDeadlineOption implements the option interface for the `write_deadline`
   664  // setting.
   665  type writeDeadlineOption struct {
   666  	noopOption
   667  	newValue time.Duration
   668  }
   669  
   670  // Apply is a no-op because the write deadline will be reloaded after options
   671  // are applied.
   672  func (w *writeDeadlineOption) Apply(server *Server) {
   673  	server.Noticef("Reloaded: write_deadline = %s", w.newValue)
   674  }
   675  
   676  // clientAdvertiseOption implements the option interface for the `client_advertise` setting.
   677  type clientAdvertiseOption struct {
   678  	noopOption
   679  	newValue string
   680  }
   681  
   682  // Apply the setting by updating the server info and regenerate the infoJSON byte array.
   683  func (c *clientAdvertiseOption) Apply(server *Server) {
   684  	server.mu.Lock()
   685  	server.setInfoHostPort()
   686  	server.mu.Unlock()
   687  	server.Noticef("Reload: client_advertise = %s", c.newValue)
   688  }
   689  
   690  // accountsOption implements the option interface.
   691  // Ensure that authorization code is executed if any change in accounts
   692  type accountsOption struct {
   693  	authOption
   694  }
   695  
   696  // Apply is a no-op. Changes will be applied in reloadAuthorization
   697  func (a *accountsOption) Apply(s *Server) {
   698  	s.Noticef("Reloaded: accounts")
   699  }
   700  
   701  // For changes to a server's config.
   702  type jetStreamOption struct {
   703  	noopOption
   704  	newValue bool
   705  }
   706  
   707  func (a *jetStreamOption) Apply(s *Server) {
   708  	s.Noticef("Reloaded: JetStream")
   709  }
   710  
   711  func (jso jetStreamOption) IsJetStreamChange() bool {
   712  	return true
   713  }
   714  
   715  func (jso jetStreamOption) IsStatszChange() bool {
   716  	return true
   717  }
   718  
   719  type ocspOption struct {
   720  	tlsOption
   721  	newValue *OCSPConfig
   722  }
   723  
   724  func (a *ocspOption) Apply(s *Server) {
   725  	s.Noticef("Reloaded: OCSP")
   726  }
   727  
   728  type ocspResponseCacheOption struct {
   729  	tlsOption
   730  	newValue *OCSPResponseCacheConfig
   731  }
   732  
   733  func (a *ocspResponseCacheOption) Apply(s *Server) {
   734  	s.Noticef("Reloaded OCSP peer cache")
   735  }
   736  
   737  // connectErrorReports implements the option interface for the `connect_error_reports`
   738  // setting.
   739  type connectErrorReports struct {
   740  	noopOption
   741  	newValue int
   742  }
   743  
   744  // Apply is a no-op because the value will be reloaded after options are applied.
   745  func (c *connectErrorReports) Apply(s *Server) {
   746  	s.Noticef("Reloaded: connect_error_reports = %v", c.newValue)
   747  }
   748  
   749  // connectErrorReports implements the option interface for the `connect_error_reports`
   750  // setting.
   751  type reconnectErrorReports struct {
   752  	noopOption
   753  	newValue int
   754  }
   755  
   756  // Apply is a no-op because the value will be reloaded after options are applied.
   757  func (r *reconnectErrorReports) Apply(s *Server) {
   758  	s.Noticef("Reloaded: reconnect_error_reports = %v", r.newValue)
   759  }
   760  
   761  // maxTracedMsgLenOption implements the option interface for the `max_traced_msg_len` setting.
   762  type maxTracedMsgLenOption struct {
   763  	noopOption
   764  	newValue int
   765  }
   766  
   767  // Apply the setting by updating the maximum traced message length.
   768  func (m *maxTracedMsgLenOption) Apply(server *Server) {
   769  	server.mu.Lock()
   770  	defer server.mu.Unlock()
   771  	server.opts.MaxTracedMsgLen = m.newValue
   772  	server.Noticef("Reloaded: max_traced_msg_len = %d", m.newValue)
   773  }
   774  
   775  type mqttAckWaitReload struct {
   776  	noopOption
   777  	newValue time.Duration
   778  }
   779  
   780  func (o *mqttAckWaitReload) Apply(s *Server) {
   781  	s.Noticef("Reloaded: MQTT ack_wait = %v", o.newValue)
   782  }
   783  
   784  type mqttMaxAckPendingReload struct {
   785  	noopOption
   786  	newValue uint16
   787  }
   788  
   789  func (o *mqttMaxAckPendingReload) Apply(s *Server) {
   790  	s.mqttUpdateMaxAckPending(o.newValue)
   791  	s.Noticef("Reloaded: MQTT max_ack_pending = %v", o.newValue)
   792  }
   793  
   794  type mqttStreamReplicasReload struct {
   795  	noopOption
   796  	newValue int
   797  }
   798  
   799  func (o *mqttStreamReplicasReload) Apply(s *Server) {
   800  	s.Noticef("Reloaded: MQTT stream_replicas = %v", o.newValue)
   801  }
   802  
   803  type mqttConsumerReplicasReload struct {
   804  	noopOption
   805  	newValue int
   806  }
   807  
   808  func (o *mqttConsumerReplicasReload) Apply(s *Server) {
   809  	s.Noticef("Reloaded: MQTT consumer_replicas = %v", o.newValue)
   810  }
   811  
   812  type mqttConsumerMemoryStorageReload struct {
   813  	noopOption
   814  	newValue bool
   815  }
   816  
   817  func (o *mqttConsumerMemoryStorageReload) Apply(s *Server) {
   818  	s.Noticef("Reloaded: MQTT consumer_memory_storage = %v", o.newValue)
   819  }
   820  
   821  type mqttInactiveThresholdReload struct {
   822  	noopOption
   823  	newValue time.Duration
   824  }
   825  
   826  func (o *mqttInactiveThresholdReload) Apply(s *Server) {
   827  	s.Noticef("Reloaded: MQTT consumer_inactive_threshold = %v", o.newValue)
   828  }
   829  
   830  type profBlockRateReload struct {
   831  	noopOption
   832  	newValue int
   833  }
   834  
   835  func (o *profBlockRateReload) Apply(s *Server) {
   836  	s.setBlockProfileRate(o.newValue)
   837  	s.Noticef("Reloaded: prof_block_rate = %v", o.newValue)
   838  }
   839  
   840  type leafNodeOption struct {
   841  	noopOption
   842  	tlsFirstChanged    bool
   843  	compressionChanged bool
   844  }
   845  
   846  func (l *leafNodeOption) Apply(s *Server) {
   847  	opts := s.getOpts()
   848  	if l.tlsFirstChanged {
   849  		s.Noticef("Reloaded: LeafNode TLS HandshakeFirst value is: %v", opts.LeafNode.TLSHandshakeFirst)
   850  		for _, r := range opts.LeafNode.Remotes {
   851  			s.Noticef("Reloaded: LeafNode Remote to %v TLS HandshakeFirst value is: %v", r.URLs, r.TLSHandshakeFirst)
   852  		}
   853  	}
   854  	if l.compressionChanged {
   855  		var leafs []*client
   856  		acceptSideCompOpts := &opts.LeafNode.Compression
   857  
   858  		s.mu.RLock()
   859  		// First, update our internal leaf remote configurations with the new
   860  		// compress options.
   861  		// Since changing the remotes (as in adding/removing) is currently not
   862  		// supported, we know that we should have the same number in Options
   863  		// than in leafRemoteCfgs, but to be sure, use the max size.
   864  		max := len(opts.LeafNode.Remotes)
   865  		if l := len(s.leafRemoteCfgs); l < max {
   866  			max = l
   867  		}
   868  		for i := 0; i < max; i++ {
   869  			lr := s.leafRemoteCfgs[i]
   870  			lr.Lock()
   871  			lr.Compression = opts.LeafNode.Remotes[i].Compression
   872  			lr.Unlock()
   873  		}
   874  
   875  		for _, l := range s.leafs {
   876  			var co *CompressionOpts
   877  
   878  			l.mu.Lock()
   879  			if r := l.leaf.remote; r != nil {
   880  				co = &r.Compression
   881  			} else {
   882  				co = acceptSideCompOpts
   883  			}
   884  			newMode := co.Mode
   885  			// Skip leaf connections that are "not supported" (because they
   886  			// will never do compression) or the ones that have already the
   887  			// new compression mode.
   888  			if l.leaf.compression == CompressionNotSupported || l.leaf.compression == newMode {
   889  				l.mu.Unlock()
   890  				continue
   891  			}
   892  			// We need to close the connections if it had compression "off" or the new
   893  			// mode is compression "off", or if the new mode is "accept", because
   894  			// these require negotiation.
   895  			if l.leaf.compression == CompressionOff || newMode == CompressionOff || newMode == CompressionAccept {
   896  				leafs = append(leafs, l)
   897  			} else if newMode == CompressionS2Auto {
   898  				// If the mode is "s2_auto", we need to check if there is really
   899  				// need to change, and at any rate, we want to save the actual
   900  				// compression level here, not s2_auto.
   901  				l.updateS2AutoCompressionLevel(co, &l.leaf.compression)
   902  			} else {
   903  				// Simply change the compression writer
   904  				l.out.cw = s2.NewWriter(nil, s2WriterOptions(newMode)...)
   905  				l.leaf.compression = newMode
   906  			}
   907  			l.mu.Unlock()
   908  		}
   909  		s.mu.RUnlock()
   910  		// Close the connections for which negotiation is required.
   911  		for _, l := range leafs {
   912  			l.closeConnection(ClientClosed)
   913  		}
   914  		s.Noticef("Reloaded: LeafNode compression settings")
   915  	}
   916  }
   917  
   918  // Compares options and disconnects clients that are no longer listed in pinned certs. Lock must not be held.
   919  func (s *Server) recheckPinnedCerts(curOpts *Options, newOpts *Options) {
   920  	s.mu.Lock()
   921  	disconnectClients := []*client{}
   922  	protoToPinned := map[int]PinnedCertSet{}
   923  	if !reflect.DeepEqual(newOpts.TLSPinnedCerts, curOpts.TLSPinnedCerts) {
   924  		protoToPinned[NATS] = curOpts.TLSPinnedCerts
   925  	}
   926  	if !reflect.DeepEqual(newOpts.MQTT.TLSPinnedCerts, curOpts.MQTT.TLSPinnedCerts) {
   927  		protoToPinned[MQTT] = curOpts.MQTT.TLSPinnedCerts
   928  	}
   929  	if !reflect.DeepEqual(newOpts.Websocket.TLSPinnedCerts, curOpts.Websocket.TLSPinnedCerts) {
   930  		protoToPinned[WS] = curOpts.Websocket.TLSPinnedCerts
   931  	}
   932  	for _, c := range s.clients {
   933  		if c.kind != CLIENT {
   934  			continue
   935  		}
   936  		if pinned, ok := protoToPinned[c.clientType()]; ok {
   937  			if !c.matchesPinnedCert(pinned) {
   938  				disconnectClients = append(disconnectClients, c)
   939  			}
   940  		}
   941  	}
   942  	checkClients := func(kind int, clients map[uint64]*client, set PinnedCertSet) {
   943  		for _, c := range clients {
   944  			if c.kind == kind && !c.matchesPinnedCert(set) {
   945  				disconnectClients = append(disconnectClients, c)
   946  			}
   947  		}
   948  	}
   949  	if !reflect.DeepEqual(newOpts.LeafNode.TLSPinnedCerts, curOpts.LeafNode.TLSPinnedCerts) {
   950  		checkClients(LEAF, s.leafs, newOpts.LeafNode.TLSPinnedCerts)
   951  	}
   952  	if !reflect.DeepEqual(newOpts.Cluster.TLSPinnedCerts, curOpts.Cluster.TLSPinnedCerts) {
   953  		s.forEachRoute(func(c *client) {
   954  			if !c.matchesPinnedCert(newOpts.Cluster.TLSPinnedCerts) {
   955  				disconnectClients = append(disconnectClients, c)
   956  			}
   957  		})
   958  	}
   959  	if s.gateway.enabled && reflect.DeepEqual(newOpts.Gateway.TLSPinnedCerts, curOpts.Gateway.TLSPinnedCerts) {
   960  		gw := s.gateway
   961  		gw.RLock()
   962  		for _, c := range gw.out {
   963  			if !c.matchesPinnedCert(newOpts.Gateway.TLSPinnedCerts) {
   964  				disconnectClients = append(disconnectClients, c)
   965  			}
   966  		}
   967  		checkClients(GATEWAY, gw.in, newOpts.Gateway.TLSPinnedCerts)
   968  		gw.RUnlock()
   969  	}
   970  	s.mu.Unlock()
   971  	if len(disconnectClients) > 0 {
   972  		s.Noticef("Disconnect %d clients due to pinned certs reload", len(disconnectClients))
   973  		for _, c := range disconnectClients {
   974  			c.closeConnection(TLSHandshakeError)
   975  		}
   976  	}
   977  }
   978  
   979  // Reload reads the current configuration file and calls out to ReloadOptions
   980  // to apply the changes. This returns an error if the server was not started
   981  // with a config file or an option which doesn't support hot-swapping was changed.
   982  func (s *Server) Reload() error {
   983  	s.mu.Lock()
   984  	configFile := s.configFile
   985  	s.mu.Unlock()
   986  	if configFile == "" {
   987  		return errors.New("can only reload config when a file is provided using -c or --config")
   988  	}
   989  
   990  	newOpts, err := ProcessConfigFile(configFile)
   991  	if err != nil {
   992  		// TODO: Dump previous good config to a .bak file?
   993  		return err
   994  	}
   995  	return s.ReloadOptions(newOpts)
   996  }
   997  
   998  // ReloadOptions applies any supported options from the provided Option
   999  // type. This returns an error if an option which doesn't support
  1000  // hot-swapping was changed.
  1001  func (s *Server) ReloadOptions(newOpts *Options) error {
  1002  	s.mu.Lock()
  1003  
  1004  	curOpts := s.getOpts()
  1005  
  1006  	// Wipe trusted keys if needed when we have an operator.
  1007  	if len(curOpts.TrustedOperators) > 0 && len(curOpts.TrustedKeys) > 0 {
  1008  		curOpts.TrustedKeys = nil
  1009  	}
  1010  
  1011  	clientOrgPort := curOpts.Port
  1012  	clusterOrgPort := curOpts.Cluster.Port
  1013  	gatewayOrgPort := curOpts.Gateway.Port
  1014  	leafnodesOrgPort := curOpts.LeafNode.Port
  1015  	websocketOrgPort := curOpts.Websocket.Port
  1016  	mqttOrgPort := curOpts.MQTT.Port
  1017  
  1018  	s.mu.Unlock()
  1019  
  1020  	// In case "-cluster ..." was provided through the command line, this will
  1021  	// properly set the Cluster.Host/Port etc...
  1022  	if l := curOpts.Cluster.ListenStr; l != _EMPTY_ {
  1023  		newOpts.Cluster.ListenStr = l
  1024  		overrideCluster(newOpts)
  1025  	}
  1026  
  1027  	// Apply flags over config file settings.
  1028  	newOpts = MergeOptions(newOpts, FlagSnapshot)
  1029  
  1030  	// Need more processing for boolean flags...
  1031  	if FlagSnapshot != nil {
  1032  		applyBoolFlags(newOpts, FlagSnapshot)
  1033  	}
  1034  
  1035  	setBaselineOptions(newOpts)
  1036  
  1037  	// setBaselineOptions sets Port to 0 if set to -1 (RANDOM port)
  1038  	// If that's the case, set it to the saved value when the accept loop was
  1039  	// created.
  1040  	if newOpts.Port == 0 {
  1041  		newOpts.Port = clientOrgPort
  1042  	}
  1043  	// We don't do that for cluster, so check against -1.
  1044  	if newOpts.Cluster.Port == -1 {
  1045  		newOpts.Cluster.Port = clusterOrgPort
  1046  	}
  1047  	if newOpts.Gateway.Port == -1 {
  1048  		newOpts.Gateway.Port = gatewayOrgPort
  1049  	}
  1050  	if newOpts.LeafNode.Port == -1 {
  1051  		newOpts.LeafNode.Port = leafnodesOrgPort
  1052  	}
  1053  	if newOpts.Websocket.Port == -1 {
  1054  		newOpts.Websocket.Port = websocketOrgPort
  1055  	}
  1056  	if newOpts.MQTT.Port == -1 {
  1057  		newOpts.MQTT.Port = mqttOrgPort
  1058  	}
  1059  
  1060  	if err := s.reloadOptions(curOpts, newOpts); err != nil {
  1061  		return err
  1062  	}
  1063  
  1064  	s.recheckPinnedCerts(curOpts, newOpts)
  1065  
  1066  	s.mu.Lock()
  1067  	s.configTime = time.Now().UTC()
  1068  	s.updateVarzConfigReloadableFields(s.varz)
  1069  	s.mu.Unlock()
  1070  	return nil
  1071  }
  1072  func applyBoolFlags(newOpts, flagOpts *Options) {
  1073  	// Reset fields that may have been set to `true` in
  1074  	// MergeOptions() when some of the flags default to `true`
  1075  	// but have not been explicitly set and therefore value
  1076  	// from config file should take precedence.
  1077  	for name, val := range newOpts.inConfig {
  1078  		f := reflect.ValueOf(newOpts).Elem()
  1079  		names := strings.Split(name, ".")
  1080  		for _, name := range names {
  1081  			f = f.FieldByName(name)
  1082  		}
  1083  		f.SetBool(val)
  1084  	}
  1085  	// Now apply value (true or false) from flags that have
  1086  	// been explicitly set in command line
  1087  	for name, val := range flagOpts.inCmdLine {
  1088  		f := reflect.ValueOf(newOpts).Elem()
  1089  		names := strings.Split(name, ".")
  1090  		for _, name := range names {
  1091  			f = f.FieldByName(name)
  1092  		}
  1093  		f.SetBool(val)
  1094  	}
  1095  }
  1096  
  1097  // reloadOptions reloads the server config with the provided options. If an
  1098  // option that doesn't support hot-swapping is changed, this returns an error.
  1099  func (s *Server) reloadOptions(curOpts, newOpts *Options) error {
  1100  	// Apply to the new options some of the options that may have been set
  1101  	// that can't be configured in the config file (this can happen in
  1102  	// applications starting NATS Server programmatically).
  1103  	newOpts.CustomClientAuthentication = curOpts.CustomClientAuthentication
  1104  	newOpts.CustomRouterAuthentication = curOpts.CustomRouterAuthentication
  1105  
  1106  	changed, err := s.diffOptions(newOpts)
  1107  	if err != nil {
  1108  		return err
  1109  	}
  1110  
  1111  	if len(changed) != 0 {
  1112  		if err := validateOptions(newOpts); err != nil {
  1113  			return err
  1114  		}
  1115  	}
  1116  
  1117  	// Create a context that is used to pass special info that we may need
  1118  	// while applying the new options.
  1119  	ctx := reloadContext{oldClusterPerms: curOpts.Cluster.Permissions}
  1120  	s.setOpts(newOpts)
  1121  	s.applyOptions(&ctx, changed)
  1122  	return nil
  1123  }
  1124  
  1125  // For the purpose of comparing, impose a order on slice data types where order does not matter
  1126  func imposeOrder(value interface{}) error {
  1127  	switch value := value.(type) {
  1128  	case []*Account:
  1129  		sort.Slice(value, func(i, j int) bool {
  1130  			return value[i].Name < value[j].Name
  1131  		})
  1132  		for _, a := range value {
  1133  			sort.Slice(a.imports.streams, func(i, j int) bool {
  1134  				return a.imports.streams[i].acc.Name < a.imports.streams[j].acc.Name
  1135  			})
  1136  		}
  1137  	case []*User:
  1138  		sort.Slice(value, func(i, j int) bool {
  1139  			return value[i].Username < value[j].Username
  1140  		})
  1141  	case []*NkeyUser:
  1142  		sort.Slice(value, func(i, j int) bool {
  1143  			return value[i].Nkey < value[j].Nkey
  1144  		})
  1145  	case []*url.URL:
  1146  		sort.Slice(value, func(i, j int) bool {
  1147  			return value[i].String() < value[j].String()
  1148  		})
  1149  	case []string:
  1150  		sort.Strings(value)
  1151  	case []*jwt.OperatorClaims:
  1152  		sort.Slice(value, func(i, j int) bool {
  1153  			return value[i].Issuer < value[j].Issuer
  1154  		})
  1155  	case GatewayOpts:
  1156  		sort.Slice(value.Gateways, func(i, j int) bool {
  1157  			return value.Gateways[i].Name < value.Gateways[j].Name
  1158  		})
  1159  	case WebsocketOpts:
  1160  		sort.Strings(value.AllowedOrigins)
  1161  	case string, bool, uint8, int, int32, int64, time.Duration, float64, nil, LeafNodeOpts, ClusterOpts, *tls.Config, PinnedCertSet,
  1162  		*URLAccResolver, *MemAccResolver, *DirAccResolver, *CacheDirAccResolver, Authentication, MQTTOpts, jwt.TagList,
  1163  		*OCSPConfig, map[string]string, JSLimitOpts, StoreCipher, *OCSPResponseCacheConfig:
  1164  		// explicitly skipped types
  1165  	case *AuthCallout:
  1166  	default:
  1167  		// this will fail during unit tests
  1168  		return fmt.Errorf("OnReload, sort or explicitly skip type: %s",
  1169  			reflect.TypeOf(value))
  1170  	}
  1171  	return nil
  1172  }
  1173  
  1174  // diffOptions returns a slice containing options which have been changed. If
  1175  // an option that doesn't support hot-swapping is changed, this returns an
  1176  // error.
  1177  func (s *Server) diffOptions(newOpts *Options) ([]option, error) {
  1178  	var (
  1179  		oldConfig = reflect.ValueOf(s.getOpts()).Elem()
  1180  		newConfig = reflect.ValueOf(newOpts).Elem()
  1181  		diffOpts  = []option{}
  1182  
  1183  		// Need to keep track of whether JS is being disabled
  1184  		// to prevent changing limits at runtime.
  1185  		jsEnabled           = s.JetStreamEnabled()
  1186  		disableJS           bool
  1187  		jsMemLimitsChanged  bool
  1188  		jsFileLimitsChanged bool
  1189  		jsStoreDirChanged   bool
  1190  	)
  1191  	for i := 0; i < oldConfig.NumField(); i++ {
  1192  		field := oldConfig.Type().Field(i)
  1193  		// field.PkgPath is empty for exported fields, and is not for unexported ones.
  1194  		// We skip the unexported fields.
  1195  		if field.PkgPath != _EMPTY_ {
  1196  			continue
  1197  		}
  1198  		var (
  1199  			oldValue = oldConfig.Field(i).Interface()
  1200  			newValue = newConfig.Field(i).Interface()
  1201  		)
  1202  		if err := imposeOrder(oldValue); err != nil {
  1203  			return nil, err
  1204  		}
  1205  		if err := imposeOrder(newValue); err != nil {
  1206  			return nil, err
  1207  		}
  1208  
  1209  		optName := strings.ToLower(field.Name)
  1210  		// accounts and users (referencing accounts) will always differ as accounts
  1211  		// contain internal state, say locks etc..., so we don't bother here.
  1212  		// This also avoids races with atomic stats counters
  1213  		if optName != "accounts" && optName != "users" {
  1214  			if changed := !reflect.DeepEqual(oldValue, newValue); !changed {
  1215  				// Check to make sure we are running JetStream if we think we should be.
  1216  				if optName == "jetstream" && newValue.(bool) {
  1217  					if !jsEnabled {
  1218  						diffOpts = append(diffOpts, &jetStreamOption{newValue: true})
  1219  					}
  1220  				}
  1221  				continue
  1222  			}
  1223  		}
  1224  		switch optName {
  1225  		case "traceverbose":
  1226  			diffOpts = append(diffOpts, &traceVerboseOption{newValue: newValue.(bool)})
  1227  		case "trace":
  1228  			diffOpts = append(diffOpts, &traceOption{newValue: newValue.(bool)})
  1229  		case "debug":
  1230  			diffOpts = append(diffOpts, &debugOption{newValue: newValue.(bool)})
  1231  		case "logtime":
  1232  			diffOpts = append(diffOpts, &logtimeOption{newValue: newValue.(bool)})
  1233  		case "logtimeutc":
  1234  			diffOpts = append(diffOpts, &logtimeUTCOption{newValue: newValue.(bool)})
  1235  		case "logfile":
  1236  			diffOpts = append(diffOpts, &logfileOption{newValue: newValue.(string)})
  1237  		case "syslog":
  1238  			diffOpts = append(diffOpts, &syslogOption{newValue: newValue.(bool)})
  1239  		case "remotesyslog":
  1240  			diffOpts = append(diffOpts, &remoteSyslogOption{newValue: newValue.(string)})
  1241  		case "tlsconfig":
  1242  			diffOpts = append(diffOpts, &tlsOption{newValue: newValue.(*tls.Config)})
  1243  		case "tlstimeout":
  1244  			diffOpts = append(diffOpts, &tlsTimeoutOption{newValue: newValue.(float64)})
  1245  		case "tlspinnedcerts":
  1246  			diffOpts = append(diffOpts, &tlsPinnedCertOption{newValue: newValue.(PinnedCertSet)})
  1247  		case "tlshandshakefirst":
  1248  			diffOpts = append(diffOpts, &tlsHandshakeFirst{newValue: newValue.(bool)})
  1249  		case "tlshandshakefirstfallback":
  1250  			diffOpts = append(diffOpts, &tlsHandshakeFirstFallback{newValue: newValue.(time.Duration)})
  1251  		case "username":
  1252  			diffOpts = append(diffOpts, &usernameOption{})
  1253  		case "password":
  1254  			diffOpts = append(diffOpts, &passwordOption{})
  1255  		case "tags":
  1256  			diffOpts = append(diffOpts, &tagsOption{})
  1257  		case "authorization":
  1258  			diffOpts = append(diffOpts, &authorizationOption{})
  1259  		case "authtimeout":
  1260  			diffOpts = append(diffOpts, &authTimeoutOption{newValue: newValue.(float64)})
  1261  		case "users":
  1262  			diffOpts = append(diffOpts, &usersOption{})
  1263  		case "nkeys":
  1264  			diffOpts = append(diffOpts, &nkeysOption{})
  1265  		case "cluster":
  1266  			newClusterOpts := newValue.(ClusterOpts)
  1267  			oldClusterOpts := oldValue.(ClusterOpts)
  1268  			if err := validateClusterOpts(oldClusterOpts, newClusterOpts); err != nil {
  1269  				return nil, err
  1270  			}
  1271  			co := &clusterOption{
  1272  				newValue:        newClusterOpts,
  1273  				permsChanged:    !reflect.DeepEqual(newClusterOpts.Permissions, oldClusterOpts.Permissions),
  1274  				compressChanged: !reflect.DeepEqual(oldClusterOpts.Compression, newClusterOpts.Compression),
  1275  			}
  1276  			co.diffPoolAndAccounts(&oldClusterOpts)
  1277  			// If there are added accounts, first make sure that we can look them up.
  1278  			// If we can't let's fail the reload.
  1279  			for _, acc := range co.accsAdded {
  1280  				if _, err := s.LookupAccount(acc); err != nil {
  1281  					return nil, fmt.Errorf("unable to add account %q to the list of dedicated routes: %v", acc, err)
  1282  				}
  1283  			}
  1284  			// If pool_size has been set to negative (but was not before), then let's
  1285  			// add the system account to the list of removed accounts (we don't have
  1286  			// to check if already there, duplicates are ok in that case).
  1287  			if newClusterOpts.PoolSize < 0 && oldClusterOpts.PoolSize >= 0 {
  1288  				if sys := s.SystemAccount(); sys != nil {
  1289  					co.accsRemoved = append(co.accsRemoved, sys.GetName())
  1290  				}
  1291  			}
  1292  			diffOpts = append(diffOpts, co)
  1293  		case "routes":
  1294  			add, remove := diffRoutes(oldValue.([]*url.URL), newValue.([]*url.URL))
  1295  			diffOpts = append(diffOpts, &routesOption{add: add, remove: remove})
  1296  		case "maxconn":
  1297  			diffOpts = append(diffOpts, &maxConnOption{newValue: newValue.(int)})
  1298  		case "pidfile":
  1299  			diffOpts = append(diffOpts, &pidFileOption{newValue: newValue.(string)})
  1300  		case "portsfiledir":
  1301  			diffOpts = append(diffOpts, &portsFileDirOption{newValue: newValue.(string), oldValue: oldValue.(string)})
  1302  		case "maxcontrolline":
  1303  			diffOpts = append(diffOpts, &maxControlLineOption{newValue: newValue.(int32)})
  1304  		case "maxpayload":
  1305  			diffOpts = append(diffOpts, &maxPayloadOption{newValue: newValue.(int32)})
  1306  		case "pinginterval":
  1307  			diffOpts = append(diffOpts, &pingIntervalOption{newValue: newValue.(time.Duration)})
  1308  		case "maxpingsout":
  1309  			diffOpts = append(diffOpts, &maxPingsOutOption{newValue: newValue.(int)})
  1310  		case "writedeadline":
  1311  			diffOpts = append(diffOpts, &writeDeadlineOption{newValue: newValue.(time.Duration)})
  1312  		case "clientadvertise":
  1313  			cliAdv := newValue.(string)
  1314  			if cliAdv != "" {
  1315  				// Validate ClientAdvertise syntax
  1316  				if _, _, err := parseHostPort(cliAdv, 0); err != nil {
  1317  					return nil, fmt.Errorf("invalid ClientAdvertise value of %s, err=%v", cliAdv, err)
  1318  				}
  1319  			}
  1320  			diffOpts = append(diffOpts, &clientAdvertiseOption{newValue: cliAdv})
  1321  		case "accounts":
  1322  			diffOpts = append(diffOpts, &accountsOption{})
  1323  		case "resolver", "accountresolver", "accountsresolver":
  1324  			// We can't move from no resolver to one. So check for that.
  1325  			if (oldValue == nil && newValue != nil) ||
  1326  				(oldValue != nil && newValue == nil) {
  1327  				return nil, fmt.Errorf("config reload does not support moving to or from an account resolver")
  1328  			}
  1329  			diffOpts = append(diffOpts, &accountsOption{})
  1330  		case "accountresolvertlsconfig":
  1331  			diffOpts = append(diffOpts, &accountsOption{})
  1332  		case "gateway":
  1333  			// Not supported for now, but report warning if configuration of gateway
  1334  			// is actually changed so that user knows that it won't take effect.
  1335  
  1336  			// Any deep-equal is likely to fail for when there is a TLSConfig. so
  1337  			// remove for the test.
  1338  			tmpOld := oldValue.(GatewayOpts)
  1339  			tmpNew := newValue.(GatewayOpts)
  1340  			tmpOld.TLSConfig = nil
  1341  			tmpNew.TLSConfig = nil
  1342  			tmpOld.tlsConfigOpts = nil
  1343  			tmpNew.tlsConfigOpts = nil
  1344  
  1345  			// Need to do the same for remote gateways' TLS configs.
  1346  			// But we can't just set remotes' TLSConfig to nil otherwise this
  1347  			// would lose the real TLS configuration.
  1348  			tmpOld.Gateways = copyRemoteGWConfigsWithoutTLSConfig(tmpOld.Gateways)
  1349  			tmpNew.Gateways = copyRemoteGWConfigsWithoutTLSConfig(tmpNew.Gateways)
  1350  
  1351  			// If there is really a change prevents reload.
  1352  			if !reflect.DeepEqual(tmpOld, tmpNew) {
  1353  				// See TODO(ik) note below about printing old/new values.
  1354  				return nil, fmt.Errorf("config reload not supported for %s: old=%v, new=%v",
  1355  					field.Name, oldValue, newValue)
  1356  			}
  1357  		case "leafnode":
  1358  			// Similar to gateways
  1359  			tmpOld := oldValue.(LeafNodeOpts)
  1360  			tmpNew := newValue.(LeafNodeOpts)
  1361  			tmpOld.TLSConfig = nil
  1362  			tmpNew.TLSConfig = nil
  1363  			tmpOld.tlsConfigOpts = nil
  1364  			tmpNew.tlsConfigOpts = nil
  1365  			// We will allow TLSHandshakeFirst to me config reloaded. First,
  1366  			// we just want to detect if there was a change in the leafnodes{}
  1367  			// block, and if not, we will check the remotes.
  1368  			handshakeFirstChanged := tmpOld.TLSHandshakeFirst != tmpNew.TLSHandshakeFirst
  1369  			// If changed, set them (in the temporary variables) to false so that the
  1370  			// rest of the comparison does not fail.
  1371  			if handshakeFirstChanged {
  1372  				tmpOld.TLSHandshakeFirst, tmpNew.TLSHandshakeFirst = false, false
  1373  			} else if len(tmpOld.Remotes) == len(tmpNew.Remotes) {
  1374  				// Since we don't support changes in the remotes, we will do a
  1375  				// simple pass to see if there was a change of this field.
  1376  				for i := 0; i < len(tmpOld.Remotes); i++ {
  1377  					if tmpOld.Remotes[i].TLSHandshakeFirst != tmpNew.Remotes[i].TLSHandshakeFirst {
  1378  						handshakeFirstChanged = true
  1379  						break
  1380  					}
  1381  				}
  1382  			}
  1383  			// We also support config reload for compression. Check if it changed before
  1384  			// blanking them out for the deep-equal check at the end.
  1385  			compressionChanged := !reflect.DeepEqual(tmpOld.Compression, tmpNew.Compression)
  1386  			if compressionChanged {
  1387  				tmpOld.Compression, tmpNew.Compression = CompressionOpts{}, CompressionOpts{}
  1388  			} else if len(tmpOld.Remotes) == len(tmpNew.Remotes) {
  1389  				// Same that for tls first check, do the remotes now.
  1390  				for i := 0; i < len(tmpOld.Remotes); i++ {
  1391  					if !reflect.DeepEqual(tmpOld.Remotes[i].Compression, tmpNew.Remotes[i].Compression) {
  1392  						compressionChanged = true
  1393  						break
  1394  					}
  1395  				}
  1396  			}
  1397  
  1398  			// Need to do the same for remote leafnodes' TLS configs.
  1399  			// But we can't just set remotes' TLSConfig to nil otherwise this
  1400  			// would lose the real TLS configuration.
  1401  			tmpOld.Remotes = copyRemoteLNConfigForReloadCompare(tmpOld.Remotes)
  1402  			tmpNew.Remotes = copyRemoteLNConfigForReloadCompare(tmpNew.Remotes)
  1403  
  1404  			// Special check for leafnode remotes changes which are not supported right now.
  1405  			leafRemotesChanged := func(a, b LeafNodeOpts) bool {
  1406  				if len(a.Remotes) != len(b.Remotes) {
  1407  					return true
  1408  				}
  1409  
  1410  				// Check whether all remotes URLs are still the same.
  1411  				for _, oldRemote := range a.Remotes {
  1412  					var found bool
  1413  
  1414  					if oldRemote.LocalAccount == _EMPTY_ {
  1415  						oldRemote.LocalAccount = globalAccountName
  1416  					}
  1417  
  1418  					for _, newRemote := range b.Remotes {
  1419  						// Bind to global account in case not defined.
  1420  						if newRemote.LocalAccount == _EMPTY_ {
  1421  							newRemote.LocalAccount = globalAccountName
  1422  						}
  1423  
  1424  						if reflect.DeepEqual(oldRemote, newRemote) {
  1425  							found = true
  1426  							break
  1427  						}
  1428  					}
  1429  					if !found {
  1430  						return true
  1431  					}
  1432  				}
  1433  
  1434  				return false
  1435  			}
  1436  
  1437  			// First check whether remotes changed at all. If they did not,
  1438  			// skip them in the complete equal check.
  1439  			if !leafRemotesChanged(tmpOld, tmpNew) {
  1440  				tmpOld.Remotes = nil
  1441  				tmpNew.Remotes = nil
  1442  			}
  1443  
  1444  			// Special check for auth users to detect changes.
  1445  			// If anything is off will fall through and fail below.
  1446  			// If we detect they are semantically the same we nil them out
  1447  			// to pass the check below.
  1448  			if tmpOld.Users != nil || tmpNew.Users != nil {
  1449  				if len(tmpOld.Users) == len(tmpNew.Users) {
  1450  					oua := make(map[string]*User, len(tmpOld.Users))
  1451  					nua := make(map[string]*User, len(tmpOld.Users))
  1452  					for _, u := range tmpOld.Users {
  1453  						oua[u.Username] = u
  1454  					}
  1455  					for _, u := range tmpNew.Users {
  1456  						nua[u.Username] = u
  1457  					}
  1458  					same := true
  1459  					for uname, u := range oua {
  1460  						// If we can not find new one with same name, drop through to fail.
  1461  						nu, ok := nua[uname]
  1462  						if !ok {
  1463  							same = false
  1464  							break
  1465  						}
  1466  						// If username or password or account different break.
  1467  						if u.Username != nu.Username || u.Password != nu.Password || u.Account.GetName() != nu.Account.GetName() {
  1468  							same = false
  1469  							break
  1470  						}
  1471  					}
  1472  					// We can nil out here.
  1473  					if same {
  1474  						tmpOld.Users, tmpNew.Users = nil, nil
  1475  					}
  1476  				}
  1477  			}
  1478  
  1479  			// If there is really a change prevents reload.
  1480  			if !reflect.DeepEqual(tmpOld, tmpNew) {
  1481  				// See TODO(ik) note below about printing old/new values.
  1482  				return nil, fmt.Errorf("config reload not supported for %s: old=%v, new=%v",
  1483  					field.Name, oldValue, newValue)
  1484  			}
  1485  
  1486  			diffOpts = append(diffOpts, &leafNodeOption{
  1487  				tlsFirstChanged:    handshakeFirstChanged,
  1488  				compressionChanged: compressionChanged,
  1489  			})
  1490  		case "jetstream":
  1491  			new := newValue.(bool)
  1492  			old := oldValue.(bool)
  1493  			if new != old {
  1494  				diffOpts = append(diffOpts, &jetStreamOption{newValue: new})
  1495  			}
  1496  
  1497  			// Mark whether JS will be disabled.
  1498  			disableJS = !new
  1499  		case "storedir":
  1500  			new := newValue.(string)
  1501  			old := oldValue.(string)
  1502  			modified := new != old
  1503  
  1504  			// Check whether JS is being disabled and/or storage dir attempted to change.
  1505  			if jsEnabled && modified {
  1506  				if new == _EMPTY_ {
  1507  					// This means that either JS is being disabled or it is using an temp dir.
  1508  					// Allow the change but error in case JS was not disabled.
  1509  					jsStoreDirChanged = true
  1510  				} else {
  1511  					return nil, fmt.Errorf("config reload not supported for jetstream storage directory")
  1512  				}
  1513  			}
  1514  		case "jetstreammaxmemory", "jetstreammaxstore":
  1515  			old := oldValue.(int64)
  1516  			new := newValue.(int64)
  1517  
  1518  			// Check whether JS is being disabled and/or limits are being changed.
  1519  			var (
  1520  				modified  = new != old
  1521  				fromUnset = old == -1
  1522  				fromSet   = !fromUnset
  1523  				toUnset   = new == -1
  1524  				toSet     = !toUnset
  1525  			)
  1526  			if jsEnabled && modified {
  1527  				// Cannot change limits from dynamic storage at runtime.
  1528  				switch {
  1529  				case fromSet && toUnset:
  1530  					// Limits changed but it may mean that JS is being disabled,
  1531  					// keep track of the change and error in case it is not.
  1532  					switch optName {
  1533  					case "jetstreammaxmemory":
  1534  						jsMemLimitsChanged = true
  1535  					case "jetstreammaxstore":
  1536  						jsFileLimitsChanged = true
  1537  					default:
  1538  						return nil, fmt.Errorf("config reload not supported for jetstream max memory and store")
  1539  					}
  1540  				case fromUnset && toSet:
  1541  					// Prevent changing from dynamic max memory / file at runtime.
  1542  					return nil, fmt.Errorf("config reload not supported for jetstream dynamic max memory and store")
  1543  				default:
  1544  					return nil, fmt.Errorf("config reload not supported for jetstream max memory and store")
  1545  				}
  1546  			}
  1547  		case "websocket":
  1548  			// Similar to gateways
  1549  			tmpOld := oldValue.(WebsocketOpts)
  1550  			tmpNew := newValue.(WebsocketOpts)
  1551  			tmpOld.TLSConfig, tmpOld.tlsConfigOpts = nil, nil
  1552  			tmpNew.TLSConfig, tmpNew.tlsConfigOpts = nil, nil
  1553  			// If there is really a change prevents reload.
  1554  			if !reflect.DeepEqual(tmpOld, tmpNew) {
  1555  				// See TODO(ik) note below about printing old/new values.
  1556  				return nil, fmt.Errorf("config reload not supported for %s: old=%v, new=%v",
  1557  					field.Name, oldValue, newValue)
  1558  			}
  1559  		case "mqtt":
  1560  			diffOpts = append(diffOpts, &mqttAckWaitReload{newValue: newValue.(MQTTOpts).AckWait})
  1561  			diffOpts = append(diffOpts, &mqttMaxAckPendingReload{newValue: newValue.(MQTTOpts).MaxAckPending})
  1562  			diffOpts = append(diffOpts, &mqttStreamReplicasReload{newValue: newValue.(MQTTOpts).StreamReplicas})
  1563  			diffOpts = append(diffOpts, &mqttConsumerReplicasReload{newValue: newValue.(MQTTOpts).ConsumerReplicas})
  1564  			diffOpts = append(diffOpts, &mqttConsumerMemoryStorageReload{newValue: newValue.(MQTTOpts).ConsumerMemoryStorage})
  1565  			diffOpts = append(diffOpts, &mqttInactiveThresholdReload{newValue: newValue.(MQTTOpts).ConsumerInactiveThreshold})
  1566  
  1567  			// Nil out/set to 0 the options that we allow to be reloaded so that
  1568  			// we only fail reload if some that we don't support are changed.
  1569  			tmpOld := oldValue.(MQTTOpts)
  1570  			tmpNew := newValue.(MQTTOpts)
  1571  			tmpOld.TLSConfig, tmpOld.tlsConfigOpts, tmpOld.AckWait, tmpOld.MaxAckPending, tmpOld.StreamReplicas, tmpOld.ConsumerReplicas, tmpOld.ConsumerMemoryStorage = nil, nil, 0, 0, 0, 0, false
  1572  			tmpOld.ConsumerInactiveThreshold = 0
  1573  			tmpNew.TLSConfig, tmpNew.tlsConfigOpts, tmpNew.AckWait, tmpNew.MaxAckPending, tmpNew.StreamReplicas, tmpNew.ConsumerReplicas, tmpNew.ConsumerMemoryStorage = nil, nil, 0, 0, 0, 0, false
  1574  			tmpNew.ConsumerInactiveThreshold = 0
  1575  
  1576  			if !reflect.DeepEqual(tmpOld, tmpNew) {
  1577  				// See TODO(ik) note below about printing old/new values.
  1578  				return nil, fmt.Errorf("config reload not supported for %s: old=%v, new=%v",
  1579  					field.Name, oldValue, newValue)
  1580  			}
  1581  			tmpNew.AckWait = newValue.(MQTTOpts).AckWait
  1582  			tmpNew.MaxAckPending = newValue.(MQTTOpts).MaxAckPending
  1583  			tmpNew.StreamReplicas = newValue.(MQTTOpts).StreamReplicas
  1584  			tmpNew.ConsumerReplicas = newValue.(MQTTOpts).ConsumerReplicas
  1585  			tmpNew.ConsumerMemoryStorage = newValue.(MQTTOpts).ConsumerMemoryStorage
  1586  			tmpNew.ConsumerInactiveThreshold = newValue.(MQTTOpts).ConsumerInactiveThreshold
  1587  		case "connecterrorreports":
  1588  			diffOpts = append(diffOpts, &connectErrorReports{newValue: newValue.(int)})
  1589  		case "reconnecterrorreports":
  1590  			diffOpts = append(diffOpts, &reconnectErrorReports{newValue: newValue.(int)})
  1591  		case "nolog", "nosigs":
  1592  			// Ignore NoLog and NoSigs options since they are not parsed and only used in
  1593  			// testing.
  1594  			continue
  1595  		case "disableshortfirstping":
  1596  			newOpts.DisableShortFirstPing = oldValue.(bool)
  1597  			continue
  1598  		case "maxtracedmsglen":
  1599  			diffOpts = append(diffOpts, &maxTracedMsgLenOption{newValue: newValue.(int)})
  1600  		case "port":
  1601  			// check to see if newValue == 0 and continue if so.
  1602  			if newValue == 0 {
  1603  				// ignore RANDOM_PORT
  1604  				continue
  1605  			}
  1606  			fallthrough
  1607  		case "noauthuser":
  1608  			if oldValue != _EMPTY_ && newValue == _EMPTY_ {
  1609  				for _, user := range newOpts.Users {
  1610  					if user.Username == oldValue {
  1611  						return nil, fmt.Errorf("config reload not supported for %s: old=%v, new=%v",
  1612  							field.Name, oldValue, newValue)
  1613  					}
  1614  				}
  1615  			} else {
  1616  				return nil, fmt.Errorf("config reload not supported for %s: old=%v, new=%v",
  1617  					field.Name, oldValue, newValue)
  1618  			}
  1619  		case "systemaccount":
  1620  			if oldValue != DEFAULT_SYSTEM_ACCOUNT || newValue != _EMPTY_ {
  1621  				return nil, fmt.Errorf("config reload not supported for %s: old=%v, new=%v",
  1622  					field.Name, oldValue, newValue)
  1623  			}
  1624  		case "ocspconfig":
  1625  			diffOpts = append(diffOpts, &ocspOption{newValue: newValue.(*OCSPConfig)})
  1626  		case "ocspcacheconfig":
  1627  			diffOpts = append(diffOpts, &ocspResponseCacheOption{newValue: newValue.(*OCSPResponseCacheConfig)})
  1628  		case "profblockrate":
  1629  			new := newValue.(int)
  1630  			old := oldValue.(int)
  1631  			if new != old {
  1632  				diffOpts = append(diffOpts, &profBlockRateReload{newValue: new})
  1633  			}
  1634  		default:
  1635  			// TODO(ik): Implement String() on those options to have a nice print.
  1636  			// %v is difficult to figure what's what, %+v print private fields and
  1637  			// would print passwords. Tried json.Marshal but it is too verbose for
  1638  			// the URL array.
  1639  
  1640  			// Bail out if attempting to reload any unsupported options.
  1641  			return nil, fmt.Errorf("config reload not supported for %s: old=%v, new=%v",
  1642  				field.Name, oldValue, newValue)
  1643  		}
  1644  	}
  1645  
  1646  	// If not disabling JS but limits have changed then it is an error.
  1647  	if !disableJS {
  1648  		if jsMemLimitsChanged || jsFileLimitsChanged {
  1649  			return nil, fmt.Errorf("config reload not supported for jetstream max memory and max store")
  1650  		}
  1651  		if jsStoreDirChanged {
  1652  			return nil, fmt.Errorf("config reload not supported for jetstream storage dir")
  1653  		}
  1654  	}
  1655  
  1656  	return diffOpts, nil
  1657  }
  1658  
  1659  func copyRemoteGWConfigsWithoutTLSConfig(current []*RemoteGatewayOpts) []*RemoteGatewayOpts {
  1660  	l := len(current)
  1661  	if l == 0 {
  1662  		return nil
  1663  	}
  1664  	rgws := make([]*RemoteGatewayOpts, 0, l)
  1665  	for _, rcfg := range current {
  1666  		cp := *rcfg
  1667  		cp.TLSConfig = nil
  1668  		cp.tlsConfigOpts = nil
  1669  		rgws = append(rgws, &cp)
  1670  	}
  1671  	return rgws
  1672  }
  1673  
  1674  func copyRemoteLNConfigForReloadCompare(current []*RemoteLeafOpts) []*RemoteLeafOpts {
  1675  	l := len(current)
  1676  	if l == 0 {
  1677  		return nil
  1678  	}
  1679  	rlns := make([]*RemoteLeafOpts, 0, l)
  1680  	for _, rcfg := range current {
  1681  		cp := *rcfg
  1682  		cp.TLSConfig = nil
  1683  		cp.tlsConfigOpts = nil
  1684  		cp.TLSHandshakeFirst = false
  1685  		// This is set only when processing a CONNECT, so reset here so that we
  1686  		// don't fail the DeepEqual comparison.
  1687  		cp.TLS = false
  1688  		// For now, remove DenyImports/Exports since those get modified at runtime
  1689  		// to add JS APIs.
  1690  		cp.DenyImports, cp.DenyExports = nil, nil
  1691  		// Remove compression mode
  1692  		cp.Compression = CompressionOpts{}
  1693  		rlns = append(rlns, &cp)
  1694  	}
  1695  	return rlns
  1696  }
  1697  
  1698  func (s *Server) applyOptions(ctx *reloadContext, opts []option) {
  1699  	var (
  1700  		reloadLogging      = false
  1701  		reloadAuth         = false
  1702  		reloadClusterPerms = false
  1703  		reloadClientTrcLvl = false
  1704  		reloadJetstream    = false
  1705  		jsEnabled          = false
  1706  		isStatszChange     = false
  1707  		co                 *clusterOption
  1708  	)
  1709  	for _, opt := range opts {
  1710  		opt.Apply(s)
  1711  		if opt.IsLoggingChange() {
  1712  			reloadLogging = true
  1713  		}
  1714  		if opt.IsTraceLevelChange() {
  1715  			reloadClientTrcLvl = true
  1716  		}
  1717  		if opt.IsAuthChange() {
  1718  			reloadAuth = true
  1719  		}
  1720  		if opt.IsClusterPoolSizeOrAccountsChange() {
  1721  			co = opt.(*clusterOption)
  1722  		}
  1723  		if opt.IsClusterPermsChange() {
  1724  			reloadClusterPerms = true
  1725  		}
  1726  		if opt.IsJetStreamChange() {
  1727  			reloadJetstream = true
  1728  			jsEnabled = opt.(*jetStreamOption).newValue
  1729  		}
  1730  		if opt.IsStatszChange() {
  1731  			isStatszChange = true
  1732  		}
  1733  	}
  1734  
  1735  	if reloadLogging {
  1736  		s.ConfigureLogger()
  1737  	}
  1738  	if reloadClientTrcLvl {
  1739  		s.reloadClientTraceLevel()
  1740  	}
  1741  	if reloadAuth {
  1742  		s.reloadAuthorization()
  1743  	}
  1744  	if reloadClusterPerms {
  1745  		s.reloadClusterPermissions(ctx.oldClusterPerms)
  1746  	}
  1747  	newOpts := s.getOpts()
  1748  	// If we need to reload cluster pool/per-account, then co will be not nil
  1749  	if co != nil {
  1750  		s.reloadClusterPoolAndAccounts(co, newOpts)
  1751  	}
  1752  	if reloadJetstream {
  1753  		if !jsEnabled {
  1754  			s.DisableJetStream()
  1755  		} else if !s.JetStreamEnabled() {
  1756  			if err := s.restartJetStream(); err != nil {
  1757  				s.Warnf("Can't start JetStream: %v", err)
  1758  			}
  1759  		}
  1760  		// Make sure to reset the internal loop's version of JS.
  1761  		s.resetInternalLoopInfo()
  1762  	}
  1763  	if isStatszChange {
  1764  		s.sendStatszUpdate()
  1765  	}
  1766  
  1767  	// For remote gateways and leafnodes, make sure that their TLS configuration
  1768  	// is updated (since the config is "captured" early and changes would otherwise
  1769  	// not be visible).
  1770  	if s.gateway.enabled {
  1771  		s.gateway.updateRemotesTLSConfig(newOpts)
  1772  	}
  1773  	if len(newOpts.LeafNode.Remotes) > 0 {
  1774  		s.updateRemoteLeafNodesTLSConfig(newOpts)
  1775  	}
  1776  
  1777  	// Always restart OCSP monitoring on reload.
  1778  	if err := s.reloadOCSP(); err != nil {
  1779  		s.Warnf("Can't restart OCSP features: %v", err)
  1780  	}
  1781  
  1782  	s.Noticef("Reloaded server configuration")
  1783  }
  1784  
  1785  // This will send a reset to the internal send loop.
  1786  func (s *Server) resetInternalLoopInfo() {
  1787  	var resetCh chan struct{}
  1788  	s.mu.Lock()
  1789  	if s.sys != nil {
  1790  		// can't hold the lock as go routine reading it may be waiting for lock as well
  1791  		resetCh = s.sys.resetCh
  1792  	}
  1793  	s.mu.Unlock()
  1794  
  1795  	if resetCh != nil {
  1796  		resetCh <- struct{}{}
  1797  	}
  1798  }
  1799  
  1800  // Update all cached debug and trace settings for every client
  1801  func (s *Server) reloadClientTraceLevel() {
  1802  	opts := s.getOpts()
  1803  
  1804  	if opts.NoLog {
  1805  		return
  1806  	}
  1807  
  1808  	// Create a list of all clients.
  1809  	// Update their trace level when not holding server or gateway lock
  1810  
  1811  	s.mu.Lock()
  1812  	clientCnt := 1 + len(s.clients) + len(s.grTmpClients) + s.numRoutes() + len(s.leafs)
  1813  	s.mu.Unlock()
  1814  
  1815  	s.gateway.RLock()
  1816  	clientCnt += len(s.gateway.in) + len(s.gateway.outo)
  1817  	s.gateway.RUnlock()
  1818  
  1819  	clients := make([]*client, 0, clientCnt)
  1820  
  1821  	s.mu.Lock()
  1822  	if s.eventsEnabled() {
  1823  		clients = append(clients, s.sys.client)
  1824  	}
  1825  
  1826  	cMaps := []map[uint64]*client{s.clients, s.grTmpClients, s.leafs}
  1827  	for _, m := range cMaps {
  1828  		for _, c := range m {
  1829  			clients = append(clients, c)
  1830  		}
  1831  	}
  1832  	s.forEachRoute(func(c *client) {
  1833  		clients = append(clients, c)
  1834  	})
  1835  	s.mu.Unlock()
  1836  
  1837  	s.gateway.RLock()
  1838  	for _, c := range s.gateway.in {
  1839  		clients = append(clients, c)
  1840  	}
  1841  	clients = append(clients, s.gateway.outo...)
  1842  	s.gateway.RUnlock()
  1843  
  1844  	for _, c := range clients {
  1845  		// client.trace is commonly read while holding the lock
  1846  		c.mu.Lock()
  1847  		c.setTraceLevel()
  1848  		c.mu.Unlock()
  1849  	}
  1850  }
  1851  
  1852  // reloadAuthorization reconfigures the server authorization settings,
  1853  // disconnects any clients who are no longer authorized, and removes any
  1854  // unauthorized subscriptions.
  1855  func (s *Server) reloadAuthorization() {
  1856  	// This map will contain the names of accounts that have their streams
  1857  	// import configuration changed.
  1858  	var awcsti map[string]struct{}
  1859  	checkJetStream := false
  1860  	opts := s.getOpts()
  1861  	s.mu.Lock()
  1862  
  1863  	deletedAccounts := make(map[string]*Account)
  1864  
  1865  	// This can not be changed for now so ok to check server's trustedKeys unlocked.
  1866  	// If plain configured accounts, process here.
  1867  	if s.trustedKeys == nil {
  1868  		// Make a map of the configured account names so we figure out the accounts
  1869  		// that should be removed later on.
  1870  		configAccs := make(map[string]struct{}, len(opts.Accounts))
  1871  		for _, acc := range opts.Accounts {
  1872  			configAccs[acc.GetName()] = struct{}{}
  1873  		}
  1874  		// Now range over existing accounts and keep track of the ones deleted
  1875  		// so some cleanup can be made after releasing the server lock.
  1876  		s.accounts.Range(func(k, v interface{}) bool {
  1877  			an, acc := k.(string), v.(*Account)
  1878  			// Exclude default and system account from this test since those
  1879  			// may not actually be in opts.Accounts.
  1880  			if an == DEFAULT_GLOBAL_ACCOUNT || an == DEFAULT_SYSTEM_ACCOUNT {
  1881  				return true
  1882  			}
  1883  			// Check check if existing account is still in opts.Accounts.
  1884  			if _, ok := configAccs[an]; !ok {
  1885  				deletedAccounts[an] = acc
  1886  				s.accounts.Delete(k)
  1887  			}
  1888  			return true
  1889  		})
  1890  		// This will update existing and add new ones.
  1891  		awcsti, _ = s.configureAccounts(true)
  1892  		s.configureAuthorization()
  1893  		// Double check any JetStream configs.
  1894  		checkJetStream = s.getJetStream() != nil
  1895  	} else if opts.AccountResolver != nil {
  1896  		s.configureResolver()
  1897  		if _, ok := s.accResolver.(*MemAccResolver); ok {
  1898  			// Check preloads so we can issue warnings etc if needed.
  1899  			s.checkResolvePreloads()
  1900  			// With a memory resolver we want to do something similar to configured accounts.
  1901  			// We will walk the accounts and delete them if they are no longer present via fetch.
  1902  			// If they are present we will force a claim update to process changes.
  1903  			s.accounts.Range(func(k, v interface{}) bool {
  1904  				acc := v.(*Account)
  1905  				// Skip global account.
  1906  				if acc == s.gacc {
  1907  					return true
  1908  				}
  1909  				accName := acc.GetName()
  1910  				// Release server lock for following actions
  1911  				s.mu.Unlock()
  1912  				accClaims, claimJWT, _ := s.fetchAccountClaims(accName)
  1913  				if accClaims != nil {
  1914  					if err := s.updateAccountWithClaimJWT(acc, claimJWT); err != nil {
  1915  						s.Noticef("Reloaded: deleting account [bad claims]: %q", accName)
  1916  						s.accounts.Delete(k)
  1917  					}
  1918  				} else {
  1919  					s.Noticef("Reloaded: deleting account [removed]: %q", accName)
  1920  					s.accounts.Delete(k)
  1921  				}
  1922  				// Regrab server lock.
  1923  				s.mu.Lock()
  1924  				return true
  1925  			})
  1926  		}
  1927  	}
  1928  
  1929  	var (
  1930  		cclientsa [64]*client
  1931  		cclients  = cclientsa[:0]
  1932  		clientsa  [64]*client
  1933  		clients   = clientsa[:0]
  1934  		routesa   [64]*client
  1935  		routes    = routesa[:0]
  1936  	)
  1937  
  1938  	// Gather clients that changed accounts. We will close them and they
  1939  	// will reconnect, doing the right thing.
  1940  	for _, client := range s.clients {
  1941  		if s.clientHasMovedToDifferentAccount(client) {
  1942  			cclients = append(cclients, client)
  1943  		} else {
  1944  			clients = append(clients, client)
  1945  		}
  1946  	}
  1947  	s.forEachRoute(func(route *client) {
  1948  		routes = append(routes, route)
  1949  	})
  1950  	// Check here for any system/internal clients which will not be in the servers map of normal clients.
  1951  	if s.sys != nil && s.sys.account != nil && !opts.NoSystemAccount {
  1952  		s.accounts.Store(s.sys.account.Name, s.sys.account)
  1953  	}
  1954  
  1955  	s.accounts.Range(func(k, v interface{}) bool {
  1956  		acc := v.(*Account)
  1957  		acc.mu.RLock()
  1958  		// Check for sysclients accounting, ignore the system account.
  1959  		if acc.sysclients > 0 && (s.sys == nil || s.sys.account != acc) {
  1960  			for c := range acc.clients {
  1961  				if c.kind != CLIENT && c.kind != LEAF {
  1962  					clients = append(clients, c)
  1963  				}
  1964  			}
  1965  		}
  1966  		acc.mu.RUnlock()
  1967  		return true
  1968  	})
  1969  
  1970  	var resetCh chan struct{}
  1971  	if s.sys != nil {
  1972  		// can't hold the lock as go routine reading it may be waiting for lock as well
  1973  		resetCh = s.sys.resetCh
  1974  	}
  1975  	s.mu.Unlock()
  1976  
  1977  	// Clear some timers and remove service import subs for deleted accounts.
  1978  	for _, acc := range deletedAccounts {
  1979  		acc.mu.Lock()
  1980  		clearTimer(&acc.etmr)
  1981  		clearTimer(&acc.ctmr)
  1982  		for _, se := range acc.exports.services {
  1983  			se.clearResponseThresholdTimer()
  1984  		}
  1985  		acc.mu.Unlock()
  1986  		acc.removeAllServiceImportSubs()
  1987  	}
  1988  
  1989  	if resetCh != nil {
  1990  		resetCh <- struct{}{}
  1991  	}
  1992  
  1993  	// Check that publish retained messages sources are still allowed to publish.
  1994  	s.mqttCheckPubRetainedPerms()
  1995  
  1996  	// Close clients that have moved accounts
  1997  	for _, client := range cclients {
  1998  		client.closeConnection(ClientClosed)
  1999  	}
  2000  
  2001  	for _, c := range clients {
  2002  		// Disconnect any unauthorized clients.
  2003  		// Ignore internal clients.
  2004  		if (c.kind == CLIENT || c.kind == LEAF) && !s.isClientAuthorized(c) {
  2005  			c.authViolation()
  2006  			continue
  2007  		}
  2008  		// Check to make sure account is correct.
  2009  		c.swapAccountAfterReload()
  2010  		// Remove any unauthorized subscriptions and check for account imports.
  2011  		c.processSubsOnConfigReload(awcsti)
  2012  	}
  2013  
  2014  	for _, route := range routes {
  2015  		// Disconnect any unauthorized routes.
  2016  		// Do this only for routes that were accepted, not initiated
  2017  		// because in the later case, we don't have the user name/password
  2018  		// of the remote server.
  2019  		if !route.isSolicitedRoute() && !s.isRouterAuthorized(route) {
  2020  			route.setNoReconnect()
  2021  			route.authViolation()
  2022  		}
  2023  	}
  2024  
  2025  	if res := s.AccountResolver(); res != nil {
  2026  		res.Reload()
  2027  	}
  2028  
  2029  	// We will double check all JetStream configs on a reload.
  2030  	if checkJetStream {
  2031  		if err := s.enableJetStreamAccounts(); err != nil {
  2032  			s.Errorf(err.Error())
  2033  		}
  2034  	}
  2035  }
  2036  
  2037  // Returns true if given client current account has changed (or user
  2038  // no longer exist) in the new config, false if the user did not
  2039  // change accounts.
  2040  // Server lock is held on entry.
  2041  func (s *Server) clientHasMovedToDifferentAccount(c *client) bool {
  2042  	var (
  2043  		nu *NkeyUser
  2044  		u  *User
  2045  	)
  2046  	c.mu.Lock()
  2047  	defer c.mu.Unlock()
  2048  	if c.opts.Nkey != _EMPTY_ {
  2049  		if s.nkeys != nil {
  2050  			nu = s.nkeys[c.opts.Nkey]
  2051  		}
  2052  	} else if c.opts.Username != _EMPTY_ {
  2053  		if s.users != nil {
  2054  			u = s.users[c.opts.Username]
  2055  		}
  2056  	} else {
  2057  		return false
  2058  	}
  2059  	// Get the current account name
  2060  	var curAccName string
  2061  	if c.acc != nil {
  2062  		curAccName = c.acc.Name
  2063  	}
  2064  	if nu != nil && nu.Account != nil {
  2065  		return curAccName != nu.Account.Name
  2066  	} else if u != nil && u.Account != nil {
  2067  		return curAccName != u.Account.Name
  2068  	}
  2069  	// user/nkey no longer exists.
  2070  	return true
  2071  }
  2072  
  2073  // reloadClusterPermissions reconfigures the cluster's permssions
  2074  // and set the permissions to all existing routes, sending an
  2075  // update INFO protocol so that remote can resend their local
  2076  // subs if needed, and sending local subs matching cluster's
  2077  // import subjects.
  2078  func (s *Server) reloadClusterPermissions(oldPerms *RoutePermissions) {
  2079  	s.mu.Lock()
  2080  	newPerms := s.getOpts().Cluster.Permissions
  2081  	routes := make(map[uint64]*client, s.numRoutes())
  2082  	// Get all connected routes
  2083  	s.forEachRoute(func(route *client) {
  2084  		route.mu.Lock()
  2085  		routes[route.cid] = route
  2086  		route.mu.Unlock()
  2087  	})
  2088  	// If new permissions is nil, then clear routeInfo import/export
  2089  	if newPerms == nil {
  2090  		s.routeInfo.Import = nil
  2091  		s.routeInfo.Export = nil
  2092  	} else {
  2093  		s.routeInfo.Import = newPerms.Import
  2094  		s.routeInfo.Export = newPerms.Export
  2095  	}
  2096  	infoJSON := generateInfoJSON(&s.routeInfo)
  2097  	s.mu.Unlock()
  2098  
  2099  	// Close connections for routes that don't understand async INFO.
  2100  	for _, route := range routes {
  2101  		route.mu.Lock()
  2102  		close := route.opts.Protocol < RouteProtoInfo
  2103  		cid := route.cid
  2104  		route.mu.Unlock()
  2105  		if close {
  2106  			route.closeConnection(RouteRemoved)
  2107  			delete(routes, cid)
  2108  		}
  2109  	}
  2110  
  2111  	// If there are no route left, we are done
  2112  	if len(routes) == 0 {
  2113  		return
  2114  	}
  2115  
  2116  	// Fake clients to test cluster permissions
  2117  	oldPermsTester := &client{}
  2118  	oldPermsTester.setRoutePermissions(oldPerms)
  2119  	newPermsTester := &client{}
  2120  	newPermsTester.setRoutePermissions(newPerms)
  2121  
  2122  	var (
  2123  		_localSubs       [4096]*subscription
  2124  		subsNeedSUB      = map[*client][]*subscription{}
  2125  		subsNeedUNSUB    = map[*client][]*subscription{}
  2126  		deleteRoutedSubs []*subscription
  2127  	)
  2128  
  2129  	getRouteForAccount := func(accName string, poolIdx int) *client {
  2130  		for _, r := range routes {
  2131  			r.mu.Lock()
  2132  			ok := (poolIdx >= 0 && poolIdx == r.route.poolIdx) || (string(r.route.accName) == accName) || r.route.noPool
  2133  			r.mu.Unlock()
  2134  			if ok {
  2135  				return r
  2136  			}
  2137  		}
  2138  		return nil
  2139  	}
  2140  
  2141  	// First set the new permissions on all routes.
  2142  	for _, route := range routes {
  2143  		route.mu.Lock()
  2144  		route.setRoutePermissions(newPerms)
  2145  		route.mu.Unlock()
  2146  	}
  2147  
  2148  	// Then, go over all accounts and gather local subscriptions that need to be
  2149  	// sent over as SUB or removed as UNSUB, and routed subscriptions that need
  2150  	// to be dropped due to export permissions.
  2151  	s.accounts.Range(func(_, v interface{}) bool {
  2152  		acc := v.(*Account)
  2153  		acc.mu.RLock()
  2154  		accName, sl, poolIdx := acc.Name, acc.sl, acc.routePoolIdx
  2155  		acc.mu.RUnlock()
  2156  		// Get the route handling this account. If no route or sublist, bail out.
  2157  		route := getRouteForAccount(accName, poolIdx)
  2158  		if route == nil || sl == nil {
  2159  			return true
  2160  		}
  2161  		localSubs := _localSubs[:0]
  2162  		sl.localSubs(&localSubs, false)
  2163  
  2164  		// Go through all local subscriptions
  2165  		for _, sub := range localSubs {
  2166  			// Get all subs that can now be imported
  2167  			subj := string(sub.subject)
  2168  			couldImportThen := oldPermsTester.canImport(subj)
  2169  			canImportNow := newPermsTester.canImport(subj)
  2170  			if canImportNow {
  2171  				// If we could not before, then will need to send a SUB protocol.
  2172  				if !couldImportThen {
  2173  					subsNeedSUB[route] = append(subsNeedSUB[route], sub)
  2174  				}
  2175  			} else if couldImportThen {
  2176  				// We were previously able to import this sub, but now
  2177  				// we can't so we need to send an UNSUB protocol
  2178  				subsNeedUNSUB[route] = append(subsNeedUNSUB[route], sub)
  2179  			}
  2180  		}
  2181  		deleteRoutedSubs = deleteRoutedSubs[:0]
  2182  		route.mu.Lock()
  2183  		for key, sub := range route.subs {
  2184  			if an := strings.Fields(key)[0]; an != accName {
  2185  				continue
  2186  			}
  2187  			// If we can't export, we need to drop the subscriptions that
  2188  			// we have on behalf of this route.
  2189  			subj := string(sub.subject)
  2190  			if !route.canExport(subj) {
  2191  				delete(route.subs, string(sub.sid))
  2192  				deleteRoutedSubs = append(deleteRoutedSubs, sub)
  2193  			}
  2194  		}
  2195  		route.mu.Unlock()
  2196  		// Remove as a batch all the subs that we have removed from each route.
  2197  		sl.RemoveBatch(deleteRoutedSubs)
  2198  		return true
  2199  	})
  2200  
  2201  	// Send an update INFO, which will allow remote server to show
  2202  	// our current route config in monitoring and resend subscriptions
  2203  	// that we now possibly allow with a change of Export permissions.
  2204  	for _, route := range routes {
  2205  		route.mu.Lock()
  2206  		route.enqueueProto(infoJSON)
  2207  		// Now send SUB and UNSUB protocols as needed.
  2208  		if subs, ok := subsNeedSUB[route]; ok && len(subs) > 0 {
  2209  			route.sendRouteSubProtos(subs, false, nil)
  2210  		}
  2211  		if unsubs, ok := subsNeedUNSUB[route]; ok && len(unsubs) > 0 {
  2212  			route.sendRouteUnSubProtos(unsubs, false, nil)
  2213  		}
  2214  		route.mu.Unlock()
  2215  	}
  2216  }
  2217  
  2218  func (s *Server) reloadClusterPoolAndAccounts(co *clusterOption, opts *Options) {
  2219  	s.mu.Lock()
  2220  	// Prevent adding new routes until we are ready to do so.
  2221  	s.routesReject = true
  2222  	var ch chan struct{}
  2223  	// For accounts that have been added to the list of dedicated routes,
  2224  	// send a protocol to their current assigned routes to allow the
  2225  	// other side to prepare for the changes.
  2226  	if len(co.accsAdded) > 0 {
  2227  		protosSent := 0
  2228  		s.accAddedReqID = nuid.Next()
  2229  		for _, an := range co.accsAdded {
  2230  			if s.accRoutes == nil {
  2231  				s.accRoutes = make(map[string]map[string]*client)
  2232  			}
  2233  			// In case a config reload was first done on another server,
  2234  			// we may have already switched this account to a dedicated route.
  2235  			// But we still want to send the protocol over the routes that
  2236  			// would have otherwise handled it.
  2237  			if _, ok := s.accRoutes[an]; !ok {
  2238  				s.accRoutes[an] = make(map[string]*client)
  2239  			}
  2240  			if a, ok := s.accounts.Load(an); ok {
  2241  				acc := a.(*Account)
  2242  				acc.mu.Lock()
  2243  				sl := acc.sl
  2244  				// Get the current route pool index before calling setRouteInfo.
  2245  				rpi := acc.routePoolIdx
  2246  				// Switch to per-account route if not already done.
  2247  				if rpi >= 0 {
  2248  					s.setRouteInfo(acc)
  2249  				} else {
  2250  					// If it was transitioning, make sure we set it to the state
  2251  					// that indicates that it has a dedicated route
  2252  					if rpi == accTransitioningToDedicatedRoute {
  2253  						acc.routePoolIdx = accDedicatedRoute
  2254  					}
  2255  					// Otherwise get the route pool index it would have been before
  2256  					// the move so we can send the protocol to those routes.
  2257  					rpi = s.computeRoutePoolIdx(acc)
  2258  				}
  2259  				acc.mu.Unlock()
  2260  				// Generate the INFO protocol to send indicating that this account
  2261  				// is being moved to a dedicated route.
  2262  				ri := Info{
  2263  					RoutePoolSize: s.routesPoolSize,
  2264  					RouteAccount:  an,
  2265  					RouteAccReqID: s.accAddedReqID,
  2266  				}
  2267  				proto := generateInfoJSON(&ri)
  2268  				// Go over each remote's route at pool index `rpi` and remove
  2269  				// remote subs for this account and send the protocol.
  2270  				s.forEachRouteIdx(rpi, func(r *client) bool {
  2271  					r.mu.Lock()
  2272  					// Exclude routes to servers that don't support pooling.
  2273  					if !r.route.noPool {
  2274  						if subs := r.removeRemoteSubsForAcc(an); len(subs) > 0 {
  2275  							sl.RemoveBatch(subs)
  2276  						}
  2277  						r.enqueueProto(proto)
  2278  						protosSent++
  2279  					}
  2280  					r.mu.Unlock()
  2281  					return true
  2282  				})
  2283  			}
  2284  		}
  2285  		if protosSent > 0 {
  2286  			s.accAddedCh = make(chan struct{}, protosSent)
  2287  			ch = s.accAddedCh
  2288  		}
  2289  	}
  2290  	// Collect routes that need to be closed.
  2291  	routes := make(map[*client]struct{})
  2292  	// Collect the per-account routes that need to be closed.
  2293  	if len(co.accsRemoved) > 0 {
  2294  		for _, an := range co.accsRemoved {
  2295  			if remotes, ok := s.accRoutes[an]; ok && remotes != nil {
  2296  				for _, r := range remotes {
  2297  					if r != nil {
  2298  						r.setNoReconnect()
  2299  						routes[r] = struct{}{}
  2300  					}
  2301  				}
  2302  			}
  2303  		}
  2304  	}
  2305  	// If the pool size has changed, we need to close all pooled routes.
  2306  	if co.poolSizeChanged {
  2307  		s.forEachNonPerAccountRoute(func(r *client) {
  2308  			routes[r] = struct{}{}
  2309  		})
  2310  	}
  2311  	// If there are routes to close, we need to release the server lock.
  2312  	// Same if we need to wait on responses from the remotes when
  2313  	// processing new per-account routes.
  2314  	if len(routes) > 0 || len(ch) > 0 {
  2315  		s.mu.Unlock()
  2316  
  2317  		for done := false; !done && len(ch) > 0; {
  2318  			select {
  2319  			case <-ch:
  2320  			case <-time.After(2 * time.Second):
  2321  				s.Warnf("Timed out waiting for confirmation from all routes regarding per-account routes changes")
  2322  				done = true
  2323  			}
  2324  		}
  2325  
  2326  		for r := range routes {
  2327  			r.closeConnection(RouteRemoved)
  2328  		}
  2329  
  2330  		s.mu.Lock()
  2331  	}
  2332  	// Clear the accAddedCh/ReqID fields in case they were set.
  2333  	s.accAddedReqID, s.accAddedCh = _EMPTY_, nil
  2334  	// Now that per-account routes that needed to be closed are closed,
  2335  	// remove them from s.accRoutes. Doing so before would prevent
  2336  	// removeRoute() to do proper cleanup because the route would not
  2337  	// be found in s.accRoutes.
  2338  	for _, an := range co.accsRemoved {
  2339  		delete(s.accRoutes, an)
  2340  		// Do not lookup and call setRouteInfo() on the accounts here.
  2341  		// We need first to set the new s.routesPoolSize value and
  2342  		// anyway, there is no need to do here if the pool size has
  2343  		// changed (since it will be called for all accounts).
  2344  	}
  2345  	// We have already added the accounts to s.accRoutes that needed to
  2346  	// be added.
  2347  
  2348  	// We should always have at least the system account with a dedicated route,
  2349  	// but in case we have a configuration that disables pooling and without
  2350  	// a system account, possibly set the accRoutes to nil.
  2351  	if len(opts.Cluster.PinnedAccounts) == 0 {
  2352  		s.accRoutes = nil
  2353  	}
  2354  	// Now deal with pool size updates.
  2355  	if ps := opts.Cluster.PoolSize; ps > 0 {
  2356  		s.routesPoolSize = ps
  2357  		s.routeInfo.RoutePoolSize = ps
  2358  	} else {
  2359  		s.routesPoolSize = 1
  2360  		s.routeInfo.RoutePoolSize = 0
  2361  	}
  2362  	// If the pool size has changed, we need to recompute all accounts' route
  2363  	// pool index. Note that the added/removed accounts will be reset there
  2364  	// too, but that's ok (we could use a map to exclude them, but not worth it).
  2365  	if co.poolSizeChanged {
  2366  		s.accounts.Range(func(_, v interface{}) bool {
  2367  			acc := v.(*Account)
  2368  			acc.mu.Lock()
  2369  			s.setRouteInfo(acc)
  2370  			acc.mu.Unlock()
  2371  			return true
  2372  		})
  2373  	} else if len(co.accsRemoved) > 0 {
  2374  		// For accounts that no longer have a dedicated route, we need to send
  2375  		// the subsriptions on the existing pooled routes for those accounts.
  2376  		for _, an := range co.accsRemoved {
  2377  			if a, ok := s.accounts.Load(an); ok {
  2378  				acc := a.(*Account)
  2379  				acc.mu.Lock()
  2380  				// First call this which will assign a new route pool index.
  2381  				s.setRouteInfo(acc)
  2382  				// Get the value so we can send the subscriptions interest
  2383  				// on all routes with this pool index.
  2384  				rpi := acc.routePoolIdx
  2385  				acc.mu.Unlock()
  2386  				s.forEachRouteIdx(rpi, func(r *client) bool {
  2387  					// We have the guarantee that if the route exists, it
  2388  					// is not a new one that would have been created when
  2389  					// we released the server lock if some routes needed
  2390  					// to be closed, because we have set s.routesReject
  2391  					// to `true` at the top of this function.
  2392  					s.sendSubsToRoute(r, rpi, an)
  2393  					return true
  2394  				})
  2395  			}
  2396  		}
  2397  	}
  2398  	// Allow routes to be accepted now.
  2399  	s.routesReject = false
  2400  	// If there is a pool size change or added accounts, solicit routes now.
  2401  	if co.poolSizeChanged || len(co.accsAdded) > 0 {
  2402  		s.solicitRoutes(opts.Routes, co.accsAdded)
  2403  	}
  2404  	s.mu.Unlock()
  2405  }
  2406  
  2407  // validateClusterOpts ensures the new ClusterOpts does not change some of the
  2408  // fields that do not support reload.
  2409  func validateClusterOpts(old, new ClusterOpts) error {
  2410  	if old.Host != new.Host {
  2411  		return fmt.Errorf("config reload not supported for cluster host: old=%s, new=%s",
  2412  			old.Host, new.Host)
  2413  	}
  2414  	if old.Port != new.Port {
  2415  		return fmt.Errorf("config reload not supported for cluster port: old=%d, new=%d",
  2416  			old.Port, new.Port)
  2417  	}
  2418  	// Validate Cluster.Advertise syntax
  2419  	if new.Advertise != "" {
  2420  		if _, _, err := parseHostPort(new.Advertise, 0); err != nil {
  2421  			return fmt.Errorf("invalid Cluster.Advertise value of %s, err=%v", new.Advertise, err)
  2422  		}
  2423  	}
  2424  	return nil
  2425  }
  2426  
  2427  // diffRoutes diffs the old routes and the new routes and returns the ones that
  2428  // should be added and removed from the server.
  2429  func diffRoutes(old, new []*url.URL) (add, remove []*url.URL) {
  2430  	// Find routes to remove.
  2431  removeLoop:
  2432  	for _, oldRoute := range old {
  2433  		for _, newRoute := range new {
  2434  			if urlsAreEqual(oldRoute, newRoute) {
  2435  				continue removeLoop
  2436  			}
  2437  		}
  2438  		remove = append(remove, oldRoute)
  2439  	}
  2440  
  2441  	// Find routes to add.
  2442  addLoop:
  2443  	for _, newRoute := range new {
  2444  		for _, oldRoute := range old {
  2445  			if urlsAreEqual(oldRoute, newRoute) {
  2446  				continue addLoop
  2447  			}
  2448  		}
  2449  		add = append(add, newRoute)
  2450  	}
  2451  
  2452  	return add, remove
  2453  }