dial_socketopt.go 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. // Copyright 2019 Google LLC.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. //go:build go1.11 && linux
  5. // +build go1.11,linux
  6. package grpc
  7. import (
  8. "context"
  9. "net"
  10. "syscall"
  11. "google.golang.org/grpc"
  12. )
  13. const (
  14. // defaultTCPUserTimeout is the default TCP_USER_TIMEOUT socket option. By
  15. // default is 20 seconds.
  16. tcpUserTimeoutMilliseconds = 20000
  17. // Copied from golang.org/x/sys/unix.TCP_USER_TIMEOUT.
  18. tcpUserTimeoutOp = 0x12
  19. )
  20. func init() {
  21. // timeoutDialerOption is a grpc.DialOption that contains dialer with
  22. // socket option TCP_USER_TIMEOUT. This dialer requires go versions 1.11+.
  23. timeoutDialerOption = grpc.WithContextDialer(dialTCPUserTimeout)
  24. }
  25. func dialTCPUserTimeout(ctx context.Context, addr string) (net.Conn, error) {
  26. control := func(network, address string, c syscall.RawConn) error {
  27. var syscallErr error
  28. controlErr := c.Control(func(fd uintptr) {
  29. syscallErr = syscall.SetsockoptInt(
  30. int(fd), syscall.IPPROTO_TCP, tcpUserTimeoutOp, tcpUserTimeoutMilliseconds)
  31. })
  32. if syscallErr != nil {
  33. return syscallErr
  34. }
  35. if controlErr != nil {
  36. return controlErr
  37. }
  38. return nil
  39. }
  40. d := &net.Dialer{
  41. Control: control,
  42. }
  43. return d.DialContext(ctx, "tcp", addr)
  44. }