github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/grpc/xds/internal/xdsclient/client.go (about)

     1  /*
     2   *
     3   * Copyright 2019 gRPC authors.
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   *
    17   */
    18  
    19  // Package xdsclient implements a full fledged gRPC client for the xDS API used
    20  // by the xds resolver and balancer implementations.
    21  package xdsclient
    22  
    23  import (
    24  	"fmt"
    25  	"sync"
    26  	"time"
    27  
    28  	"github.com/hxx258456/ccgo/grpc/internal/cache"
    29  	"github.com/hxx258456/ccgo/grpc/internal/grpclog"
    30  	"github.com/hxx258456/ccgo/grpc/internal/grpcsync"
    31  	"github.com/hxx258456/ccgo/grpc/xds/internal/xdsclient/bootstrap"
    32  	"github.com/hxx258456/ccgo/grpc/xds/internal/xdsclient/xdsresource"
    33  )
    34  
    35  // clientImpl is the real implementation of the xds client. The exported Client
    36  // is a wrapper of this struct with a ref count.
    37  //
    38  // Implements UpdateHandler interface.
    39  // TODO(easwars): Make a wrapper struct which implements this interface in the
    40  // style of ccBalancerWrapper so that the Client type does not implement these
    41  // exported methods.
    42  type clientImpl struct {
    43  	done   *grpcsync.Event
    44  	config *bootstrap.Config
    45  
    46  	// authorityMu protects the authority fields. It's necessary because an
    47  	// authority is created when it's used.
    48  	authorityMu sync.Mutex
    49  	// authorities is a map from ServerConfig to authority. So that
    50  	// different authorities sharing the same ServerConfig can share the
    51  	// authority.
    52  	//
    53  	// The key is **ServerConfig.String()**, not the authority name.
    54  	//
    55  	// An authority is either in authorities, or idleAuthorities,
    56  	// never both.
    57  	authorities map[string]*authority
    58  	// idleAuthorities keeps the authorities that are not used (the last
    59  	// watch on it was canceled). They are kept in the cache and will be deleted
    60  	// after a timeout. The key is ServerConfig.String().
    61  	//
    62  	// An authority is either in authorities, or idleAuthorities,
    63  	// never both.
    64  	idleAuthorities *cache.TimeoutCache
    65  
    66  	logger             *grpclog.PrefixLogger
    67  	watchExpiryTimeout time.Duration
    68  }
    69  
    70  // newWithConfig returns a new xdsClient with the given config.
    71  func newWithConfig(config *bootstrap.Config, watchExpiryTimeout time.Duration, idleAuthorityDeleteTimeout time.Duration) (_ *clientImpl, retErr error) {
    72  	c := &clientImpl{
    73  		done:               grpcsync.NewEvent(),
    74  		config:             config,
    75  		watchExpiryTimeout: watchExpiryTimeout,
    76  
    77  		authorities:     make(map[string]*authority),
    78  		idleAuthorities: cache.NewTimeoutCache(idleAuthorityDeleteTimeout),
    79  	}
    80  
    81  	defer func() {
    82  		if retErr != nil {
    83  			c.Close()
    84  		}
    85  	}()
    86  
    87  	c.logger = prefixLogger(c)
    88  	c.logger.Infof("Created ClientConn to xDS management server: %s", config.XDSServer)
    89  
    90  	c.logger.Infof("Created")
    91  	return c, nil
    92  }
    93  
    94  // BootstrapConfig returns the configuration read from the bootstrap file.
    95  // Callers must treat the return value as read-only.
    96  func (c *clientRefCounted) BootstrapConfig() *bootstrap.Config {
    97  	return c.config
    98  }
    99  
   100  // Close closes the gRPC connection to the management server.
   101  func (c *clientImpl) Close() {
   102  	if c.done.HasFired() {
   103  		return
   104  	}
   105  	c.done.Fire()
   106  	// TODO: Should we invoke the registered callbacks here with an error that
   107  	// the client is closed?
   108  
   109  	// Note that Close needs to check for nils even if some of them are always
   110  	// set in the constructor. This is because the constructor defers Close() in
   111  	// error cases, and the fields might not be set when the error happens.
   112  
   113  	c.authorityMu.Lock()
   114  	for _, a := range c.authorities {
   115  		a.close()
   116  	}
   117  	c.idleAuthorities.Clear(true)
   118  	c.authorityMu.Unlock()
   119  
   120  	c.logger.Infof("Shutdown")
   121  }
   122  
   123  func (c *clientImpl) filterChainUpdateValidator(fc *xdsresource.FilterChain) error {
   124  	if fc == nil {
   125  		return nil
   126  	}
   127  	return c.securityConfigUpdateValidator(fc.SecurityCfg)
   128  }
   129  
   130  func (c *clientImpl) securityConfigUpdateValidator(sc *xdsresource.SecurityConfig) error {
   131  	if sc == nil {
   132  		return nil
   133  	}
   134  	if sc.IdentityInstanceName != "" {
   135  		if _, ok := c.config.CertProviderConfigs[sc.IdentityInstanceName]; !ok {
   136  			return fmt.Errorf("identitiy certificate provider instance name %q missing in bootstrap configuration", sc.IdentityInstanceName)
   137  		}
   138  	}
   139  	if sc.RootInstanceName != "" {
   140  		if _, ok := c.config.CertProviderConfigs[sc.RootInstanceName]; !ok {
   141  			return fmt.Errorf("root certificate provider instance name %q missing in bootstrap configuration", sc.RootInstanceName)
   142  		}
   143  	}
   144  	return nil
   145  }
   146  
   147  func (c *clientImpl) updateValidator(u interface{}) error {
   148  	switch update := u.(type) {
   149  	case xdsresource.ListenerUpdate:
   150  		if update.InboundListenerCfg == nil || update.InboundListenerCfg.FilterChains == nil {
   151  			return nil
   152  		}
   153  		return update.InboundListenerCfg.FilterChains.Validate(c.filterChainUpdateValidator)
   154  	case xdsresource.ClusterUpdate:
   155  		return c.securityConfigUpdateValidator(update.SecurityCfg)
   156  	default:
   157  		// We currently invoke this update validation function only for LDS and
   158  		// CDS updates. In the future, if we wish to invoke it for other xDS
   159  		// updates, corresponding plumbing needs to be added to those unmarshal
   160  		// functions.
   161  	}
   162  	return nil
   163  }