google.golang.org/grpc@v1.72.2/dialoptions.go (about)

     1  /*
     2   *
     3   * Copyright 2018 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 grpc
    20  
    21  import (
    22  	"context"
    23  	"net"
    24  	"net/url"
    25  	"time"
    26  
    27  	"google.golang.org/grpc/backoff"
    28  	"google.golang.org/grpc/channelz"
    29  	"google.golang.org/grpc/credentials"
    30  	"google.golang.org/grpc/credentials/insecure"
    31  	"google.golang.org/grpc/internal"
    32  	internalbackoff "google.golang.org/grpc/internal/backoff"
    33  	"google.golang.org/grpc/internal/binarylog"
    34  	"google.golang.org/grpc/internal/transport"
    35  	"google.golang.org/grpc/keepalive"
    36  	"google.golang.org/grpc/mem"
    37  	"google.golang.org/grpc/resolver"
    38  	"google.golang.org/grpc/stats"
    39  )
    40  
    41  const (
    42  	// https://github.com/grpc/proposal/blob/master/A6-client-retries.md#limits-on-retries-and-hedges
    43  	defaultMaxCallAttempts = 5
    44  )
    45  
    46  func init() {
    47  	internal.AddGlobalDialOptions = func(opt ...DialOption) {
    48  		globalDialOptions = append(globalDialOptions, opt...)
    49  	}
    50  	internal.ClearGlobalDialOptions = func() {
    51  		globalDialOptions = nil
    52  	}
    53  	internal.AddGlobalPerTargetDialOptions = func(opt any) {
    54  		if ptdo, ok := opt.(perTargetDialOption); ok {
    55  			globalPerTargetDialOptions = append(globalPerTargetDialOptions, ptdo)
    56  		}
    57  	}
    58  	internal.ClearGlobalPerTargetDialOptions = func() {
    59  		globalPerTargetDialOptions = nil
    60  	}
    61  	internal.WithBinaryLogger = withBinaryLogger
    62  	internal.JoinDialOptions = newJoinDialOption
    63  	internal.DisableGlobalDialOptions = newDisableGlobalDialOptions
    64  	internal.WithBufferPool = withBufferPool
    65  }
    66  
    67  // dialOptions configure a Dial call. dialOptions are set by the DialOption
    68  // values passed to Dial.
    69  type dialOptions struct {
    70  	unaryInt  UnaryClientInterceptor
    71  	streamInt StreamClientInterceptor
    72  
    73  	chainUnaryInts  []UnaryClientInterceptor
    74  	chainStreamInts []StreamClientInterceptor
    75  
    76  	compressorV0                Compressor
    77  	dc                          Decompressor
    78  	bs                          internalbackoff.Strategy
    79  	block                       bool
    80  	returnLastError             bool
    81  	timeout                     time.Duration
    82  	authority                   string
    83  	binaryLogger                binarylog.Logger
    84  	copts                       transport.ConnectOptions
    85  	callOptions                 []CallOption
    86  	channelzParent              channelz.Identifier
    87  	disableServiceConfig        bool
    88  	disableRetry                bool
    89  	disableHealthCheck          bool
    90  	minConnectTimeout           func() time.Duration
    91  	defaultServiceConfig        *ServiceConfig // defaultServiceConfig is parsed from defaultServiceConfigRawJSON.
    92  	defaultServiceConfigRawJSON *string
    93  	resolvers                   []resolver.Builder
    94  	idleTimeout                 time.Duration
    95  	defaultScheme               string
    96  	maxCallAttempts             int
    97  	enableLocalDNSResolution    bool // Specifies if target hostnames should be resolved when proxying is enabled.
    98  	useProxy                    bool // Specifies if a server should be connected via proxy.
    99  }
   100  
   101  // DialOption configures how we set up the connection.
   102  type DialOption interface {
   103  	apply(*dialOptions)
   104  }
   105  
   106  var globalDialOptions []DialOption
   107  
   108  // perTargetDialOption takes a parsed target and returns a dial option to apply.
   109  //
   110  // This gets called after NewClient() parses the target, and allows per target
   111  // configuration set through a returned DialOption. The DialOption will not take
   112  // effect if specifies a resolver builder, as that Dial Option is factored in
   113  // while parsing target.
   114  type perTargetDialOption interface {
   115  	// DialOption returns a Dial Option to apply.
   116  	DialOptionForTarget(parsedTarget url.URL) DialOption
   117  }
   118  
   119  var globalPerTargetDialOptions []perTargetDialOption
   120  
   121  // EmptyDialOption does not alter the dial configuration. It can be embedded in
   122  // another structure to build custom dial options.
   123  //
   124  // # Experimental
   125  //
   126  // Notice: This type is EXPERIMENTAL and may be changed or removed in a
   127  // later release.
   128  type EmptyDialOption struct{}
   129  
   130  func (EmptyDialOption) apply(*dialOptions) {}
   131  
   132  type disableGlobalDialOptions struct{}
   133  
   134  func (disableGlobalDialOptions) apply(*dialOptions) {}
   135  
   136  // newDisableGlobalDialOptions returns a DialOption that prevents the ClientConn
   137  // from applying the global DialOptions (set via AddGlobalDialOptions).
   138  func newDisableGlobalDialOptions() DialOption {
   139  	return &disableGlobalDialOptions{}
   140  }
   141  
   142  // funcDialOption wraps a function that modifies dialOptions into an
   143  // implementation of the DialOption interface.
   144  type funcDialOption struct {
   145  	f func(*dialOptions)
   146  }
   147  
   148  func (fdo *funcDialOption) apply(do *dialOptions) {
   149  	fdo.f(do)
   150  }
   151  
   152  func newFuncDialOption(f func(*dialOptions)) *funcDialOption {
   153  	return &funcDialOption{
   154  		f: f,
   155  	}
   156  }
   157  
   158  type joinDialOption struct {
   159  	opts []DialOption
   160  }
   161  
   162  func (jdo *joinDialOption) apply(do *dialOptions) {
   163  	for _, opt := range jdo.opts {
   164  		opt.apply(do)
   165  	}
   166  }
   167  
   168  func newJoinDialOption(opts ...DialOption) DialOption {
   169  	return &joinDialOption{opts: opts}
   170  }
   171  
   172  // WithSharedWriteBuffer allows reusing per-connection transport write buffer.
   173  // If this option is set to true every connection will release the buffer after
   174  // flushing the data on the wire.
   175  //
   176  // # Experimental
   177  //
   178  // Notice: This API is EXPERIMENTAL and may be changed or removed in a
   179  // later release.
   180  func WithSharedWriteBuffer(val bool) DialOption {
   181  	return newFuncDialOption(func(o *dialOptions) {
   182  		o.copts.SharedWriteBuffer = val
   183  	})
   184  }
   185  
   186  // WithWriteBufferSize determines how much data can be batched before doing a
   187  // write on the wire. The default value for this buffer is 32KB.
   188  //
   189  // Zero or negative values will disable the write buffer such that each write
   190  // will be on underlying connection. Note: A Send call may not directly
   191  // translate to a write.
   192  func WithWriteBufferSize(s int) DialOption {
   193  	return newFuncDialOption(func(o *dialOptions) {
   194  		o.copts.WriteBufferSize = s
   195  	})
   196  }
   197  
   198  // WithReadBufferSize lets you set the size of read buffer, this determines how
   199  // much data can be read at most for each read syscall.
   200  //
   201  // The default value for this buffer is 32KB. Zero or negative values will
   202  // disable read buffer for a connection so data framer can access the
   203  // underlying conn directly.
   204  func WithReadBufferSize(s int) DialOption {
   205  	return newFuncDialOption(func(o *dialOptions) {
   206  		o.copts.ReadBufferSize = s
   207  	})
   208  }
   209  
   210  // WithInitialWindowSize returns a DialOption which sets the value for initial
   211  // window size on a stream. The lower bound for window size is 64K and any value
   212  // smaller than that will be ignored.
   213  func WithInitialWindowSize(s int32) DialOption {
   214  	return newFuncDialOption(func(o *dialOptions) {
   215  		o.copts.InitialWindowSize = s
   216  	})
   217  }
   218  
   219  // WithInitialConnWindowSize returns a DialOption which sets the value for
   220  // initial window size on a connection. The lower bound for window size is 64K
   221  // and any value smaller than that will be ignored.
   222  func WithInitialConnWindowSize(s int32) DialOption {
   223  	return newFuncDialOption(func(o *dialOptions) {
   224  		o.copts.InitialConnWindowSize = s
   225  	})
   226  }
   227  
   228  // WithMaxMsgSize returns a DialOption which sets the maximum message size the
   229  // client can receive.
   230  //
   231  // Deprecated: use WithDefaultCallOptions(MaxCallRecvMsgSize(s)) instead.  Will
   232  // be supported throughout 1.x.
   233  func WithMaxMsgSize(s int) DialOption {
   234  	return WithDefaultCallOptions(MaxCallRecvMsgSize(s))
   235  }
   236  
   237  // WithDefaultCallOptions returns a DialOption which sets the default
   238  // CallOptions for calls over the connection.
   239  func WithDefaultCallOptions(cos ...CallOption) DialOption {
   240  	return newFuncDialOption(func(o *dialOptions) {
   241  		o.callOptions = append(o.callOptions, cos...)
   242  	})
   243  }
   244  
   245  // WithCodec returns a DialOption which sets a codec for message marshaling and
   246  // unmarshaling.
   247  //
   248  // Deprecated: use WithDefaultCallOptions(ForceCodec(_)) instead.  Will be
   249  // supported throughout 1.x.
   250  func WithCodec(c Codec) DialOption {
   251  	return WithDefaultCallOptions(CallCustomCodec(c))
   252  }
   253  
   254  // WithCompressor returns a DialOption which sets a Compressor to use for
   255  // message compression. It has lower priority than the compressor set by the
   256  // UseCompressor CallOption.
   257  //
   258  // Deprecated: use UseCompressor instead.  Will be supported throughout 1.x.
   259  func WithCompressor(cp Compressor) DialOption {
   260  	return newFuncDialOption(func(o *dialOptions) {
   261  		o.compressorV0 = cp
   262  	})
   263  }
   264  
   265  // WithDecompressor returns a DialOption which sets a Decompressor to use for
   266  // incoming message decompression.  If incoming response messages are encoded
   267  // using the decompressor's Type(), it will be used.  Otherwise, the message
   268  // encoding will be used to look up the compressor registered via
   269  // encoding.RegisterCompressor, which will then be used to decompress the
   270  // message.  If no compressor is registered for the encoding, an Unimplemented
   271  // status error will be returned.
   272  //
   273  // Deprecated: use encoding.RegisterCompressor instead.  Will be supported
   274  // throughout 1.x.
   275  func WithDecompressor(dc Decompressor) DialOption {
   276  	return newFuncDialOption(func(o *dialOptions) {
   277  		o.dc = dc
   278  	})
   279  }
   280  
   281  // WithConnectParams configures the ClientConn to use the provided ConnectParams
   282  // for creating and maintaining connections to servers.
   283  //
   284  // The backoff configuration specified as part of the ConnectParams overrides
   285  // all defaults specified in
   286  // https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md. Consider
   287  // using the backoff.DefaultConfig as a base, in cases where you want to
   288  // override only a subset of the backoff configuration.
   289  func WithConnectParams(p ConnectParams) DialOption {
   290  	return newFuncDialOption(func(o *dialOptions) {
   291  		o.bs = internalbackoff.Exponential{Config: p.Backoff}
   292  		o.minConnectTimeout = func() time.Duration {
   293  			return p.MinConnectTimeout
   294  		}
   295  	})
   296  }
   297  
   298  // WithBackoffMaxDelay configures the dialer to use the provided maximum delay
   299  // when backing off after failed connection attempts.
   300  //
   301  // Deprecated: use WithConnectParams instead. Will be supported throughout 1.x.
   302  func WithBackoffMaxDelay(md time.Duration) DialOption {
   303  	return WithBackoffConfig(BackoffConfig{MaxDelay: md})
   304  }
   305  
   306  // WithBackoffConfig configures the dialer to use the provided backoff
   307  // parameters after connection failures.
   308  //
   309  // Deprecated: use WithConnectParams instead. Will be supported throughout 1.x.
   310  func WithBackoffConfig(b BackoffConfig) DialOption {
   311  	bc := backoff.DefaultConfig
   312  	bc.MaxDelay = b.MaxDelay
   313  	return withBackoff(internalbackoff.Exponential{Config: bc})
   314  }
   315  
   316  // withBackoff sets the backoff strategy used for connectRetryNum after a failed
   317  // connection attempt.
   318  //
   319  // This can be exported if arbitrary backoff strategies are allowed by gRPC.
   320  func withBackoff(bs internalbackoff.Strategy) DialOption {
   321  	return newFuncDialOption(func(o *dialOptions) {
   322  		o.bs = bs
   323  	})
   324  }
   325  
   326  // WithBlock returns a DialOption which makes callers of Dial block until the
   327  // underlying connection is up. Without this, Dial returns immediately and
   328  // connecting the server happens in background.
   329  //
   330  // Use of this feature is not recommended.  For more information, please see:
   331  // https://github.com/grpc/grpc-go/blob/master/Documentation/anti-patterns.md
   332  //
   333  // Deprecated: this DialOption is not supported by NewClient.
   334  // Will be supported throughout 1.x.
   335  func WithBlock() DialOption {
   336  	return newFuncDialOption(func(o *dialOptions) {
   337  		o.block = true
   338  	})
   339  }
   340  
   341  // WithReturnConnectionError returns a DialOption which makes the client connection
   342  // return a string containing both the last connection error that occurred and
   343  // the context.DeadlineExceeded error.
   344  // Implies WithBlock()
   345  //
   346  // Use of this feature is not recommended.  For more information, please see:
   347  // https://github.com/grpc/grpc-go/blob/master/Documentation/anti-patterns.md
   348  //
   349  // Deprecated: this DialOption is not supported by NewClient.
   350  // Will be supported throughout 1.x.
   351  func WithReturnConnectionError() DialOption {
   352  	return newFuncDialOption(func(o *dialOptions) {
   353  		o.block = true
   354  		o.returnLastError = true
   355  	})
   356  }
   357  
   358  // WithInsecure returns a DialOption which disables transport security for this
   359  // ClientConn. Under the hood, it uses insecure.NewCredentials().
   360  //
   361  // Note that using this DialOption with per-RPC credentials (through
   362  // WithCredentialsBundle or WithPerRPCCredentials) which require transport
   363  // security is incompatible and will cause grpc.Dial() to fail.
   364  //
   365  // Deprecated: use WithTransportCredentials and insecure.NewCredentials()
   366  // instead. Will be supported throughout 1.x.
   367  func WithInsecure() DialOption {
   368  	return newFuncDialOption(func(o *dialOptions) {
   369  		o.copts.TransportCredentials = insecure.NewCredentials()
   370  	})
   371  }
   372  
   373  // WithNoProxy returns a DialOption which disables the use of proxies for this
   374  // ClientConn. This is ignored if WithDialer or WithContextDialer are used.
   375  //
   376  // # Experimental
   377  //
   378  // Notice: This API is EXPERIMENTAL and may be changed or removed in a
   379  // later release.
   380  func WithNoProxy() DialOption {
   381  	return newFuncDialOption(func(o *dialOptions) {
   382  		o.useProxy = false
   383  	})
   384  }
   385  
   386  // WithLocalDNSResolution forces local DNS name resolution even when a proxy is
   387  // specified in the environment.  By default, the server name is provided
   388  // directly to the proxy as part of the CONNECT handshake. This is ignored if
   389  // WithNoProxy is used.
   390  //
   391  // # Experimental
   392  //
   393  // Notice: This API is EXPERIMENTAL and may be changed or removed in a
   394  // later release.
   395  func WithLocalDNSResolution() DialOption {
   396  	return newFuncDialOption(func(o *dialOptions) {
   397  		o.enableLocalDNSResolution = true
   398  	})
   399  }
   400  
   401  // WithTransportCredentials returns a DialOption which configures a connection
   402  // level security credentials (e.g., TLS/SSL). This should not be used together
   403  // with WithCredentialsBundle.
   404  func WithTransportCredentials(creds credentials.TransportCredentials) DialOption {
   405  	return newFuncDialOption(func(o *dialOptions) {
   406  		o.copts.TransportCredentials = creds
   407  	})
   408  }
   409  
   410  // WithPerRPCCredentials returns a DialOption which sets credentials and places
   411  // auth state on each outbound RPC.
   412  func WithPerRPCCredentials(creds credentials.PerRPCCredentials) DialOption {
   413  	return newFuncDialOption(func(o *dialOptions) {
   414  		o.copts.PerRPCCredentials = append(o.copts.PerRPCCredentials, creds)
   415  	})
   416  }
   417  
   418  // WithCredentialsBundle returns a DialOption to set a credentials bundle for
   419  // the ClientConn.WithCreds. This should not be used together with
   420  // WithTransportCredentials.
   421  //
   422  // # Experimental
   423  //
   424  // Notice: This API is EXPERIMENTAL and may be changed or removed in a
   425  // later release.
   426  func WithCredentialsBundle(b credentials.Bundle) DialOption {
   427  	return newFuncDialOption(func(o *dialOptions) {
   428  		o.copts.CredsBundle = b
   429  	})
   430  }
   431  
   432  // WithTimeout returns a DialOption that configures a timeout for dialing a
   433  // ClientConn initially. This is valid if and only if WithBlock() is present.
   434  //
   435  // Deprecated: this DialOption is not supported by NewClient.
   436  // Will be supported throughout 1.x.
   437  func WithTimeout(d time.Duration) DialOption {
   438  	return newFuncDialOption(func(o *dialOptions) {
   439  		o.timeout = d
   440  	})
   441  }
   442  
   443  // WithContextDialer returns a DialOption that sets a dialer to create
   444  // connections. If FailOnNonTempDialError() is set to true, and an error is
   445  // returned by f, gRPC checks the error's Temporary() method to decide if it
   446  // should try to reconnect to the network address.
   447  //
   448  // Note that gRPC by default performs name resolution on the target passed to
   449  // NewClient. To bypass name resolution and cause the target string to be
   450  // passed directly to the dialer here instead, use the "passthrough" resolver
   451  // by specifying it in the target string, e.g. "passthrough:target".
   452  //
   453  // Note: All supported releases of Go (as of December 2023) override the OS
   454  // defaults for TCP keepalive time and interval to 15s. To enable TCP keepalive
   455  // with OS defaults for keepalive time and interval, use a net.Dialer that sets
   456  // the KeepAlive field to a negative value, and sets the SO_KEEPALIVE socket
   457  // option to true from the Control field. For a concrete example of how to do
   458  // this, see internal.NetDialerWithTCPKeepalive().
   459  //
   460  // For more information, please see [issue 23459] in the Go GitHub repo.
   461  //
   462  // [issue 23459]: https://github.com/golang/go/issues/23459
   463  func WithContextDialer(f func(context.Context, string) (net.Conn, error)) DialOption {
   464  	return newFuncDialOption(func(o *dialOptions) {
   465  		o.copts.Dialer = f
   466  	})
   467  }
   468  
   469  // WithDialer returns a DialOption that specifies a function to use for dialing
   470  // network addresses. If FailOnNonTempDialError() is set to true, and an error
   471  // is returned by f, gRPC checks the error's Temporary() method to decide if it
   472  // should try to reconnect to the network address.
   473  //
   474  // Deprecated: use WithContextDialer instead.  Will be supported throughout
   475  // 1.x.
   476  func WithDialer(f func(string, time.Duration) (net.Conn, error)) DialOption {
   477  	return WithContextDialer(
   478  		func(ctx context.Context, addr string) (net.Conn, error) {
   479  			if deadline, ok := ctx.Deadline(); ok {
   480  				return f(addr, time.Until(deadline))
   481  			}
   482  			return f(addr, 0)
   483  		})
   484  }
   485  
   486  // WithStatsHandler returns a DialOption that specifies the stats handler for
   487  // all the RPCs and underlying network connections in this ClientConn.
   488  func WithStatsHandler(h stats.Handler) DialOption {
   489  	return newFuncDialOption(func(o *dialOptions) {
   490  		if h == nil {
   491  			logger.Error("ignoring nil parameter in grpc.WithStatsHandler ClientOption")
   492  			// Do not allow a nil stats handler, which would otherwise cause
   493  			// panics.
   494  			return
   495  		}
   496  		o.copts.StatsHandlers = append(o.copts.StatsHandlers, h)
   497  	})
   498  }
   499  
   500  // withBinaryLogger returns a DialOption that specifies the binary logger for
   501  // this ClientConn.
   502  func withBinaryLogger(bl binarylog.Logger) DialOption {
   503  	return newFuncDialOption(func(o *dialOptions) {
   504  		o.binaryLogger = bl
   505  	})
   506  }
   507  
   508  // FailOnNonTempDialError returns a DialOption that specifies if gRPC fails on
   509  // non-temporary dial errors. If f is true, and dialer returns a non-temporary
   510  // error, gRPC will fail the connection to the network address and won't try to
   511  // reconnect. The default value of FailOnNonTempDialError is false.
   512  //
   513  // FailOnNonTempDialError only affects the initial dial, and does not do
   514  // anything useful unless you are also using WithBlock().
   515  //
   516  // Use of this feature is not recommended.  For more information, please see:
   517  // https://github.com/grpc/grpc-go/blob/master/Documentation/anti-patterns.md
   518  //
   519  // Deprecated: this DialOption is not supported by NewClient.
   520  // This API may be changed or removed in a
   521  // later release.
   522  func FailOnNonTempDialError(f bool) DialOption {
   523  	return newFuncDialOption(func(o *dialOptions) {
   524  		o.copts.FailOnNonTempDialError = f
   525  	})
   526  }
   527  
   528  // WithUserAgent returns a DialOption that specifies a user agent string for all
   529  // the RPCs.
   530  func WithUserAgent(s string) DialOption {
   531  	return newFuncDialOption(func(o *dialOptions) {
   532  		o.copts.UserAgent = s + " " + grpcUA
   533  	})
   534  }
   535  
   536  // WithKeepaliveParams returns a DialOption that specifies keepalive parameters
   537  // for the client transport.
   538  //
   539  // Keepalive is disabled by default.
   540  func WithKeepaliveParams(kp keepalive.ClientParameters) DialOption {
   541  	if kp.Time < internal.KeepaliveMinPingTime {
   542  		logger.Warningf("Adjusting keepalive ping interval to minimum period of %v", internal.KeepaliveMinPingTime)
   543  		kp.Time = internal.KeepaliveMinPingTime
   544  	}
   545  	return newFuncDialOption(func(o *dialOptions) {
   546  		o.copts.KeepaliveParams = kp
   547  	})
   548  }
   549  
   550  // WithUnaryInterceptor returns a DialOption that specifies the interceptor for
   551  // unary RPCs.
   552  func WithUnaryInterceptor(f UnaryClientInterceptor) DialOption {
   553  	return newFuncDialOption(func(o *dialOptions) {
   554  		o.unaryInt = f
   555  	})
   556  }
   557  
   558  // WithChainUnaryInterceptor returns a DialOption that specifies the chained
   559  // interceptor for unary RPCs. The first interceptor will be the outer most,
   560  // while the last interceptor will be the inner most wrapper around the real call.
   561  // All interceptors added by this method will be chained, and the interceptor
   562  // defined by WithUnaryInterceptor will always be prepended to the chain.
   563  func WithChainUnaryInterceptor(interceptors ...UnaryClientInterceptor) DialOption {
   564  	return newFuncDialOption(func(o *dialOptions) {
   565  		o.chainUnaryInts = append(o.chainUnaryInts, interceptors...)
   566  	})
   567  }
   568  
   569  // WithStreamInterceptor returns a DialOption that specifies the interceptor for
   570  // streaming RPCs.
   571  func WithStreamInterceptor(f StreamClientInterceptor) DialOption {
   572  	return newFuncDialOption(func(o *dialOptions) {
   573  		o.streamInt = f
   574  	})
   575  }
   576  
   577  // WithChainStreamInterceptor returns a DialOption that specifies the chained
   578  // interceptor for streaming RPCs. The first interceptor will be the outer most,
   579  // while the last interceptor will be the inner most wrapper around the real call.
   580  // All interceptors added by this method will be chained, and the interceptor
   581  // defined by WithStreamInterceptor will always be prepended to the chain.
   582  func WithChainStreamInterceptor(interceptors ...StreamClientInterceptor) DialOption {
   583  	return newFuncDialOption(func(o *dialOptions) {
   584  		o.chainStreamInts = append(o.chainStreamInts, interceptors...)
   585  	})
   586  }
   587  
   588  // WithAuthority returns a DialOption that specifies the value to be used as the
   589  // :authority pseudo-header and as the server name in authentication handshake.
   590  func WithAuthority(a string) DialOption {
   591  	return newFuncDialOption(func(o *dialOptions) {
   592  		o.authority = a
   593  	})
   594  }
   595  
   596  // WithChannelzParentID returns a DialOption that specifies the channelz ID of
   597  // current ClientConn's parent. This function is used in nested channel creation
   598  // (e.g. grpclb dial).
   599  //
   600  // # Experimental
   601  //
   602  // Notice: This API is EXPERIMENTAL and may be changed or removed in a
   603  // later release.
   604  func WithChannelzParentID(c channelz.Identifier) DialOption {
   605  	return newFuncDialOption(func(o *dialOptions) {
   606  		o.channelzParent = c
   607  	})
   608  }
   609  
   610  // WithDisableServiceConfig returns a DialOption that causes gRPC to ignore any
   611  // service config provided by the resolver and provides a hint to the resolver
   612  // to not fetch service configs.
   613  //
   614  // Note that this dial option only disables service config from resolver. If
   615  // default service config is provided, gRPC will use the default service config.
   616  func WithDisableServiceConfig() DialOption {
   617  	return newFuncDialOption(func(o *dialOptions) {
   618  		o.disableServiceConfig = true
   619  	})
   620  }
   621  
   622  // WithDefaultServiceConfig returns a DialOption that configures the default
   623  // service config, which will be used in cases where:
   624  //
   625  // 1. WithDisableServiceConfig is also used, or
   626  //
   627  // 2. The name resolver does not provide a service config or provides an
   628  // invalid service config.
   629  //
   630  // The parameter s is the JSON representation of the default service config.
   631  // For more information about service configs, see:
   632  // https://github.com/grpc/grpc/blob/master/doc/service_config.md
   633  // For a simple example of usage, see:
   634  // examples/features/load_balancing/client/main.go
   635  func WithDefaultServiceConfig(s string) DialOption {
   636  	return newFuncDialOption(func(o *dialOptions) {
   637  		o.defaultServiceConfigRawJSON = &s
   638  	})
   639  }
   640  
   641  // WithDisableRetry returns a DialOption that disables retries, even if the
   642  // service config enables them.  This does not impact transparent retries, which
   643  // will happen automatically if no data is written to the wire or if the RPC is
   644  // unprocessed by the remote server.
   645  func WithDisableRetry() DialOption {
   646  	return newFuncDialOption(func(o *dialOptions) {
   647  		o.disableRetry = true
   648  	})
   649  }
   650  
   651  // MaxHeaderListSizeDialOption is a DialOption that specifies the maximum
   652  // (uncompressed) size of header list that the client is prepared to accept.
   653  type MaxHeaderListSizeDialOption struct {
   654  	MaxHeaderListSize uint32
   655  }
   656  
   657  func (o MaxHeaderListSizeDialOption) apply(do *dialOptions) {
   658  	do.copts.MaxHeaderListSize = &o.MaxHeaderListSize
   659  }
   660  
   661  // WithMaxHeaderListSize returns a DialOption that specifies the maximum
   662  // (uncompressed) size of header list that the client is prepared to accept.
   663  func WithMaxHeaderListSize(s uint32) DialOption {
   664  	return MaxHeaderListSizeDialOption{
   665  		MaxHeaderListSize: s,
   666  	}
   667  }
   668  
   669  // WithDisableHealthCheck disables the LB channel health checking for all
   670  // SubConns of this ClientConn.
   671  //
   672  // # Experimental
   673  //
   674  // Notice: This API is EXPERIMENTAL and may be changed or removed in a
   675  // later release.
   676  func WithDisableHealthCheck() DialOption {
   677  	return newFuncDialOption(func(o *dialOptions) {
   678  		o.disableHealthCheck = true
   679  	})
   680  }
   681  
   682  func defaultDialOptions() dialOptions {
   683  	return dialOptions{
   684  		copts: transport.ConnectOptions{
   685  			ReadBufferSize:  defaultReadBufSize,
   686  			WriteBufferSize: defaultWriteBufSize,
   687  			UserAgent:       grpcUA,
   688  			BufferPool:      mem.DefaultBufferPool(),
   689  		},
   690  		bs:                       internalbackoff.DefaultExponential,
   691  		idleTimeout:              30 * time.Minute,
   692  		defaultScheme:            "dns",
   693  		maxCallAttempts:          defaultMaxCallAttempts,
   694  		useProxy:                 true,
   695  		enableLocalDNSResolution: false,
   696  	}
   697  }
   698  
   699  // withMinConnectDeadline specifies the function that clientconn uses to
   700  // get minConnectDeadline. This can be used to make connection attempts happen
   701  // faster/slower.
   702  //
   703  // For testing purpose only.
   704  func withMinConnectDeadline(f func() time.Duration) DialOption {
   705  	return newFuncDialOption(func(o *dialOptions) {
   706  		o.minConnectTimeout = f
   707  	})
   708  }
   709  
   710  // withDefaultScheme is used to allow Dial to use "passthrough" as the default
   711  // name resolver, while NewClient uses "dns" otherwise.
   712  func withDefaultScheme(s string) DialOption {
   713  	return newFuncDialOption(func(o *dialOptions) {
   714  		o.defaultScheme = s
   715  	})
   716  }
   717  
   718  // WithResolvers allows a list of resolver implementations to be registered
   719  // locally with the ClientConn without needing to be globally registered via
   720  // resolver.Register.  They will be matched against the scheme used for the
   721  // current Dial only, and will take precedence over the global registry.
   722  //
   723  // # Experimental
   724  //
   725  // Notice: This API is EXPERIMENTAL and may be changed or removed in a
   726  // later release.
   727  func WithResolvers(rs ...resolver.Builder) DialOption {
   728  	return newFuncDialOption(func(o *dialOptions) {
   729  		o.resolvers = append(o.resolvers, rs...)
   730  	})
   731  }
   732  
   733  // WithIdleTimeout returns a DialOption that configures an idle timeout for the
   734  // channel. If the channel is idle for the configured timeout, i.e there are no
   735  // ongoing RPCs and no new RPCs are initiated, the channel will enter idle mode
   736  // and as a result the name resolver and load balancer will be shut down. The
   737  // channel will exit idle mode when the Connect() method is called or when an
   738  // RPC is initiated.
   739  //
   740  // A default timeout of 30 minutes will be used if this dial option is not set
   741  // at dial time and idleness can be disabled by passing a timeout of zero.
   742  //
   743  // # Experimental
   744  //
   745  // Notice: This API is EXPERIMENTAL and may be changed or removed in a
   746  // later release.
   747  func WithIdleTimeout(d time.Duration) DialOption {
   748  	return newFuncDialOption(func(o *dialOptions) {
   749  		o.idleTimeout = d
   750  	})
   751  }
   752  
   753  // WithMaxCallAttempts returns a DialOption that configures the maximum number
   754  // of attempts per call (including retries and hedging) using the channel.
   755  // Service owners may specify a higher value for these parameters, but higher
   756  // values will be treated as equal to the maximum value by the client
   757  // implementation. This mitigates security concerns related to the service
   758  // config being transferred to the client via DNS.
   759  //
   760  // A value of 5 will be used if this dial option is not set or n < 2.
   761  func WithMaxCallAttempts(n int) DialOption {
   762  	return newFuncDialOption(func(o *dialOptions) {
   763  		if n < 2 {
   764  			n = defaultMaxCallAttempts
   765  		}
   766  		o.maxCallAttempts = n
   767  	})
   768  }
   769  
   770  func withBufferPool(bufferPool mem.BufferPool) DialOption {
   771  	return newFuncDialOption(func(o *dialOptions) {
   772  		o.copts.BufferPool = bufferPool
   773  	})
   774  }