blob: c4bf09f9e9409288d813297c7ad2c9b3eb1c74d9 [file] [log] [blame]
khenaidoo5fc5cea2021-08-11 17:39:16 -04001/*
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 "fmt"
24 "net"
25 "time"
26
27 "google.golang.org/grpc/backoff"
28 "google.golang.org/grpc/balancer"
29 "google.golang.org/grpc/credentials"
khenaidoo257f3192021-12-15 16:46:37 -050030 "google.golang.org/grpc/credentials/insecure"
khenaidoo5fc5cea2021-08-11 17:39:16 -040031 "google.golang.org/grpc/internal"
32 internalbackoff "google.golang.org/grpc/internal/backoff"
khenaidoo5fc5cea2021-08-11 17:39:16 -040033 "google.golang.org/grpc/internal/transport"
34 "google.golang.org/grpc/keepalive"
35 "google.golang.org/grpc/resolver"
36 "google.golang.org/grpc/stats"
37)
38
39// dialOptions configure a Dial call. dialOptions are set by the DialOption
40// values passed to Dial.
41type 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
khenaidoo5fc5cea2021-08-11 17:39:16 -040053 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.
72type 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.
83type EmptyDialOption struct{}
84
85func (EmptyDialOption) apply(*dialOptions) {}
86
87// funcDialOption wraps a function that modifies dialOptions into an
88// implementation of the DialOption interface.
89type funcDialOption struct {
90 f func(*dialOptions)
91}
92
93func (fdo *funcDialOption) apply(do *dialOptions) {
94 fdo.f(do)
95}
96
97func 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.
110func 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.
121func 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.
130func 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.
139func 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.
150func 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.
156func 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.
167func 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.
176func 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.
192func 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.
207func 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.
224func WithServiceConfig(c <-chan ServiceConfig) DialOption {
225 return newFuncDialOption(func(o *dialOptions) {
226 o.scChan = c
227 })
228}
229
khenaidoo257f3192021-12-15 16:46:37 -0500230// WithConnectParams configures the ClientConn to use the provided ConnectParams
231// for creating and maintaining connections to servers.
khenaidoo5fc5cea2021-08-11 17:39:16 -0400232//
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.
khenaidoo5fc5cea2021-08-11 17:39:16 -0400238func 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.
251func 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.
259func 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.
269func withBackoff(bs internalbackoff.Strategy) DialOption {
270 return newFuncDialOption(func(o *dialOptions) {
271 o.bs = bs
272 })
273}
274
khenaidoo257f3192021-12-15 16:46:37 -0500275// WithBlock returns a DialOption which makes callers of Dial block until the
khenaidoo5fc5cea2021-08-11 17:39:16 -0400276// underlying connection is up. Without this, Dial returns immediately and
277// connecting the server happens in background.
278func 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.
293func 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
khenaidoo257f3192021-12-15 16:46:37 -0500301// 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.
khenaidoo5fc5cea2021-08-11 17:39:16 -0400309func WithInsecure() DialOption {
310 return newFuncDialOption(func(o *dialOptions) {
khenaidoo257f3192021-12-15 16:46:37 -0500311 o.copts.TransportCredentials = insecure.NewCredentials()
khenaidoo5fc5cea2021-08-11 17:39:16 -0400312 })
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.
322func 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.
331func 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.
339func 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.
353func 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.
364func 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.
374func WithContextDialer(f func(context.Context, string) (net.Conn, error)) DialOption {
375 return newFuncDialOption(func(o *dialOptions) {
376 o.copts.Dialer = f
377 })
378}
379
380func 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.
391func 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.
403func 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.
421func 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.
429func 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.
437func 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.
449func 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.
460func 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.
468func 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.
479func 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
khenaidoo5cb0d402021-12-08 14:09:16 -0500486// :authority pseudo-header and as the server name in authentication handshake.
khenaidoo5fc5cea2021-08-11 17:39:16 -0400487func 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.
501func 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.
513func 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//
khenaidoo5cb0d402021-12-08 14:09:16 -0500522// 1. WithDisableServiceConfig is also used, or
khenaidoo5fc5cea2021-08-11 17:39:16 -0400523//
khenaidoo5cb0d402021-12-08 14:09:16 -0500524// 2. The name resolver does not provide a service config or provides an
525// invalid service config.
khenaidoo5fc5cea2021-08-11 17:39:16 -0400526//
khenaidoo5cb0d402021-12-08 14:09:16 -0500527// 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
khenaidoo5fc5cea2021-08-11 17:39:16 -0400532func 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//
khenaidoo5cb0d402021-12-08 14:09:16 -0500543// Retry support is currently enabled by default, but may be disabled by
544// setting the environment variable "GRPC_GO_RETRY" to "off".
khenaidoo5fc5cea2021-08-11 17:39:16 -0400545func 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.
553func 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.
566func 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.
576func withHealthCheckFunc(f internal.HealthChecker) DialOption {
577 return newFuncDialOption(func(o *dialOptions) {
578 o.healthCheckFunc = f
579 })
580}
581
582func defaultDialOptions() dialOptions {
583 return dialOptions{
khenaidoo5fc5cea2021-08-11 17:39:16 -0400584 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.
598func 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.
613func WithResolvers(rs ...resolver.Builder) DialOption {
614 return newFuncDialOption(func(o *dialOptions) {
615 o.resolvers = append(o.resolvers, rs...)
616 })
617}