mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2024-11-16 19:56:51 +08:00
76 lines
1.7 KiB
Go
76 lines
1.7 KiB
Go
//go:build windows
|
|
|
|
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) {
|
|
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
|
|
}
|