chore: adapt new ReadWait interfaces

This commit is contained in:
wwqgtxx 2023-12-07 23:32:37 +08:00
parent c5d1db7905
commit cbec564af9
12 changed files with 249 additions and 114 deletions

View file

@ -20,6 +20,7 @@ import (
restlsC "github.com/3andne/restls-client-go" restlsC "github.com/3andne/restls-client-go"
shadowsocks "github.com/metacubex/sing-shadowsocks2" shadowsocks "github.com/metacubex/sing-shadowsocks2"
"github.com/sagernet/sing/common/bufio"
M "github.com/sagernet/sing/common/metadata" M "github.com/sagernet/sing/common/metadata"
"github.com/sagernet/sing/common/uot" "github.com/sagernet/sing/common/uot"
) )
@ -187,7 +188,7 @@ func (ss *ShadowSocks) ListenPacketWithDialer(ctx context.Context, dialer C.Dial
if err != nil { if err != nil {
return nil, err return nil, err
} }
pc = ss.method.DialPacketConn(N.NewBindPacketConn(pc, addr)) pc = ss.method.DialPacketConn(bufio.NewBindPacketConn(pc, addr))
return newPacketConn(pc, ss), nil return newPacketConn(pc, ss), nil
} }

149
common/net/deadline/conn.go Normal file
View file

@ -0,0 +1,149 @@
package deadline
import (
"net"
"os"
"time"
"github.com/metacubex/mihomo/common/atomic"
"github.com/sagernet/sing/common/buf"
"github.com/sagernet/sing/common/bufio"
"github.com/sagernet/sing/common/network"
)
type connReadResult struct {
buffer []byte
err error
}
type Conn struct {
network.ExtendedConn
deadline atomic.TypedValue[time.Time]
pipeDeadline pipeDeadline
disablePipe atomic.Bool
inRead atomic.Bool
resultCh chan *connReadResult
}
func NewConn(conn net.Conn) *Conn {
c := &Conn{
ExtendedConn: bufio.NewExtendedConn(conn),
pipeDeadline: makePipeDeadline(),
resultCh: make(chan *connReadResult, 1),
}
c.resultCh <- nil
return c
}
func (c *Conn) Read(p []byte) (n int, err error) {
select {
case result := <-c.resultCh:
if result != nil {
n = copy(p, result.buffer)
err = result.err
if n >= len(result.buffer) {
c.resultCh <- nil // finish cache read
} else {
result.buffer = result.buffer[n:]
c.resultCh <- result // push back for next call
}
return
} else {
c.resultCh <- nil
break
}
case <-c.pipeDeadline.wait():
return 0, os.ErrDeadlineExceeded
}
if c.disablePipe.Load() {
return c.ExtendedConn.Read(p)
} else if c.deadline.Load().IsZero() {
c.inRead.Store(true)
defer c.inRead.Store(false)
return c.ExtendedConn.Read(p)
}
<-c.resultCh
go c.pipeRead(len(p))
return c.Read(p)
}
func (c *Conn) pipeRead(size int) {
buffer := make([]byte, size)
n, err := c.ExtendedConn.Read(buffer)
buffer = buffer[:n]
c.resultCh <- &connReadResult{
buffer: buffer,
err: err,
}
}
func (c *Conn) ReadBuffer(buffer *buf.Buffer) (err error) {
select {
case result := <-c.resultCh:
if result != nil {
n, _ := buffer.Write(result.buffer)
err = result.err
if n >= len(result.buffer) {
c.resultCh <- nil // finish cache read
} else {
result.buffer = result.buffer[n:]
c.resultCh <- result // push back for next call
}
return
} else {
c.resultCh <- nil
break
}
case <-c.pipeDeadline.wait():
return os.ErrDeadlineExceeded
}
if c.disablePipe.Load() {
return c.ExtendedConn.ReadBuffer(buffer)
} else if c.deadline.Load().IsZero() {
c.inRead.Store(true)
defer c.inRead.Store(false)
return c.ExtendedConn.ReadBuffer(buffer)
}
<-c.resultCh
go c.pipeRead(buffer.FreeLen())
return c.ReadBuffer(buffer)
}
func (c *Conn) SetReadDeadline(t time.Time) error {
if c.disablePipe.Load() {
return c.ExtendedConn.SetReadDeadline(t)
} else if c.inRead.Load() {
c.disablePipe.Store(true)
return c.ExtendedConn.SetReadDeadline(t)
}
c.deadline.Store(t)
c.pipeDeadline.set(t)
return nil
}
func (c *Conn) ReaderReplaceable() bool {
select {
case result := <-c.resultCh:
c.resultCh <- result
if result != nil {
return false // cache reading
} else {
break
}
default:
return false // pipe reading
}
return c.disablePipe.Load() || c.deadline.Load().IsZero()
}
func (c *Conn) Upstream() any {
return c.ExtendedConn
}

View file

@ -5,6 +5,7 @@ import (
"runtime" "runtime"
"github.com/metacubex/mihomo/common/net/packet" "github.com/metacubex/mihomo/common/net/packet"
"github.com/sagernet/sing/common/buf" "github.com/sagernet/sing/common/buf"
"github.com/sagernet/sing/common/bufio" "github.com/sagernet/sing/common/bufio"
M "github.com/sagernet/sing/common/metadata" M "github.com/sagernet/sing/common/metadata"
@ -121,17 +122,18 @@ type singPacketReadWaiter struct {
type singWaitReadResult singReadResult type singWaitReadResult singReadResult
func (c *singPacketReadWaiter) InitializeReadWaiter(newBuffer func() *buf.Buffer) { func (c *singPacketReadWaiter) InitializeReadWaiter(options N.ReadWaitOptions) (needCopy bool) {
c.packetReadWaiter.InitializeReadWaiter(newBuffer) return c.packetReadWaiter.InitializeReadWaiter(options)
} }
func (c *singPacketReadWaiter) WaitReadPacket() (destination M.Socksaddr, err error) { func (c *singPacketReadWaiter) WaitReadPacket() (buffer *buf.Buffer, destination M.Socksaddr, err error) {
FOR: FOR:
for { for {
select { select {
case result := <-c.netPacketConn.resultCh: case result := <-c.netPacketConn.resultCh:
if result != nil { if result != nil {
if result, ok := result.(*singWaitReadResult); ok { if result, ok := result.(*singWaitReadResult); ok {
buffer = result.buffer
destination = result.destination destination = result.destination
err = result.err err = result.err
c.netPacketConn.resultCh <- nil // finish cache read c.netPacketConn.resultCh <- nil // finish cache read
@ -145,7 +147,7 @@ FOR:
break FOR break FOR
} }
case <-c.netPacketConn.pipeDeadline.wait(): case <-c.netPacketConn.pipeDeadline.wait():
return M.Socksaddr{}, os.ErrDeadlineExceeded return nil, M.Socksaddr{}, os.ErrDeadlineExceeded
} }
} }
@ -154,8 +156,7 @@ FOR:
} else if c.netPacketConn.deadline.Load().IsZero() { } else if c.netPacketConn.deadline.Load().IsZero() {
c.netPacketConn.inRead.Store(true) c.netPacketConn.inRead.Store(true)
defer c.netPacketConn.inRead.Store(false) defer c.netPacketConn.inRead.Store(false)
destination, err = c.packetReadWaiter.WaitReadPacket() return c.packetReadWaiter.WaitReadPacket()
return
} }
<-c.netPacketConn.resultCh <-c.netPacketConn.resultCh
@ -165,8 +166,9 @@ FOR:
} }
func (c *singPacketReadWaiter) pipeWaitReadPacket() { func (c *singPacketReadWaiter) pipeWaitReadPacket() {
destination, err := c.packetReadWaiter.WaitReadPacket() buffer, destination, err := c.packetReadWaiter.WaitReadPacket()
result := &singWaitReadResult{} result := &singWaitReadResult{}
result.buffer = buffer
result.destination = destination result.destination = destination
result.err = err result.err = err
c.netPacketConn.resultCh <- result c.netPacketConn.resultCh <- result

View file

@ -24,16 +24,16 @@ type enhanceSingPacketConn struct {
func (c *enhanceSingPacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) { func (c *enhanceSingPacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) {
var buff *buf.Buffer var buff *buf.Buffer
var dest M.Socksaddr var dest M.Socksaddr
newBuffer := func() *buf.Buffer { rwOptions := N.ReadWaitOptions{}
buff = buf.NewPacket() // do not use stack buffer
return buff
}
if c.packetReadWaiter != nil { if c.packetReadWaiter != nil {
c.packetReadWaiter.InitializeReadWaiter(newBuffer) c.packetReadWaiter.InitializeReadWaiter(rwOptions)
defer c.packetReadWaiter.InitializeReadWaiter(nil) buff, dest, err = c.packetReadWaiter.WaitReadPacket()
dest, err = c.packetReadWaiter.WaitReadPacket()
} else { } else {
dest, err = c.SingPacketConn.ReadPacket(newBuffer()) buff = rwOptions.NewPacketBuffer()
dest, err = c.SingPacketConn.ReadPacket(buff)
if buff != nil {
rwOptions.PostReturn(buff)
}
} }
if dest.IsFqdn() { if dest.IsFqdn() {
addr = dest addr = dest
@ -41,9 +41,7 @@ func (c *enhanceSingPacketConn) WaitReadFrom() (data []byte, put func(), addr ne
addr = dest.UDPAddr() addr = dest.UDPAddr()
} }
if err != nil { if err != nil {
if buff != nil {
buff.Release() buff.Release()
}
return return
} }
if buff == nil { if buff == nil {

View file

@ -5,9 +5,10 @@ import (
"net" "net"
"runtime" "runtime"
"github.com/metacubex/mihomo/common/net/deadline"
"github.com/sagernet/sing/common" "github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/bufio" "github.com/sagernet/sing/common/bufio"
"github.com/sagernet/sing/common/bufio/deadline"
"github.com/sagernet/sing/common/network" "github.com/sagernet/sing/common/network"
) )
@ -19,8 +20,10 @@ type ExtendedConn = network.ExtendedConn
type ExtendedWriter = network.ExtendedWriter type ExtendedWriter = network.ExtendedWriter
type ExtendedReader = network.ExtendedReader type ExtendedReader = network.ExtendedReader
var WriteBuffer = bufio.WriteBuffer
func NewDeadlineConn(conn net.Conn) ExtendedConn { func NewDeadlineConn(conn net.Conn) ExtendedConn {
return deadline.NewFallbackConn(conn) return deadline.NewConn(conn)
} }
func NeedHandshake(conn any) bool { func NeedHandshake(conn any) bool {

22
go.mod
View file

@ -21,12 +21,12 @@ require (
github.com/mdlayher/netlink v1.7.2 github.com/mdlayher/netlink v1.7.2
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759
github.com/metacubex/quic-go v0.40.1-0.20231130135418-0c1b47cf9394 github.com/metacubex/quic-go v0.40.1-0.20231130135418-0c1b47cf9394
github.com/metacubex/sing-quic v0.0.0-20231130141855-0022295e524b github.com/metacubex/sing-quic v0.0.0-20231207122758-cc17b154daa8
github.com/metacubex/sing-shadowsocks v0.2.5 github.com/metacubex/sing-shadowsocks v0.2.5
github.com/metacubex/sing-shadowsocks2 v0.1.4 github.com/metacubex/sing-shadowsocks2 v0.1.5-0.20231207115048-3abf19378f0d
github.com/metacubex/sing-tun v0.1.15-0.20231103033938-170591e8d5bd github.com/metacubex/sing-tun v0.1.15-0.20231207115657-1aa1d8cadd9a
github.com/metacubex/sing-vmess v0.1.9-0.20230921005247-a0488d7dac74 github.com/metacubex/sing-vmess v0.1.9-0.20231207122118-72303677451f
github.com/metacubex/sing-wireguard v0.0.0-20231001110902-321836559170 github.com/metacubex/sing-wireguard v0.0.0-20231207123053-1367f0b8f173
github.com/miekg/dns v1.1.57 github.com/miekg/dns v1.1.57
github.com/mroth/weightedrand/v2 v2.1.0 github.com/mroth/weightedrand/v2 v2.1.0
github.com/openacid/low v0.1.21 github.com/openacid/low v0.1.21
@ -34,8 +34,8 @@ require (
github.com/puzpuzpuz/xsync/v3 v3.0.2 github.com/puzpuzpuz/xsync/v3 v3.0.2
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97
github.com/sagernet/sing v0.2.18-0.20231108041402-4fbbd193203c github.com/sagernet/sing v0.2.19-0.20231207034108-445cd4f41e3f
github.com/sagernet/sing-mux v0.1.5-0.20231109075101-6b086ed6bb07 github.com/sagernet/sing-mux v0.1.6-0.20231207143704-9f6c20fb5266
github.com/sagernet/sing-shadowtls v0.1.4 github.com/sagernet/sing-shadowtls v0.1.4
github.com/sagernet/tfo-go v0.0.0-20230816093905-5a5c285d44a6 github.com/sagernet/tfo-go v0.0.0-20230816093905-5a5c285d44a6
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2 github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2
@ -49,7 +49,7 @@ require (
go.uber.org/automaxprocs v1.5.3 go.uber.org/automaxprocs v1.5.3
golang.org/x/crypto v0.16.0 golang.org/x/crypto v0.16.0
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa
golang.org/x/net v0.18.0 golang.org/x/net v0.19.0
golang.org/x/sync v0.5.0 golang.org/x/sync v0.5.0
golang.org/x/sys v0.15.0 golang.org/x/sys v0.15.0
google.golang.org/protobuf v1.31.0 google.golang.org/protobuf v1.31.0
@ -105,11 +105,11 @@ require (
github.com/yusufpapurcu/wmi v1.2.3 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect
gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec // indirect gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec // indirect
go.uber.org/mock v0.3.0 // indirect go.uber.org/mock v0.3.0 // indirect
go4.org/netipx v0.0.0-20230824141953-6213f710f925 // indirect go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
golang.org/x/mod v0.14.0 // indirect golang.org/x/mod v0.14.0 // indirect
golang.org/x/text v0.14.0 // indirect golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.3.0 // indirect golang.org/x/time v0.4.0 // indirect
golang.org/x/tools v0.15.0 // indirect golang.org/x/tools v0.15.0 // indirect
) )
replace github.com/sagernet/sing => github.com/metacubex/sing v0.0.0-20231118023733-957d84f17d2c replace github.com/sagernet/sing => github.com/metacubex/sing v0.0.0-20231207144554-52b6f9095d02

41
go.sum
View file

@ -107,20 +107,20 @@ github.com/metacubex/gvisor v0.0.0-20231206145044-b6960a648d8b h1:xJHepHYyQ7NOpU
github.com/metacubex/gvisor v0.0.0-20231206145044-b6960a648d8b/go.mod h1:rhBU9tD5ktoGPBtXUquhWuGJ4u+8ZZzBMi2cAdv9q8Y= github.com/metacubex/gvisor v0.0.0-20231206145044-b6960a648d8b/go.mod h1:rhBU9tD5ktoGPBtXUquhWuGJ4u+8ZZzBMi2cAdv9q8Y=
github.com/metacubex/quic-go v0.40.1-0.20231130135418-0c1b47cf9394 h1:dIT+KB2hknBCrwVAXPeY9tpzzkOZP5m40yqUteRT6/Y= github.com/metacubex/quic-go v0.40.1-0.20231130135418-0c1b47cf9394 h1:dIT+KB2hknBCrwVAXPeY9tpzzkOZP5m40yqUteRT6/Y=
github.com/metacubex/quic-go v0.40.1-0.20231130135418-0c1b47cf9394/go.mod h1:F/t8VnA47xoia8ABlNA4InkZjssvFJ5p6E6jKdbkgAs= github.com/metacubex/quic-go v0.40.1-0.20231130135418-0c1b47cf9394/go.mod h1:F/t8VnA47xoia8ABlNA4InkZjssvFJ5p6E6jKdbkgAs=
github.com/metacubex/sing v0.0.0-20231118023733-957d84f17d2c h1:SZwaf42NVCIDaHw5X2HOnNcEiK9ao6yO+N4zYyKfXe8= github.com/metacubex/sing v0.0.0-20231207144554-52b6f9095d02 h1:gB2vNdDTaOfko9z9WJXQkNn+rbdSEMTM7s61V4TaKhI=
github.com/metacubex/sing v0.0.0-20231118023733-957d84f17d2c/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo= github.com/metacubex/sing v0.0.0-20231207144554-52b6f9095d02/go.mod h1:Ce5LNojQOgOiWhiD8pPD6E9H7e2KgtOe3Zxx4Ou5u80=
github.com/metacubex/sing-quic v0.0.0-20231130141855-0022295e524b h1:7XXoEePvxfkQN9b2wB8UXU3uzb9uL8syEFF7A9VAKKQ= github.com/metacubex/sing-quic v0.0.0-20231207122758-cc17b154daa8 h1:gmZb7M2Z4y6BQSWljJORGVGZlKaYWEpoIJlVMg9naEY=
github.com/metacubex/sing-quic v0.0.0-20231130141855-0022295e524b/go.mod h1:Gu5/zqZDd5G1AUtoV2yjAPWOEy7zwbU2DBUjdxJh0Kw= github.com/metacubex/sing-quic v0.0.0-20231207122758-cc17b154daa8/go.mod h1:E1e1Uu6YaJddD+c0DtJlSOkfMI0NLdOVhM60KAlcssY=
github.com/metacubex/sing-shadowsocks v0.2.5 h1:O2RRSHlKGEpAVG/OHJQxyHqDy8uvvdCW/oW2TDBOIhc= github.com/metacubex/sing-shadowsocks v0.2.5 h1:O2RRSHlKGEpAVG/OHJQxyHqDy8uvvdCW/oW2TDBOIhc=
github.com/metacubex/sing-shadowsocks v0.2.5/go.mod h1:Xz2uW9BEYGEoA8B4XEpoxt7ERHClFCwsMAvWaruoyMo= github.com/metacubex/sing-shadowsocks v0.2.5/go.mod h1:Xz2uW9BEYGEoA8B4XEpoxt7ERHClFCwsMAvWaruoyMo=
github.com/metacubex/sing-shadowsocks2 v0.1.4 h1:OOCf8lgsVcpTOJUeaFAMzyKVebaQOBnKirDdUdBoKIE= github.com/metacubex/sing-shadowsocks2 v0.1.5-0.20231207115048-3abf19378f0d h1:hMs2isnO6198XaBwqbPff5bYt3uz1498osDC0sVe/dA=
github.com/metacubex/sing-shadowsocks2 v0.1.4/go.mod h1:Qz028sLfdY3qxGRm9FDI+IM2Ae3ty2wR7HIzD/56h/k= github.com/metacubex/sing-shadowsocks2 v0.1.5-0.20231207115048-3abf19378f0d/go.mod h1:Y7Dm/rJpieN2xkU/pnxJCQxqmFptUCYiGd8oJhiHd0w=
github.com/metacubex/sing-tun v0.1.15-0.20231103033938-170591e8d5bd h1:k0+92eARqyTAovGhg2AxdsMWHjUsdiGCnR5NuXF3CQY= github.com/metacubex/sing-tun v0.1.15-0.20231207115657-1aa1d8cadd9a h1:uVDQ9vdp9MXzaX0GUf5sTqCYkf3P3v+vNcddR84F7F4=
github.com/metacubex/sing-tun v0.1.15-0.20231103033938-170591e8d5bd/go.mod h1:Q7zmpJ+qOvMMXyUoYlxGQuWkqALUpXzFSSqO+KLPyzA= github.com/metacubex/sing-tun v0.1.15-0.20231207115657-1aa1d8cadd9a/go.mod h1:c/FrkpUp2emectVh3getHn5BxvvaEiNuEVrBdonw8U8=
github.com/metacubex/sing-vmess v0.1.9-0.20230921005247-a0488d7dac74 h1:FtupiyFkaVjFvRa7B/uDtRWg5BNsoyPC9MTev3sDasY= github.com/metacubex/sing-vmess v0.1.9-0.20231207122118-72303677451f h1:QjXrHKbTMBip/C+R79bvbfr42xH1gZl3uFb0RELdZiQ=
github.com/metacubex/sing-vmess v0.1.9-0.20230921005247-a0488d7dac74/go.mod h1:8EWBZpc+qNvf5gmvjAtMHK1/DpcWqzfcBL842K00BsM= github.com/metacubex/sing-vmess v0.1.9-0.20231207122118-72303677451f/go.mod h1:olVkD4FChQ5gKMHG4ZzuD7+fMkJY1G8vwOKpRehjrmY=
github.com/metacubex/sing-wireguard v0.0.0-20231001110902-321836559170 h1:DBGA0hmrP4pVIwLiXUONdphjcppED+plmVaKf1oqkwk= github.com/metacubex/sing-wireguard v0.0.0-20231207123053-1367f0b8f173 h1:q5wu7tynMlhGPsRXgZ2+a16vDo6uOe9cwz483n7MRwM=
github.com/metacubex/sing-wireguard v0.0.0-20231001110902-321836559170/go.mod h1:/VbJfbdLnANE+SKXyMk/96sTRrD4GdFLh5mkegqqFcY= github.com/metacubex/sing-wireguard v0.0.0-20231207123053-1367f0b8f173/go.mod h1:swI5NYmpSOavsMyKnxSLikD9CvnCUcpjzwLdaWPNS9g=
github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM= github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM=
github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk= github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk=
github.com/mroth/weightedrand/v2 v2.1.0 h1:o1ascnB1CIVzsqlfArQQjeMy1U0NcIbBO5rfd5E/OeU= github.com/mroth/weightedrand/v2 v2.1.0 h1:o1ascnB1CIVzsqlfArQQjeMy1U0NcIbBO5rfd5E/OeU=
@ -158,8 +158,8 @@ github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 h1:5+m7c
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61/go.mod h1:QUQ4RRHD6hGGHdFMEtR8T2P6GS6R3D/CXKdaYHKKXms= github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61/go.mod h1:QUQ4RRHD6hGGHdFMEtR8T2P6GS6R3D/CXKdaYHKKXms=
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE= github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE=
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM= github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
github.com/sagernet/sing-mux v0.1.5-0.20231109075101-6b086ed6bb07 h1:ncKb5tVOsCQgCsv6UpsA0jinbNb5OQ5GMPJlyQP3EHM= github.com/sagernet/sing-mux v0.1.6-0.20231207143704-9f6c20fb5266 h1:QqwwUyEfmOuoGVTZ2cYvUJEeSWlzunvQLRmv+9B41uk=
github.com/sagernet/sing-mux v0.1.5-0.20231109075101-6b086ed6bb07/go.mod h1:u/MZf32xPG8jEKe3t+xUV67EBnKtDtCaPhsJQOQGUYU= github.com/sagernet/sing-mux v0.1.6-0.20231207143704-9f6c20fb5266/go.mod h1:uxpcXa8JqSR+ufC1sGAPsCs027wpE7v1ltnhuJKqyBQ=
github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k= github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k=
github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4= github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4=
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as= github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as=
@ -221,8 +221,8 @@ go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8=
go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0= go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0=
go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo=
go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
go4.org/netipx v0.0.0-20230824141953-6213f710f925 h1:eeQDDVKFkx0g4Hyy8pHgmZaK0EqB4SD6rvKbUdN3ziQ= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
go4.org/netipx v0.0.0-20230824141953-6213f710f925/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
@ -235,8 +235,8 @@ golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
@ -256,14 +256,13 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.4.0 h1:Z81tqI5ddIoXDPvVQ7/7CC9TnLM7ubaFG2qXYd5BbYY=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.4.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8= golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8=
golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk= golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk=

View file

@ -138,41 +138,36 @@ func (h *ListenerHandler) NewConnection(ctx context.Context, conn net.Conn, meta
} }
func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network.PacketConn, metadata M.Metadata) error { func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network.PacketConn, metadata M.Metadata) error {
if deadline.NeedAdditionalReadDeadline(conn) {
conn = deadline.NewFallbackPacketConn(bufio.NewNetPacketConn(conn)) // conn from sing should check NeedAdditionalReadDeadline
}
defer func() { _ = conn.Close() }() defer func() { _ = conn.Close() }()
mutex := sync.Mutex{} mutex := sync.Mutex{}
conn2 := conn // a new interface to set nil in defer conn2 := bufio.NewNetPacketConn(conn) // a new interface to set nil in defer
defer func() { defer func() {
mutex.Lock() // this goroutine must exit after all conn.WritePacket() is not running mutex.Lock() // this goroutine must exit after all conn.WritePacket() is not running
defer mutex.Unlock() defer mutex.Unlock()
conn2 = nil conn2 = nil
}() }()
var buff *buf.Buffer rwOptions := network.ReadWaitOptions{}
newBuffer := func() *buf.Buffer {
buff = buf.NewPacket() // do not use stack buffer
return buff
}
readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(conn) readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(conn)
if isReadWaiter { if isReadWaiter {
readWaiter.InitializeReadWaiter(newBuffer) readWaiter.InitializeReadWaiter(rwOptions)
} }
for { for {
var ( var (
buff *buf.Buffer
dest M.Socksaddr dest M.Socksaddr
err error err error
) )
buff = nil // clear last loop status, avoid repeat release
if isReadWaiter { if isReadWaiter {
dest, err = readWaiter.WaitReadPacket() buff, dest, err = readWaiter.WaitReadPacket()
} else { } else {
dest, err = conn.ReadPacket(newBuffer()) buff = rwOptions.NewPacketBuffer()
dest, err = conn.ReadPacket(buff)
if buff != nil {
rwOptions.PostReturn(buff)
}
} }
if err != nil { if err != nil {
if buff != nil {
buff.Release() buff.Release()
}
if ShouldIgnorePacketError(err) { if ShouldIgnorePacketError(err) {
break break
} }
@ -212,7 +207,7 @@ func ShouldIgnorePacketError(err error) bool {
} }
type packet struct { type packet struct {
conn *network.PacketConn conn *network.NetPacketConn
mutex *sync.Mutex mutex *sync.Mutex
rAddr net.Addr rAddr net.Addr
lAddr net.Addr lAddr net.Addr
@ -238,18 +233,7 @@ func (c *packet) WriteBack(b []byte, addr net.Addr) (n int, err error) {
return return
} }
buff := buf.NewPacket() return conn.WriteTo(b, addr)
defer buff.Release()
n, err = buff.Write(b)
if err != nil {
return
}
err = conn.WritePacket(buff, M.SocksaddrFromNet(addr))
if err != nil {
return
}
return
} }
// LocalAddr returns the source IP/Port of UDP Packet // LocalAddr returns the source IP/Port of UDP Packet

View file

@ -23,6 +23,7 @@ import (
"github.com/sagernet/sing/common/buf" "github.com/sagernet/sing/common/buf"
"github.com/sagernet/sing/common/bufio" "github.com/sagernet/sing/common/bufio"
M "github.com/sagernet/sing/common/metadata" M "github.com/sagernet/sing/common/metadata"
"github.com/sagernet/sing/common/network"
) )
type Listener struct { type Listener struct {
@ -96,30 +97,33 @@ func New(config LC.ShadowsocksServer, tunnel C.Tunnel, additions ...inbound.Addi
go func() { go func() {
conn := bufio.NewPacketConn(ul) conn := bufio.NewPacketConn(ul)
var buff *buf.Buffer rwOptions := network.ReadWaitOptions{
newBuffer := func() *buf.Buffer { FrontHeadroom: network.CalculateFrontHeadroom(sl.service),
buff = buf.NewPacket() // do not use stack buffer RearHeadroom: network.CalculateRearHeadroom(sl.service),
return buff MTU: network.CalculateMTU(conn, sl.service),
} }
readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(conn) readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(conn)
if isReadWaiter { if isReadWaiter {
readWaiter.InitializeReadWaiter(newBuffer) readWaiter.InitializeReadWaiter(rwOptions)
} }
for { for {
var ( var (
buff *buf.Buffer
dest M.Socksaddr dest M.Socksaddr
err error err error
) )
buff = nil // clear last loop status, avoid repeat release buff = nil // clear last loop status, avoid repeat release
if isReadWaiter { if isReadWaiter {
dest, err = readWaiter.WaitReadPacket() buff, dest, err = readWaiter.WaitReadPacket()
} else { } else {
dest, err = conn.ReadPacket(newBuffer()) buff = rwOptions.NewPacketBuffer()
dest, err = conn.ReadPacket(buff)
if buff != nil {
rwOptions.PostReturn(buff)
}
} }
if err != nil { if err != nil {
if buff != nil {
buff.Release() buff.Release()
}
if sl.closed { if sl.closed {
break break
} }

View file

@ -109,29 +109,29 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network.
defer mutex.Unlock() defer mutex.Unlock()
conn2 = nil conn2 = nil
}() }()
rwOptions := network.ReadWaitOptions{
var buff *buf.Buffer MTU: 2 * 1024, // safe size which is 1232 from https://dnsflagday.net/2020/, so 2048 is enough
newBuffer := func() *buf.Buffer {
// safe size which is 1232 from https://dnsflagday.net/2020/.
// so 2048 is enough
buff = buf.NewSize(2 * 1024)
return buff
} }
readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(conn) readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(conn)
if isReadWaiter { if isReadWaiter {
readWaiter.InitializeReadWaiter(newBuffer) readWaiter.InitializeReadWaiter(rwOptions)
} }
for { for {
var ( var (
buff *buf.Buffer
dest M.Socksaddr dest M.Socksaddr
err error err error
) )
_ = conn.SetReadDeadline(time.Now().Add(DefaultDnsReadTimeout)) _ = conn.SetReadDeadline(time.Now().Add(DefaultDnsReadTimeout))
buff = nil // clear last loop status, avoid repeat release buff = nil // clear last loop status, avoid repeat release
if isReadWaiter { if isReadWaiter {
dest, err = readWaiter.WaitReadPacket() buff, dest, err = readWaiter.WaitReadPacket()
} else { } else {
dest, err = conn.ReadPacket(newBuffer()) buff = rwOptions.NewPacketBuffer()
dest, err = conn.ReadPacket(buff)
if buff != nil {
rwOptions.PostReturn(buff)
}
} }
if err != nil { if err != nil {
if buff != nil { if buff != nil {
@ -142,7 +142,7 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network.
} }
return err return err
} }
go func(buff *buf.Buffer) { go func() {
ctx, cancel := context.WithTimeout(ctx, DefaultDnsRelayTimeout) ctx, cancel := context.WithTimeout(ctx, DefaultDnsRelayTimeout)
defer cancel() defer cancel()
inData := buff.Bytes() inData := buff.Bytes()
@ -167,7 +167,7 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network.
if err != nil { if err != nil {
return return
} }
}(buff) // catch buff at goroutine create, avoid next loop change buff }()
} }
return nil return nil
} }

View file

@ -157,14 +157,7 @@ func (vc *Conn) ReadBuffer(buffer *buf.Buffer) error {
func (vc *Conn) Write(p []byte) (int, error) { func (vc *Conn) Write(p []byte) (int, error) {
if vc.writeFilterApplicationData { if vc.writeFilterApplicationData {
buffer := buf.New() return N.WriteBuffer(vc, buf.As(p))
defer buffer.Release()
buffer.Write(p)
err := vc.WriteBuffer(buffer)
if err != nil {
return 0, err
}
return len(p), nil
} }
return vc.ExtendedWriter.Write(p) return vc.ExtendedWriter.Write(p)
} }
@ -266,6 +259,10 @@ func (vc *Conn) FrontHeadroom() int {
return PaddingHeaderLen - uuid.Size return PaddingHeaderLen - uuid.Size
} }
func (vc *Conn) RearHeadroom() int {
return 500 + 900
}
func (vc *Conn) NeedHandshake() bool { func (vc *Conn) NeedHandshake() bool {
return vc.needHandshake return vc.needHandshake
} }

View file

@ -375,7 +375,6 @@ func handleUDPConn(packet C.PacketAdapter) {
cond.Broadcast() cond.Broadcast()
}() }()
pCtx := icontext.NewPacketConnContext(metadata)
proxy, rule, err := resolveMetadata(metadata) proxy, rule, err := resolveMetadata(metadata)
if err != nil { if err != nil {
log.Warnln("[UDP] Parse metadata failed: %s", err.Error()) log.Warnln("[UDP] Parse metadata failed: %s", err.Error())
@ -402,7 +401,6 @@ func handleUDPConn(packet C.PacketAdapter) {
if err != nil { if err != nil {
return return
} }
pCtx.InjectPacketConn(rawPc)
pc := statistic.NewUDPTracker(rawPc, statistic.DefaultManager, metadata, rule, 0, 0, true) pc := statistic.NewUDPTracker(rawPc, statistic.DefaultManager, metadata, rule, 0, 0, true)