github.com/metacubex/mihomo@v1.18.5/common/net/packet/packet_sing.go (about) 1 package packet 2 3 import ( 4 "net" 5 6 "github.com/sagernet/sing/common/buf" 7 "github.com/sagernet/sing/common/bufio" 8 M "github.com/sagernet/sing/common/metadata" 9 N "github.com/sagernet/sing/common/network" 10 ) 11 12 type SingPacketConn = N.NetPacketConn 13 14 type EnhanceSingPacketConn interface { 15 SingPacketConn 16 EnhancePacketConn 17 } 18 19 type enhanceSingPacketConn struct { 20 SingPacketConn 21 packetReadWaiter N.PacketReadWaiter 22 } 23 24 func (c *enhanceSingPacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) { 25 var buff *buf.Buffer 26 var dest M.Socksaddr 27 rwOptions := N.ReadWaitOptions{} 28 if c.packetReadWaiter != nil { 29 c.packetReadWaiter.InitializeReadWaiter(rwOptions) 30 buff, dest, err = c.packetReadWaiter.WaitReadPacket() 31 } else { 32 buff = rwOptions.NewPacketBuffer() 33 dest, err = c.SingPacketConn.ReadPacket(buff) 34 if buff != nil { 35 rwOptions.PostReturn(buff) 36 } 37 } 38 if dest.IsFqdn() { 39 addr = dest 40 } else { 41 addr = dest.UDPAddr() 42 } 43 if err != nil { 44 buff.Release() 45 return 46 } 47 if buff == nil { 48 return 49 } 50 if buff.IsEmpty() { 51 buff.Release() 52 return 53 } 54 data = buff.Bytes() 55 put = buff.Release 56 return 57 } 58 59 func (c *enhanceSingPacketConn) Upstream() any { 60 return c.SingPacketConn 61 } 62 63 func (c *enhanceSingPacketConn) WriterReplaceable() bool { 64 return true 65 } 66 67 func (c *enhanceSingPacketConn) ReaderReplaceable() bool { 68 return true 69 } 70 71 func newEnhanceSingPacketConn(conn SingPacketConn) *enhanceSingPacketConn { 72 epc := &enhanceSingPacketConn{SingPacketConn: conn} 73 if readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(conn); isReadWaiter { 74 epc.packetReadWaiter = readWaiter 75 } 76 return epc 77 }