From 8822349f946143362137c0b7c4350b408ae9f274 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Thu, 21 Dec 2023 21:18:26 +0800 Subject: [PATCH] chore: support waitRead in windows --- common/net/packet/packet_windows.go | 62 ++++++++++++++++++++++++++++- go.mod | 4 +- go.sum | 4 +- 3 files changed, 65 insertions(+), 5 deletions(-) diff --git a/common/net/packet/packet_windows.go b/common/net/packet/packet_windows.go index cb4c518ba..3c467c6dc 100644 --- a/common/net/packet/packet_windows.go +++ b/common/net/packet/packet_windows.go @@ -4,12 +4,72 @@ package packet import ( "net" + "strconv" + "syscall" + + "github.com/metacubex/mihomo/common/pool" + + "golang.org/x/sys/windows" ) type enhanceUDPConn struct { *net.UDPConn + rawConn syscall.RawConn } func (c *enhanceUDPConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) { - return waitReadFrom(c.UDPConn) + if c.rawConn == nil { + c.rawConn, _ = c.UDPConn.SyscallConn() + } + var readErr error + hasData := false + err = c.rawConn.Read(func(fd uintptr) (done bool) { + if !hasData { + hasData = true + // golang's internal/poll.FD.RawRead will Use a zero-byte read as a way to get notified when this + // socket is readable if we return false. So the `recvfrom` syscall will not block the system thread. + return false + } + readBuf := pool.Get(pool.UDPBufferSize) + put = func() { + _ = pool.Put(readBuf) + } + var readFrom windows.Sockaddr + var readN int + readN, readFrom, readErr = windows.Recvfrom(windows.Handle(fd), readBuf, 0) + if readN > 0 { + data = readBuf[:readN] + } else { + put() + put = nil + data = nil + } + if readErr == windows.WSAEWOULDBLOCK { + return false + } + if readFrom != nil { + switch from := readFrom.(type) { + case *windows.SockaddrInet4: + ip := from.Addr // copy from.Addr; ip escapes, so this line allocates 4 bytes + addr = &net.UDPAddr{IP: ip[:], Port: from.Port} + case *windows.SockaddrInet6: + ip := from.Addr // copy from.Addr; ip escapes, so this line allocates 16 bytes + addr = &net.UDPAddr{IP: ip[:], Port: from.Port, Zone: strconv.FormatInt(int64(from.ZoneId), 10)} + } + } + // udp should not convert readN == 0 to io.EOF + //if readN == 0 { + // readErr = io.EOF + //} + hasData = false + return true + }) + if err != nil { + return + } + if readErr != nil { + err = readErr + return + } + return } diff --git a/go.mod b/go.mod index 054b04dcc..866ac0350 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( github.com/puzpuzpuz/xsync/v3 v3.0.2 github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 - github.com/sagernet/sing v0.3.0-beta.6 + github.com/sagernet/sing v0.3.0-rc.3 github.com/sagernet/sing-mux v0.1.6-beta.1 github.com/sagernet/sing-shadowtls v0.1.4 github.com/sagernet/tfo-go v0.0.0-20231209031829-7b5343ac1dc6 @@ -112,4 +112,4 @@ require ( golang.org/x/tools v0.16.0 // indirect ) -replace github.com/sagernet/sing => github.com/metacubex/sing v0.0.0-20231218144940-fc8dd41d68e8 +replace github.com/sagernet/sing => github.com/metacubex/sing v0.0.0-20231221131356-d73c21c7ea3f diff --git a/go.sum b/go.sum index 0637fff6d..3f80c92de 100644 --- a/go.sum +++ b/go.sum @@ -110,8 +110,8 @@ github.com/metacubex/gvisor v0.0.0-20231209122014-3e43224c7bbc h1:+yTZ6q2EeQCAJN github.com/metacubex/gvisor v0.0.0-20231209122014-3e43224c7bbc/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/go.mod h1:F/t8VnA47xoia8ABlNA4InkZjssvFJ5p6E6jKdbkgAs= -github.com/metacubex/sing v0.0.0-20231218144940-fc8dd41d68e8 h1:VEos1wHxHMPoFUGTq4HNrPhhbaFmwM1IsvE9rwwQp0Q= -github.com/metacubex/sing v0.0.0-20231218144940-fc8dd41d68e8/go.mod h1:9pfuAH6mZfgnz/YjP6xu5sxx882rfyjpcrTdUpd6w3g= +github.com/metacubex/sing v0.0.0-20231221131356-d73c21c7ea3f h1:T2PuaAiXMSC3mjRRUmIomuiu3jhi7EWSbzXtVIrVUC4= +github.com/metacubex/sing v0.0.0-20231221131356-d73c21c7ea3f/go.mod h1:9pfuAH6mZfgnz/YjP6xu5sxx882rfyjpcrTdUpd6w3g= github.com/metacubex/sing-quic v0.0.0-20231220152840-85620b446796 h1:xiCPttMGAaIh4Ad6t85VxUoUv+Sg88eXzzUvYN8gT5w= github.com/metacubex/sing-quic v0.0.0-20231220152840-85620b446796/go.mod h1:E1e1Uu6YaJddD+c0DtJlSOkfMI0NLdOVhM60KAlcssY= github.com/metacubex/sing-shadowsocks v0.2.6 h1:6oEB3QcsFYnNiFeoevcXrCwJ3sAablwVSgtE9R3QeFQ=