blob: 69c003159d49dd359adb8ca330394cdecff7392b [file] [log] [blame]
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -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
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
72}
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
421// 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
432// 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
440// 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
451// 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
469// WithDisableServiceConfig returns a DialOption that causes gRPC to ignore any
470// service config provided by the resolver and provides a hint to the resolver
471// to not fetch service configs.
472//
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.
475func WithDisableServiceConfig() DialOption {
476 return newFuncDialOption(func(o *dialOptions) {
477 o.disableServiceConfig = true
478 })
479}
480
481// 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
493// 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
517// WithDisableHealthCheck disables the LB channel health checking for all
518// SubConns of this ClientConn.
519//
520// This API is EXPERIMENTAL.
521func WithDisableHealthCheck() DialOption {
522 return newFuncDialOption(func(o *dialOptions) {
523 o.disableHealthCheck = true
524 })
525}
526
527// withHealthCheckFunc replaces the default health check function with the
528// provided one. It makes tests easier to change the health check function.
529//
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}
548
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}