github.com/igoogolx/clash@v1.19.8/transport/vmess/vmess.go (about)

     1  package vmess
     2  
     3  import (
     4  	"fmt"
     5  	"math/rand"
     6  	"net"
     7  	"runtime"
     8  
     9  	"github.com/gofrs/uuid/v5"
    10  )
    11  
    12  // Version of vmess
    13  const Version byte = 1
    14  
    15  // Request Options
    16  const (
    17  	OptionChunkStream  byte = 1
    18  	OptionChunkMasking byte = 4
    19  )
    20  
    21  // Security type vmess
    22  type Security = byte
    23  
    24  // Cipher types
    25  const (
    26  	SecurityAES128GCM        Security = 3
    27  	SecurityCHACHA20POLY1305 Security = 4
    28  	SecurityNone             Security = 5
    29  	SecurityZero             Security = 6
    30  )
    31  
    32  // Command types
    33  const (
    34  	CommandTCP byte = 1
    35  	CommandUDP byte = 2
    36  )
    37  
    38  // Addr types
    39  const (
    40  	AtypIPv4       byte = 1
    41  	AtypDomainName byte = 2
    42  	AtypIPv6       byte = 3
    43  )
    44  
    45  // DstAddr store destination address
    46  type DstAddr struct {
    47  	UDP      bool
    48  	AddrType byte
    49  	Addr     []byte
    50  	Port     uint
    51  }
    52  
    53  // Client is vmess connection generator
    54  type Client struct {
    55  	user     []*ID
    56  	uuid     *uuid.UUID
    57  	security Security
    58  	isAead   bool
    59  	isVless  bool
    60  }
    61  
    62  // Config of vmess
    63  type Config struct {
    64  	UUID     string
    65  	AlterID  uint16
    66  	Security string
    67  	Port     string
    68  	HostName string
    69  	IsAead   bool
    70  	IsVless  bool
    71  }
    72  
    73  // StreamConn return a Conn with net.Conn and DstAddr
    74  func (c *Client) StreamConn(conn net.Conn, dst *DstAddr) (net.Conn, error) {
    75  	r := rand.Intn(len(c.user))
    76  	return newConn(conn, c.user[r], dst, c.security, c.isAead, c.isVless)
    77  }
    78  
    79  // NewClient return Client instance
    80  func NewClient(config Config) (*Client, error) {
    81  	uid, err := uuid.FromString(config.UUID)
    82  	if err != nil {
    83  		return nil, err
    84  	}
    85  
    86  	if config.IsVless {
    87  		config.AlterID = 0
    88  		config.Security = "zero"
    89  	}
    90  
    91  	var security Security
    92  	switch config.Security {
    93  	case "aes-128-gcm":
    94  		security = SecurityAES128GCM
    95  	case "chacha20-poly1305":
    96  		security = SecurityCHACHA20POLY1305
    97  	case "none":
    98  		security = SecurityNone
    99  	case "zero":
   100  		security = SecurityZero
   101  	case "auto":
   102  		security = SecurityCHACHA20POLY1305
   103  		if runtime.GOARCH == "amd64" || runtime.GOARCH == "s390x" || runtime.GOARCH == "arm64" {
   104  			security = SecurityAES128GCM
   105  		}
   106  	default:
   107  		return nil, fmt.Errorf("unknown security type: %s", config.Security)
   108  	}
   109  
   110  	return &Client{
   111  		user:     newAlterIDs(newID(&uid), config.AlterID),
   112  		uuid:     &uid,
   113  		security: security,
   114  		isAead:   config.IsAead,
   115  		isVless:  config.IsVless,
   116  	}, nil
   117  }