sing-box/transport/vless/protocol.go
2022-09-12 21:59:27 +08:00

105 lines
2.6 KiB
Go

package vless
import (
"encoding/binary"
"io"
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/buf"
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
"github.com/sagernet/sing/common/rw"
)
const (
Version = 0
CommandTCP = 1
CommandUDP = 2
CommandMux = 3
NetworkUDP = 2
)
var AddressSerializer = M.NewSerializer(
M.AddressFamilyByte(0x01, M.AddressFamilyIPv4),
M.AddressFamilyByte(0x02, M.AddressFamilyFqdn),
M.AddressFamilyByte(0x03, M.AddressFamilyIPv6),
M.PortThenAddress(),
)
type Request struct {
UUID []byte
Command byte
Destination M.Socksaddr
}
func WriteRequest(writer io.Writer, request Request, payload []byte) error {
var requestLen int
requestLen += 1 // version
requestLen += 16 // uuid
requestLen += 1 // protobuf length
requestLen += 1 // command
requestLen += AddressSerializer.AddrPortLen(request.Destination)
requestLen += len(payload)
_buffer := buf.StackNewSize(requestLen)
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
defer buffer.Release()
common.Must(
buffer.WriteByte(Version),
common.Error(buffer.Write(request.UUID)),
buffer.WriteByte(0),
buffer.WriteByte(CommandTCP),
AddressSerializer.WriteAddrPort(buffer, request.Destination),
common.Error(buffer.Write(payload)),
)
return common.Error(writer.Write(buffer.Bytes()))
}
func WritePacketRequest(writer io.Writer, request Request, payload []byte) error {
var requestLen int
requestLen += 1 // version
requestLen += 16 // uuid
requestLen += 1 // protobuf length
requestLen += 1 // command
requestLen += AddressSerializer.AddrPortLen(request.Destination)
if len(payload) > 0 {
requestLen += 2
requestLen += len(payload)
}
_buffer := buf.StackNewSize(requestLen)
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
defer buffer.Release()
common.Must(
buffer.WriteByte(Version),
common.Error(buffer.Write(request.UUID)),
buffer.WriteByte(0),
buffer.WriteByte(CommandUDP),
AddressSerializer.WriteAddrPort(buffer, request.Destination),
binary.Write(buffer, binary.BigEndian, uint16(len(payload))),
common.Error(buffer.Write(payload)),
)
return common.Error(writer.Write(buffer.Bytes()))
}
func ReadResponse(reader io.Reader) error {
version, err := rw.ReadByte(reader)
if err != nil {
return err
}
if version != Version {
return E.New("unknown version: ", version)
}
protobufLength, err := rw.ReadByte(reader)
if err != nil {
return err
}
if protobufLength > 0 {
err = rw.SkipN(reader, int(protobufLength))
if err != nil {
return err
}
}
return nil
}