github.com/v2fly/v2ray-core/v5@v5.16.2-0.20240507031116-8191faa6e095/common/net/packetaddr/connection_adaptor.go (about)

     1  package packetaddr
     2  
     3  import (
     4  	"context"
     5  	gonet "net"
     6  	"sync"
     7  	"time"
     8  
     9  	"github.com/v2fly/v2ray-core/v5/common"
    10  	"github.com/v2fly/v2ray-core/v5/common/buf"
    11  	"github.com/v2fly/v2ray-core/v5/common/errors"
    12  	"github.com/v2fly/v2ray-core/v5/common/net"
    13  	"github.com/v2fly/v2ray-core/v5/features/routing"
    14  	"github.com/v2fly/v2ray-core/v5/transport"
    15  )
    16  
    17  var (
    18  	errNotPacketConn = errors.New("not a packet connection")
    19  	errUnsupported   = errors.New("unsupported action")
    20  )
    21  
    22  func ToPacketAddrConn(link *transport.Link, dest net.Destination) (net.PacketConn, error) {
    23  	if !dest.Address.Family().IsDomain() {
    24  		return nil, errNotPacketConn
    25  	}
    26  	switch dest.Address.Domain() {
    27  	case seqPacketMagicAddress:
    28  		return &packetConnectionAdaptor{
    29  			readerAccess: &sync.Mutex{},
    30  			readerBuffer: nil,
    31  			link:         link,
    32  		}, nil
    33  	default:
    34  		return nil, errNotPacketConn
    35  	}
    36  }
    37  
    38  func CreatePacketAddrConn(ctx context.Context, dispatcher routing.Dispatcher, isStream bool) (net.PacketConn, error) {
    39  	if isStream {
    40  		return nil, errUnsupported
    41  	}
    42  	packetDest := net.Destination{
    43  		Address: net.DomainAddress(seqPacketMagicAddress),
    44  		Port:    0,
    45  		Network: net.Network_UDP,
    46  	}
    47  	link, err := dispatcher.Dispatch(ctx, packetDest)
    48  	if err != nil {
    49  		return nil, err
    50  	}
    51  	return &packetConnectionAdaptor{
    52  		readerAccess: &sync.Mutex{},
    53  		readerBuffer: nil,
    54  		link:         link,
    55  	}, nil
    56  }
    57  
    58  type packetConnectionAdaptor struct {
    59  	readerAccess *sync.Mutex
    60  	readerBuffer buf.MultiBuffer
    61  	link         *transport.Link
    62  }
    63  
    64  func (c *packetConnectionAdaptor) ReadFrom(p []byte) (n int, addr gonet.Addr, err error) {
    65  	c.readerAccess.Lock()
    66  	defer c.readerAccess.Unlock()
    67  	if c.readerBuffer.IsEmpty() {
    68  		c.readerBuffer, err = c.link.Reader.ReadMultiBuffer()
    69  		if err != nil {
    70  			return 0, nil, err
    71  		}
    72  	}
    73  	c.readerBuffer, n = buf.SplitFirstBytes(c.readerBuffer, p)
    74  	var w *buf.Buffer
    75  	w, addr, err = ExtractAddressFromPacket(buf.FromBytes(p[:n]))
    76  	n = copy(p, w.Bytes())
    77  	w.Release()
    78  	return
    79  }
    80  
    81  func (c *packetConnectionAdaptor) WriteTo(p []byte, addr gonet.Addr) (n int, err error) {
    82  	payloadLen := len(p)
    83  	var buffer *buf.Buffer
    84  	buffer, err = AttachAddressToPacket(buf.FromBytes(p), addr)
    85  	if err != nil {
    86  		return 0, err
    87  	}
    88  	mb := buf.MultiBuffer{buffer}
    89  	err = c.link.Writer.WriteMultiBuffer(mb)
    90  	if err != nil {
    91  		return 0, err
    92  	}
    93  	return payloadLen, nil
    94  }
    95  
    96  func (c *packetConnectionAdaptor) Close() error {
    97  	c.readerAccess.Lock()
    98  	defer c.readerAccess.Unlock()
    99  	c.readerBuffer = buf.ReleaseMulti(c.readerBuffer)
   100  	return common.Interrupt(c.link)
   101  }
   102  
   103  func (c packetConnectionAdaptor) LocalAddr() gonet.Addr {
   104  	return &gonet.UnixAddr{Name: "unsupported"}
   105  }
   106  
   107  func (c packetConnectionAdaptor) SetDeadline(t time.Time) error {
   108  	return nil
   109  }
   110  
   111  func (c packetConnectionAdaptor) SetReadDeadline(t time.Time) error {
   112  	return nil
   113  }
   114  
   115  func (c packetConnectionAdaptor) SetWriteDeadline(t time.Time) error {
   116  	return nil
   117  }
   118  
   119  func ToPacketAddrConnWrapper(conn net.PacketConn, isStream bool) FusedConnection {
   120  	return &packetConnWrapper{conn}
   121  }
   122  
   123  type packetConnWrapper struct {
   124  	net.PacketConn
   125  }
   126  
   127  func (pc *packetConnWrapper) RemoteAddr() gonet.Addr {
   128  	return nil
   129  }
   130  
   131  type FusedConnection interface {
   132  	net.PacketConn
   133  	net.Conn
   134  }
   135  
   136  func (pc *packetConnWrapper) Read(p []byte) (n int, err error) {
   137  	recbuf := buf.StackNew()
   138  	recbuf.Extend(2048)
   139  	n, addr, err := pc.PacketConn.ReadFrom(recbuf.Bytes())
   140  	if err != nil {
   141  		return 0, err
   142  	}
   143  	recbuf.Resize(0, int32(n))
   144  	result, err := AttachAddressToPacket(&recbuf, addr)
   145  	if err != nil {
   146  		return 0, err
   147  	}
   148  	n = copy(p, result.Bytes())
   149  	result.Release()
   150  	return n, nil
   151  }
   152  
   153  func (pc *packetConnWrapper) Write(p []byte) (n int, err error) {
   154  	data, addr, err := ExtractAddressFromPacket(buf.FromBytes(p))
   155  	if err != nil {
   156  		return 0, err
   157  	}
   158  	_, err = pc.PacketConn.WriteTo(data.Bytes(), addr)
   159  	if err != nil {
   160  		return 0, err
   161  	}
   162  	data.Release()
   163  	return len(p), nil
   164  }
   165  
   166  func (pc *packetConnWrapper) Close() error {
   167  	return pc.PacketConn.Close()
   168  }
   169  
   170  func GetDestinationSubsetOf(dest net.Destination) (bool, error) {
   171  	if !dest.Address.Family().IsDomain() {
   172  		return false, errNotPacketConn
   173  	}
   174  	switch dest.Address.Domain() {
   175  	case seqPacketMagicAddress:
   176  		return false, nil
   177  	default:
   178  		return false, errNotPacketConn
   179  	}
   180  }