mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2025-12-19 16:30:07 +08:00
chore: ready for handwritten addons parsing
This commit is contained in:
parent
108bf645fa
commit
0d3d31dc5f
61
transport/vless/addons.go
Normal file
61
transport/vless/addons.go
Normal file
@ -0,0 +1,61 @@
|
||||
package vless
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
func ReadAddons(data []byte) (*Addons, error) {
|
||||
reader := bytes.NewReader(data)
|
||||
var addons Addons
|
||||
for reader.Len() > 0 {
|
||||
protoHeader, err := reader.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch protoHeader {
|
||||
case (1 << 3) | 2:
|
||||
flowLen, err := binary.ReadUvarint(reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
flowBytes := make([]byte, flowLen)
|
||||
_, err = io.ReadFull(reader, flowBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addons.Flow = string(flowBytes)
|
||||
case (2 << 3) | 2:
|
||||
seedLen, err := binary.ReadUvarint(reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
seedBytes := make([]byte, seedLen)
|
||||
_, err = io.ReadFull(reader, seedBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addons.Seed = seedBytes
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown protobuf message header: %v", protoHeader)
|
||||
}
|
||||
}
|
||||
return &addons, nil
|
||||
}
|
||||
|
||||
func WriteAddons(addons *Addons) []byte {
|
||||
var writer bytes.Buffer
|
||||
if len(addons.Flow) > 0 {
|
||||
writer.WriteByte((1 << 3) | 2)
|
||||
writer.Write(binary.AppendUvarint(nil, uint64(len(addons.Flow))))
|
||||
writer.WriteString(addons.Flow)
|
||||
}
|
||||
if len(addons.Seed) > 0 {
|
||||
writer.WriteByte((2 << 3) | 2)
|
||||
writer.Write(binary.AppendUvarint(nil, uint64(len(addons.Seed))))
|
||||
writer.Write(addons.Seed)
|
||||
}
|
||||
return writer.Bytes()
|
||||
}
|
||||
95
transport/vless/addons_test.go
Normal file
95
transport/vless/addons_test.go
Normal file
@ -0,0 +1,95 @@
|
||||
package vless
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func TestAddons(t *testing.T) {
|
||||
var tests = []struct {
|
||||
flow string
|
||||
seed []byte
|
||||
}{
|
||||
{XRV, nil},
|
||||
{XRS, []byte{1, 2, 3}},
|
||||
{"", []byte{1, 2, 3}},
|
||||
{"", nil},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
t.Run(strconv.Itoa(i), func(t *testing.T) {
|
||||
t.Run("proto->handwritten", func(t *testing.T) {
|
||||
addons := new(Addons)
|
||||
addons.Flow = test.flow
|
||||
addons.Seed = test.seed
|
||||
|
||||
addonsBytes, err := proto.Marshal(addons)
|
||||
if err != nil {
|
||||
t.Errorf("error marshalling addons: %v", err)
|
||||
return
|
||||
}
|
||||
addons, err = ReadAddons(addonsBytes)
|
||||
if err != nil {
|
||||
t.Errorf("error reading addons: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if addons.Flow != test.flow {
|
||||
t.Errorf("got %v; want %v", addons.Flow, test.flow)
|
||||
return
|
||||
}
|
||||
if !bytes.Equal(addons.Seed, test.seed) {
|
||||
t.Errorf("got %v; want %v", addons.Seed, test.seed)
|
||||
return
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("handwritten->proto", func(t *testing.T) {
|
||||
addons := new(Addons)
|
||||
addons.Flow = test.flow
|
||||
addons.Seed = test.seed
|
||||
|
||||
addonsBytes := WriteAddons(addons)
|
||||
err := proto.Unmarshal(addonsBytes, addons)
|
||||
if err != nil {
|
||||
t.Errorf("error reading addons: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if addons.Flow != test.flow {
|
||||
t.Errorf("got %v; want %v", addons.Flow, test.flow)
|
||||
return
|
||||
}
|
||||
if !bytes.Equal(addons.Seed, test.seed) {
|
||||
t.Errorf("got %v; want %v", addons.Seed, test.seed)
|
||||
return
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("handwritten->handwritten", func(t *testing.T) {
|
||||
addons := new(Addons)
|
||||
addons.Flow = test.flow
|
||||
addons.Seed = test.seed
|
||||
|
||||
addonsBytes := WriteAddons(addons)
|
||||
addons, err := ReadAddons(addonsBytes)
|
||||
if err != nil {
|
||||
t.Errorf("error reading addons: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if addons.Flow != test.flow {
|
||||
t.Errorf("got %v; want %v", addons.Flow, test.flow)
|
||||
return
|
||||
}
|
||||
if !bytes.Equal(addons.Seed, test.seed) {
|
||||
t.Errorf("got %v; want %v", addons.Seed, test.seed)
|
||||
return
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -2,7 +2,6 @@ package vision
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/subtle"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
@ -57,8 +56,8 @@ func (vc *Conn) Read(b []byte) (int, error) {
|
||||
}
|
||||
|
||||
func (vc *Conn) ReadBuffer(buffer *buf.Buffer) error {
|
||||
toRead := buffer.FreeBytes()
|
||||
if vc.readRemainingContent > 0 {
|
||||
toRead := buffer.FreeBytes()
|
||||
if vc.readRemainingContent < buffer.FreeLen() {
|
||||
toRead = toRead[:vc.readRemainingContent]
|
||||
}
|
||||
@ -79,12 +78,12 @@ func (vc *Conn) ReadBuffer(buffer *buf.Buffer) error {
|
||||
switch vc.readLastCommand {
|
||||
case commandPaddingContinue:
|
||||
//if vc.isTLS || vc.packetsToFilter > 0 {
|
||||
headerUUIDLen := 0
|
||||
if vc.readFilterUUID {
|
||||
headerUUIDLen = uuid.Size
|
||||
need := PaddingHeaderLen
|
||||
if !vc.readFilterUUID {
|
||||
need = PaddingHeaderLen - uuid.Size
|
||||
}
|
||||
var header []byte
|
||||
if need := headerUUIDLen + PaddingHeaderLen - uuid.Size; buffer.FreeLen() < need {
|
||||
if buffer.FreeLen() < need {
|
||||
header = make([]byte, need)
|
||||
} else {
|
||||
header = buffer.FreeBytes()[:need]
|
||||
@ -95,9 +94,8 @@ func (vc *Conn) ReadBuffer(buffer *buf.Buffer) error {
|
||||
}
|
||||
if vc.readFilterUUID {
|
||||
vc.readFilterUUID = false
|
||||
if subtle.ConstantTimeCompare(vc.userUUID.Bytes(), header[:uuid.Size]) != 1 {
|
||||
err = fmt.Errorf("XTLS Vision server responded unknown UUID: %s",
|
||||
uuid.FromBytesOrNil(header[:uuid.Size]).String())
|
||||
if !bytes.Equal(vc.userUUID.Bytes(), header[:uuid.Size]) {
|
||||
err = fmt.Errorf("XTLS Vision server responded unknown UUID: %s", uuid.FromBytesOrNil(header[:uuid.Size]))
|
||||
log.Errorln(err.Error())
|
||||
return err
|
||||
}
|
||||
@ -180,7 +178,7 @@ func (vc *Conn) WriteBuffer(buffer *buf.Buffer) (err error) {
|
||||
for i, buffer := range buffers {
|
||||
command := commandPaddingContinue
|
||||
if applyPadding {
|
||||
if vc.isTLS && buffer.Len() > 6 && bytes.Equal(buffer.To(3), tlsApplicationDataStart) {
|
||||
if vc.isTLS && buffer.Len() > 6 && bytes.Equal(tlsApplicationDataStart, buffer.To(3)) {
|
||||
command = commandPaddingEnd
|
||||
if vc.enableXTLS {
|
||||
command = commandPaddingDirect
|
||||
|
||||
@ -5,8 +5,8 @@ import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/metacubex/mihomo/common/buf"
|
||||
N "github.com/metacubex/mihomo/common/net"
|
||||
"github.com/metacubex/mihomo/log"
|
||||
N "github.com/metacubex/sing/common/network"
|
||||
|
||||
"github.com/gofrs/uuid/v5"
|
||||
"github.com/metacubex/randv2"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user