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
19package grpc
20
21import (
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
41const (
42 // https://github.com/grpc/proposal/blob/master/A6-client-retries.md#limits-on-retries-and-hedges
43 defaultMaxCallAttempts = 5
44)
45
46func 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.
69type 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.
102type DialOption interface {
103 apply(*dialOptions)
104}
105
106var 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.
114type perTargetDialOption interface {
115 // DialOption returns a Dial Option to apply.
116 DialOptionForTarget(parsedTarget url.URL) DialOption
117}
118
119var 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.
128type EmptyDialOption struct{}
129
130func (EmptyDialOption) apply(*dialOptions) {}
131
132type disableGlobalDialOptions struct{}
133
134func (disableGlobalDialOptions) apply(*dialOptions) {}
135
136// newDisableGlobalDialOptions returns a DialOption that prevents the ClientConn
137// from applying the global DialOptions (set via AddGlobalDialOptions).
138func newDisableGlobalDialOptions() DialOption {
139 return &disableGlobalDialOptions{}
140}
141
142// funcDialOption wraps a function that modifies dialOptions into an
143// implementation of the DialOption interface.
144type funcDialOption struct {
145 f func(*dialOptions)
146}
147
148func (fdo *funcDialOption) apply(do *dialOptions) {
149 fdo.f(do)
150}
151
152func newFuncDialOption(f func(*dialOptions)) *funcDialOption {
153 return &funcDialOption{
154 f: f,
155 }
156}
157
158type joinDialOption struct {
159 opts []DialOption
160}
161
162func (jdo *joinDialOption) apply(do *dialOptions) {
163 for _, opt := range jdo.opts {
164 opt.apply(do)
165 }
166}
167
168func 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.
180func 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.
192func 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.
204func 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.
213func 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.
222func 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.
233func 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.
239func 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.
250func 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.
259func 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.
275func 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.
289func 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.
302func 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.
310func 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.
320func 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.
335func 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.
351func 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.
367func 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.
380func 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.
395func 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.
404func 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.
412func 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.
426func 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.
437func 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
463func 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.
476func 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.
488func 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.
502func 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.
522func 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.
530func 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.
540func 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.
552func 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.
563func 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.
571func 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.
582func 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.
590func 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.
604func 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.
616func 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
635func 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.
645func 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.
653type MaxHeaderListSizeDialOption struct {
654 MaxHeaderListSize uint32
655}
656
657func (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.
663func 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.
676func WithDisableHealthCheck() DialOption {
677 return newFuncDialOption(func(o *dialOptions) {
678 o.disableHealthCheck = true
679 })
680}
681
682func 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.
704func 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.
712func 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.
727func 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.
747func 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.
761func 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
770func withBufferPool(bufferPool mem.BufferPool) DialOption {
771 return newFuncDialOption(func(o *dialOptions) {
772 o.copts.BufferPool = bufferPool
773 })
774}