github.com/chwjbn/xclash@v0.2.0/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"
    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  )
    30  
    31  // CipherMapping return
    32  var CipherMapping = map[string]byte{
    33  	"none":              SecurityNone,
    34  	"aes-128-gcm":       SecurityAES128GCM,
    35  	"chacha20-poly1305": SecurityCHACHA20POLY1305,
    36  }
    37  
    38  // Command types
    39  const (
    40  	CommandTCP byte = 1
    41  	CommandUDP byte = 2
    42  )
    43  
    44  // Addr types
    45  const (
    46  	AtypIPv4       byte = 1
    47  	AtypDomainName byte = 2
    48  	AtypIPv6       byte = 3
    49  )
    50  
    51  // DstAddr store destination address
    52  type DstAddr struct {
    53  	UDP      bool
    54  	AddrType byte
    55  	Addr     []byte
    56  	Port     uint
    57  }
    58  
    59  // Client is vmess connection generator
    60  type Client struct {
    61  	user     []*ID
    62  	uuid     *uuid.UUID
    63  	security Security
    64  	isAead   bool
    65  }
    66  
    67  // Config of vmess
    68  type Config struct {
    69  	UUID     string
    70  	AlterID  uint16
    71  	Security string
    72  	Port     string
    73  	HostName string
    74  	IsAead   bool
    75  }
    76  
    77  // StreamConn return a Conn with net.Conn and DstAddr
    78  func (c *Client) StreamConn(conn net.Conn, dst *DstAddr) (net.Conn, error) {
    79  	r := rand.Intn(len(c.user))
    80  	return newConn(conn, c.user[r], dst, c.security, c.isAead)
    81  }
    82  
    83  // NewClient return Client instance
    84  func NewClient(config Config) (*Client, error) {
    85  	uid, err := uuid.FromString(config.UUID)
    86  	if err != nil {
    87  		return nil, err
    88  	}
    89  
    90  	var security Security
    91  	switch config.Security {
    92  	case "aes-128-gcm":
    93  		security = SecurityAES128GCM
    94  	case "chacha20-poly1305":
    95  		security = SecurityCHACHA20POLY1305
    96  	case "none":
    97  		security = SecurityNone
    98  	case "auto":
    99  		security = SecurityCHACHA20POLY1305
   100  		if runtime.GOARCH == "amd64" || runtime.GOARCH == "s390x" || runtime.GOARCH == "arm64" {
   101  			security = SecurityAES128GCM
   102  		}
   103  	default:
   104  		return nil, fmt.Errorf("unknown security type: %s", config.Security)
   105  	}
   106  
   107  	return &Client{
   108  		user:     newAlterIDs(newID(&uid), config.AlterID),
   109  		uuid:     &uid,
   110  		security: security,
   111  		isAead:   config.IsAead,
   112  	}, nil
   113  }