mihomo/transport/vless/conn.go

236 lines
4.8 KiB
Go
Raw Normal View History

2021-11-17 15:00:32 +08:00
package vless
import (
"encoding/binary"
"errors"
"fmt"
"io"
"net"
"sync"
2021-11-17 15:00:32 +08:00
"github.com/Dreamacro/clash/common/buf"
N "github.com/Dreamacro/clash/common/net"
"github.com/Dreamacro/clash/transport/vless/vision"
2023-04-09 15:40:17 +08:00
"github.com/gofrs/uuid/v5"
2021-11-17 15:00:32 +08:00
xtls "github.com/xtls/go"
"google.golang.org/protobuf/proto"
)
type Conn struct {
2023-02-25 13:12:19 +08:00
N.ExtendedWriter
N.ExtendedReader
net.Conn
2021-11-17 15:00:32 +08:00
dst *DstAddr
id *uuid.UUID
addons *Addons
received bool
handshakeMutex sync.Mutex
2023-02-27 12:02:44 +08:00
needHandshake bool
err error
2021-11-17 15:00:32 +08:00
}
func (vc *Conn) Read(b []byte) (int, error) {
if vc.received {
2023-02-25 13:12:19 +08:00
return vc.ExtendedReader.Read(b)
2021-11-17 15:00:32 +08:00
}
if err := vc.recvResponse(); err != nil {
return 0, err
}
vc.received = true
return vc.ExtendedReader.Read(b)
2021-11-17 15:00:32 +08:00
}
2023-01-16 09:42:03 +08:00
func (vc *Conn) ReadBuffer(buffer *buf.Buffer) error {
if vc.received {
2023-02-25 13:12:19 +08:00
return vc.ExtendedReader.ReadBuffer(buffer)
2023-01-16 09:42:03 +08:00
}
2021-11-17 15:00:32 +08:00
2023-01-16 09:42:03 +08:00
if err := vc.recvResponse(); err != nil {
return err
}
vc.received = true
return vc.ExtendedReader.ReadBuffer(buffer)
2023-01-16 09:42:03 +08:00
}
2021-11-17 15:00:32 +08:00
func (vc *Conn) Write(p []byte) (int, error) {
2023-02-27 12:02:44 +08:00
if vc.needHandshake {
vc.handshakeMutex.Lock()
if vc.needHandshake {
vc.needHandshake = false
if vc.sendRequest(p) {
vc.handshakeMutex.Unlock()
if vc.err != nil {
return 0, vc.err
}
return len(p), vc.err
}
2023-02-11 15:13:17 +08:00
if vc.err != nil {
2023-02-27 12:02:44 +08:00
vc.handshakeMutex.Unlock()
2023-02-11 15:13:17 +08:00
return 0, vc.err
}
}
2023-02-27 12:02:44 +08:00
vc.handshakeMutex.Unlock()
}
2023-02-27 12:02:44 +08:00
2023-02-25 13:12:19 +08:00
return vc.ExtendedWriter.Write(p)
}
func (vc *Conn) WriteBuffer(buffer *buf.Buffer) error {
2023-02-27 12:02:44 +08:00
if vc.needHandshake {
vc.handshakeMutex.Lock()
if vc.needHandshake {
vc.needHandshake = false
if vc.sendRequest(buffer.Bytes()) {
vc.handshakeMutex.Unlock()
return vc.err
}
if vc.err != nil {
vc.handshakeMutex.Unlock()
return vc.err
}
}
2023-02-27 12:02:44 +08:00
vc.handshakeMutex.Unlock()
}
2023-02-27 12:02:44 +08:00
2023-02-25 13:12:19 +08:00
return vc.ExtendedWriter.WriteBuffer(buffer)
}
2023-02-11 15:13:17 +08:00
func (vc *Conn) sendRequest(p []byte) bool {
2023-01-16 09:42:03 +08:00
var addonsBytes []byte
2021-11-17 15:00:32 +08:00
if vc.addons != nil {
2023-02-11 15:13:17 +08:00
addonsBytes, vc.err = proto.Marshal(vc.addons)
if vc.err != nil {
return true
2021-11-17 15:00:32 +08:00
}
}
2023-02-25 13:12:19 +08:00
var buffer *buf.Buffer
if vc.IsXTLSVisionEnabled() {
2023-02-25 13:12:19 +08:00
_buffer := buf.StackNew()
defer buf.KeepAlive(_buffer)
buffer = buf.Dup(_buffer)
defer buffer.Release()
} else {
requestLen := 1 // protocol version
requestLen += 16 // UUID
requestLen += 1 // addons length
requestLen += len(addonsBytes)
requestLen += 1 // command
if !vc.dst.Mux {
requestLen += 2 // port
requestLen += 1 // addr type
requestLen += len(vc.dst.Addr)
}
requestLen += len(p)
_buffer := buf.StackNewSize(requestLen)
defer buf.KeepAlive(_buffer)
buffer = buf.Dup(_buffer)
defer buffer.Release()
}
2023-01-16 09:42:03 +08:00
buf.Must(
buffer.WriteByte(Version), // protocol version
buf.Error(buffer.Write(vc.id.Bytes())), // 16 bytes of uuid
2023-01-16 09:42:03 +08:00
buffer.WriteByte(byte(len(addonsBytes))),
buf.Error(buffer.Write(addonsBytes)),
2023-01-16 09:42:03 +08:00
)
2021-11-17 15:00:32 +08:00
if vc.dst.Mux {
buf.Must(buffer.WriteByte(CommandMux))
2021-11-17 15:00:32 +08:00
} else {
if vc.dst.UDP {
buf.Must(buffer.WriteByte(CommandUDP))
} else {
buf.Must(buffer.WriteByte(CommandTCP))
}
2021-11-17 15:00:32 +08:00
2023-01-16 09:42:03 +08:00
binary.BigEndian.PutUint16(buffer.Extend(2), vc.dst.Port)
buf.Must(
2023-01-16 09:42:03 +08:00
buffer.WriteByte(vc.dst.AddrType),
buf.Error(buffer.Write(vc.dst.Addr)),
2023-01-16 09:42:03 +08:00
)
}
2021-11-17 15:00:32 +08:00
buf.Must(buf.Error(buffer.Write(p)))
2023-02-25 13:12:19 +08:00
_, vc.err = vc.ExtendedWriter.Write(buffer.Bytes())
2023-02-11 15:13:17 +08:00
return true
2021-11-17 15:00:32 +08:00
}
func (vc *Conn) recvResponse() error {
var buffer [2]byte
_, vc.err = io.ReadFull(vc.ExtendedReader, buffer[:])
if vc.err != nil {
return vc.err
2021-11-17 15:00:32 +08:00
}
if buffer[0] != Version {
2021-11-17 15:00:32 +08:00
return errors.New("unexpected response version")
}
length := int64(buffer[1])
2021-11-17 15:00:32 +08:00
if length != 0 { // addon data length > 0
2023-02-25 13:12:19 +08:00
io.CopyN(io.Discard, vc.ExtendedReader, length) // just discard
2021-11-17 15:00:32 +08:00
}
return nil
}
2023-01-16 09:42:03 +08:00
func (vc *Conn) Upstream() any {
return vc.Conn
2023-02-25 13:12:19 +08:00
}
func (vc *Conn) NeedHandshake() bool {
2023-02-27 12:02:44 +08:00
return vc.needHandshake
}
2023-02-25 13:12:19 +08:00
func (vc *Conn) IsXTLSVisionEnabled() bool {
return vc.addons != nil && vc.addons.Flow == XRV
2023-01-16 09:42:03 +08:00
}
2021-11-17 15:00:32 +08:00
// newConn return a Conn instance
func newConn(conn net.Conn, client *Client, dst *DstAddr) (net.Conn, error) {
2021-11-17 15:00:32 +08:00
c := &Conn{
2023-02-25 13:12:19 +08:00
ExtendedReader: N.NewExtendedReader(conn),
ExtendedWriter: N.NewExtendedWriter(conn),
Conn: conn,
id: client.uuid,
dst: dst,
2023-02-27 12:02:44 +08:00
needHandshake: true,
2021-11-17 15:00:32 +08:00
}
if !dst.UDP && client.Addons != nil {
switch client.Addons.Flow {
case XRO, XRD, XRS:
if xtlsConn, ok := conn.(*xtls.Conn); ok {
xtlsConn.RPRX = true
xtlsConn.SHOW = client.XTLSShow
xtlsConn.MARK = "XTLS"
if client.Addons.Flow == XRS {
client.Addons.Flow = XRD
}
if client.Addons.Flow == XRD {
xtlsConn.DirectMode = true
}
c.addons = client.Addons
} else {
return nil, fmt.Errorf("failed to use %s, maybe \"security\" is not \"xtls\"", client.Addons.Flow)
}
2023-02-25 13:12:19 +08:00
case XRV:
visionConn, err := vision.NewConn(c, c.id)
if err != nil {
return nil, err
2023-02-25 13:12:19 +08:00
}
c.addons = client.Addons
return visionConn, nil
2021-11-17 15:00:32 +08:00
}
}
return c, nil
}