Skip to content

Commit 46e493c

Browse files
committed
Add pause support
1 parent 7545dc2 commit 46e493c

6 files changed

Lines changed: 51 additions & 20 deletions

File tree

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ require (
88
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61
99
github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2
1010
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97
11-
github.com/sagernet/sing v0.2.9
11+
github.com/sagernet/sing v0.2.10-0.20230831053650-deb9afed5dbf
1212
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9
1313
golang.org/x/net v0.14.0
1414
golang.org/x/sys v0.11.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2/go.mod h1:1JUiV7nG
1111
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE=
1212
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
1313
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
14-
github.com/sagernet/sing v0.2.9 h1:3wsTz+JG5Wzy65eZnh6AuCrD2QqcRF6Iq6f7ttmJsAo=
15-
github.com/sagernet/sing v0.2.9/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w=
14+
github.com/sagernet/sing v0.2.10-0.20230831053650-deb9afed5dbf h1:pnmqxDWO/uw4ElokoJiFUVZhCrp80CcENpYagdRL7sI=
15+
github.com/sagernet/sing v0.2.10-0.20230831053650-deb9afed5dbf/go.mod h1:9uOZwWkhT2Z2WldolLxX34s+1svAX4i4vvz5hy8u1MA=
1616
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 h1:rc/CcqLH3lh8n+csdOuDfP+NuykE0U6AeYSJJHKDgSg=
1717
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9/go.mod h1:a/83NAfUXvEuLpmxDssAXxgUgrEy12MId3Wd7OTs76s=
1818
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=

stack_gvisor.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
E "github.com/sagernet/sing/common/exceptions"
2424
"github.com/sagernet/sing/common/logger"
2525
M "github.com/sagernet/sing/common/metadata"
26+
"github.com/sagernet/sing/service/pause"
2627
)
2728

2829
const WithGVisor = true
@@ -37,6 +38,7 @@ type GVisor struct {
3738
udpTimeout int64
3839
handler Handler
3940
logger logger.Logger
41+
pauseManager pause.Manager
4042
stack *stack.Stack
4143
endpoint stack.LinkEndpoint
4244
}
@@ -62,6 +64,7 @@ func NewGVisor(
6264
udpTimeout: options.UDPTimeout,
6365
handler: options.Handler,
6466
logger: options.Logger,
67+
pauseManager: pause.ManagerFromContext(options.Context),
6568
}
6669
return gStack, nil
6770
}
@@ -76,6 +79,10 @@ func (t *GVisor) Start() error {
7679
return err
7780
}
7881
tcpForwarder := tcp.NewForwarder(ipStack, 0, 1024, func(r *tcp.ForwarderRequest) {
82+
if t.pauseManager != nil && pause.IsPaused(t.pauseManager.NetworkPauseChan()) {
83+
r.Complete(true)
84+
return
85+
}
7986
var wq waiter.Queue
8087
handshakeCtx, cancel := context.WithCancel(context.Background())
8188
go func() {
@@ -117,6 +124,10 @@ func (t *GVisor) Start() error {
117124
ipStack.SetTransportProtocolHandler(tcp.ProtocolNumber, tcpForwarder.HandlePacket)
118125
if !t.endpointIndependentNat {
119126
udpForwarder := udp.NewForwarder(ipStack, func(request *udp.ForwarderRequest) {
127+
if t.pauseManager != nil && pause.IsPaused(t.pauseManager.NetworkPauseChan()) {
128+
(*gRequest)(unsafe.Pointer(request)).pkt.DecRef()
129+
return
130+
}
120131
var wq waiter.Queue
121132
endpoint, err := request.CreateEndpoint(&wq)
122133
if err != nil {
@@ -143,7 +154,7 @@ func (t *GVisor) Start() error {
143154
})
144155
ipStack.SetTransportProtocolHandler(udp.ProtocolNumber, udpForwarder.HandlePacket)
145156
} else {
146-
ipStack.SetTransportProtocolHandler(udp.ProtocolNumber, NewUDPForwarder(t.ctx, ipStack, t.handler, t.udpTimeout).HandlePacket)
157+
ipStack.SetTransportProtocolHandler(udp.ProtocolNumber, NewUDPForwarder(t.ctx, ipStack, t.handler, t.udpTimeout, t.pauseManager).HandlePacket)
147158
}
148159

149160
t.stack = ipStack

stack_gvisor_udp.go

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,27 @@ import (
2222
M "github.com/sagernet/sing/common/metadata"
2323
N "github.com/sagernet/sing/common/network"
2424
"github.com/sagernet/sing/common/udpnat"
25+
"github.com/sagernet/sing/service/pause"
2526
)
2627

2728
type UDPForwarder struct {
28-
ctx context.Context
29-
stack *stack.Stack
30-
udpNat *udpnat.Service[netip.AddrPort]
29+
ctx context.Context
30+
stack *stack.Stack
31+
udpNat *udpnat.Service[netip.AddrPort]
32+
pauseManager pause.Manager
3133

3234
// cache
3335
cacheProto tcpip.NetworkProtocolNumber
3436
cacheID stack.TransportEndpointID
3537
cachePacket stack.PacketBufferPtr
3638
}
3739

38-
func NewUDPForwarder(ctx context.Context, stack *stack.Stack, handler Handler, udpTimeout int64) *UDPForwarder {
40+
func NewUDPForwarder(ctx context.Context, stack *stack.Stack, handler Handler, udpTimeout int64, pauseManager pause.Manager) *UDPForwarder {
3941
return &UDPForwarder{
40-
ctx: ctx,
41-
stack: stack,
42-
udpNat: udpnat.New[netip.AddrPort](udpTimeout, handler),
42+
ctx: ctx,
43+
stack: stack,
44+
udpNat: udpnat.New[netip.AddrPort](udpTimeout, handler),
45+
pauseManager: pauseManager,
4346
}
4447
}
4548

@@ -59,7 +62,7 @@ func (f *UDPForwarder) HandlePacket(id stack.TransportEndpointID, pkt stack.Pack
5962
})
6063
f.cacheID = id
6164
f.cachePacket = pkt
62-
f.udpNat.NewPacket(
65+
f.udpNat.NewContextPacket1(
6366
f.ctx,
6467
upstreamMetadata.Source.AddrPort(),
6568
sBuffer,
@@ -69,14 +72,17 @@ func (f *UDPForwarder) HandlePacket(id stack.TransportEndpointID, pkt stack.Pack
6972
return true
7073
}
7174

72-
func (f *UDPForwarder) newUDPConn(natConn N.PacketConn) N.PacketWriter {
73-
return &UDPBackWriter{
75+
func (f *UDPForwarder) newUDPConn(natConn N.PacketConn) (context.Context, N.PacketWriter, error) {
76+
if f.pauseManager != nil && pause.IsPaused(f.pauseManager.NetworkPauseChan()) {
77+
return nil, nil, pause.ErrPaused
78+
}
79+
return f.ctx, &UDPBackWriter{
7480
stack: f.stack,
7581
source: f.cacheID.RemoteAddress,
7682
sourcePort: f.cacheID.RemotePort,
7783
sourceNetwork: f.cacheProto,
7884
packet: f.cachePacket.IncRef(),
79-
}
85+
}, nil
8086
}
8187

8288
type UDPBackWriter struct {

stack_mixed.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ func (m *Mixed) Start() error {
8282
})
8383
ipStack.SetTransportProtocolHandler(udp.ProtocolNumber, udpForwarder.HandlePacket)
8484
} else {
85-
ipStack.SetTransportProtocolHandler(udp.ProtocolNumber, NewUDPForwarder(m.ctx, ipStack, m.handler, m.udpTimeout).HandlePacket)
85+
ipStack.SetTransportProtocolHandler(udp.ProtocolNumber, NewUDPForwarder(m.ctx, ipStack, m.handler, m.udpTimeout, m.pauseManager).HandlePacket)
8686
}
8787
m.stack = ipStack
8888
m.endpoint = endpoint

stack_system.go

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
M "github.com/sagernet/sing/common/metadata"
1717
N "github.com/sagernet/sing/common/network"
1818
"github.com/sagernet/sing/common/udpnat"
19+
"github.com/sagernet/sing/service/pause"
1920
)
2021

2122
type System struct {
@@ -40,6 +41,7 @@ type System struct {
4041
udpNat *udpnat.Service[netip.AddrPort]
4142
bindInterface bool
4243
interfaceFinder control.InterfaceFinder
44+
pauseManager pause.Manager
4345
}
4446

4547
type Session struct {
@@ -62,6 +64,7 @@ func NewSystem(options StackOptions) (Stack, error) {
6264
inet6Prefixes: options.Inet6Address,
6365
bindInterface: options.ForwarderBindInterface,
6466
interfaceFinder: options.InterfaceFinder,
67+
pauseManager: pause.ManagerFromContext(options.Context),
6568
}
6669
if len(options.Inet4Address) > 0 {
6770
if options.Inet4Address[0].Bits() == 32 {
@@ -197,6 +200,11 @@ func (s *System) acceptLoop(listener net.Listener) {
197200
if err != nil {
198201
return
199202
}
203+
if s.pauseManager != nil && pause.IsPaused(s.pauseManager.NetworkPauseChan()) {
204+
conn.(*net.TCPConn).SetLinger(0)
205+
conn.Close()
206+
continue
207+
}
200208
connPort := M.SocksaddrFromNet(conn.RemoteAddr()).Port
201209
session := s.tcpNat.LookupBack(connPort)
202210
if session == nil {
@@ -330,11 +338,14 @@ func (s *System) processIPv4UDP(packet clashtcpip.IPv4Packet, header clashtcpip.
330338
Source: M.SocksaddrFromNetIP(source),
331339
Destination: M.SocksaddrFromNetIP(destination),
332340
}
333-
s.udpNat.NewPacket(s.ctx, source, data.ToOwned(), metadata, func(natConn N.PacketConn) N.PacketWriter {
341+
s.udpNat.NewContextPacket1(s.ctx, source, data.ToOwned(), metadata, func(natConn N.PacketConn) (context.Context, N.PacketWriter, error) {
342+
if s.pauseManager != nil && pause.IsPaused(s.pauseManager.NetworkPauseChan()) {
343+
return nil, nil, pause.ErrPaused
344+
}
334345
headerLen := packet.HeaderLen() + clashtcpip.UDPHeaderSize
335346
headerCopy := make([]byte, headerLen)
336347
copy(headerCopy, packet[:headerLen])
337-
return &systemUDPPacketWriter4{s.tun, headerCopy, source}
348+
return s.ctx, &systemUDPPacketWriter4{s.tun, headerCopy, source}, nil
338349
})
339350
return nil
340351
}
@@ -353,11 +364,14 @@ func (s *System) processIPv6UDP(packet clashtcpip.IPv6Packet, header clashtcpip.
353364
Source: M.SocksaddrFromNetIP(source),
354365
Destination: M.SocksaddrFromNetIP(destination),
355366
}
356-
s.udpNat.NewPacket(s.ctx, source, data.ToOwned(), metadata, func(natConn N.PacketConn) N.PacketWriter {
367+
s.udpNat.NewContextPacket1(s.ctx, source, data.ToOwned(), metadata, func(natConn N.PacketConn) (context.Context, N.PacketWriter, error) {
368+
if s.pauseManager != nil && pause.IsPaused(s.pauseManager.NetworkPauseChan()) {
369+
return nil, nil, pause.ErrPaused
370+
}
357371
headerLen := len(packet) - int(header.Length()) + clashtcpip.UDPHeaderSize
358372
headerCopy := make([]byte, headerLen)
359373
copy(headerCopy, packet[:headerLen])
360-
return &systemUDPPacketWriter6{s.tun, headerCopy, source}
374+
return s.ctx, &systemUDPPacketWriter6{s.tun, headerCopy, source}, nil
361375
})
362376
return nil
363377
}

0 commit comments

Comments
 (0)