github.com/kelleygo/clashcore@v1.0.2/transport/vless/vision/vision.go (about)

     1  // Package vision implements VLESS flow `xtls-rprx-vision` introduced by Xray-core.
     2  package vision
     3  
     4  import (
     5  	"bytes"
     6  	gotls "crypto/tls"
     7  	"errors"
     8  	"fmt"
     9  	"net"
    10  	"reflect"
    11  	"unsafe"
    12  
    13  	N "github.com/kelleygo/clashcore/common/net"
    14  	tlsC "github.com/kelleygo/clashcore/component/tls"
    15  
    16  	"github.com/gofrs/uuid/v5"
    17  	"github.com/sagernet/sing/common"
    18  	utls "github.com/sagernet/utls"
    19  )
    20  
    21  var ErrNotTLS13 = errors.New("XTLS Vision based on TLS 1.3 outer connection")
    22  
    23  type connWithUpstream interface {
    24  	net.Conn
    25  	common.WithUpstream
    26  }
    27  
    28  func NewConn(conn connWithUpstream, userUUID *uuid.UUID) (*Conn, error) {
    29  	c := &Conn{
    30  		ExtendedReader:             N.NewExtendedReader(conn),
    31  		ExtendedWriter:             N.NewExtendedWriter(conn),
    32  		upstream:                   conn,
    33  		userUUID:                   userUUID,
    34  		packetsToFilter:            6,
    35  		needHandshake:              true,
    36  		readProcess:                true,
    37  		readFilterUUID:             true,
    38  		writeFilterApplicationData: true,
    39  	}
    40  	var t reflect.Type
    41  	var p unsafe.Pointer
    42  	switch underlying := conn.Upstream().(type) {
    43  	case *gotls.Conn:
    44  		//log.Debugln("type tls")
    45  		c.Conn = underlying.NetConn()
    46  		c.tlsConn = underlying
    47  		t = reflect.TypeOf(underlying).Elem()
    48  		p = unsafe.Pointer(underlying)
    49  	case *utls.UConn:
    50  		//log.Debugln("type *utls.UConn")
    51  		c.Conn = underlying.NetConn()
    52  		c.tlsConn = underlying
    53  		t = reflect.TypeOf(underlying.Conn).Elem()
    54  		p = unsafe.Pointer(underlying.Conn)
    55  	case *tlsC.UConn:
    56  		//log.Debugln("type *tlsC.UConn")
    57  		c.Conn = underlying.NetConn()
    58  		c.tlsConn = underlying.UConn
    59  		t = reflect.TypeOf(underlying.Conn).Elem()
    60  		//log.Debugln("t:%v", t)
    61  		p = unsafe.Pointer(underlying.Conn)
    62  	default:
    63  		return nil, fmt.Errorf(`failed to use vision, maybe "security" is not "tls" or "utls"`)
    64  	}
    65  	i, _ := t.FieldByName("input")
    66  	r, _ := t.FieldByName("rawInput")
    67  	c.input = (*bytes.Reader)(unsafe.Add(p, i.Offset))
    68  	c.rawInput = (*bytes.Buffer)(unsafe.Add(p, r.Offset))
    69  	return c, nil
    70  }