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

@@ -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 {
if deadline.NeedAdditionalReadDeadline(conn) {
conn = deadline.NewFallbackPacketConn(bufio.NewNetPacketConn(conn)) // conn from sing should check NeedAdditionalReadDeadline
}
defer func() { _ = conn.Close() }()
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() {
mutex.Lock() // this goroutine must exit after all conn.WritePacket() is not running
defer mutex.Unlock()
conn2 = nil
}()
var buff *buf.Buffer
newBuffer := func() *buf.Buffer {
buff = buf.NewPacket() // do not use stack buffer
return buff
}
rwOptions := network.ReadWaitOptions{}
readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(conn)
if isReadWaiter {
readWaiter.InitializeReadWaiter(newBuffer)
readWaiter.InitializeReadWaiter(rwOptions)
}
for {
var (
buff *buf.Buffer
dest M.Socksaddr
err error
)
buff = nil // clear last loop status, avoid repeat release
if isReadWaiter {
dest, err = readWaiter.WaitReadPacket()
buff, dest, err = readWaiter.WaitReadPacket()
} else {
dest, err = conn.ReadPacket(newBuffer())
buff = rwOptions.NewPacketBuffer()
dest, err = conn.ReadPacket(buff)
if buff != nil {
rwOptions.PostReturn(buff)
}
}
if err != nil {
if buff != nil {
buff.Release()
}
buff.Release()
if ShouldIgnorePacketError(err) {
break
}
@@ -212,7 +207,7 @@ func ShouldIgnorePacketError(err error) bool {
}
type packet struct {
conn *network.PacketConn
conn *network.NetPacketConn
mutex *sync.Mutex
rAddr net.Addr
lAddr net.Addr
@@ -238,18 +233,7 @@ func (c *packet) WriteBack(b []byte, addr net.Addr) (n int, err error) {
return
}
buff := buf.NewPacket()
defer buff.Release()
n, err = buff.Write(b)
if err != nil {
return
}
err = conn.WritePacket(buff, M.SocksaddrFromNet(addr))
if err != nil {
return
}
return
return conn.WriteTo(b, addr)
}
// 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/bufio"
M "github.com/sagernet/sing/common/metadata"
"github.com/sagernet/sing/common/network"
)
type Listener struct {
@@ -96,30 +97,33 @@ func New(config LC.ShadowsocksServer, tunnel C.Tunnel, additions ...inbound.Addi
go func() {
conn := bufio.NewPacketConn(ul)
var buff *buf.Buffer
newBuffer := func() *buf.Buffer {
buff = buf.NewPacket() // do not use stack buffer
return buff
rwOptions := network.ReadWaitOptions{
FrontHeadroom: network.CalculateFrontHeadroom(sl.service),
RearHeadroom: network.CalculateRearHeadroom(sl.service),
MTU: network.CalculateMTU(conn, sl.service),
}
readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(conn)
if isReadWaiter {
readWaiter.InitializeReadWaiter(newBuffer)
readWaiter.InitializeReadWaiter(rwOptions)
}
for {
var (
buff *buf.Buffer
dest M.Socksaddr
err error
)
buff = nil // clear last loop status, avoid repeat release
if isReadWaiter {
dest, err = readWaiter.WaitReadPacket()
buff, dest, err = readWaiter.WaitReadPacket()
} else {
dest, err = conn.ReadPacket(newBuffer())
buff = rwOptions.NewPacketBuffer()
dest, err = conn.ReadPacket(buff)
if buff != nil {
rwOptions.PostReturn(buff)
}
}
if err != nil {
if buff != nil {
buff.Release()
}
buff.Release()
if sl.closed {
break
}

View File

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