From b6749830345bb9b6e82bf06f2099a10d05da0f53 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Fri, 12 May 2023 12:12:22 +0800 Subject: [PATCH] chore: improve read waiter interface --- go.mod | 2 +- go.sum | 4 ++-- listener/sing/sing.go | 22 +++++++++++---------- listener/sing_shadowsocks/server.go | 23 +++++++++++----------- listener/sing_tun/dns.go | 30 +++++++++++++++-------------- 5 files changed, 43 insertions(+), 38 deletions(-) diff --git a/go.mod b/go.mod index a0a19311..9b1e2dbd 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/openacid/low v0.1.21 github.com/oschwald/geoip2-golang v1.8.0 github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 - github.com/sagernet/sing v0.2.5-0.20230510160026-237a991b46d0 + github.com/sagernet/sing v0.2.5-0.20230512033628-9be7806bab51 github.com/sagernet/sing-mux v0.0.0-20230427141602-9836fc9b052e github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 diff --git a/go.sum b/go.sum index 53f730b8..d38293a3 100644 --- a/go.sum +++ b/go.sum @@ -143,8 +143,8 @@ github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6E github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM= github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY= github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk= -github.com/sagernet/sing v0.2.5-0.20230510160026-237a991b46d0 h1:NS4U+yQ4ToyRqFvCS91BM1D6fQbriW1qvioxSj5PvI4= -github.com/sagernet/sing v0.2.5-0.20230510160026-237a991b46d0/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w= +github.com/sagernet/sing v0.2.5-0.20230512033628-9be7806bab51 h1:ySJuouhl890pBZly51Hkb2mbDnz+qSQCLF5j+4IFHis= +github.com/sagernet/sing v0.2.5-0.20230512033628-9be7806bab51/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w= github.com/sagernet/sing-mux v0.0.0-20230427141602-9836fc9b052e h1:t8nuY9plpHEzlnPxOpuv64jhjz3teIvccu3YMFX4fJI= github.com/sagernet/sing-mux v0.0.0-20230427141602-9836fc9b052e/go.mod h1:pF+RnLvCAOhECrvauy6LYOpBakJ/vuaF1Wm4lPsWryI= github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b h1:ouW/6IDCrxkBe19YSbdCd7buHix7b+UZ6BM4Zz74XF4= diff --git a/listener/sing/sing.go b/listener/sing/sing.go index 2a2d8474..9bf52e9c 100644 --- a/listener/sing/sing.go +++ b/listener/sing/sing.go @@ -124,21 +124,23 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network. defer mutex.Unlock() conn2 = nil }() - connReader := network.UnwrapPacketReader(conn) // decrease runtime cost for bufio.CreatePacketReadWaiter + var buff *buf.Buffer + newBuffer := func() *buf.Buffer { + buff = buf.NewPacket() // do not use stack buffer + return buff + } + readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(conn) + if isReadWaiter { + readWaiter.InitializeReadWaiter(newBuffer) + } for { var ( - buff *buf.Buffer dest M.Socksaddr err error ) - newBuffer := func() *buf.Buffer { - buff = buf.NewPacket() // do not use stack buffer - return buff - } - // syscallPacketReadWaiter.WaitReadPacket will cache newBuffer function - // so create new PacketReadWaiter in each loop - if readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(connReader); isReadWaiter { - dest, err = readWaiter.WaitReadPacket(newBuffer) + buff = nil // clear last loop status, avoid repeat release + if isReadWaiter { + dest, err = readWaiter.WaitReadPacket() } else { dest, err = conn.ReadPacket(newBuffer()) } diff --git a/listener/sing_shadowsocks/server.go b/listener/sing_shadowsocks/server.go index b35e1238..1fa9a3ba 100644 --- a/listener/sing_shadowsocks/server.go +++ b/listener/sing_shadowsocks/server.go @@ -22,7 +22,6 @@ 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 { @@ -93,21 +92,23 @@ func New(config LC.ShadowsocksServer, tcpIn chan<- C.ConnContext, udpIn chan<- C go func() { conn := bufio.NewPacketConn(ul) - connReader := network.UnwrapPacketReader(conn) // decrease runtime cost for bufio.CreatePacketReadWaiter + var buff *buf.Buffer + newBuffer := func() *buf.Buffer { + buff = buf.NewPacket() // do not use stack buffer + return buff + } + readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(conn) + if isReadWaiter { + readWaiter.InitializeReadWaiter(newBuffer) + } for { var ( - buff *buf.Buffer dest M.Socksaddr err error ) - newBuffer := func() *buf.Buffer { - buff = buf.NewPacket() // do not use stack buffer - return buff - } - // syscallPacketReadWaiter.WaitReadPacket will cache newBuffer function - // so create new PacketReadWaiter in each loop - if readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(connReader); isReadWaiter { - dest, err = readWaiter.WaitReadPacket(newBuffer) + buff = nil // clear last loop status, avoid repeat release + if isReadWaiter { + dest, err = readWaiter.WaitReadPacket() } else { dest, err = conn.ReadPacket(newBuffer()) } diff --git a/listener/sing_tun/dns.go b/listener/sing_tun/dns.go index 5ec6d96b..88e3f6d6 100644 --- a/listener/sing_tun/dns.go +++ b/listener/sing_tun/dns.go @@ -110,24 +110,26 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network. conn2 = nil }() - connReader := network.UnwrapPacketReader(conn) // decrease runtime cost for bufio.CreatePacketReadWaiter + 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 + } + readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(conn) + if isReadWaiter { + readWaiter.InitializeReadWaiter(newBuffer) + } for { var ( - buff *buf.Buffer dest M.Socksaddr err error ) - 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 - } _ = conn.SetReadDeadline(time.Now().Add(DefaultDnsReadTimeout)) - // syscallPacketReadWaiter.WaitReadPacket will cache newBuffer function - // so create new PacketReadWaiter in each loop - if readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(connReader); isReadWaiter { - dest, err = readWaiter.WaitReadPacket(newBuffer) + buff = nil // clear last loop status, avoid repeat release + if isReadWaiter { + dest, err = readWaiter.WaitReadPacket() } else { dest, err = conn.ReadPacket(newBuffer()) } @@ -140,7 +142,7 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network. } return err } - go func() { + go func(buff *buf.Buffer) { ctx, cancel := context.WithTimeout(ctx, DefaultDnsRelayTimeout) defer cancel() inData := buff.Bytes() @@ -165,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 }