From 40fdca0c6aeb42544a9da86428a1d44e40e70341 Mon Sep 17 00:00:00 2001 From: viphak Date: Fri, 29 Sep 2017 13:48:13 -0700 Subject: [PATCH 1/4] darwin --- tcpkeepalive_darwin.go | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 tcpkeepalive_darwin.go diff --git a/tcpkeepalive_darwin.go b/tcpkeepalive_darwin.go new file mode 100644 index 0000000..56891ed --- /dev/null +++ b/tcpkeepalive_darwin.go @@ -0,0 +1,38 @@ +package tcpkeepalive + +import ( + "os" + "runtime" + "syscall" + "time" +) + +const sysTCP_KEEPINTVL = 0x101 + +func setIdle(fd uintptr, d time.Duration) error { + // not possible with darwin + return nil +} + +func setCount(fd uintptr, n int) error { + // not possible with darwin + return nil +} + +func setInterval(fd uintptr, d time.Duration) error { + // # from https://golang.org/src/net/tcpsockopt_darwin.go + // d += (time.Second - time.Nanosecond) + // secs := int(d.Seconds()) + // return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, sysTCP_KEEPINTVL, secs)) + // The kernel expects seconds so round to next highest second. + d += (time.Second - time.Nanosecond) + secs := int(d.Seconds()) + switch err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, sysTCP_KEEPINTVL, secs); err { + case nil, syscall.ENOPROTOOPT: // OS X 10.7 and earlier don't support this option + default: + return os.NewSyscallError("setsockopt", err) + } + err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPALIVE, secs) + runtime.KeepAlive(fd) + return os.NewSyscallError("setsockopt", err) +} From 6b4ae2424267fc545a216aef4e2a5f8b1e11a415 Mon Sep 17 00:00:00 2001 From: viphak Date: Fri, 29 Sep 2017 13:50:59 -0700 Subject: [PATCH 2/4] clean --- tcpkeepalive_darwin.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tcpkeepalive_darwin.go b/tcpkeepalive_darwin.go index 56891ed..8aa4db9 100644 --- a/tcpkeepalive_darwin.go +++ b/tcpkeepalive_darwin.go @@ -21,10 +21,6 @@ func setCount(fd uintptr, n int) error { func setInterval(fd uintptr, d time.Duration) error { // # from https://golang.org/src/net/tcpsockopt_darwin.go - // d += (time.Second - time.Nanosecond) - // secs := int(d.Seconds()) - // return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, sysTCP_KEEPINTVL, secs)) - // The kernel expects seconds so round to next highest second. d += (time.Second - time.Nanosecond) secs := int(d.Seconds()) switch err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, sysTCP_KEEPINTVL, secs); err { From aa37a82a53740fa4d89007e76617bd35b19c7cc9 Mon Sep 17 00:00:00 2001 From: viphak Date: Tue, 3 Oct 2017 11:16:05 -0700 Subject: [PATCH 3/4] implement based on netinet/tcp.h --- tcpkeepalive_darwin.go | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/tcpkeepalive_darwin.go b/tcpkeepalive_darwin.go index 8aa4db9..3f49b8a 100644 --- a/tcpkeepalive_darwin.go +++ b/tcpkeepalive_darwin.go @@ -2,33 +2,40 @@ package tcpkeepalive import ( "os" - "runtime" "syscall" "time" ) -const sysTCP_KEEPINTVL = 0x101 +const _TCP_KEEPALIVE = syscall.TCP_KEEPALIVE +const _TCP_KEEPINTVL = 0x101 /* interval between keepalives */ +const _TCP_KEEPCNT = 0x102 /* number of keepalives before close */ func setIdle(fd uintptr, d time.Duration) error { - // not possible with darwin - return nil + secs := durToSecs(d) + err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, _TCP_KEEPALIVE, secs) + return os.NewSyscallError("setsockopt", err) } func setCount(fd uintptr, n int) error { - // not possible with darwin - return nil + err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, _TCP_KEEPCNT, n) + return os.NewSyscallError("setsockopt", err) } func setInterval(fd uintptr, d time.Duration) error { // # from https://golang.org/src/net/tcpsockopt_darwin.go - d += (time.Second - time.Nanosecond) - secs := int(d.Seconds()) - switch err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, sysTCP_KEEPINTVL, secs); err { - case nil, syscall.ENOPROTOOPT: // OS X 10.7 and earlier don't support this option - default: - return os.NewSyscallError("setsockopt", err) + secs := durToSecs(d) + err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, _TCP_KEEPINTVL, secs) + + // OS X 10.7 and earlier don't support this option + if err == nil || err == syscall.ENOPROTOOPT { + return nil } - err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPALIVE, secs) - runtime.KeepAlive(fd) + return os.NewSyscallError("setsockopt", err) } + +func durToSecs(d time.Duration) int { + d += (time.Second - time.Nanosecond) + secs := int(d.Seconds()) + return secs +} From e5a14825c2546765484a17854e119755ac672bf2 Mon Sep 17 00:00:00 2001 From: viphak Date: Tue, 3 Oct 2017 11:42:48 -0700 Subject: [PATCH 4/4] ren --- tcpkeepalive_darwin.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tcpkeepalive_darwin.go b/tcpkeepalive_darwin.go index 3f49b8a..bb10d75 100644 --- a/tcpkeepalive_darwin.go +++ b/tcpkeepalive_darwin.go @@ -6,13 +6,14 @@ import ( "time" ) -const _TCP_KEEPALIVE = syscall.TCP_KEEPALIVE +const _TCP_KEEPIDLE = syscall.TCP_KEEPALIVE const _TCP_KEEPINTVL = 0x101 /* interval between keepalives */ const _TCP_KEEPCNT = 0x102 /* number of keepalives before close */ func setIdle(fd uintptr, d time.Duration) error { + // All versions of darwin support this secs := durToSecs(d) - err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, _TCP_KEEPALIVE, secs) + err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, _TCP_KEEPIDLE, secs) return os.NewSyscallError("setsockopt", err) }