Files
v2ray_simple/proxy/vless/client.go

170 lines
2.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}