github.com/metacubex/mihomo@v1.18.5/transport/vless/conn.go (about)

     1  package vless
     2  
     3  import (
     4  	"encoding/binary"
     5  	"errors"
     6  	"io"
     7  	"net"
     8  	"sync"
     9  
    10  	"github.com/metacubex/mihomo/common/buf"
    11  	N "github.com/metacubex/mihomo/common/net"
    12  	"github.com/metacubex/mihomo/transport/vless/vision"
    13  
    14  	"github.com/gofrs/uuid/v5"
    15  	"google.golang.org/protobuf/proto"
    16  )
    17  
    18  type Conn struct {
    19  	N.ExtendedWriter
    20  	N.ExtendedReader
    21  	net.Conn
    22  	dst      *DstAddr
    23  	id       *uuid.UUID
    24  	addons   *Addons
    25  	received bool
    26  
    27  	handshakeMutex sync.Mutex
    28  	needHandshake  bool
    29  	err            error
    30  }
    31  
    32  func (vc *Conn) Read(b []byte) (int, error) {
    33  	if vc.received {
    34  		return vc.ExtendedReader.Read(b)
    35  	}
    36  
    37  	if err := vc.recvResponse(); err != nil {
    38  		return 0, err
    39  	}
    40  	vc.received = true
    41  	return vc.ExtendedReader.Read(b)
    42  }
    43  
    44  func (vc *Conn) ReadBuffer(buffer *buf.Buffer) error {
    45  	if vc.received {
    46  		return vc.ExtendedReader.ReadBuffer(buffer)
    47  	}
    48  
    49  	if err := vc.recvResponse(); err != nil {
    50  		return err
    51  	}
    52  	vc.received = true
    53  	return vc.ExtendedReader.ReadBuffer(buffer)
    54  }
    55  
    56  func (vc *Conn) Write(p []byte) (int, error) {
    57  	if vc.needHandshake {
    58  		vc.handshakeMutex.Lock()
    59  		if vc.needHandshake {
    60  			vc.needHandshake = false
    61  			if vc.sendRequest(p) {
    62  				vc.handshakeMutex.Unlock()
    63  				if vc.err != nil {
    64  					return 0, vc.err
    65  				}
    66  				return len(p), vc.err
    67  			}
    68  			if vc.err != nil {
    69  				vc.handshakeMutex.Unlock()
    70  				return 0, vc.err
    71  			}
    72  		}
    73  		vc.handshakeMutex.Unlock()
    74  	}
    75  
    76  	return vc.ExtendedWriter.Write(p)
    77  }
    78  
    79  func (vc *Conn) WriteBuffer(buffer *buf.Buffer) error {
    80  	if vc.needHandshake {
    81  		vc.handshakeMutex.Lock()
    82  		if vc.needHandshake {
    83  			vc.needHandshake = false
    84  			if vc.sendRequest(buffer.Bytes()) {
    85  				vc.handshakeMutex.Unlock()
    86  				return vc.err
    87  			}
    88  			if vc.err != nil {
    89  				vc.handshakeMutex.Unlock()
    90  				return vc.err
    91  			}
    92  		}
    93  		vc.handshakeMutex.Unlock()
    94  	}
    95  
    96  	return vc.ExtendedWriter.WriteBuffer(buffer)
    97  }
    98  
    99  func (vc *Conn) sendRequest(p []byte) bool {
   100  	var addonsBytes []byte
   101  	if vc.addons != nil {
   102  		addonsBytes, vc.err = proto.Marshal(vc.addons)
   103  		if vc.err != nil {
   104  			return true
   105  		}
   106  	}
   107  
   108  	var buffer *buf.Buffer
   109  	if vc.IsXTLSVisionEnabled() {
   110  		buffer = buf.New()
   111  		defer buffer.Release()
   112  	} else {
   113  		requestLen := 1  // protocol version
   114  		requestLen += 16 // UUID
   115  		requestLen += 1  // addons length
   116  		requestLen += len(addonsBytes)
   117  		requestLen += 1 // command
   118  		if !vc.dst.Mux {
   119  			requestLen += 2 // port
   120  			requestLen += 1 // addr type
   121  			requestLen += len(vc.dst.Addr)
   122  		}
   123  		requestLen += len(p)
   124  
   125  		buffer = buf.NewSize(requestLen)
   126  		defer buffer.Release()
   127  	}
   128  
   129  	buf.Must(
   130  		buffer.WriteByte(Version),              // protocol version
   131  		buf.Error(buffer.Write(vc.id.Bytes())), // 16 bytes of uuid
   132  		buffer.WriteByte(byte(len(addonsBytes))),
   133  		buf.Error(buffer.Write(addonsBytes)),
   134  	)
   135  
   136  	if vc.dst.Mux {
   137  		buf.Must(buffer.WriteByte(CommandMux))
   138  	} else {
   139  		if vc.dst.UDP {
   140  			buf.Must(buffer.WriteByte(CommandUDP))
   141  		} else {
   142  			buf.Must(buffer.WriteByte(CommandTCP))
   143  		}
   144  
   145  		binary.BigEndian.PutUint16(buffer.Extend(2), vc.dst.Port)
   146  		buf.Must(
   147  			buffer.WriteByte(vc.dst.AddrType),
   148  			buf.Error(buffer.Write(vc.dst.Addr)),
   149  		)
   150  	}
   151  
   152  	buf.Must(buf.Error(buffer.Write(p)))
   153  
   154  	_, vc.err = vc.ExtendedWriter.Write(buffer.Bytes())
   155  	return true
   156  }
   157  
   158  func (vc *Conn) recvResponse() error {
   159  	var buffer [2]byte
   160  	_, vc.err = io.ReadFull(vc.ExtendedReader, buffer[:])
   161  	if vc.err != nil {
   162  		return vc.err
   163  	}
   164  
   165  	if buffer[0] != Version {
   166  		return errors.New("unexpected response version")
   167  	}
   168  
   169  	length := int64(buffer[1])
   170  	if length != 0 { // addon data length > 0
   171  		io.CopyN(io.Discard, vc.ExtendedReader, length) // just discard
   172  	}
   173  
   174  	return nil
   175  }
   176  
   177  func (vc *Conn) Upstream() any {
   178  	return vc.Conn
   179  }
   180  
   181  func (vc *Conn) NeedHandshake() bool {
   182  	return vc.needHandshake
   183  }
   184  
   185  func (vc *Conn) IsXTLSVisionEnabled() bool {
   186  	return vc.addons != nil && vc.addons.Flow == XRV
   187  }
   188  
   189  // newConn return a Conn instance
   190  func newConn(conn net.Conn, client *Client, dst *DstAddr) (net.Conn, error) {
   191  	c := &Conn{
   192  		ExtendedReader: N.NewExtendedReader(conn),
   193  		ExtendedWriter: N.NewExtendedWriter(conn),
   194  		Conn:           conn,
   195  		id:             client.uuid,
   196  		dst:            dst,
   197  		needHandshake:  true,
   198  	}
   199  
   200  	if client.Addons != nil {
   201  		switch client.Addons.Flow {
   202  		case XRV:
   203  			visionConn, err := vision.NewConn(c, c.id)
   204  			if err != nil {
   205  				return nil, err
   206  			}
   207  			c.addons = client.Addons
   208  			return visionConn, nil
   209  		}
   210  	}
   211  
   212  	return c, nil
   213  }