//go:build phoboscref
/* SPDX-License-Identifier: MIT
*
* Phobos
*/
package phobos
import (
"bytes"
"math/rand"
"testing"
"golang.zx2c4.com/wireguard/windows/phobos/cref"
)
var socks5Maskings = map[Masking]int{MaskingSTUN: 1, MaskingMEDIA: 2, MaskingTLS: 3}
var socks5MediaParams = MediaParams{PayloadType: 102, SSRC: 0xC0FFEE, TimestampStep: 3000}
func TestSocks5FramingGoEncodeCDecode(t *testing.T) {
rng := rand.New(rand.NewSource(21))
for masking, id := range socks5Maskings {
for _, length := range []int{1, 64, 1023, 1024, 1025, 4096, s5EncodeReadMax} {
payload := make([]byte, length)
rng.Read(payload)
var encoder s5Encoder
out := make([]byte, s5BufferSize+length)
n := encoder.encode(masking, socks5MediaParams, payload, out)
if n < 0 {
t.Fatalf("%v: go encode failed at length %d", masking, length)
}
cref.Socks5Reset()
var decoded []byte
for offset := 0; offset < n; offset += s5EncodeReadMax {
chunk := out[offset:min(offset+s5EncodeReadMax, n)]
decoded = append(decoded, cref.Socks5Decode(id, socks5MediaParams.PayloadType, socks5MediaParams.SSRC, chunk, s5BufferSize)...)
}
if !bytes.Equal(decoded, payload) {
t.Fatalf("%v: C cannot decode Go frames at length %d", masking, length)
}
}
}
}
func TestSocks5FramingCEncodeGoDecode(t *testing.T) {
rng := rand.New(rand.NewSource(22))
for masking, id := range socks5Maskings {
for _, length := range []int{1, 64, 1023, 1024, 1025, 4096} {
payload := make([]byte, length)
rng.Read(payload)
cref.Socks5Reset()
frames := cref.Socks5Encode(id, socks5MediaParams.PayloadType, socks5MediaParams.SSRC,
socks5MediaParams.TimestampStep, payload, s5BufferSize+length)
if frames == nil {
t.Fatalf("%v: C encode failed at length %d", masking, length)
}
var decoder s5Decoder
out := make([]byte, s5BufferSize+length)
n := decoder.decode(masking, socks5MediaParams, frames, out)
if n < 0 || !bytes.Equal(out[:n], payload) {
t.Fatalf("%v: Go cannot decode C frames at length %d", masking, length)
}
}
}
}
func TestSocks5FramingDecodesAcrossChunks(t *testing.T) {
rng := rand.New(rand.NewSource(23))
for masking, id := range socks5Maskings {
payload := make([]byte, 4096)
rng.Read(payload)
cref.Socks5Reset()
frames := cref.Socks5Encode(id, socks5MediaParams.PayloadType, socks5MediaParams.SSRC,
socks5MediaParams.TimestampStep, payload, s5BufferSize*2)
var decoder s5Decoder
out := make([]byte, s5BufferSize)
var assembled []byte
for offset := 0; offset < len(frames); offset += 7 {
chunk := frames[offset:min(offset+7, len(frames))]
n := decoder.decode(masking, socks5MediaParams, chunk, out)
if n < 0 {
t.Fatalf("%v: chunked decode failed", masking)
}
assembled = append(assembled, out[:n]...)
}
if !bytes.Equal(assembled, payload) {
t.Fatalf("%v: chunked decode produced %d bytes, want %d", masking, len(assembled), len(payload))
}
}
}
func TestSocks5FramingRejectsGarbage(t *testing.T) {
for masking := range socks5Maskings {
var decoder s5Decoder
out := make([]byte, s5BufferSize)
garbage := bytes.Repeat([]byte{0xA5}, 64)
if n := decoder.decode(masking, socks5MediaParams, garbage, out); n >= 0 {
t.Errorf("%v: garbage should not decode", masking)
}
}
}