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  }