package vless import ( "bytes" "io" "net" "net/url" "strconv" "github.com/hahahrfool/v2ray_simple/netLayer" "github.com/hahahrfool/v2ray_simple/proxy" "github.com/hahahrfool/v2ray_simple/utils" ) func init() { proxy.RegisterClient(Name, ClientCreator{}) } //实现 proxy.UserClient,以及 netLayer.UDP_Putter type Client struct { proxy.ProxyCommonStruct version int user *proxy.V2rayUser udp_multi bool } type ClientCreator struct{} func (_ ClientCreator) NewClientFromURL(u *url.URL) (proxy.Client, error) { return NewClientByURL(u) } func (_ ClientCreator) NewClient(dc *proxy.DialConf) (proxy.Client, error) { uuidStr := dc.Uuid id, err := proxy.NewV2rayUser(uuidStr) if err != nil { return nil, err } c := Client{ user: id, } v := dc.Version if v >= 0 { if v == 1 { c.version = 1 } } return &c, nil } func NewClientByURL(url *url.URL) (proxy.Client, error) { uuidStr := url.User.Username() id, err := proxy.NewV2rayUser(uuidStr) if err != nil { return nil, err } c := Client{ user: id, } vStr := url.Query().Get("version") if vStr != "" { v, err := strconv.Atoi(vStr) if err == nil { if v == 1 { c.version = 1 } } } return &c, nil } func (c *Client) Name() string { if c.version == 0 { return Name } return Name + "_" + strconv.Itoa(c.version) } func (c *Client) Version() int { return c.version } func (c *Client) GetUser() proxy.User { return c.user } func (c *Client) IsUDP_MultiChannel() bool { return c.udp_multi } func (c *Client) Handshake(underlay net.Conn, target netLayer.Addr) (io.ReadWriteCloser, error) { var err error port := target.Port addr, atyp := target.AddressBytes() buf := c.getBufWithCmd(CmdTCP) buf.WriteByte(byte(uint16(port) >> 8)) buf.WriteByte(byte(uint16(port) << 8 >> 8)) buf.WriteByte(atyp) buf.Write(addr) _, err = underlay.Write(buf.Bytes()) utils.PutBuf(buf) if c.version == 0 { return &UserTCPConn{ Conn: underlay, uuid: *c.user, version: c.version, underlayIsBasic: netLayer.IsBasicConn(underlay), }, err } else { return underlay, nil } } func (c *Client) EstablishUDPChannel(underlay net.Conn, target netLayer.Addr) (netLayer.MsgConn, error) { var err error buf := c.getBufWithCmd(CmdUDP) port := target.Port buf.WriteByte(byte(uint16(port) >> 8)) buf.WriteByte(byte(uint16(port) << 8 >> 8)) addr, atyp := target.AddressBytes() buf.WriteByte(atyp) buf.Write(addr) _, err = underlay.Write(buf.Bytes()) utils.PutBuf(buf) return &UDPConn{Conn: underlay, version: c.version, isClientEnd: true, raddr: target}, err } func (c *Client) getBufWithCmd(cmd byte) *bytes.Buffer { v := c.version buf := utils.GetBuf() buf.WriteByte(byte(c.version)) //version buf.Write(c.user[:]) if v == 0 { buf.WriteByte(0) //addon length } else { switch { default: buf.WriteByte(0) //no addon case c.udp_multi: buf.WriteByte(addon_udp_multi_flag) } } buf.WriteByte(cmd) // cmd return buf }