github.com/xmplusdev/xmcore@v1.8.11-0.20240412132628-5518b55526af/common/singbridge/packet.go (about)

     1  package singbridge
     2  
     3  import (
     4  	"context"
     5  
     6  	B "github.com/sagernet/sing/common/buf"
     7  	"github.com/sagernet/sing/common/bufio"
     8  	M "github.com/sagernet/sing/common/metadata"
     9  	"github.com/xmplusdev/xmcore/common/buf"
    10  	"github.com/xmplusdev/xmcore/common/net"
    11  	"github.com/xmplusdev/xmcore/transport"
    12  )
    13  
    14  func CopyPacketConn(ctx context.Context, inboundConn net.Conn, link *transport.Link, destination net.Destination, serverConn net.PacketConn) error {
    15  	conn := &PacketConnWrapper{
    16  		Reader: link.Reader,
    17  		Writer: link.Writer,
    18  		Dest:   destination,
    19  		Conn:   inboundConn,
    20  	}
    21  	return ReturnError(bufio.CopyPacketConn(ctx, conn, bufio.NewPacketConn(serverConn)))
    22  }
    23  
    24  type PacketConnWrapper struct {
    25  	buf.Reader
    26  	buf.Writer
    27  	net.Conn
    28  	Dest   net.Destination
    29  	cached buf.MultiBuffer
    30  }
    31  
    32  func (w *PacketConnWrapper) ReadPacket(buffer *B.Buffer) (M.Socksaddr, error) {
    33  	if w.cached != nil {
    34  		mb, bb := buf.SplitFirst(w.cached)
    35  		if bb == nil {
    36  			w.cached = nil
    37  		} else {
    38  			buffer.Write(bb.Bytes())
    39  			w.cached = mb
    40  			var destination net.Destination
    41  			if bb.UDP != nil {
    42  				destination = *bb.UDP
    43  			} else {
    44  				destination = w.Dest
    45  			}
    46  			bb.Release()
    47  			return ToSocksaddr(destination), nil
    48  		}
    49  	}
    50  	mb, err := w.ReadMultiBuffer()
    51  	if err != nil {
    52  		return M.Socksaddr{}, err
    53  	}
    54  	nb, bb := buf.SplitFirst(mb)
    55  	if bb == nil {
    56  		return M.Socksaddr{}, nil
    57  	} else {
    58  		buffer.Write(bb.Bytes())
    59  		w.cached = nb
    60  		var destination net.Destination
    61  		if bb.UDP != nil {
    62  			destination = *bb.UDP
    63  		} else {
    64  			destination = w.Dest
    65  		}
    66  		bb.Release()
    67  		return ToSocksaddr(destination), nil
    68  	}
    69  }
    70  
    71  func (w *PacketConnWrapper) WritePacket(buffer *B.Buffer, destination M.Socksaddr) error {
    72  	vBuf := buf.New()
    73  	vBuf.Write(buffer.Bytes())
    74  	endpoint := ToDestination(destination, net.Network_UDP)
    75  	vBuf.UDP = &endpoint
    76  	return w.Writer.WriteMultiBuffer(buf.MultiBuffer{vBuf})
    77  }
    78  
    79  func (w *PacketConnWrapper) Close() error {
    80  	buf.ReleaseMulti(w.cached)
    81  	return nil
    82  }