Skip to content

Commit 519bae1

Browse files
committed
dial: use OS defaults for TCP keepalive params
Fixes #605
1 parent 7041bdd commit 519bae1

File tree

3 files changed

+63
-16
lines changed

3 files changed

+63
-16
lines changed

dial.go

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ package forwarder
99
import (
1010
"context"
1111
"net"
12+
"syscall"
1213
"time"
1314
)
1415

@@ -21,20 +22,15 @@ type DialConfig struct {
2122
// often around 3 minutes.
2223
DialTimeout time.Duration
2324

24-
// KeepAlive specifies the interval between keep-alive
25-
// probes for an active network connection.
26-
// If zero, keep-alive probes are sent with a default value
27-
// (currently 15 seconds), if supported by the protocol and operating
28-
// system. Network protocols or operating systems that do
29-
// not support keep-alives ignore this field.
30-
// If negative, keep-alive probes are disabled.
31-
KeepAlive time.Duration
25+
// KeepAlive enables TCP keep-alive probes for an active network connection.
26+
// The keep-alive probes are sent with OS specific intervals.
27+
KeepAlive bool
3228
}
3329

3430
func DefaultDialConfig() *DialConfig {
3531
return &DialConfig{
3632
DialTimeout: 10 * time.Second,
37-
KeepAlive: 30 * time.Second,
33+
KeepAlive: true,
3834
}
3935
}
4036

@@ -43,15 +39,23 @@ type Dialer struct {
4339
}
4440

4541
func NewDialer(cfg *DialConfig) *Dialer {
46-
return &Dialer{
47-
net.Dialer{
48-
Timeout: cfg.DialTimeout,
49-
KeepAlive: cfg.KeepAlive,
50-
Resolver: &net.Resolver{
51-
PreferGo: true,
52-
},
42+
nd := net.Dialer{
43+
Timeout: cfg.DialTimeout,
44+
KeepAlive: -1,
45+
Resolver: &net.Resolver{
46+
PreferGo: true,
5347
},
5448
}
49+
50+
if cfg.KeepAlive {
51+
nd.Control = func(network, address string, c syscall.RawConn) error {
52+
return c.Control(enableTCPKeepAlive)
53+
}
54+
}
55+
56+
return &Dialer{
57+
nd: nd,
58+
}
5559
}
5660

5761
func (d *Dialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {

dial_unix.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2023 Sauce Labs Inc., all rights reserved.
2+
//
3+
// This Source Code Form is subject to the terms of the Mozilla Public
4+
// License, v. 2.0. If a copy of the MPL was not distributed with this
5+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
6+
7+
//go:build unix
8+
9+
package forwarder
10+
11+
import (
12+
"fmt"
13+
"os"
14+
"syscall"
15+
)
16+
17+
func enableTCPKeepAlive(fd uintptr) {
18+
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil {
19+
fmt.Fprintf(os.Stderr, "failed to set SO_KEEPALIVE: %v\n", err)
20+
}
21+
}

dial_windows.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2023 Sauce Labs Inc., all rights reserved.
2+
//
3+
// This Source Code Form is subject to the terms of the Mozilla Public
4+
// License, v. 2.0. If a copy of the MPL was not distributed with this
5+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
6+
7+
//go:build windows
8+
9+
package forwarder
10+
11+
import (
12+
"fmt"
13+
"os"
14+
15+
"golang.org/x/sys/windows"
16+
)
17+
18+
func enableTCPKeepAlive(fd uintptr) {
19+
if err := windows.SetsockoptInt(windows.Handle(fd), windows.SOL_SOCKET, windows.SO_KEEPALIVE, 1); err != nil {
20+
fmt.Fprintf(os.Stderr, "failed to set SO_KEEPALIVE: %v\n", err)
21+
}
22+
}

0 commit comments

Comments
 (0)