github.com/sagernet/sing@v0.4.0-beta.19.0.20240518125136-f67a0988a636/common/bufio/fallback.go (about) 1 package bufio 2 3 import ( 4 "net" 5 6 "github.com/sagernet/sing/common" 7 "github.com/sagernet/sing/common/buf" 8 M "github.com/sagernet/sing/common/metadata" 9 N "github.com/sagernet/sing/common/network" 10 ) 11 12 var _ N.NetPacketConn = (*FallbackPacketConn)(nil) 13 14 type FallbackPacketConn struct { 15 N.PacketConn 16 writer N.NetPacketWriter 17 } 18 19 func NewNetPacketConn(conn N.PacketConn) N.NetPacketConn { 20 if packetConn, loaded := conn.(N.NetPacketConn); loaded { 21 return packetConn 22 } 23 return &FallbackPacketConn{ 24 PacketConn: conn, 25 writer: NewNetPacketWriter(conn), 26 } 27 } 28 29 func (c *FallbackPacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { 30 buffer := buf.With(p) 31 destination, err := c.ReadPacket(buffer) 32 if err != nil { 33 return 34 } 35 n = buffer.Len() 36 if buffer.Start() > 0 { 37 copy(p, buffer.Bytes()) 38 } 39 addr = destination.UDPAddr() 40 return 41 } 42 43 func (c *FallbackPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { 44 return c.writer.WriteTo(p, addr) 45 } 46 47 func (c *FallbackPacketConn) ReaderReplaceable() bool { 48 return true 49 } 50 51 func (c *FallbackPacketConn) WriterReplaceable() bool { 52 return true 53 } 54 55 func (c *FallbackPacketConn) Upstream() any { 56 return c.PacketConn 57 } 58 59 func (c *FallbackPacketConn) UpstreamWriter() any { 60 return c.writer 61 } 62 63 var _ N.NetPacketWriter = (*FallbackPacketWriter)(nil) 64 65 type FallbackPacketWriter struct { 66 N.PacketWriter 67 frontHeadroom int 68 rearHeadroom int 69 } 70 71 func NewNetPacketWriter(writer N.PacketWriter) N.NetPacketWriter { 72 if packetWriter, loaded := writer.(N.NetPacketWriter); loaded { 73 return packetWriter 74 } 75 return &FallbackPacketWriter{ 76 PacketWriter: writer, 77 frontHeadroom: N.CalculateFrontHeadroom(writer), 78 rearHeadroom: N.CalculateRearHeadroom(writer), 79 } 80 } 81 82 func (c *FallbackPacketWriter) WriteTo(p []byte, addr net.Addr) (n int, err error) { 83 if c.frontHeadroom > 0 || c.rearHeadroom > 0 { 84 buffer := buf.NewSize(len(p) + c.frontHeadroom + c.rearHeadroom) 85 buffer.Resize(c.frontHeadroom, 0) 86 common.Must1(buffer.Write(p)) 87 err = c.PacketWriter.WritePacket(buffer, M.SocksaddrFromNet(addr)) 88 } else { 89 err = c.PacketWriter.WritePacket(buf.As(p), M.SocksaddrFromNet(addr)) 90 } 91 if err != nil { 92 return 93 } 94 n = len(p) 95 return 96 } 97 98 func (c *FallbackPacketWriter) WriterReplaceable() bool { 99 return true 100 } 101 102 func (c *FallbackPacketWriter) Upstream() any { 103 return c.PacketWriter 104 }