From 91dd03a9e5fd08efe75e34188f0f4f8deb643ebb Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Tue, 22 Sep 2026 17:07:49 +0800 Subject: [PATCH] chore: support lazy receive buffer reads for mipstack and gvisor --- adapter/outbound/base.go | 21 +++++++++-- common/net/packet/packet.go | 3 ++ common/net/packet/packet_with_buffer.go | 48 +++++++++++++++++++++++++ go.mod | 10 +++--- go.sum | 20 +++++------ 5 files changed, 85 insertions(+), 17 deletions(-) create mode 100644 common/net/packet/packet_with_buffer.go diff --git a/adapter/outbound/base.go b/adapter/outbound/base.go index 01e00798..d6942ba0 100644 --- a/adapter/outbound/base.go +++ b/adapter/outbound/base.go @@ -274,8 +274,20 @@ func (c *conn) AddRef(ref any) { c.ExtendedConn = N.NewRefConn(c.ExtendedConn, ref) // add ref for autoCloseProxyAdapter } +// ipstackConn is a common experimental API interface implemented by: +// *mipstack.TCPConn, *mipstack.UDPConn, *mipstack.IPConn +// it's also implemented by our gVisor fork +type ipstackConn interface { + ReadWithBuffer(getBuffer func(sizeHint int) []byte) (int, error) +} + func NewConn(c net.Conn, a C.ProxyAdapter) C.Conn { - if _, ok := c.(syscall.Conn); !ok { // exclusion system conn like *net.TCPConn + switch c.(type) { + case syscall.Conn: // exclusion system conn like *net.TCPConn + break + case ipstackConn: // exclusion *mipstack.TCPConn + break + default: c = N.NewDeadlineConn(c) // most conn from outbound can't handle readDeadline correctly } cc := &conn{N.NewExtendedConn(c), nil, nil, a.Addr()} @@ -341,7 +353,12 @@ func (c *packetConn) AddRef(ref any) { func NewPacketConn(pc net.PacketConn, a ProxyAdapter) C.PacketConn { epc := N.NewEnhancePacketConn(pc) - if _, ok := pc.(syscall.Conn); !ok { // exclusion system conn like *net.UDPConn + switch pc.(type) { + case syscall.Conn: // exclusion system conn like *net.UDPConn + break + case ipstackConn: // exclusion *mipstack.UDPConn + break + default: epc = N.NewDeadlineEnhancePacketConn(epc) // most conn from outbound can't handle readDeadline correctly } cpc := &packetConn{epc, nil, nil, a.Name(), utils.NewUUIDV4().String(), a.Addr(), a.ResolveUDP} diff --git a/common/net/packet/packet.go b/common/net/packet/packet.go index 0cdbccae..1ab17d71 100644 --- a/common/net/packet/packet.go +++ b/common/net/packet/packet.go @@ -25,6 +25,9 @@ func NewEnhancePacketConn(pc net.PacketConn) EnhancePacketConn { if singPC, isSingPC := pc.(SingPacketConn); isSingPC { return newEnhanceSingPacketConn(singPC) } + if withBufferPC, isWithBufferPC := pc.(withBufferPacketConn); isWithBufferPC { + return &enhanceWithBufferPacketConn{withBufferPacketConn: withBufferPC} + } return &enhancePacketConn{PacketConn: pc} } diff --git a/common/net/packet/packet_with_buffer.go b/common/net/packet/packet_with_buffer.go new file mode 100644 index 00000000..b3442702 --- /dev/null +++ b/common/net/packet/packet_with_buffer.go @@ -0,0 +1,48 @@ +package packet + +import ( + "net" + + "github.com/metacubex/mihomo/common/pool" +) + +type withBufferPacketConn interface { + net.PacketConn + ReadFromWithBuffer(func(sizeHint int) []byte) (int, net.Addr, error) +} + +type enhanceWithBufferPacketConn struct { + withBufferPacketConn +} + +func (c *enhanceWithBufferPacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) { + var readBuf []byte + getBuffer := func(sizeHint int) []byte { + readBuf = pool.Get(sizeHint) + put = func() { + _ = pool.Put(readBuf) + } + return readBuf + } + var readN int + readN, addr, err = c.ReadFromWithBuffer(getBuffer) + if readN > 0 && readBuf != nil { + data = readBuf[:readN] + } else if put != nil { + put() + put = nil + } + return +} + +func (c *enhanceWithBufferPacketConn) Upstream() any { + return c.withBufferPacketConn +} + +func (c *enhanceWithBufferPacketConn) WriterReplaceable() bool { + return true +} + +func (c *enhanceWithBufferPacketConn) ReaderReplaceable() bool { + return true +} diff --git a/go.mod b/go.mod index 9e95db18..0e5acd0f 100644 --- a/go.mod +++ b/go.mod @@ -28,18 +28,18 @@ require ( github.com/metacubex/jls-tls v0.0.0-20260723084315-67adc0e2f796 github.com/metacubex/kcp-go v0.0.0-20260105040817-550693377604 github.com/metacubex/mhurl v0.1.0 - github.com/metacubex/mipstack v0.0.0-20260910230046-ba762df4c91d + github.com/metacubex/mipstack v0.0.0-20260922000335-dbef50b1df45 github.com/metacubex/mlkem v0.1.0 github.com/metacubex/quic-go v0.61.1-0.20260727080200-2548683b76f4 github.com/metacubex/randv2 v0.2.0 github.com/metacubex/restls-client-go v0.1.9 github.com/metacubex/sevenzip v1.6.4 - github.com/metacubex/sing v0.5.7 + github.com/metacubex/sing v0.5.8 github.com/metacubex/sing-mux v0.3.10 github.com/metacubex/sing-quic v0.0.0-20260904234848-1c242664697a github.com/metacubex/sing-shadowsocks v0.2.13 github.com/metacubex/sing-shadowsocks2 v0.2.8 - github.com/metacubex/sing-tun v0.4.24 + github.com/metacubex/sing-tun v0.4.25 github.com/metacubex/sing-vmess v0.2.5 github.com/metacubex/sing-wireguard v0.0.0-20260826105301-c3ae17d19f9e github.com/metacubex/smux v0.0.0-20260105030934-d0c8756d3141 @@ -61,7 +61,7 @@ require ( gitlab.com/go-extension/aes-ccm v0.0.0-20230221065045-e58665ef23c7 go.uber.org/automaxprocs v1.6.0 go.yaml.in/yaml/v3 v3.0.5 - go4.org/netipx v0.0.0-20231129151722-fdeea329fbba + go4.org/netipx v0.0.0-20260823151212-3075585bcbeb ) // lastest version compatible with golang1.20 @@ -110,7 +110,7 @@ require ( github.com/klauspost/reedsolomon v1.12.3 // indirect github.com/mdlayher/socket v0.5.1 // indirect github.com/metacubex/ascon v0.1.0 // indirect - github.com/metacubex/gvisor v0.0.0-20260826100401-79317d808312 // indirect + github.com/metacubex/gvisor v0.0.0-20260922041103-e2cbcd6e7400 // indirect github.com/metacubex/hkdf v0.1.0 // indirect github.com/metacubex/hpke v0.1.0 // indirect github.com/metacubex/jsonv2 v0.0.0-20260721082349-16b4998c8f89 // indirect diff --git a/go.sum b/go.sum index 9c29187c..8ed892aa 100644 --- a/go.sum +++ b/go.sum @@ -117,8 +117,8 @@ github.com/metacubex/fswatch v0.1.1 h1:jqU7C/v+g0qc2RUFgmAOPoVvfl2BXXUXEumn6oQux github.com/metacubex/fswatch v0.1.1/go.mod h1:czrTT7Zlbz7vWft8RQu9Qqh+JoX+Nnb+UabuyN1YsgI= github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 h1:cjd4biTvOzK9ubNCCkQ+ldc4YSH/rILn53l/xGBFHHI= github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759/go.mod h1:UHOv2xu+RIgLwpXca7TLrXleEd4oR3sPatW6IF8wU88= -github.com/metacubex/gvisor v0.0.0-20260826100401-79317d808312 h1:GDSN5oSkugLGImDSM0W4UCovF5FLpTa6vL1g2f2+1do= -github.com/metacubex/gvisor v0.0.0-20260826100401-79317d808312/go.mod h1:mBJW3UXUusd8ZYO5M6mig0uScIey9iIubgdIiQAk2ug= +github.com/metacubex/gvisor v0.0.0-20260922041103-e2cbcd6e7400 h1:r9YO+xZUWi+xQROzdYkKL2twoliSJh34vOHMVAqsaL8= +github.com/metacubex/gvisor v0.0.0-20260922041103-e2cbcd6e7400/go.mod h1:mBJW3UXUusd8ZYO5M6mig0uScIey9iIubgdIiQAk2ug= github.com/metacubex/hkdf v0.1.0 h1:fPA6VzXK8cU1foc/TOmGCDmSa7pZbxlnqhl3RNsthaA= github.com/metacubex/hkdf v0.1.0/go.mod h1:3seEfds3smgTAXqUGn+tgEJH3uXdsUjOiduG/2EtvZ4= github.com/metacubex/hpke v0.1.0 h1:gu2jUNhraehWi0P/z5HX2md3d7L1FhPQE6/Q0E9r9xQ= @@ -135,8 +135,8 @@ github.com/metacubex/kcp-go v0.0.0-20260105040817-550693377604 h1:hJwCVlE3ojViC3 github.com/metacubex/kcp-go v0.0.0-20260105040817-550693377604/go.mod h1:lpmN3m269b3V5jFCWtffqBLS4U3QQoIid9ugtO+OhVc= github.com/metacubex/mhurl v0.1.0 h1:ZdW4Zxe3j3uJ89gNytOazHu6kbHn5owutN/VfXOI8GE= github.com/metacubex/mhurl v0.1.0/go.mod h1:2qpQImCbXoUs6GwJrjuEXKelPyoimsIXr07eNKZdS00= -github.com/metacubex/mipstack v0.0.0-20260910230046-ba762df4c91d h1:hc1OeKdo7YIcmTrzwlJLjNZ4EZDKRHi/Ntv7GdYs2YI= -github.com/metacubex/mipstack v0.0.0-20260910230046-ba762df4c91d/go.mod h1:+bbwALZI0pbi2auSG5A3ptdpV2DZ2eLObziXo+P7oj0= +github.com/metacubex/mipstack v0.0.0-20260922000335-dbef50b1df45 h1:q+JWw5cv5hsppSVIq0/+TPwnLem9Zc8zqqzYduJJ4yU= +github.com/metacubex/mipstack v0.0.0-20260922000335-dbef50b1df45/go.mod h1:+bbwALZI0pbi2auSG5A3ptdpV2DZ2eLObziXo+P7oj0= github.com/metacubex/mlkem v0.1.0 h1:wFClitonSFcmipzzQvax75beLQU+D7JuC+VK1RzSL8I= github.com/metacubex/mlkem v0.1.0/go.mod h1:amhaXZVeYNShuy9BILcR7P0gbeo/QLZsnqCdL8U2PDQ= github.com/metacubex/nftables v0.0.0-20260426003805-208c2c1ba2cb h1:wk6mHYPURSUvWcUv72gNP79oiylFsscBSDPJ6ieV6Iw= @@ -153,8 +153,8 @@ github.com/metacubex/restls-client-go v0.1.9 h1:QmLKwVFuAjB6rL9lQNKj8CuwHqGMJjV3 github.com/metacubex/restls-client-go v0.1.9/go.mod h1:BN/U52vPw7j8VTSh2vleD/MnmVKCov84mS5VcjVHH4g= github.com/metacubex/sevenzip v1.6.4 h1:OIL+DeOeSAbKNsjqxcYUMiarRmX6Kaxakb0GT7E9Oik= github.com/metacubex/sevenzip v1.6.4/go.mod h1:FP3X9bzFKj9wPxifGN9B3w2fIEicMjzKYIGIhnu+1pw= -github.com/metacubex/sing v0.5.7 h1:8OC+fhKFSv/l9ehEhJRaZZAOuthfZo68SteBVLe8QqM= -github.com/metacubex/sing v0.5.7/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w= +github.com/metacubex/sing v0.5.8 h1:OwJDSPP+pza6Ywt7NMR4kEYq+UNrsIywSk/eAMlqxz8= +github.com/metacubex/sing v0.5.8/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w= github.com/metacubex/sing-mux v0.3.10 h1:r5CuZ/KuwFsEcRRwpLvzLncW4fDzNfmSEcBEWcy/+94= github.com/metacubex/sing-mux v0.3.10/go.mod h1:8bT7ZKT3clRrJjYc/x5CRYibC1TX/bK73a3r3+2E+Fc= github.com/metacubex/sing-quic v0.0.0-20260904234848-1c242664697a h1:qZzQwtWDrPU1LXoMow0/iLHY3mb7uauS/mho8hYcenE= @@ -163,8 +163,8 @@ github.com/metacubex/sing-shadowsocks v0.2.13 h1:PKmInHy9+4nY3FLhmKcWdASUBo9WZ/K github.com/metacubex/sing-shadowsocks v0.2.13/go.mod h1:2e5EIaw0rxKrm1YTRmiMnDulwbGxH9hAFlrwQLQMQkU= github.com/metacubex/sing-shadowsocks2 v0.2.8 h1:6MoODu7BAcnwIC0w9muq+2LZVz01wWD07L5IRhOty9Q= github.com/metacubex/sing-shadowsocks2 v0.2.8/go.mod h1:vOEbfKC60txi0ca+yUlqEwOGc3Obl6cnSgx9Gf45KjE= -github.com/metacubex/sing-tun v0.4.24 h1:2H/RhlwQxUgc1K8h46giwV5uTUovx+DhQGpVPlUB4Yo= -github.com/metacubex/sing-tun v0.4.24/go.mod h1:YLk0jq8ITecb0LlNKAXC+NTkYTYmvihQxFAR495LN8c= +github.com/metacubex/sing-tun v0.4.25 h1:/dYsAE9EYex20WLWYy+llEJHQLUa4KliqGXZCmvRN7Y= +github.com/metacubex/sing-tun v0.4.25/go.mod h1:+mS6xdBPSbJlujqM7MZ3JFdJ+DoLAbczAkPSFStlkkQ= github.com/metacubex/sing-vmess v0.2.5 h1:m9Zt5I27lB9fmLMZfism9sH2LcnAfShZfwSkf6/KJoE= github.com/metacubex/sing-vmess v0.2.5/go.mod h1:AwtlzUgf8COe9tRYAKqWZ+leDH7p5U98a0ZUpYehl8Q= github.com/metacubex/sing-wireguard v0.0.0-20260826105301-c3ae17d19f9e h1:KGKZt//rrELT/dEwgYcHCqNYEGr3a7uVutlZrzrZZWY= @@ -284,8 +284,8 @@ go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= go4.org/mem v0.0.0-20240501181205-ae6ca9944745 h1:Tl++JLUCe4sxGu8cTpDzRLd3tN7US4hOxG5YpKCzkek= go4.org/mem v0.0.0-20240501181205-ae6ca9944745/go.mod h1:reUoABIJ9ikfM5sgtSF3Wushcza7+WeD01VB9Lirh3g= -go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M= -go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= +go4.org/netipx v0.0.0-20260823151212-3075585bcbeb h1:XBM4hvfwGAttkkiTIFfeigdfcL1xIfdKXqFdgiHGtDs= +go4.org/netipx v0.0.0-20260823151212-3075585bcbeb/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-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=