blob: 69c003159d49dd359adb8ca330394cdecff7392b [file] [log] [blame]
William Kurkianea869482019-04-09 15:16:11 -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/balancer"
28 "google.golang.org/grpc/credentials"
29 "google.golang.org/grpc/grpclog"
30 "google.golang.org/grpc/internal"
31 "google.golang.org/grpc/internal/backoff"
32 "google.golang.org/grpc/internal/envconfig"
33 "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 {
Abhilash S.L3b494632019-07-16 15:51:09 +053042 unaryInt UnaryClientInterceptor
43 streamInt StreamClientInterceptor
44
45 chainUnaryInts []UnaryClientInterceptor
46 chainStreamInts []StreamClientInterceptor
47
William Kurkianea869482019-04-09 15:16:11 -040048 cp Compressor
49 dc Decompressor
50 bs backoff.Strategy
51 block bool
52 insecure bool
53 timeout time.Duration
54 scChan <-chan ServiceConfig
55 authority string
56 copts transport.ConnectOptions
57 callOptions []CallOption
58 // This is used by v1 balancer dial option WithBalancer to support v1
59 // balancer, and also by WithBalancerName dial option.
60 balancerBuilder balancer.Builder
61 // This is to support grpclb.
Abhilash S.L3b494632019-07-16 15:51:09 +053062 resolverBuilder resolver.Builder
63 reqHandshake envconfig.RequireHandshakeSetting
64 channelzParentID int64
65 disableServiceConfig bool
66 disableRetry bool
67 disableHealthCheck bool
68 healthCheckFunc internal.HealthChecker
69 minConnectTimeout func() time.Duration
70 defaultServiceConfig *ServiceConfig // defaultServiceConfig is parsed from defaultServiceConfigRawJSON.
71 defaultServiceConfigRawJSON *string
William Kurkianea869482019-04-09 15:16:11 -040072}
73
74// DialOption configures how we set up the connection.
75type DialOption interface {
76 apply(*dialOptions)
77}
78
79// EmptyDialOption does not alter the dial configuration. It can be embedded in
80// another structure to build custom dial options.
81//
82// This API is EXPERIMENTAL.
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// WithWaitForHandshake blocks until the initial settings frame is received from
104// the server before assigning RPCs to the connection.
105//
106// Deprecated: this is the default behavior, and this option will be removed
107// after the 1.18 release.
108func WithWaitForHandshake() DialOption {
109 return newFuncDialOption(func(o *dialOptions) {
110 o.reqHandshake = envconfig.RequireHandshakeOn
111 })
112}
113
114// WithWriteBufferSize determines how much data can be batched before doing a
115// write on the wire. The corresponding memory allocation for this buffer will
116// be twice the size to keep syscalls low. The default value for this buffer is
117// 32KB.
118//
119// Zero will disable the write buffer such that each write will be on underlying
120// connection. Note: A Send call may not directly translate to a write.
121func WithWriteBufferSize(s int) DialOption {
122 return newFuncDialOption(func(o *dialOptions) {
123 o.copts.WriteBufferSize = s
124 })
125}
126
127// WithReadBufferSize lets you set the size of read buffer, this determines how
128// much data can be read at most for each read syscall.
129//
130// The default value for this buffer is 32KB. Zero will disable read buffer for
131// a connection so data framer can access the underlying conn directly.
132func WithReadBufferSize(s int) DialOption {
133 return newFuncDialOption(func(o *dialOptions) {
134 o.copts.ReadBufferSize = s
135 })
136}
137
138// WithInitialWindowSize returns a DialOption which sets the value for initial
139// window size on a stream. The lower bound for window size is 64K and any value
140// smaller than that will be ignored.
141func WithInitialWindowSize(s int32) DialOption {
142 return newFuncDialOption(func(o *dialOptions) {
143 o.copts.InitialWindowSize = s
144 })
145}
146
147// WithInitialConnWindowSize returns a DialOption which sets the value for
148// initial window size on a connection. The lower bound for window size is 64K
149// and any value smaller than that will be ignored.
150func WithInitialConnWindowSize(s int32) DialOption {
151 return newFuncDialOption(func(o *dialOptions) {
152 o.copts.InitialConnWindowSize = s
153 })
154}
155
156// WithMaxMsgSize returns a DialOption which sets the maximum message size the
157// client can receive.
158//
159// Deprecated: use WithDefaultCallOptions(MaxCallRecvMsgSize(s)) instead.
160func WithMaxMsgSize(s int) DialOption {
161 return WithDefaultCallOptions(MaxCallRecvMsgSize(s))
162}
163
164// WithDefaultCallOptions returns a DialOption which sets the default
165// CallOptions for calls over the connection.
166func WithDefaultCallOptions(cos ...CallOption) DialOption {
167 return newFuncDialOption(func(o *dialOptions) {
168 o.callOptions = append(o.callOptions, cos...)
169 })
170}
171
172// WithCodec returns a DialOption which sets a codec for message marshaling and
173// unmarshaling.
174//
175// Deprecated: use WithDefaultCallOptions(ForceCodec(_)) instead.
176func WithCodec(c Codec) DialOption {
177 return WithDefaultCallOptions(CallCustomCodec(c))
178}
179
180// WithCompressor returns a DialOption which sets a Compressor to use for
181// message compression. It has lower priority than the compressor set by the
182// UseCompressor CallOption.
183//
184// Deprecated: use UseCompressor instead.
185func WithCompressor(cp Compressor) DialOption {
186 return newFuncDialOption(func(o *dialOptions) {
187 o.cp = cp
188 })
189}
190
191// WithDecompressor returns a DialOption which sets a Decompressor to use for
192// incoming message decompression. If incoming response messages are encoded
193// using the decompressor's Type(), it will be used. Otherwise, the message
194// encoding will be used to look up the compressor registered via
195// encoding.RegisterCompressor, which will then be used to decompress the
196// message. If no compressor is registered for the encoding, an Unimplemented
197// status error will be returned.
198//
199// Deprecated: use encoding.RegisterCompressor instead.
200func WithDecompressor(dc Decompressor) DialOption {
201 return newFuncDialOption(func(o *dialOptions) {
202 o.dc = dc
203 })
204}
205
206// WithBalancer returns a DialOption which sets a load balancer with the v1 API.
207// Name resolver will be ignored if this DialOption is specified.
208//
209// Deprecated: use the new balancer APIs in balancer package and
210// WithBalancerName.
211func WithBalancer(b Balancer) DialOption {
212 return newFuncDialOption(func(o *dialOptions) {
213 o.balancerBuilder = &balancerWrapperBuilder{
214 b: b,
215 }
216 })
217}
218
219// WithBalancerName sets the balancer that the ClientConn will be initialized
220// with. Balancer registered with balancerName will be used. This function
221// panics if no balancer was registered by balancerName.
222//
223// The balancer cannot be overridden by balancer option specified by service
224// config.
225//
226// This is an EXPERIMENTAL API.
227func WithBalancerName(balancerName string) DialOption {
228 builder := balancer.Get(balancerName)
229 if builder == nil {
230 panic(fmt.Sprintf("grpc.WithBalancerName: no balancer is registered for name %v", balancerName))
231 }
232 return newFuncDialOption(func(o *dialOptions) {
233 o.balancerBuilder = builder
234 })
235}
236
237// withResolverBuilder is only for grpclb.
238func withResolverBuilder(b resolver.Builder) DialOption {
239 return newFuncDialOption(func(o *dialOptions) {
240 o.resolverBuilder = b
241 })
242}
243
244// WithServiceConfig returns a DialOption which has a channel to read the
245// service configuration.
246//
247// Deprecated: service config should be received through name resolver, as
248// specified here.
249// https://github.com/grpc/grpc/blob/master/doc/service_config.md
250func WithServiceConfig(c <-chan ServiceConfig) DialOption {
251 return newFuncDialOption(func(o *dialOptions) {
252 o.scChan = c
253 })
254}
255
256// WithBackoffMaxDelay configures the dialer to use the provided maximum delay
257// when backing off after failed connection attempts.
258func WithBackoffMaxDelay(md time.Duration) DialOption {
259 return WithBackoffConfig(BackoffConfig{MaxDelay: md})
260}
261
262// WithBackoffConfig configures the dialer to use the provided backoff
263// parameters after connection failures.
264//
265// Use WithBackoffMaxDelay until more parameters on BackoffConfig are opened up
266// for use.
267func WithBackoffConfig(b BackoffConfig) DialOption {
268 return withBackoff(backoff.Exponential{
269 MaxDelay: b.MaxDelay,
270 })
271}
272
273// withBackoff sets the backoff strategy used for connectRetryNum after a failed
274// connection attempt.
275//
276// This can be exported if arbitrary backoff strategies are allowed by gRPC.
277func withBackoff(bs backoff.Strategy) DialOption {
278 return newFuncDialOption(func(o *dialOptions) {
279 o.bs = bs
280 })
281}
282
283// WithBlock returns a DialOption which makes caller of Dial blocks until the
284// underlying connection is up. Without this, Dial returns immediately and
285// connecting the server happens in background.
286func WithBlock() DialOption {
287 return newFuncDialOption(func(o *dialOptions) {
288 o.block = true
289 })
290}
291
292// WithInsecure returns a DialOption which disables transport security for this
293// ClientConn. Note that transport security is required unless WithInsecure is
294// set.
295func WithInsecure() DialOption {
296 return newFuncDialOption(func(o *dialOptions) {
297 o.insecure = true
298 })
299}
300
301// WithTransportCredentials returns a DialOption which configures a connection
302// level security credentials (e.g., TLS/SSL). This should not be used together
303// with WithCredentialsBundle.
304func WithTransportCredentials(creds credentials.TransportCredentials) DialOption {
305 return newFuncDialOption(func(o *dialOptions) {
306 o.copts.TransportCredentials = creds
307 })
308}
309
310// WithPerRPCCredentials returns a DialOption which sets credentials and places
311// auth state on each outbound RPC.
312func WithPerRPCCredentials(creds credentials.PerRPCCredentials) DialOption {
313 return newFuncDialOption(func(o *dialOptions) {
314 o.copts.PerRPCCredentials = append(o.copts.PerRPCCredentials, creds)
315 })
316}
317
318// WithCredentialsBundle returns a DialOption to set a credentials bundle for
319// the ClientConn.WithCreds. This should not be used together with
320// WithTransportCredentials.
321//
322// This API is experimental.
323func WithCredentialsBundle(b credentials.Bundle) DialOption {
324 return newFuncDialOption(func(o *dialOptions) {
325 o.copts.CredsBundle = b
326 })
327}
328
329// WithTimeout returns a DialOption that configures a timeout for dialing a
330// ClientConn initially. This is valid if and only if WithBlock() is present.
331//
332// Deprecated: use DialContext and context.WithTimeout instead.
333func WithTimeout(d time.Duration) DialOption {
334 return newFuncDialOption(func(o *dialOptions) {
335 o.timeout = d
336 })
337}
338
339// WithContextDialer returns a DialOption that sets a dialer to create
340// connections. If FailOnNonTempDialError() is set to true, and an error is
341// returned by f, gRPC checks the error's Temporary() method to decide if it
342// should try to reconnect to the network address.
343func WithContextDialer(f func(context.Context, string) (net.Conn, error)) DialOption {
344 return newFuncDialOption(func(o *dialOptions) {
345 o.copts.Dialer = f
346 })
347}
348
349func init() {
350 internal.WithResolverBuilder = withResolverBuilder
351 internal.WithHealthCheckFunc = withHealthCheckFunc
352}
353
354// WithDialer returns a DialOption that specifies a function to use for dialing
355// network addresses. If FailOnNonTempDialError() is set to true, and an error
356// is returned by f, gRPC checks the error's Temporary() method to decide if it
357// should try to reconnect to the network address.
358//
359// Deprecated: use WithContextDialer instead
360func WithDialer(f func(string, time.Duration) (net.Conn, error)) DialOption {
361 return WithContextDialer(
362 func(ctx context.Context, addr string) (net.Conn, error) {
363 if deadline, ok := ctx.Deadline(); ok {
364 return f(addr, time.Until(deadline))
365 }
366 return f(addr, 0)
367 })
368}
369
370// WithStatsHandler returns a DialOption that specifies the stats handler for
371// all the RPCs and underlying network connections in this ClientConn.
372func WithStatsHandler(h stats.Handler) DialOption {
373 return newFuncDialOption(func(o *dialOptions) {
374 o.copts.StatsHandler = h
375 })
376}
377
378// FailOnNonTempDialError returns a DialOption that specifies if gRPC fails on
379// non-temporary dial errors. If f is true, and dialer returns a non-temporary
380// error, gRPC will fail the connection to the network address and won't try to
381// reconnect. The default value of FailOnNonTempDialError is false.
382//
383// FailOnNonTempDialError only affects the initial dial, and does not do
384// anything useful unless you are also using WithBlock().
385//
386// This is an EXPERIMENTAL API.
387func FailOnNonTempDialError(f bool) DialOption {
388 return newFuncDialOption(func(o *dialOptions) {
389 o.copts.FailOnNonTempDialError = f
390 })
391}
392
393// WithUserAgent returns a DialOption that specifies a user agent string for all
394// the RPCs.
395func WithUserAgent(s string) DialOption {
396 return newFuncDialOption(func(o *dialOptions) {
397 o.copts.UserAgent = s
398 })
399}
400
401// WithKeepaliveParams returns a DialOption that specifies keepalive parameters
402// for the client transport.
403func WithKeepaliveParams(kp keepalive.ClientParameters) DialOption {
404 if kp.Time < internal.KeepaliveMinPingTime {
405 grpclog.Warningf("Adjusting keepalive ping interval to minimum period of %v", internal.KeepaliveMinPingTime)
406 kp.Time = internal.KeepaliveMinPingTime
407 }
408 return newFuncDialOption(func(o *dialOptions) {
409 o.copts.KeepaliveParams = kp
410 })
411}
412
413// WithUnaryInterceptor returns a DialOption that specifies the interceptor for
414// unary RPCs.
415func WithUnaryInterceptor(f UnaryClientInterceptor) DialOption {
416 return newFuncDialOption(func(o *dialOptions) {
417 o.unaryInt = f
418 })
419}
420
Abhilash S.L3b494632019-07-16 15:51:09 +0530421// WithChainUnaryInterceptor returns a DialOption that specifies the chained
422// interceptor for unary RPCs. The first interceptor will be the outer most,
423// while the last interceptor will be the inner most wrapper around the real call.
424// All interceptors added by this method will be chained, and the interceptor
425// defined by WithUnaryInterceptor will always be prepended to the chain.
426func WithChainUnaryInterceptor(interceptors ...UnaryClientInterceptor) DialOption {
427 return newFuncDialOption(func(o *dialOptions) {
428 o.chainUnaryInts = append(o.chainUnaryInts, interceptors...)
429 })
430}
431
William Kurkianea869482019-04-09 15:16:11 -0400432// WithStreamInterceptor returns a DialOption that specifies the interceptor for
433// streaming RPCs.
434func WithStreamInterceptor(f StreamClientInterceptor) DialOption {
435 return newFuncDialOption(func(o *dialOptions) {
436 o.streamInt = f
437 })
438}
439
Abhilash S.L3b494632019-07-16 15:51:09 +0530440// WithChainStreamInterceptor returns a DialOption that specifies the chained
441// interceptor for unary RPCs. The first interceptor will be the outer most,
442// while the last interceptor will be the inner most wrapper around the real call.
443// All interceptors added by this method will be chained, and the interceptor
444// defined by WithStreamInterceptor will always be prepended to the chain.
445func WithChainStreamInterceptor(interceptors ...StreamClientInterceptor) DialOption {
446 return newFuncDialOption(func(o *dialOptions) {
447 o.chainStreamInts = append(o.chainStreamInts, interceptors...)
448 })
449}
450
William Kurkianea869482019-04-09 15:16:11 -0400451// WithAuthority returns a DialOption that specifies the value to be used as the
452// :authority pseudo-header. This value only works with WithInsecure and has no
453// effect if TransportCredentials are present.
454func WithAuthority(a string) DialOption {
455 return newFuncDialOption(func(o *dialOptions) {
456 o.authority = a
457 })
458}
459
460// WithChannelzParentID returns a DialOption that specifies the channelz ID of
461// current ClientConn's parent. This function is used in nested channel creation
462// (e.g. grpclb dial).
463func WithChannelzParentID(id int64) DialOption {
464 return newFuncDialOption(func(o *dialOptions) {
465 o.channelzParentID = id
466 })
467}
468
Abhilash S.L3b494632019-07-16 15:51:09 +0530469// WithDisableServiceConfig returns a DialOption that causes gRPC to ignore any
William Kurkianea869482019-04-09 15:16:11 -0400470// service config provided by the resolver and provides a hint to the resolver
471// to not fetch service configs.
Abhilash S.L3b494632019-07-16 15:51:09 +0530472//
473// Note that this dial option only disables service config from resolver. If
474// default service config is provided, gRPC will use the default service config.
William Kurkianea869482019-04-09 15:16:11 -0400475func WithDisableServiceConfig() DialOption {
476 return newFuncDialOption(func(o *dialOptions) {
477 o.disableServiceConfig = true
478 })
479}
480
Abhilash S.L3b494632019-07-16 15:51:09 +0530481// WithDefaultServiceConfig returns a DialOption that configures the default
482// service config, which will be used in cases where:
483// 1. WithDisableServiceConfig is called.
484// 2. Resolver does not return service config or if the resolver gets and invalid config.
485//
486// This API is EXPERIMENTAL.
487func WithDefaultServiceConfig(s string) DialOption {
488 return newFuncDialOption(func(o *dialOptions) {
489 o.defaultServiceConfigRawJSON = &s
490 })
491}
492
William Kurkianea869482019-04-09 15:16:11 -0400493// WithDisableRetry returns a DialOption that disables retries, even if the
494// service config enables them. This does not impact transparent retries, which
495// will happen automatically if no data is written to the wire or if the RPC is
496// unprocessed by the remote server.
497//
498// Retry support is currently disabled by default, but will be enabled by
499// default in the future. Until then, it may be enabled by setting the
500// environment variable "GRPC_GO_RETRY" to "on".
501//
502// This API is EXPERIMENTAL.
503func WithDisableRetry() DialOption {
504 return newFuncDialOption(func(o *dialOptions) {
505 o.disableRetry = true
506 })
507}
508
509// WithMaxHeaderListSize returns a DialOption that specifies the maximum
510// (uncompressed) size of header list that the client is prepared to accept.
511func WithMaxHeaderListSize(s uint32) DialOption {
512 return newFuncDialOption(func(o *dialOptions) {
513 o.copts.MaxHeaderListSize = &s
514 })
515}
516
Abhilash S.L3b494632019-07-16 15:51:09 +0530517// WithDisableHealthCheck disables the LB channel health checking for all
518// SubConns of this ClientConn.
William Kurkianea869482019-04-09 15:16:11 -0400519//
520// This API is EXPERIMENTAL.
521func WithDisableHealthCheck() DialOption {
522 return newFuncDialOption(func(o *dialOptions) {
523 o.disableHealthCheck = true
524 })
525}
526
Abhilash S.L3b494632019-07-16 15:51:09 +0530527// withHealthCheckFunc replaces the default health check function with the
528// provided one. It makes tests easier to change the health check function.
William Kurkianea869482019-04-09 15:16:11 -0400529//
530// For testing purpose only.
531func withHealthCheckFunc(f internal.HealthChecker) DialOption {
532 return newFuncDialOption(func(o *dialOptions) {
533 o.healthCheckFunc = f
534 })
535}
536
537func defaultDialOptions() dialOptions {
538 return dialOptions{
539 disableRetry: !envconfig.Retry,
540 reqHandshake: envconfig.RequireHandshake,
541 healthCheckFunc: internal.HealthCheckFunc,
542 copts: transport.ConnectOptions{
543 WriteBufferSize: defaultWriteBufSize,
544 ReadBufferSize: defaultReadBufSize,
545 },
546 }
547}
Abhilash S.L3b494632019-07-16 15:51:09 +0530548
549// withGetMinConnectDeadline specifies the function that clientconn uses to
550// get minConnectDeadline. This can be used to make connection attempts happen
551// faster/slower.
552//
553// For testing purpose only.
554func withMinConnectDeadline(f func() time.Duration) DialOption {
555 return newFuncDialOption(func(o *dialOptions) {
556 o.minConnectTimeout = f
557 })
558}