Code: refresh code
This commit is contained in:
109
transport/vless/conn.go
Normal file
109
transport/vless/conn.go
Normal file
@ -0,0 +1,109 @@
|
||||
package vless
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
)
|
||||
|
||||
/*var (
|
||||
|
||||
//proto.Marshal(addons) bytes for Flow: "xtls-rprx-direct"
|
||||
addOnBytes, _ = hex.DecodeString("120a1078746c732d727072782d646972656374")
|
||||
addOnBytesLen = len(addOnBytes)
|
||||
|
||||
//proto.Marshal(addons) bytes for Flow: ""
|
||||
//addOnEmptyBytes, _ = hex.DecodeString("00")
|
||||
//addOnEmptyBytesLen = len(addOnEmptyBytes)
|
||||
)*/
|
||||
|
||||
type Conn struct {
|
||||
net.Conn
|
||||
dst *DstAddr
|
||||
id *uuid.UUID
|
||||
|
||||
received bool
|
||||
}
|
||||
|
||||
func (vc *Conn) Read(b []byte) (int, error) {
|
||||
if vc.received {
|
||||
return vc.Conn.Read(b)
|
||||
}
|
||||
|
||||
if err := vc.recvResponse(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
vc.received = true
|
||||
return vc.Conn.Read(b)
|
||||
}
|
||||
|
||||
func (vc *Conn) sendRequest() error {
|
||||
buf := &bytes.Buffer{}
|
||||
|
||||
buf.WriteByte(Version) // protocol version
|
||||
buf.Write(vc.id.Bytes()) // 16 bytes of uuid
|
||||
|
||||
// command
|
||||
if vc.dst.UDP {
|
||||
buf.WriteByte(0) // addon data length. 0 means no addon data
|
||||
//buf.WriteByte(byte(addOnEmptyBytesLen))
|
||||
//buf.Write(addOnEmptyBytes)
|
||||
buf.WriteByte(CommandUDP)
|
||||
} else {
|
||||
buf.WriteByte(0) // addon data length. 0 means no addon data
|
||||
//buf.WriteByte(byte(addOnBytesLen))
|
||||
//buf.Write(addOnBytes)
|
||||
buf.WriteByte(CommandTCP)
|
||||
}
|
||||
|
||||
// Port AddrType Addr
|
||||
binary.Write(buf, binary.BigEndian, uint16(vc.dst.Port))
|
||||
buf.WriteByte(vc.dst.AddrType)
|
||||
buf.Write(vc.dst.Addr)
|
||||
|
||||
_, err := vc.Conn.Write(buf.Bytes())
|
||||
return err
|
||||
}
|
||||
|
||||
func (vc *Conn) recvResponse() error {
|
||||
var err error
|
||||
buf := make([]byte, 1)
|
||||
_, err = io.ReadFull(vc.Conn, buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if buf[0] != Version {
|
||||
return errors.New("unexpected response version")
|
||||
}
|
||||
|
||||
_, err = io.ReadFull(vc.Conn, buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
length := int64(buf[0])
|
||||
if length != 0 { // addon data length > 0
|
||||
io.CopyN(ioutil.Discard, vc.Conn, length) // just discard
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// newConn return a Conn instance
|
||||
func newConn(conn net.Conn, id *uuid.UUID, dst *DstAddr) (*Conn, error) {
|
||||
c := &Conn{
|
||||
Conn: conn,
|
||||
id: id,
|
||||
dst: dst,
|
||||
}
|
||||
if err := c.sendRequest(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c, nil
|
||||
}
|
61
transport/vless/vless.go
Normal file
61
transport/vless/vless.go
Normal file
@ -0,0 +1,61 @@
|
||||
package vless
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
)
|
||||
|
||||
const Version byte = 0 // protocol version. preview version is 0
|
||||
|
||||
// Command types
|
||||
const (
|
||||
CommandTCP byte = 1
|
||||
CommandUDP byte = 2
|
||||
)
|
||||
|
||||
// Addr types
|
||||
const (
|
||||
AtypIPv4 byte = 1
|
||||
AtypDomainName byte = 2
|
||||
AtypIPv6 byte = 3
|
||||
)
|
||||
|
||||
// DstAddr store destination address
|
||||
type DstAddr struct {
|
||||
UDP bool
|
||||
AddrType byte
|
||||
Addr []byte
|
||||
Port uint
|
||||
}
|
||||
|
||||
// Config of vless
|
||||
type Config struct {
|
||||
UUID string
|
||||
AlterID uint16
|
||||
Security string
|
||||
Port string
|
||||
HostName string
|
||||
}
|
||||
|
||||
// Client is vless connection generator
|
||||
type Client struct {
|
||||
uuid *uuid.UUID
|
||||
}
|
||||
|
||||
// StreamConn return a Conn with net.Conn and DstAddr
|
||||
func (c *Client) StreamConn(conn net.Conn, dst *DstAddr) (net.Conn, error) {
|
||||
return newConn(conn, c.uuid, dst)
|
||||
}
|
||||
|
||||
// NewClient return Client instance
|
||||
func NewClient(uuidStr string) (*Client, error) {
|
||||
uid, err := uuid.FromString(uuidStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Client{
|
||||
uuid: &uid,
|
||||
}, nil
|
||||
}
|
Reference in New Issue
Block a user