github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/grpc/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  	"fmt"
    24  	"net"
    25  	"time"
    26  
    27  	"github.com/hxx258456/ccgo/grpc/backoff"
    28  	"github.com/hxx258456/ccgo/grpc/balancer"
    29  	"github.com/hxx258456/ccgo/grpc/credentials"
    30  	"github.com/hxx258456/ccgo/grpc/credentials/insecure"
    31  	"github.com/hxx258456/ccgo/grpc/internal"
    32  	internalbackoff "github.com/hxx258456/ccgo/grpc/internal/backoff"
    33  	"github.com/hxx258456/ccgo/grpc/internal/transport"
    34  	"github.com/hxx258456/ccgo/grpc/keepalive"
    35  	"github.com/hxx258456/ccgo/grpc/resolver"
    36  	"github.com/hxx258456/ccgo/grpc/stats"
    37  )
    38  
    39  // dialOptions configure a Dial call. dialOptions are set by the DialOption
    40  // values passed to Dial.
    41  type dialOptions struct {
    42  	unaryInt  UnaryClientInterceptor
    43  	streamInt StreamClientInterceptor
    44  
    45  	chainUnaryInts  []UnaryClientInterceptor
    46  	chainStreamInts []StreamClientInterceptor
    47  
    48  	cp              Compressor
    49  	dc              Decompressor
    50  	bs              internalbackoff.Strategy
    51  	block           bool
    52  	returnLastError bool
    53  	timeout         time.Duration
    54  	scChan          <-chan ServiceConfig
    55  	authority       string
    56  	copts           transport.ConnectOptions
    57  	callOptions     []CallOption
    58  	// This is used by WithBalancerName dial option.
    59  	balancerBuilder             balancer.Builder
    60  	channelzParentID            int64
    61  	disableServiceConfig        bool
    62  	disableRetry                bool
    63  	disableHealthCheck          bool
    64  	healthCheckFunc             internal.HealthChecker
    65  	minConnectTimeout           func() time.Duration
    66  	defaultServiceConfig        *ServiceConfig // defaultServiceConfig is parsed from defaultServiceConfigRawJSON.
    67  	defaultServiceConfigRawJSON *string
    68  	resolvers                   []resolver.Builder
    69  }
    70  
    71  // DialOption configures how we set up the connection.
    72  type DialOption interface {
    73  	apply(*dialOptions)
    74  }
    75  
    76  // EmptyDialOption does not alter the dial configuration. It can be embedded in
    77  // another structure to build custom dial options.
    78  //
    79  // Experimental
    80  //
    81  // Notice: This type is EXPERIMENTAL and may be changed or removed in a
    82  // later release.
    83  type EmptyDialOption struct{}
    84  
    85  func (EmptyDialOption) apply(*dialOptions) {}
    86  
    87  // funcDialOption wraps a function that modifies dialOptions into an
    88  // implementation of the DialOption interface.
    89  type funcDialOption struct {
    90  	f func(*dialOptions)
    91  }
    92  
    93  func (fdo *funcDialOption) apply(do *dialOptions) {
    94  	fdo.f(do)
    95  }
    96  
    97  func newFuncDialOption(f func(*dialOptions)) *funcDialOption {
    98  	return &funcDialOption{
    99  		f: f,
   100  	}
   101  }
   102  
   103  // WithWriteBufferSize determines how much data can be batched before doing a
   104  // write on the wire. The corresponding memory allocation for this buffer will
   105  // be twice the size to keep syscalls low. The default value for this buffer is
   106  // 32KB.
   107  //
   108  // Zero will disable the write buffer such that each write will be on underlying
   109  // connection. Note: A Send call may not directly translate to a write.
   110  func WithWriteBufferSize(s int) DialOption {
   111  	return newFuncDialOption(func(o *dialOptions) {
   112  		o.copts.WriteBufferSize = s
   113  	})
   114  }
   115  
   116  // WithReadBufferSize lets you set the size of read buffer, this determines how
   117  // much data can be read at most for each read syscall.
   118  //
   119  // The default value for this buffer is 32KB. Zero will disable read buffer for
   120  // a connection so data framer can access the underlying conn directly.
   121  func WithReadBufferSize(s int) DialOption {
   122  	return newFuncDialOption(func(o *dialOptions) {
   123  		o.copts.ReadBufferSize = s
   124  	})
   125  }
   126  
   127  // WithInitialWindowSize returns a DialOption which sets the value for initial
   128  // window size on a stream. The lower bound for window size is 64K and any value
   129  // smaller than that will be ignored.
   130  func WithInitialWindowSize(s int32) DialOption {
   131  	return newFuncDialOption(func(o *dialOptions) {
   132  		o.copts.InitialWindowSize = s
   133  	})
   134  }
   135  
   136  // WithInitialConnWindowSize returns a DialOption which sets the value for
   137  // initial window size on a connection. The lower bound for window size is 64K
   138  // and any value smaller than that will be ignored.
   139  func WithInitialConnWindowSize(s int32) DialOption {
   140  	return newFuncDialOption(func(o *dialOptions) {
   141  		o.copts.InitialConnWindowSize = s
   142  	})
   143  }
   144  
   145  // WithMaxMsgSize returns a DialOption which sets the maximum message size the
   146  // client can receive.
   147  //
   148  // Deprecated: use WithDefaultCallOptions(MaxCallRecvMsgSize(s)) instead.  Will
   149  // be supported throughout 1.x.
   150  func WithMaxMsgSize(s int) DialOption {
   151  	return WithDefaultCallOptions(MaxCallRecvMsgSize(s))
   152  }
   153  
   154  // WithDefaultCallOptions returns a DialOption which sets the default
   155  // CallOptions for calls over the connection.
   156  func WithDefaultCallOptions(cos ...CallOption) DialOption {
   157  	return newFuncDialOption(func(o *dialOptions) {
   158  		o.callOptions = append(o.callOptions, cos...)
   159  	})
   160  }
   161  
   162  // WithCodec returns a DialOption which sets a codec for message marshaling and
   163  // unmarshaling.
   164  //
   165  // Deprecated: use WithDefaultCallOptions(ForceCodec(_)) instead.  Will be
   166  // supported throughout 1.x.
   167  func WithCodec(c Codec) DialOption {
   168  	return WithDefaultCallOptions(CallCustomCodec(c))
   169  }
   170  
   171  // WithCompressor returns a DialOption which sets a Compressor to use for
   172  // message compression. It has lower priority than the compressor set by the
   173  // UseCompressor CallOption.
   174  //
   175  // Deprecated: use UseCompressor instead.  Will be supported throughout 1.x.
   176  func WithCompressor(cp Compressor) DialOption {
   177  	return newFuncDialOption(func(o *dialOptions) {
   178  		o.cp = cp
   179  	})
   180  }
   181  
   182  // WithDecompressor returns a DialOption which sets a Decompressor to use for
   183  // incoming message decompression.  If incoming response messages are encoded
   184  // using the decompressor's Type(), it will be used.  Otherwise, the message
   185  // encoding will be used to look up the compressor registered via
   186  // encoding.RegisterCompressor, which will then be used to decompress the
   187  // message.  If no compressor is registered for the encoding, an Unimplemented
   188  // status error will be returned.
   189  //
   190  // Deprecated: use encoding.RegisterCompressor instead.  Will be supported
   191  // throughout 1.x.
   192  func WithDecompressor(dc Decompressor) DialOption {
   193  	return newFuncDialOption(func(o *dialOptions) {
   194  		o.dc = dc
   195  	})
   196  }
   197  
   198  // WithBalancerName sets the balancer that the ClientConn will be initialized
   199  // with. Balancer registered with balancerName will be used. This function
   200  // panics if no balancer was registered by balancerName.
   201  //
   202  // The balancer cannot be overridden by balancer option specified by service
   203  // config.
   204  //
   205  // Deprecated: use WithDefaultServiceConfig and WithDisableServiceConfig
   206  // instead.  Will be removed in a future 1.x release.
   207  func WithBalancerName(balancerName string) DialOption {
   208  	builder := balancer.Get(balancerName)
   209  	if builder == nil {
   210  		panic(fmt.Sprintf("grpc.WithBalancerName: no balancer is registered for name %v", balancerName))
   211  	}
   212  	return newFuncDialOption(func(o *dialOptions) {
   213  		o.balancerBuilder = builder
   214  	})
   215  }
   216  
   217  // WithServiceConfig returns a DialOption which has a channel to read the
   218  // service configuration.
   219  //
   220  // Deprecated: service config should be received through name resolver or via
   221  // WithDefaultServiceConfig, as specified at
   222  // https://github.com/grpc/grpc/blob/master/doc/service_config.md.  Will be
   223  // removed in a future 1.x release.
   224  func WithServiceConfig(c <-chan ServiceConfig) DialOption {
   225  	return newFuncDialOption(func(o *dialOptions) {
   226  		o.scChan = c
   227  	})
   228  }
   229  
   230  // WithConnectParams configures the ClientConn to use the provided ConnectParams
   231  // for creating and maintaining connections to servers.
   232  //
   233  // The backoff configuration specified as part of the ConnectParams overrides
   234  // all defaults specified in
   235  // https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md. Consider
   236  // using the backoff.DefaultConfig as a base, in cases where you want to
   237  // override only a subset of the backoff configuration.
   238  func WithConnectParams(p ConnectParams) DialOption {
   239  	return newFuncDialOption(func(o *dialOptions) {
   240  		o.bs = internalbackoff.Exponential{Config: p.Backoff}
   241  		o.minConnectTimeout = func() time.Duration {
   242  			return p.MinConnectTimeout
   243  		}
   244  	})
   245  }
   246  
   247  // WithBackoffMaxDelay configures the dialer to use the provided maximum delay
   248  // when backing off after failed connection attempts.
   249  //
   250  // Deprecated: use WithConnectParams instead. Will be supported throughout 1.x.
   251  func WithBackoffMaxDelay(md time.Duration) DialOption {
   252  	return WithBackoffConfig(BackoffConfig{MaxDelay: md})
   253  }
   254  
   255  // WithBackoffConfig configures the dialer to use the provided backoff
   256  // parameters after connection failures.
   257  //
   258  // Deprecated: use WithConnectParams instead. Will be supported throughout 1.x.
   259  func WithBackoffConfig(b BackoffConfig) DialOption {
   260  	bc := backoff.DefaultConfig
   261  	bc.MaxDelay = b.MaxDelay
   262  	return withBackoff(internalbackoff.Exponential{Config: bc})
   263  }
   264  
   265  // withBackoff sets the backoff strategy used for connectRetryNum after a failed
   266  // connection attempt.
   267  //
   268  // This can be exported if arbitrary backoff strategies are allowed by gRPC.
   269  func withBackoff(bs internalbackoff.Strategy) DialOption {
   270  	return newFuncDialOption(func(o *dialOptions) {
   271  		o.bs = bs
   272  	})
   273  }
   274  
   275  // WithBlock returns a DialOption which makes callers of Dial block until the
   276  // underlying connection is up. Without this, Dial returns immediately and
   277  // connecting the server happens in background.
   278  func WithBlock() DialOption {
   279  	return newFuncDialOption(func(o *dialOptions) {
   280  		o.block = true
   281  	})
   282  }
   283  
   284  // WithReturnConnectionError returns a DialOption which makes the client connection
   285  // return a string containing both the last connection error that occurred and
   286  // the context.DeadlineExceeded error.
   287  // Implies WithBlock()
   288  //
   289  // Experimental
   290  //
   291  // Notice: This API is EXPERIMENTAL and may be changed or removed in a
   292  // later release.
   293  func WithReturnConnectionError() DialOption {
   294  	return newFuncDialOption(func(o *dialOptions) {
   295  		o.block = true
   296  		o.returnLastError = true
   297  	})
   298  }
   299  
   300  // WithInsecure returns a DialOption which disables transport security for this
   301  // ClientConn. Under the hood, it uses insecure.NewCredentials().
   302  //
   303  // Note that using this DialOption with per-RPC credentials (through
   304  // WithCredentialsBundle or WithPerRPCCredentials) which require transport
   305  // security is incompatible and will cause grpc.Dial() to fail.
   306  //
   307  // Deprecated: use WithTransportCredentials and insecure.NewCredentials() instead.
   308  // Will be supported throughout 1.x.
   309  func WithInsecure() DialOption {
   310  	return newFuncDialOption(func(o *dialOptions) {
   311  		o.copts.TransportCredentials = insecure.NewCredentials()
   312  	})
   313  }
   314  
   315  // WithNoProxy returns a DialOption which disables the use of proxies for this
   316  // ClientConn. This is ignored if WithDialer or WithContextDialer are used.
   317  //
   318  // Experimental
   319  //
   320  // Notice: This API is EXPERIMENTAL and may be changed or removed in a
   321  // later release.
   322  func WithNoProxy() DialOption {
   323  	return newFuncDialOption(func(o *dialOptions) {
   324  		o.copts.UseProxy = false
   325  	})
   326  }
   327  
   328  // WithTransportCredentials returns a DialOption which configures a connection
   329  // level security credentials (e.g., TLS/SSL). This should not be used together
   330  // with WithCredentialsBundle.
   331  func WithTransportCredentials(creds credentials.TransportCredentials) DialOption {
   332  	return newFuncDialOption(func(o *dialOptions) {
   333  		o.copts.TransportCredentials = creds
   334  	})
   335  }
   336  
   337  // WithPerRPCCredentials returns a DialOption which sets credentials and places
   338  // auth state on each outbound RPC.
   339  func WithPerRPCCredentials(creds credentials.PerRPCCredentials) DialOption {
   340  	return newFuncDialOption(func(o *dialOptions) {
   341  		o.copts.PerRPCCredentials = append(o.copts.PerRPCCredentials, creds)
   342  	})
   343  }
   344  
   345  // WithCredentialsBundle returns a DialOption to set a credentials bundle for
   346  // the ClientConn.WithCreds. This should not be used together with
   347  // WithTransportCredentials.
   348  //
   349  // Experimental
   350  //
   351  // Notice: This API is EXPERIMENTAL and may be changed or removed in a
   352  // later release.
   353  func WithCredentialsBundle(b credentials.Bundle) DialOption {
   354  	return newFuncDialOption(func(o *dialOptions) {
   355  		o.copts.CredsBundle = b
   356  	})
   357  }
   358  
   359  // WithTimeout returns a DialOption that configures a timeout for dialing a
   360  // ClientConn initially. This is valid if and only if WithBlock() is present.
   361  //
   362  // Deprecated: use DialContext instead of Dial and context.WithTimeout
   363  // instead.  Will be supported throughout 1.x.
   364  func WithTimeout(d time.Duration) DialOption {
   365  	return newFuncDialOption(func(o *dialOptions) {
   366  		o.timeout = d
   367  	})
   368  }
   369  
   370  // WithContextDialer returns a DialOption that sets a dialer to create
   371  // connections. If FailOnNonTempDialError() is set to true, and an error is
   372  // returned by f, gRPC checks the error's Temporary() method to decide if it
   373  // should try to reconnect to the network address.
   374  func WithContextDialer(f func(context.Context, string) (net.Conn, error)) DialOption {
   375  	return newFuncDialOption(func(o *dialOptions) {
   376  		o.copts.Dialer = f
   377  	})
   378  }
   379  
   380  func init() {
   381  	internal.WithHealthCheckFunc = withHealthCheckFunc
   382  }
   383  
   384  // WithDialer returns a DialOption that specifies a function to use for dialing
   385  // network addresses. If FailOnNonTempDialError() is set to true, and an error
   386  // is returned by f, gRPC checks the error's Temporary() method to decide if it
   387  // should try to reconnect to the network address.
   388  //
   389  // Deprecated: use WithContextDialer instead.  Will be supported throughout
   390  // 1.x.
   391  func WithDialer(f func(string, time.Duration) (net.Conn, error)) DialOption {
   392  	return WithContextDialer(
   393  		func(ctx context.Context, addr string) (net.Conn, error) {
   394  			if deadline, ok := ctx.Deadline(); ok {
   395  				return f(addr, time.Until(deadline))
   396  			}
   397  			return f(addr, 0)
   398  		})
   399  }
   400  
   401  // WithStatsHandler returns a DialOption that specifies the stats handler for
   402  // all the RPCs and underlying network connections in this ClientConn.
   403  func WithStatsHandler(h stats.Handler) DialOption {
   404  	return newFuncDialOption(func(o *dialOptions) {
   405  		o.copts.StatsHandler = h
   406  	})
   407  }
   408  
   409  // FailOnNonTempDialError returns a DialOption that specifies if gRPC fails on
   410  // non-temporary dial errors. If f is true, and dialer returns a non-temporary
   411  // error, gRPC will fail the connection to the network address and won't try to
   412  // reconnect. The default value of FailOnNonTempDialError is false.
   413  //
   414  // FailOnNonTempDialError only affects the initial dial, and does not do
   415  // anything useful unless you are also using WithBlock().
   416  //
   417  // Experimental
   418  //
   419  // Notice: This API is EXPERIMENTAL and may be changed or removed in a
   420  // later release.
   421  func FailOnNonTempDialError(f bool) DialOption {
   422  	return newFuncDialOption(func(o *dialOptions) {
   423  		o.copts.FailOnNonTempDialError = f
   424  	})
   425  }
   426  
   427  // WithUserAgent returns a DialOption that specifies a user agent string for all
   428  // the RPCs.
   429  func WithUserAgent(s string) DialOption {
   430  	return newFuncDialOption(func(o *dialOptions) {
   431  		o.copts.UserAgent = s
   432  	})
   433  }
   434  
   435  // WithKeepaliveParams returns a DialOption that specifies keepalive parameters
   436  // for the client transport.
   437  func WithKeepaliveParams(kp keepalive.ClientParameters) DialOption {
   438  	if kp.Time < internal.KeepaliveMinPingTime {
   439  		logger.Warningf("Adjusting keepalive ping interval to minimum period of %v", internal.KeepaliveMinPingTime)
   440  		kp.Time = internal.KeepaliveMinPingTime
   441  	}
   442  	return newFuncDialOption(func(o *dialOptions) {
   443  		o.copts.KeepaliveParams = kp
   444  	})
   445  }
   446  
   447  // WithUnaryInterceptor returns a DialOption that specifies the interceptor for
   448  // unary RPCs.
   449  func WithUnaryInterceptor(f UnaryClientInterceptor) DialOption {
   450  	return newFuncDialOption(func(o *dialOptions) {
   451  		o.unaryInt = f
   452  	})
   453  }
   454  
   455  // WithChainUnaryInterceptor returns a DialOption that specifies the chained
   456  // interceptor for unary RPCs. The first interceptor will be the outer most,
   457  // while the last interceptor will be the inner most wrapper around the real call.
   458  // All interceptors added by this method will be chained, and the interceptor
   459  // defined by WithUnaryInterceptor will always be prepended to the chain.
   460  func WithChainUnaryInterceptor(interceptors ...UnaryClientInterceptor) DialOption {
   461  	return newFuncDialOption(func(o *dialOptions) {
   462  		o.chainUnaryInts = append(o.chainUnaryInts, interceptors...)
   463  	})
   464  }
   465  
   466  // WithStreamInterceptor returns a DialOption that specifies the interceptor for
   467  // streaming RPCs.
   468  func WithStreamInterceptor(f StreamClientInterceptor) DialOption {
   469  	return newFuncDialOption(func(o *dialOptions) {
   470  		o.streamInt = f
   471  	})
   472  }
   473  
   474  // WithChainStreamInterceptor returns a DialOption that specifies the chained
   475  // interceptor for streaming RPCs. The first interceptor will be the outer most,
   476  // while the last interceptor will be the inner most wrapper around the real call.
   477  // All interceptors added by this method will be chained, and the interceptor
   478  // defined by WithStreamInterceptor will always be prepended to the chain.
   479  func WithChainStreamInterceptor(interceptors ...StreamClientInterceptor) DialOption {
   480  	return newFuncDialOption(func(o *dialOptions) {
   481  		o.chainStreamInts = append(o.chainStreamInts, interceptors...)
   482  	})
   483  }
   484  
   485  // WithAuthority returns a DialOption that specifies the value to be used as the
   486  // :authority pseudo-header and as the server name in authentication handshake.
   487  func WithAuthority(a string) DialOption {
   488  	return newFuncDialOption(func(o *dialOptions) {
   489  		o.authority = a
   490  	})
   491  }
   492  
   493  // WithChannelzParentID returns a DialOption that specifies the channelz ID of
   494  // current ClientConn's parent. This function is used in nested channel creation
   495  // (e.g. grpclb dial).
   496  //
   497  // Experimental
   498  //
   499  // Notice: This API is EXPERIMENTAL and may be changed or removed in a
   500  // later release.
   501  func WithChannelzParentID(id int64) DialOption {
   502  	return newFuncDialOption(func(o *dialOptions) {
   503  		o.channelzParentID = id
   504  	})
   505  }
   506  
   507  // WithDisableServiceConfig returns a DialOption that causes gRPC to ignore any
   508  // service config provided by the resolver and provides a hint to the resolver
   509  // to not fetch service configs.
   510  //
   511  // Note that this dial option only disables service config from resolver. If
   512  // default service config is provided, gRPC will use the default service config.
   513  func WithDisableServiceConfig() DialOption {
   514  	return newFuncDialOption(func(o *dialOptions) {
   515  		o.disableServiceConfig = true
   516  	})
   517  }
   518  
   519  // WithDefaultServiceConfig returns a DialOption that configures the default
   520  // service config, which will be used in cases where:
   521  //
   522  // 1. WithDisableServiceConfig is also used, or
   523  //
   524  // 2. The name resolver does not provide a service config or provides an
   525  // invalid service config.
   526  //
   527  // The parameter s is the JSON representation of the default service config.
   528  // For more information about service configs, see:
   529  // https://github.com/grpc/grpc/blob/master/doc/service_config.md
   530  // For a simple example of usage, see:
   531  // examples/features/load_balancing/client/main.go
   532  func WithDefaultServiceConfig(s string) DialOption {
   533  	return newFuncDialOption(func(o *dialOptions) {
   534  		o.defaultServiceConfigRawJSON = &s
   535  	})
   536  }
   537  
   538  // WithDisableRetry returns a DialOption that disables retries, even if the
   539  // service config enables them.  This does not impact transparent retries, which
   540  // will happen automatically if no data is written to the wire or if the RPC is
   541  // unprocessed by the remote server.
   542  //
   543  // Retry support is currently enabled by default, but may be disabled by
   544  // setting the environment variable "GRPC_GO_RETRY" to "off".
   545  func WithDisableRetry() DialOption {
   546  	return newFuncDialOption(func(o *dialOptions) {
   547  		o.disableRetry = true
   548  	})
   549  }
   550  
   551  // WithMaxHeaderListSize returns a DialOption that specifies the maximum
   552  // (uncompressed) size of header list that the client is prepared to accept.
   553  func WithMaxHeaderListSize(s uint32) DialOption {
   554  	return newFuncDialOption(func(o *dialOptions) {
   555  		o.copts.MaxHeaderListSize = &s
   556  	})
   557  }
   558  
   559  // WithDisableHealthCheck disables the LB channel health checking for all
   560  // SubConns of this ClientConn.
   561  //
   562  // Experimental
   563  //
   564  // Notice: This API is EXPERIMENTAL and may be changed or removed in a
   565  // later release.
   566  func WithDisableHealthCheck() DialOption {
   567  	return newFuncDialOption(func(o *dialOptions) {
   568  		o.disableHealthCheck = true
   569  	})
   570  }
   571  
   572  // withHealthCheckFunc replaces the default health check function with the
   573  // provided one. It makes tests easier to change the health check function.
   574  //
   575  // For testing purpose only.
   576  func withHealthCheckFunc(f internal.HealthChecker) DialOption {
   577  	return newFuncDialOption(func(o *dialOptions) {
   578  		o.healthCheckFunc = f
   579  	})
   580  }
   581  
   582  func defaultDialOptions() dialOptions {
   583  	return dialOptions{
   584  		healthCheckFunc: internal.HealthCheckFunc,
   585  		copts: transport.ConnectOptions{
   586  			WriteBufferSize: defaultWriteBufSize,
   587  			ReadBufferSize:  defaultReadBufSize,
   588  			UseProxy:        true,
   589  		},
   590  	}
   591  }
   592  
   593  // withGetMinConnectDeadline specifies the function that clientconn uses to
   594  // get minConnectDeadline. This can be used to make connection attempts happen
   595  // faster/slower.
   596  //
   597  // For testing purpose only.
   598  func withMinConnectDeadline(f func() time.Duration) DialOption {
   599  	return newFuncDialOption(func(o *dialOptions) {
   600  		o.minConnectTimeout = f
   601  	})
   602  }
   603  
   604  // WithResolvers allows a list of resolver implementations to be registered
   605  // locally with the ClientConn without needing to be globally registered via
   606  // resolver.Register.  They will be matched against the scheme used for the
   607  // current Dial only, and will take precedence over the global registry.
   608  //
   609  // Experimental
   610  //
   611  // Notice: This API is EXPERIMENTAL and may be changed or removed in a
   612  // later release.
   613  func WithResolvers(rs ...resolver.Builder) DialOption {
   614  	return newFuncDialOption(func(o *dialOptions) {
   615  		o.resolvers = append(o.resolvers, rs...)
   616  	})
   617  }