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 19 package grpc 20 21 import ( 22 "context" 23 "net" 24 "time" 25 26 "google.golang.org/grpc/backoff" 27 "google.golang.org/grpc/channelz" 28 "google.golang.org/grpc/credentials" 29 "google.golang.org/grpc/credentials/insecure" 30 "google.golang.org/grpc/internal" 31 internalbackoff "google.golang.org/grpc/internal/backoff" 32 "google.golang.org/grpc/internal/binarylog" 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 func init() { 40 internal.AddGlobalDialOptions = func(opt ...DialOption) { 41 globalDialOptions = append(globalDialOptions, opt...) 42 } 43 internal.ClearGlobalDialOptions = func() { 44 globalDialOptions = nil 45 } 46 internal.WithBinaryLogger = withBinaryLogger 47 internal.JoinDialOptions = newJoinDialOption 48 internal.DisableGlobalDialOptions = newDisableGlobalDialOptions 49 internal.WithRecvBufferPool = withRecvBufferPool 50 } 51 52 // dialOptions configure a Dial call. dialOptions are set by the DialOption 53 // values passed to Dial. 54 type dialOptions struct { 55 unaryInt UnaryClientInterceptor 56 streamInt StreamClientInterceptor 57 58 chainUnaryInts []UnaryClientInterceptor 59 chainStreamInts []StreamClientInterceptor 60 61 cp Compressor 62 dc Decompressor 63 bs internalbackoff.Strategy 64 block bool 65 returnLastError bool 66 timeout time.Duration 67 authority string 68 binaryLogger binarylog.Logger 69 copts transport.ConnectOptions 70 callOptions []CallOption 71 channelzParent channelz.Identifier 72 disableServiceConfig bool 73 disableRetry bool 74 disableHealthCheck bool 75 healthCheckFunc internal.HealthChecker 76 minConnectTimeout func() time.Duration 77 defaultServiceConfig *ServiceConfig // defaultServiceConfig is parsed from defaultServiceConfigRawJSON. 78 defaultServiceConfigRawJSON *string 79 resolvers []resolver.Builder 80 idleTimeout time.Duration 81 recvBufferPool SharedBufferPool 82 defaultScheme string 83 } 84 85 // DialOption configures how we set up the connection. 86 type DialOption interface { 87 apply(*dialOptions) 88 } 89 90 var globalDialOptions []DialOption 91 92 // EmptyDialOption does not alter the dial configuration. It can be embedded in 93 // another structure to build custom dial options. 94 // 95 // # Experimental 96 // 97 // Notice: This type is EXPERIMENTAL and may be changed or removed in a 98 // later release. 99 type EmptyDialOption struct{} 100 101 func (EmptyDialOption) apply(*dialOptions) {} 102 103 type disableGlobalDialOptions struct{} 104 105 func (disableGlobalDialOptions) apply(*dialOptions) {} 106 107 // newDisableGlobalDialOptions returns a DialOption that prevents the ClientConn 108 // from applying the global DialOptions (set via AddGlobalDialOptions). 109 func newDisableGlobalDialOptions() DialOption { 110 return &disableGlobalDialOptions{} 111 } 112 113 // funcDialOption wraps a function that modifies dialOptions into an 114 // implementation of the DialOption interface. 115 type funcDialOption struct { 116 f func(*dialOptions) 117 } 118 119 func (fdo *funcDialOption) apply(do *dialOptions) { 120 fdo.f(do) 121 } 122 123 func newFuncDialOption(f func(*dialOptions)) *funcDialOption { 124 return &funcDialOption{ 125 f: f, 126 } 127 } 128 129 type joinDialOption struct { 130 opts []DialOption 131 } 132 133 func (jdo *joinDialOption) apply(do *dialOptions) { 134 for _, opt := range jdo.opts { 135 opt.apply(do) 136 } 137 } 138 139 func newJoinDialOption(opts ...DialOption) DialOption { 140 return &joinDialOption{opts: opts} 141 } 142 143 // WithSharedWriteBuffer allows reusing per-connection transport write buffer. 144 // If this option is set to true every connection will release the buffer after 145 // flushing the data on the wire. 146 // 147 // # Experimental 148 // 149 // Notice: This API is EXPERIMENTAL and may be changed or removed in a 150 // later release. 151 func WithSharedWriteBuffer(val bool) DialOption { 152 return newFuncDialOption(func(o *dialOptions) { 153 o.copts.SharedWriteBuffer = val 154 }) 155 } 156 157 // WithWriteBufferSize determines how much data can be batched before doing a 158 // write on the wire. The default value for this buffer is 32KB. 159 // 160 // Zero or negative values will disable the write buffer such that each write 161 // will be on underlying connection. Note: A Send call may not directly 162 // translate to a write. 163 func WithWriteBufferSize(s int) DialOption { 164 return newFuncDialOption(func(o *dialOptions) { 165 o.copts.WriteBufferSize = s 166 }) 167 } 168 169 // WithReadBufferSize lets you set the size of read buffer, this determines how 170 // much data can be read at most for each read syscall. 171 // 172 // The default value for this buffer is 32KB. Zero or negative values will 173 // disable read buffer for a connection so data framer can access the 174 // underlying conn directly. 175 func WithReadBufferSize(s int) DialOption { 176 return newFuncDialOption(func(o *dialOptions) { 177 o.copts.ReadBufferSize = s 178 }) 179 } 180 181 // WithInitialWindowSize returns a DialOption which sets the value for initial 182 // window size on a stream. The lower bound for window size is 64K and any value 183 // smaller than that will be ignored. 184 func WithInitialWindowSize(s int32) DialOption { 185 return newFuncDialOption(func(o *dialOptions) { 186 o.copts.InitialWindowSize = s 187 }) 188 } 189 190 // WithInitialConnWindowSize returns a DialOption which sets the value for 191 // initial window size on a connection. The lower bound for window size is 64K 192 // and any value smaller than that will be ignored. 193 func WithInitialConnWindowSize(s int32) DialOption { 194 return newFuncDialOption(func(o *dialOptions) { 195 o.copts.InitialConnWindowSize = s 196 }) 197 } 198 199 // WithMaxMsgSize returns a DialOption which sets the maximum message size the 200 // client can receive. 201 // 202 // Deprecated: use WithDefaultCallOptions(MaxCallRecvMsgSize(s)) instead. Will 203 // be supported throughout 1.x. 204 func WithMaxMsgSize(s int) DialOption { 205 return WithDefaultCallOptions(MaxCallRecvMsgSize(s)) 206 } 207 208 // WithDefaultCallOptions returns a DialOption which sets the default 209 // CallOptions for calls over the connection. 210 func WithDefaultCallOptions(cos ...CallOption) DialOption { 211 return newFuncDialOption(func(o *dialOptions) { 212 o.callOptions = append(o.callOptions, cos...) 213 }) 214 } 215 216 // WithCodec returns a DialOption which sets a codec for message marshaling and 217 // unmarshaling. 218 // 219 // Deprecated: use WithDefaultCallOptions(ForceCodec(_)) instead. Will be 220 // supported throughout 1.x. 221 func WithCodec(c Codec) DialOption { 222 return WithDefaultCallOptions(CallCustomCodec(c)) 223 } 224 225 // WithCompressor returns a DialOption which sets a Compressor to use for 226 // message compression. It has lower priority than the compressor set by the 227 // UseCompressor CallOption. 228 // 229 // Deprecated: use UseCompressor instead. Will be supported throughout 1.x. 230 func WithCompressor(cp Compressor) DialOption { 231 return newFuncDialOption(func(o *dialOptions) { 232 o.cp = cp 233 }) 234 } 235 236 // WithDecompressor returns a DialOption which sets a Decompressor to use for 237 // incoming message decompression. If incoming response messages are encoded 238 // using the decompressor's Type(), it will be used. Otherwise, the message 239 // encoding will be used to look up the compressor registered via 240 // encoding.RegisterCompressor, which will then be used to decompress the 241 // message. If no compressor is registered for the encoding, an Unimplemented 242 // status error will be returned. 243 // 244 // Deprecated: use encoding.RegisterCompressor instead. Will be supported 245 // throughout 1.x. 246 func WithDecompressor(dc Decompressor) DialOption { 247 return newFuncDialOption(func(o *dialOptions) { 248 o.dc = dc 249 }) 250 } 251 252 // WithConnectParams configures the ClientConn to use the provided ConnectParams 253 // for creating and maintaining connections to servers. 254 // 255 // The backoff configuration specified as part of the ConnectParams overrides 256 // all defaults specified in 257 // https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md. Consider 258 // using the backoff.DefaultConfig as a base, in cases where you want to 259 // override only a subset of the backoff configuration. 260 func WithConnectParams(p ConnectParams) DialOption { 261 return newFuncDialOption(func(o *dialOptions) { 262 o.bs = internalbackoff.Exponential{Config: p.Backoff} 263 o.minConnectTimeout = func() time.Duration { 264 return p.MinConnectTimeout 265 } 266 }) 267 } 268 269 // WithBackoffMaxDelay configures the dialer to use the provided maximum delay 270 // when backing off after failed connection attempts. 271 // 272 // Deprecated: use WithConnectParams instead. Will be supported throughout 1.x. 273 func WithBackoffMaxDelay(md time.Duration) DialOption { 274 return WithBackoffConfig(BackoffConfig{MaxDelay: md}) 275 } 276 277 // WithBackoffConfig configures the dialer to use the provided backoff 278 // parameters after connection failures. 279 // 280 // Deprecated: use WithConnectParams instead. Will be supported throughout 1.x. 281 func WithBackoffConfig(b BackoffConfig) DialOption { 282 bc := backoff.DefaultConfig 283 bc.MaxDelay = b.MaxDelay 284 return withBackoff(internalbackoff.Exponential{Config: bc}) 285 } 286 287 // withBackoff sets the backoff strategy used for connectRetryNum after a failed 288 // connection attempt. 289 // 290 // This can be exported if arbitrary backoff strategies are allowed by gRPC. 291 func withBackoff(bs internalbackoff.Strategy) DialOption { 292 return newFuncDialOption(func(o *dialOptions) { 293 o.bs = bs 294 }) 295 } 296 297 // WithBlock returns a DialOption which makes callers of Dial block until the 298 // underlying connection is up. Without this, Dial returns immediately and 299 // connecting the server happens in background. 300 // 301 // Use of this feature is not recommended. For more information, please see: 302 // https://github.com/grpc/grpc-go/blob/master/Documentation/anti-patterns.md 303 // 304 // Deprecated: this DialOption is not supported by NewClient. 305 // Will be supported throughout 1.x. 306 func WithBlock() DialOption { 307 return newFuncDialOption(func(o *dialOptions) { 308 o.block = true 309 }) 310 } 311 312 // WithReturnConnectionError returns a DialOption which makes the client connection 313 // return a string containing both the last connection error that occurred and 314 // the context.DeadlineExceeded error. 315 // Implies WithBlock() 316 // 317 // Use of this feature is not recommended. For more information, please see: 318 // https://github.com/grpc/grpc-go/blob/master/Documentation/anti-patterns.md 319 // 320 // Deprecated: this DialOption is not supported by NewClient. 321 // Will be supported throughout 1.x. 322 func WithReturnConnectionError() DialOption { 323 return newFuncDialOption(func(o *dialOptions) { 324 o.block = true 325 o.returnLastError = true 326 }) 327 } 328 329 // WithInsecure returns a DialOption which disables transport security for this 330 // ClientConn. Under the hood, it uses insecure.NewCredentials(). 331 // 332 // Note that using this DialOption with per-RPC credentials (through 333 // WithCredentialsBundle or WithPerRPCCredentials) which require transport 334 // security is incompatible and will cause grpc.Dial() to fail. 335 // 336 // Deprecated: use WithTransportCredentials and insecure.NewCredentials() 337 // instead. Will be supported throughout 1.x. 338 func WithInsecure() DialOption { 339 return newFuncDialOption(func(o *dialOptions) { 340 o.copts.TransportCredentials = insecure.NewCredentials() 341 }) 342 } 343 344 // WithNoProxy returns a DialOption which disables the use of proxies for this 345 // ClientConn. This is ignored if WithDialer or WithContextDialer are used. 346 // 347 // # Experimental 348 // 349 // Notice: This API is EXPERIMENTAL and may be changed or removed in a 350 // later release. 351 func WithNoProxy() DialOption { 352 return newFuncDialOption(func(o *dialOptions) { 353 o.copts.UseProxy = false 354 }) 355 } 356 357 // WithTransportCredentials returns a DialOption which configures a connection 358 // level security credentials (e.g., TLS/SSL). This should not be used together 359 // with WithCredentialsBundle. 360 func WithTransportCredentials(creds credentials.TransportCredentials) DialOption { 361 return newFuncDialOption(func(o *dialOptions) { 362 o.copts.TransportCredentials = creds 363 }) 364 } 365 366 // WithPerRPCCredentials returns a DialOption which sets credentials and places 367 // auth state on each outbound RPC. 368 func WithPerRPCCredentials(creds credentials.PerRPCCredentials) DialOption { 369 return newFuncDialOption(func(o *dialOptions) { 370 o.copts.PerRPCCredentials = append(o.copts.PerRPCCredentials, creds) 371 }) 372 } 373 374 // WithCredentialsBundle returns a DialOption to set a credentials bundle for 375 // the ClientConn.WithCreds. This should not be used together with 376 // WithTransportCredentials. 377 // 378 // # Experimental 379 // 380 // Notice: This API is EXPERIMENTAL and may be changed or removed in a 381 // later release. 382 func WithCredentialsBundle(b credentials.Bundle) DialOption { 383 return newFuncDialOption(func(o *dialOptions) { 384 o.copts.CredsBundle = b 385 }) 386 } 387 388 // WithTimeout returns a DialOption that configures a timeout for dialing a 389 // ClientConn initially. This is valid if and only if WithBlock() is present. 390 // 391 // Deprecated: this DialOption is not supported by NewClient. 392 // Will be supported throughout 1.x. 393 func WithTimeout(d time.Duration) DialOption { 394 return newFuncDialOption(func(o *dialOptions) { 395 o.timeout = d 396 }) 397 } 398 399 // WithContextDialer returns a DialOption that sets a dialer to create 400 // connections. If FailOnNonTempDialError() is set to true, and an error is 401 // returned by f, gRPC checks the error's Temporary() method to decide if it 402 // should try to reconnect to the network address. 403 // 404 // Note: All supported releases of Go (as of December 2023) override the OS 405 // defaults for TCP keepalive time and interval to 15s. To enable TCP keepalive 406 // with OS defaults for keepalive time and interval, use a net.Dialer that sets 407 // the KeepAlive field to a negative value, and sets the SO_KEEPALIVE socket 408 // option to true from the Control field. For a concrete example of how to do 409 // this, see internal.NetDialerWithTCPKeepalive(). 410 // 411 // For more information, please see [issue 23459] in the Go github repo. 412 // 413 // [issue 23459]: https://github.com/golang/go/issues/23459 414 func WithContextDialer(f func(context.Context, string) (net.Conn, error)) DialOption { 415 return newFuncDialOption(func(o *dialOptions) { 416 o.copts.Dialer = f 417 }) 418 } 419 420 func init() { 421 internal.WithHealthCheckFunc = withHealthCheckFunc 422 } 423 424 // WithDialer returns a DialOption that specifies a function to use for dialing 425 // network addresses. If FailOnNonTempDialError() is set to true, and an error 426 // is returned by f, gRPC checks the error's Temporary() method to decide if it 427 // should try to reconnect to the network address. 428 // 429 // Deprecated: use WithContextDialer instead. Will be supported throughout 430 // 1.x. 431 func WithDialer(f func(string, time.Duration) (net.Conn, error)) DialOption { 432 return WithContextDialer( 433 func(ctx context.Context, addr string) (net.Conn, error) { 434 if deadline, ok := ctx.Deadline(); ok { 435 return f(addr, time.Until(deadline)) 436 } 437 return f(addr, 0) 438 }) 439 } 440 441 // WithStatsHandler returns a DialOption that specifies the stats handler for 442 // all the RPCs and underlying network connections in this ClientConn. 443 func WithStatsHandler(h stats.Handler) DialOption { 444 return newFuncDialOption(func(o *dialOptions) { 445 if h == nil { 446 logger.Error("ignoring nil parameter in grpc.WithStatsHandler ClientOption") 447 // Do not allow a nil stats handler, which would otherwise cause 448 // panics. 449 return 450 } 451 o.copts.StatsHandlers = append(o.copts.StatsHandlers, h) 452 }) 453 } 454 455 // withBinaryLogger returns a DialOption that specifies the binary logger for 456 // this ClientConn. 457 func withBinaryLogger(bl binarylog.Logger) DialOption { 458 return newFuncDialOption(func(o *dialOptions) { 459 o.binaryLogger = bl 460 }) 461 } 462 463 // FailOnNonTempDialError returns a DialOption that specifies if gRPC fails on 464 // non-temporary dial errors. If f is true, and dialer returns a non-temporary 465 // error, gRPC will fail the connection to the network address and won't try to 466 // reconnect. The default value of FailOnNonTempDialError is false. 467 // 468 // FailOnNonTempDialError only affects the initial dial, and does not do 469 // anything useful unless you are also using WithBlock(). 470 // 471 // Use of this feature is not recommended. For more information, please see: 472 // https://github.com/grpc/grpc-go/blob/master/Documentation/anti-patterns.md 473 // 474 // Deprecated: this DialOption is not supported by NewClient. 475 // This API may be changed or removed in a 476 // later release. 477 func FailOnNonTempDialError(f bool) DialOption { 478 return newFuncDialOption(func(o *dialOptions) { 479 o.copts.FailOnNonTempDialError = f 480 }) 481 } 482 483 // WithUserAgent returns a DialOption that specifies a user agent string for all 484 // the RPCs. 485 func WithUserAgent(s string) DialOption { 486 return newFuncDialOption(func(o *dialOptions) { 487 o.copts.UserAgent = s + " " + grpcUA 488 }) 489 } 490 491 // WithKeepaliveParams returns a DialOption that specifies keepalive parameters 492 // for the client transport. 493 func WithKeepaliveParams(kp keepalive.ClientParameters) DialOption { 494 if kp.Time < internal.KeepaliveMinPingTime { 495 logger.Warningf("Adjusting keepalive ping interval to minimum period of %v", internal.KeepaliveMinPingTime) 496 kp.Time = internal.KeepaliveMinPingTime 497 } 498 return newFuncDialOption(func(o *dialOptions) { 499 o.copts.KeepaliveParams = kp 500 }) 501 } 502 503 // WithUnaryInterceptor returns a DialOption that specifies the interceptor for 504 // unary RPCs. 505 func WithUnaryInterceptor(f UnaryClientInterceptor) DialOption { 506 return newFuncDialOption(func(o *dialOptions) { 507 o.unaryInt = f 508 }) 509 } 510 511 // WithChainUnaryInterceptor returns a DialOption that specifies the chained 512 // interceptor for unary RPCs. The first interceptor will be the outer most, 513 // while the last interceptor will be the inner most wrapper around the real call. 514 // All interceptors added by this method will be chained, and the interceptor 515 // defined by WithUnaryInterceptor will always be prepended to the chain. 516 func WithChainUnaryInterceptor(interceptors ...UnaryClientInterceptor) DialOption { 517 return newFuncDialOption(func(o *dialOptions) { 518 o.chainUnaryInts = append(o.chainUnaryInts, interceptors...) 519 }) 520 } 521 522 // WithStreamInterceptor returns a DialOption that specifies the interceptor for 523 // streaming RPCs. 524 func WithStreamInterceptor(f StreamClientInterceptor) DialOption { 525 return newFuncDialOption(func(o *dialOptions) { 526 o.streamInt = f 527 }) 528 } 529 530 // WithChainStreamInterceptor returns a DialOption that specifies the chained 531 // interceptor for streaming RPCs. The first interceptor will be the outer most, 532 // while the last interceptor will be the inner most wrapper around the real call. 533 // All interceptors added by this method will be chained, and the interceptor 534 // defined by WithStreamInterceptor will always be prepended to the chain. 535 func WithChainStreamInterceptor(interceptors ...StreamClientInterceptor) DialOption { 536 return newFuncDialOption(func(o *dialOptions) { 537 o.chainStreamInts = append(o.chainStreamInts, interceptors...) 538 }) 539 } 540 541 // WithAuthority returns a DialOption that specifies the value to be used as the 542 // :authority pseudo-header and as the server name in authentication handshake. 543 func WithAuthority(a string) DialOption { 544 return newFuncDialOption(func(o *dialOptions) { 545 o.authority = a 546 }) 547 } 548 549 // WithChannelzParentID returns a DialOption that specifies the channelz ID of 550 // current ClientConn's parent. This function is used in nested channel creation 551 // (e.g. grpclb dial). 552 // 553 // # Experimental 554 // 555 // Notice: This API is EXPERIMENTAL and may be changed or removed in a 556 // later release. 557 func WithChannelzParentID(c channelz.Identifier) DialOption { 558 return newFuncDialOption(func(o *dialOptions) { 559 o.channelzParent = c 560 }) 561 } 562 563 // WithDisableServiceConfig returns a DialOption that causes gRPC to ignore any 564 // service config provided by the resolver and provides a hint to the resolver 565 // to not fetch service configs. 566 // 567 // Note that this dial option only disables service config from resolver. If 568 // default service config is provided, gRPC will use the default service config. 569 func WithDisableServiceConfig() DialOption { 570 return newFuncDialOption(func(o *dialOptions) { 571 o.disableServiceConfig = true 572 }) 573 } 574 575 // WithDefaultServiceConfig returns a DialOption that configures the default 576 // service config, which will be used in cases where: 577 // 578 // 1. WithDisableServiceConfig is also used, or 579 // 580 // 2. The name resolver does not provide a service config or provides an 581 // invalid service config. 582 // 583 // The parameter s is the JSON representation of the default service config. 584 // For more information about service configs, see: 585 // https://github.com/grpc/grpc/blob/master/doc/service_config.md 586 // For a simple example of usage, see: 587 // examples/features/load_balancing/client/main.go 588 func WithDefaultServiceConfig(s string) DialOption { 589 return newFuncDialOption(func(o *dialOptions) { 590 o.defaultServiceConfigRawJSON = &s 591 }) 592 } 593 594 // WithDisableRetry returns a DialOption that disables retries, even if the 595 // service config enables them. This does not impact transparent retries, which 596 // will happen automatically if no data is written to the wire or if the RPC is 597 // unprocessed by the remote server. 598 func WithDisableRetry() DialOption { 599 return newFuncDialOption(func(o *dialOptions) { 600 o.disableRetry = true 601 }) 602 } 603 604 // MaxHeaderListSizeDialOption is a DialOption that specifies the maximum 605 // (uncompressed) size of header list that the client is prepared to accept. 606 type MaxHeaderListSizeDialOption struct { 607 MaxHeaderListSize uint32 608 } 609 610 func (o MaxHeaderListSizeDialOption) apply(do *dialOptions) { 611 do.copts.MaxHeaderListSize = &o.MaxHeaderListSize 612 } 613 614 // WithMaxHeaderListSize returns a DialOption that specifies the maximum 615 // (uncompressed) size of header list that the client is prepared to accept. 616 func WithMaxHeaderListSize(s uint32) DialOption { 617 return MaxHeaderListSizeDialOption{ 618 MaxHeaderListSize: s, 619 } 620 } 621 622 // WithDisableHealthCheck disables the LB channel health checking for all 623 // SubConns of this ClientConn. 624 // 625 // # Experimental 626 // 627 // Notice: This API is EXPERIMENTAL and may be changed or removed in a 628 // later release. 629 func WithDisableHealthCheck() DialOption { 630 return newFuncDialOption(func(o *dialOptions) { 631 o.disableHealthCheck = true 632 }) 633 } 634 635 // withHealthCheckFunc replaces the default health check function with the 636 // provided one. It makes tests easier to change the health check function. 637 // 638 // For testing purpose only. 639 func withHealthCheckFunc(f internal.HealthChecker) DialOption { 640 return newFuncDialOption(func(o *dialOptions) { 641 o.healthCheckFunc = f 642 }) 643 } 644 645 func defaultDialOptions() dialOptions { 646 return dialOptions{ 647 copts: transport.ConnectOptions{ 648 ReadBufferSize: defaultReadBufSize, 649 WriteBufferSize: defaultWriteBufSize, 650 UseProxy: true, 651 UserAgent: grpcUA, 652 }, 653 bs: internalbackoff.DefaultExponential, 654 healthCheckFunc: internal.HealthCheckFunc, 655 idleTimeout: 30 * time.Minute, 656 recvBufferPool: nopBufferPool{}, 657 defaultScheme: "dns", 658 } 659 } 660 661 // withMinConnectDeadline specifies the function that clientconn uses to 662 // get minConnectDeadline. This can be used to make connection attempts happen 663 // faster/slower. 664 // 665 // For testing purpose only. 666 func withMinConnectDeadline(f func() time.Duration) DialOption { 667 return newFuncDialOption(func(o *dialOptions) { 668 o.minConnectTimeout = f 669 }) 670 } 671 672 // withDefaultScheme is used to allow Dial to use "passthrough" as the default 673 // name resolver, while NewClient uses "dns" otherwise. 674 func withDefaultScheme(s string) DialOption { 675 return newFuncDialOption(func(o *dialOptions) { 676 o.defaultScheme = s 677 }) 678 } 679 680 // WithResolvers allows a list of resolver implementations to be registered 681 // locally with the ClientConn without needing to be globally registered via 682 // resolver.Register. They will be matched against the scheme used for the 683 // current Dial only, and will take precedence over the global registry. 684 // 685 // # Experimental 686 // 687 // Notice: This API is EXPERIMENTAL and may be changed or removed in a 688 // later release. 689 func WithResolvers(rs ...resolver.Builder) DialOption { 690 return newFuncDialOption(func(o *dialOptions) { 691 o.resolvers = append(o.resolvers, rs...) 692 }) 693 } 694 695 // WithIdleTimeout returns a DialOption that configures an idle timeout for the 696 // channel. If the channel is idle for the configured timeout, i.e there are no 697 // ongoing RPCs and no new RPCs are initiated, the channel will enter idle mode 698 // and as a result the name resolver and load balancer will be shut down. The 699 // channel will exit idle mode when the Connect() method is called or when an 700 // RPC is initiated. 701 // 702 // A default timeout of 30 minutes will be used if this dial option is not set 703 // at dial time and idleness can be disabled by passing a timeout of zero. 704 // 705 // # Experimental 706 // 707 // Notice: This API is EXPERIMENTAL and may be changed or removed in a 708 // later release. 709 func WithIdleTimeout(d time.Duration) DialOption { 710 return newFuncDialOption(func(o *dialOptions) { 711 o.idleTimeout = d 712 }) 713 } 714 715 // WithRecvBufferPool returns a DialOption that configures the ClientConn 716 // to use the provided shared buffer pool for parsing incoming messages. Depending 717 // on the application's workload, this could result in reduced memory allocation. 718 // 719 // If you are unsure about how to implement a memory pool but want to utilize one, 720 // begin with grpc.NewSharedBufferPool. 721 // 722 // Note: The shared buffer pool feature will not be active if any of the following 723 // options are used: WithStatsHandler, EnableTracing, or binary logging. In such 724 // cases, the shared buffer pool will be ignored. 725 // 726 // Deprecated: use experimental.WithRecvBufferPool instead. Will be deleted in 727 // v1.60.0 or later. 728 func WithRecvBufferPool(bufferPool SharedBufferPool) DialOption { 729 return withRecvBufferPool(bufferPool) 730 } 731 732 func withRecvBufferPool(bufferPool SharedBufferPool) DialOption { 733 return newFuncDialOption(func(o *dialOptions) { 734 o.recvBufferPool = bufferPool 735 }) 736 } 737