| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748 |
- //go:build linux
-
- package network
-
- import (
- "net"
- "syscall"
- "time"
-
- "golang.org/x/sys/unix"
- )
-
- // Go runtime defaults for KeepAliveConfig when fields are zero.
- const (
- goDefaultKeepAliveIdle = 15 * time.Second
- goDefaultKeepAliveInterval = 15 * time.Second
- goDefaultKeepAliveCount = 9
- )
-
- // setTCPUserTimeout sets TCP_USER_TIMEOUT on a socket. If transmitted
- // data remains unacknowledged for this long, the kernel closes the
- // connection. As recommended by Cloudflare
- // (https://blog.cloudflare.com/when-tcp-sockets-refuse-to-die/),
- // the value is computed as: keepidle + keepintvl * keepcnt. This
- // ensures TCP_USER_TIMEOUT and keepalives agree on when to give up.
- // Best-effort: silently ignored if unsupported.
- func setTCPUserTimeout(conn syscall.RawConn, cfg net.KeepAliveConfig) {
- idle := cfg.Idle
- if idle == 0 {
- idle = goDefaultKeepAliveIdle
- }
-
- interval := cfg.Interval
- if interval == 0 {
- interval = goDefaultKeepAliveInterval
- }
-
- count := cfg.Count
- if count == 0 {
- count = goDefaultKeepAliveCount
- }
-
- timeout := idle + interval*time.Duration(count)
-
- conn.Control(func(fd uintptr) { //nolint: errcheck
- unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_USER_TIMEOUT, int(timeout.Milliseconds())) //nolint: errcheck
- })
- }
|