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