Skip to content

Commit af73211

Browse files
committed
chore: better apply tcp keepalive to listeners
1 parent 6c03830 commit af73211

30 files changed

+180
-100
lines changed

adapter/inbound/listen.go

+22
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ package inbound
33
import (
44
"context"
55
"net"
6+
"sync"
7+
8+
"github.com/metacubex/mihomo/component/keepalive"
69

710
"github.com/metacubex/tfo-go"
811
)
@@ -11,28 +14,47 @@ var (
1114
lc = tfo.ListenConfig{
1215
DisableTFO: true,
1316
}
17+
mutex sync.RWMutex
1418
)
1519

1620
func SetTfo(open bool) {
21+
mutex.Lock()
22+
defer mutex.Unlock()
1723
lc.DisableTFO = !open
1824
}
1925

2026
func Tfo() bool {
27+
mutex.RLock()
28+
defer mutex.RUnlock()
2129
return !lc.DisableTFO
2230
}
2331

2432
func SetMPTCP(open bool) {
33+
mutex.Lock()
34+
defer mutex.Unlock()
2535
setMultiPathTCP(&lc.ListenConfig, open)
2636
}
2737

2838
func MPTCP() bool {
39+
mutex.RLock()
40+
defer mutex.RUnlock()
2941
return getMultiPathTCP(&lc.ListenConfig)
3042
}
3143

3244
func ListenContext(ctx context.Context, network, address string) (net.Listener, error) {
45+
mutex.RLock()
46+
defer mutex.RUnlock()
3347
return lc.Listen(ctx, network, address)
3448
}
3549

3650
func Listen(network, address string) (net.Listener, error) {
3751
return ListenContext(context.Background(), network, address)
3852
}
53+
54+
func init() {
55+
keepalive.SetDisableKeepAliveCallback.Register(func(b bool) {
56+
mutex.Lock()
57+
defer mutex.Unlock()
58+
keepalive.SetNetListenConfig(&lc.ListenConfig)
59+
})
60+
}

adapter/outbound/direct.go

-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"os"
77
"strconv"
88

9-
N "github.com/metacubex/mihomo/common/net"
109
"github.com/metacubex/mihomo/component/dialer"
1110
"github.com/metacubex/mihomo/component/loopback"
1211
"github.com/metacubex/mihomo/component/resolver"
@@ -38,7 +37,6 @@ func (d *Direct) DialContext(ctx context.Context, metadata *C.Metadata, opts ...
3837
if err != nil {
3938
return nil, err
4039
}
41-
N.TCPKeepAlive(c)
4240
return d.loopBack.NewConn(NewConn(c, d)), nil
4341
}
4442

adapter/outbound/http.go

-3
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,11 @@ import (
77
"encoding/base64"
88
"errors"
99
"fmt"
10-
1110
"io"
1211
"net"
1312
"net/http"
1413
"strconv"
1514

16-
N "github.com/metacubex/mihomo/common/net"
1715
"github.com/metacubex/mihomo/component/ca"
1816
"github.com/metacubex/mihomo/component/dialer"
1917
"github.com/metacubex/mihomo/component/proxydialer"
@@ -76,7 +74,6 @@ func (h *Http) DialContextWithDialer(ctx context.Context, dialer C.Dialer, metad
7674
if err != nil {
7775
return nil, fmt.Errorf("%s connect error: %w", h.addr, err)
7876
}
79-
N.TCPKeepAlive(c)
8077

8178
defer func(c net.Conn) {
8279
safeConnClose(c, err)

adapter/outbound/shadowsocks.go

-1
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,6 @@ func (ss *ShadowSocks) DialContextWithDialer(ctx context.Context, dialer C.Diale
149149
if err != nil {
150150
return nil, fmt.Errorf("%s connect error: %w", ss.addr, err)
151151
}
152-
N.TCPKeepAlive(c)
153152

154153
defer func(c net.Conn) {
155154
safeConnClose(c, err)

adapter/outbound/shadowsocksr.go

-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ func (ssr *ShadowSocksR) DialContextWithDialer(ctx context.Context, dialer C.Dia
8080
if err != nil {
8181
return nil, fmt.Errorf("%s connect error: %w", ssr.addr, err)
8282
}
83-
N.TCPKeepAlive(c)
8483

8584
defer func(c net.Conn) {
8685
safeConnClose(c, err)

adapter/outbound/snell.go

+1-5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"net"
77
"strconv"
88

9-
N "github.com/metacubex/mihomo/common/net"
109
"github.com/metacubex/mihomo/common/structure"
1110
"github.com/metacubex/mihomo/component/dialer"
1211
"github.com/metacubex/mihomo/component/proxydialer"
@@ -94,7 +93,6 @@ func (s *Snell) DialContextWithDialer(ctx context.Context, dialer C.Dialer, meta
9493
if err != nil {
9594
return nil, fmt.Errorf("%s connect error: %w", s.addr, err)
9695
}
97-
N.TCPKeepAlive(c)
9896

9997
defer func(c net.Conn) {
10098
safeConnClose(c, err)
@@ -122,7 +120,6 @@ func (s *Snell) ListenPacketWithDialer(ctx context.Context, dialer C.Dialer, met
122120
if err != nil {
123121
return nil, err
124122
}
125-
N.TCPKeepAlive(c)
126123
c = streamConn(c, streamOption{s.psk, s.version, s.addr, s.obfsOption})
127124

128125
err = snell.WriteUDPHeader(c, s.version)
@@ -207,8 +204,7 @@ func NewSnell(option SnellOption) (*Snell, error) {
207204
if err != nil {
208205
return nil, err
209206
}
210-
211-
N.TCPKeepAlive(c)
207+
212208
return streamConn(c, streamOption{psk, option.Version, addr, obfsOption}), nil
213209
})
214210
}

adapter/outbound/socks5.go

-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
"net/netip"
1111
"strconv"
1212

13-
N "github.com/metacubex/mihomo/common/net"
1413
"github.com/metacubex/mihomo/component/ca"
1514
"github.com/metacubex/mihomo/component/dialer"
1615
"github.com/metacubex/mihomo/component/proxydialer"
@@ -82,7 +81,6 @@ func (ss *Socks5) DialContextWithDialer(ctx context.Context, dialer C.Dialer, me
8281
if err != nil {
8382
return nil, fmt.Errorf("%s connect error: %w", ss.addr, err)
8483
}
85-
N.TCPKeepAlive(c)
8684

8785
defer func(c net.Conn) {
8886
safeConnClose(c, err)
@@ -128,7 +126,6 @@ func (ss *Socks5) ListenPacketContext(ctx context.Context, metadata *C.Metadata,
128126
safeConnClose(c, err)
129127
}(c)
130128

131-
N.TCPKeepAlive(c)
132129
var user *socks5.User
133130
if ss.user != "" {
134131
user = &socks5.User{

adapter/outbound/ssh.go

-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ func (s *sshClient) connect(ctx context.Context, cDialer C.Dialer, addr string)
7777
if err != nil {
7878
return nil, err
7979
}
80-
N.TCPKeepAlive(c)
8180

8281
defer func(c net.Conn) {
8382
safeConnClose(c, err)

adapter/outbound/trojan.go

-4
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"net/http"
1010
"strconv"
1111

12-
N "github.com/metacubex/mihomo/common/net"
1312
"github.com/metacubex/mihomo/component/ca"
1413
"github.com/metacubex/mihomo/component/dialer"
1514
"github.com/metacubex/mihomo/component/proxydialer"
@@ -154,7 +153,6 @@ func (t *Trojan) DialContextWithDialer(ctx context.Context, dialer C.Dialer, met
154153
if err != nil {
155154
return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
156155
}
157-
N.TCPKeepAlive(c)
158156

159157
defer func(c net.Conn) {
160158
safeConnClose(c, err)
@@ -212,7 +210,6 @@ func (t *Trojan) ListenPacketWithDialer(ctx context.Context, dialer C.Dialer, me
212210
defer func(c net.Conn) {
213211
safeConnClose(c, err)
214212
}(c)
215-
N.TCPKeepAlive(c)
216213
c, err = t.plainStream(ctx, c)
217214
if err != nil {
218215
return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
@@ -314,7 +311,6 @@ func NewTrojan(option TrojanOption) (*Trojan, error) {
314311
if err != nil {
315312
return nil, fmt.Errorf("%s connect error: %s", t.addr, err.Error())
316313
}
317-
N.TCPKeepAlive(c)
318314
return c, nil
319315
}
320316

adapter/outbound/vless.go

-3
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,6 @@ func (v *Vless) DialContextWithDialer(ctx context.Context, dialer C.Dialer, meta
262262
if err != nil {
263263
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
264264
}
265-
N.TCPKeepAlive(c)
266265
defer func(c net.Conn) {
267266
safeConnClose(c, err)
268267
}(c)
@@ -327,7 +326,6 @@ func (v *Vless) ListenPacketWithDialer(ctx context.Context, dialer C.Dialer, met
327326
if err != nil {
328327
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
329328
}
330-
N.TCPKeepAlive(c)
331329
defer func(c net.Conn) {
332330
safeConnClose(c, err)
333331
}(c)
@@ -574,7 +572,6 @@ func NewVless(option VlessOption) (*Vless, error) {
574572
if err != nil {
575573
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
576574
}
577-
N.TCPKeepAlive(c)
578575
return c, nil
579576
}
580577

adapter/outbound/vmess.go

-3
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,6 @@ func (v *Vmess) DialContextWithDialer(ctx context.Context, dialer C.Dialer, meta
312312
if err != nil {
313313
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
314314
}
315-
N.TCPKeepAlive(c)
316315
defer func(c net.Conn) {
317316
safeConnClose(c, err)
318317
}(c)
@@ -373,7 +372,6 @@ func (v *Vmess) ListenPacketWithDialer(ctx context.Context, dialer C.Dialer, met
373372
if err != nil {
374373
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
375374
}
376-
N.TCPKeepAlive(c)
377375
defer func(c net.Conn) {
378376
safeConnClose(c, err)
379377
}(c)
@@ -473,7 +471,6 @@ func NewVmess(option VmessOption) (*Vmess, error) {
473471
if err != nil {
474472
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
475473
}
476-
N.TCPKeepAlive(c)
477474
return c, nil
478475
}
479476

common/net/tcp_keepalive.go

-23
This file was deleted.

common/net/tcp_keepalive_go122.go

-10
This file was deleted.

common/net/tcp_keepalive_go123.go

-19
This file was deleted.

component/dialer/dialer.go

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"sync"
1313
"time"
1414

15+
"github.com/metacubex/mihomo/component/keepalive"
1516
"github.com/metacubex/mihomo/component/resolver"
1617
"github.com/metacubex/mihomo/log"
1718
)
@@ -144,6 +145,7 @@ func dialContext(ctx context.Context, network string, destination netip.Addr, po
144145
}
145146

146147
dialer := netDialer.(*net.Dialer)
148+
keepalive.SetNetDialer(dialer)
147149
if opt.mpTcp {
148150
setMultiPathTCP(dialer)
149151
}

component/keepalive/tcp_keepalive.go

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package keepalive
2+
3+
import (
4+
"net"
5+
"runtime"
6+
"time"
7+
8+
"github.com/metacubex/mihomo/common/atomic"
9+
"github.com/metacubex/mihomo/common/utils"
10+
)
11+
12+
var (
13+
keepAliveIdle = atomic.NewTypedValue[time.Duration](0 * time.Second)
14+
keepAliveInterval = atomic.NewTypedValue[time.Duration](0 * time.Second)
15+
disableKeepAlive = atomic.NewBool(false)
16+
17+
SetDisableKeepAliveCallback = utils.NewCallback[bool]()
18+
)
19+
20+
func SetKeepAliveIdle(t time.Duration) {
21+
keepAliveIdle.Store(t)
22+
}
23+
24+
func SetKeepAliveInterval(t time.Duration) {
25+
keepAliveInterval.Store(t)
26+
}
27+
28+
func KeepAliveIdle() time.Duration {
29+
return keepAliveIdle.Load()
30+
}
31+
32+
func KeepAliveInterval() time.Duration {
33+
return keepAliveInterval.Load()
34+
}
35+
36+
func SetDisableKeepAlive(disable bool) {
37+
if runtime.GOOS == "android" {
38+
setDisableKeepAlive(false)
39+
} else {
40+
setDisableKeepAlive(disable)
41+
}
42+
}
43+
44+
func setDisableKeepAlive(disable bool) {
45+
disableKeepAlive.Store(disable)
46+
SetDisableKeepAliveCallback.Emit(disable)
47+
}
48+
49+
func DisableKeepAlive() bool {
50+
return disableKeepAlive.Load()
51+
}
52+
53+
func SetNetDialer(dialer *net.Dialer) {
54+
setNetDialer(dialer)
55+
}
56+
57+
func SetNetListenConfig(lc *net.ListenConfig) {
58+
setNetListenConfig(lc)
59+
}
60+
61+
func TCPKeepAlive(c net.Conn) {
62+
if tcp, ok := c.(*net.TCPConn); ok && tcp != nil {
63+
tcpKeepAlive(tcp)
64+
}
65+
}

0 commit comments

Comments
 (0)