2019-07-28 10:58:45 +00:00
|
|
|
package multiplex
|
|
|
|
|
|
|
|
import (
|
2019-08-02 22:23:54 +00:00
|
|
|
"bytes"
|
2019-08-03 21:05:06 +00:00
|
|
|
"github.com/cbeuw/Cloak/internal/util"
|
2019-07-28 10:58:45 +00:00
|
|
|
"math/rand"
|
|
|
|
"net"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
2019-08-14 09:04:27 +00:00
|
|
|
func setupSesh(unordered bool) *Session {
|
2019-08-02 15:37:48 +00:00
|
|
|
sessionKey := make([]byte, 32)
|
|
|
|
rand.Read(sessionKey)
|
2019-09-01 19:23:45 +00:00
|
|
|
obfuscator, _ := GenerateObfs(0x00, sessionKey, true)
|
2019-08-11 23:22:15 +00:00
|
|
|
|
|
|
|
seshConfig := &SessionConfig{
|
|
|
|
Obfuscator: obfuscator,
|
|
|
|
Valve: nil,
|
|
|
|
UnitRead: util.ReadTLS,
|
2019-08-14 09:04:27 +00:00
|
|
|
Unordered: unordered,
|
2019-08-11 23:22:15 +00:00
|
|
|
}
|
|
|
|
return MakeSession(0, seshConfig)
|
2019-07-28 10:58:45 +00:00
|
|
|
}
|
|
|
|
|
2019-08-16 22:39:41 +00:00
|
|
|
func BenchmarkStream_Write_Ordered(b *testing.B) {
|
2019-08-07 16:06:31 +00:00
|
|
|
const PAYLOAD_LEN = 1000
|
2019-07-28 10:58:45 +00:00
|
|
|
hole := newBlackHole()
|
2019-08-14 09:04:27 +00:00
|
|
|
sesh := setupSesh(false)
|
2019-07-28 10:58:45 +00:00
|
|
|
sesh.AddConnection(hole)
|
|
|
|
testData := make([]byte, PAYLOAD_LEN)
|
|
|
|
rand.Read(testData)
|
|
|
|
|
|
|
|
stream, _ := sesh.OpenStream()
|
|
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
_, err := stream.Write(testData)
|
|
|
|
if err != nil {
|
|
|
|
b.Error(
|
|
|
|
"For", "stream write",
|
|
|
|
"got", err,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
b.SetBytes(PAYLOAD_LEN)
|
|
|
|
}
|
|
|
|
}
|
2019-08-02 22:23:54 +00:00
|
|
|
|
2019-08-16 22:39:41 +00:00
|
|
|
func BenchmarkStream_Read_Ordered(b *testing.B) {
|
2019-08-14 09:04:27 +00:00
|
|
|
sesh := setupSesh(false)
|
2019-08-11 23:22:15 +00:00
|
|
|
const PAYLOAD_LEN = 1000
|
|
|
|
testPayload := make([]byte, PAYLOAD_LEN)
|
|
|
|
rand.Read(testPayload)
|
|
|
|
|
|
|
|
f := &Frame{
|
|
|
|
1,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
testPayload,
|
|
|
|
}
|
|
|
|
|
|
|
|
obfsBuf := make([]byte, 17000)
|
|
|
|
|
|
|
|
l, _ := net.Listen("tcp", "127.0.0.1:0")
|
|
|
|
go func() {
|
|
|
|
// potentially bottlenecked here rather than the actual stream read throughput
|
|
|
|
conn, _ := net.Dial("tcp", l.Addr().String())
|
|
|
|
for {
|
|
|
|
i, _ := sesh.Obfs(f, obfsBuf)
|
|
|
|
f.Seq += 1
|
|
|
|
_, err := conn.Write(obfsBuf[:i])
|
|
|
|
if err != nil {
|
|
|
|
b.Error("cannot write to connection", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
conn, _ := l.Accept()
|
|
|
|
|
|
|
|
sesh.AddConnection(conn)
|
|
|
|
stream, err := sesh.Accept()
|
|
|
|
if err != nil {
|
|
|
|
b.Error("failed to accept stream", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
//time.Sleep(5*time.Second) // wait for buffer to fill up
|
|
|
|
|
|
|
|
readBuf := make([]byte, PAYLOAD_LEN)
|
|
|
|
b.ResetTimer()
|
|
|
|
for j := 0; j < b.N; j++ {
|
|
|
|
n, err := stream.Read(readBuf)
|
|
|
|
if !bytes.Equal(readBuf, testPayload) {
|
|
|
|
b.Error("paylod not equal")
|
|
|
|
}
|
|
|
|
b.SetBytes(int64(n))
|
|
|
|
if err != nil {
|
|
|
|
b.Error(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-08-02 22:23:54 +00:00
|
|
|
func TestStream_Read(t *testing.T) {
|
2019-08-14 09:04:27 +00:00
|
|
|
sesh := setupSesh(false)
|
|
|
|
testPayload := []byte{42, 42, 42}
|
|
|
|
const PAYLOAD_LEN = 3
|
|
|
|
|
|
|
|
f := &Frame{
|
|
|
|
1,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
testPayload,
|
|
|
|
}
|
|
|
|
|
|
|
|
ch := make(chan []byte)
|
|
|
|
l, _ := net.Listen("tcp", "127.0.0.1:0")
|
|
|
|
go func() {
|
|
|
|
conn, _ := net.Dial("tcp", l.Addr().String())
|
|
|
|
for {
|
|
|
|
data := <-ch
|
|
|
|
_, err := conn.Write(data)
|
|
|
|
if err != nil {
|
|
|
|
t.Error("cannot write to connection", err)
|
2019-09-01 19:23:45 +00:00
|
|
|
return
|
2019-08-14 09:04:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
conn, _ := l.Accept()
|
|
|
|
sesh.AddConnection(conn)
|
|
|
|
|
|
|
|
var streamID uint32
|
|
|
|
buf := make([]byte, 10)
|
|
|
|
|
|
|
|
obfsBuf := make([]byte, 512)
|
|
|
|
t.Run("Plain read", func(t *testing.T) {
|
|
|
|
f.StreamID = streamID
|
|
|
|
i, _ := sesh.Obfs(f, obfsBuf)
|
|
|
|
streamID++
|
|
|
|
ch <- obfsBuf[:i]
|
|
|
|
time.Sleep(100 * time.Microsecond)
|
|
|
|
stream, err := sesh.Accept()
|
|
|
|
if err != nil {
|
|
|
|
t.Error("failed to accept stream", err)
|
2019-09-01 19:23:45 +00:00
|
|
|
return
|
2019-08-14 09:04:27 +00:00
|
|
|
}
|
|
|
|
i, err = stream.Read(buf)
|
|
|
|
if err != nil {
|
|
|
|
t.Error("failed to read", err)
|
2019-09-01 19:23:45 +00:00
|
|
|
return
|
2019-08-14 09:04:27 +00:00
|
|
|
}
|
|
|
|
if i != PAYLOAD_LEN {
|
|
|
|
t.Errorf("expected read %v, got %v", PAYLOAD_LEN, i)
|
2019-09-01 19:23:45 +00:00
|
|
|
return
|
2019-08-14 09:04:27 +00:00
|
|
|
}
|
|
|
|
if !bytes.Equal(buf[:i], testPayload) {
|
|
|
|
t.Error("expected", testPayload,
|
|
|
|
"got", buf[:i])
|
2019-09-01 19:23:45 +00:00
|
|
|
return
|
2019-08-14 09:04:27 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
t.Run("Nil buf", func(t *testing.T) {
|
|
|
|
f.StreamID = streamID
|
|
|
|
i, _ := sesh.Obfs(f, obfsBuf)
|
|
|
|
streamID++
|
|
|
|
ch <- obfsBuf[:i]
|
|
|
|
time.Sleep(100 * time.Microsecond)
|
|
|
|
stream, _ := sesh.Accept()
|
|
|
|
i, err := stream.Read(nil)
|
|
|
|
if i != 0 || err != nil {
|
|
|
|
t.Error("expecting", 0, nil,
|
|
|
|
"got", i, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
stream.Close()
|
|
|
|
i, err = stream.Read(nil)
|
|
|
|
if i != 0 || err != ErrBrokenStream {
|
|
|
|
t.Error("expecting", 0, ErrBrokenStream,
|
|
|
|
"got", i, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
t.Run("Read after stream close", func(t *testing.T) {
|
|
|
|
f.StreamID = streamID
|
|
|
|
i, _ := sesh.Obfs(f, obfsBuf)
|
|
|
|
streamID++
|
|
|
|
ch <- obfsBuf[:i]
|
|
|
|
time.Sleep(100 * time.Microsecond)
|
|
|
|
stream, _ := sesh.Accept()
|
|
|
|
stream.Close()
|
|
|
|
i, err := stream.Read(buf)
|
|
|
|
if err != nil {
|
|
|
|
t.Error("failed to read", err)
|
|
|
|
}
|
|
|
|
if i != PAYLOAD_LEN {
|
|
|
|
t.Errorf("expected read %v, got %v", PAYLOAD_LEN, i)
|
|
|
|
}
|
|
|
|
if !bytes.Equal(buf[:i], testPayload) {
|
|
|
|
t.Error("expected", testPayload,
|
|
|
|
"got", buf[:i])
|
|
|
|
}
|
|
|
|
_, err = stream.Read(buf)
|
|
|
|
if err == nil {
|
|
|
|
t.Error("expecting error", ErrBrokenStream,
|
|
|
|
"got nil error")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
t.Run("Read after session close", func(t *testing.T) {
|
|
|
|
f.StreamID = streamID
|
|
|
|
i, _ := sesh.Obfs(f, obfsBuf)
|
|
|
|
streamID++
|
|
|
|
ch <- obfsBuf[:i]
|
|
|
|
time.Sleep(100 * time.Microsecond)
|
|
|
|
stream, _ := sesh.Accept()
|
|
|
|
sesh.Close()
|
|
|
|
i, err := stream.Read(buf)
|
|
|
|
if err != nil {
|
|
|
|
t.Error("failed to read", err)
|
|
|
|
}
|
|
|
|
if i != PAYLOAD_LEN {
|
|
|
|
t.Errorf("expected read %v, got %v", PAYLOAD_LEN, i)
|
|
|
|
}
|
|
|
|
if !bytes.Equal(buf[:i], testPayload) {
|
|
|
|
t.Error("expected", testPayload,
|
|
|
|
"got", buf[:i])
|
|
|
|
}
|
|
|
|
_, err = stream.Read(buf)
|
|
|
|
if err == nil {
|
|
|
|
t.Error("expecting error", ErrBrokenStream,
|
|
|
|
"got nil error")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestStream_UnorderedRead(t *testing.T) {
|
|
|
|
sesh := setupSesh(true)
|
2019-08-02 22:23:54 +00:00
|
|
|
testPayload := []byte{42, 42, 42}
|
|
|
|
const PAYLOAD_LEN = 3
|
|
|
|
|
|
|
|
f := &Frame{
|
|
|
|
1,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
testPayload,
|
|
|
|
}
|
|
|
|
|
|
|
|
ch := make(chan []byte)
|
2019-08-08 14:08:16 +00:00
|
|
|
l, _ := net.Listen("tcp", "127.0.0.1:0")
|
2019-08-02 22:23:54 +00:00
|
|
|
go func() {
|
|
|
|
conn, _ := net.Dial("tcp", l.Addr().String())
|
|
|
|
for {
|
|
|
|
data := <-ch
|
|
|
|
_, err := conn.Write(data)
|
|
|
|
if err != nil {
|
|
|
|
t.Error("cannot write to connection", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
conn, _ := l.Accept()
|
|
|
|
sesh.AddConnection(conn)
|
|
|
|
|
|
|
|
var streamID uint32
|
|
|
|
buf := make([]byte, 10)
|
2019-08-04 09:38:49 +00:00
|
|
|
|
|
|
|
obfsBuf := make([]byte, 512)
|
2019-08-02 22:23:54 +00:00
|
|
|
t.Run("Plain read", func(t *testing.T) {
|
|
|
|
f.StreamID = streamID
|
2019-08-04 09:38:49 +00:00
|
|
|
i, _ := sesh.Obfs(f, obfsBuf)
|
2019-08-02 22:23:54 +00:00
|
|
|
streamID++
|
2019-08-04 09:38:49 +00:00
|
|
|
ch <- obfsBuf[:i]
|
2019-08-05 21:14:11 +00:00
|
|
|
time.Sleep(100 * time.Microsecond)
|
2019-08-02 22:23:54 +00:00
|
|
|
stream, err := sesh.Accept()
|
|
|
|
if err != nil {
|
|
|
|
t.Error("failed to accept stream", err)
|
|
|
|
}
|
2019-08-04 09:38:49 +00:00
|
|
|
i, err = stream.Read(buf)
|
2019-08-02 22:23:54 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Error("failed to read", err)
|
|
|
|
}
|
|
|
|
if i != PAYLOAD_LEN {
|
|
|
|
t.Errorf("expected read %v, got %v", PAYLOAD_LEN, i)
|
|
|
|
}
|
|
|
|
if !bytes.Equal(buf[:i], testPayload) {
|
|
|
|
t.Error("expected", testPayload,
|
|
|
|
"got", buf[:i])
|
|
|
|
}
|
|
|
|
})
|
|
|
|
t.Run("Nil buf", func(t *testing.T) {
|
|
|
|
f.StreamID = streamID
|
2019-08-04 09:38:49 +00:00
|
|
|
i, _ := sesh.Obfs(f, obfsBuf)
|
2019-08-02 22:23:54 +00:00
|
|
|
streamID++
|
2019-08-04 09:38:49 +00:00
|
|
|
ch <- obfsBuf[:i]
|
2019-08-05 21:14:11 +00:00
|
|
|
time.Sleep(100 * time.Microsecond)
|
2019-08-02 22:23:54 +00:00
|
|
|
stream, _ := sesh.Accept()
|
|
|
|
i, err := stream.Read(nil)
|
|
|
|
if i != 0 || err != nil {
|
|
|
|
t.Error("expecting", 0, nil,
|
|
|
|
"got", i, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
stream.Close()
|
|
|
|
i, err = stream.Read(nil)
|
|
|
|
if i != 0 || err != ErrBrokenStream {
|
|
|
|
t.Error("expecting", 0, ErrBrokenStream,
|
|
|
|
"got", i, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
t.Run("Read after stream close", func(t *testing.T) {
|
|
|
|
f.StreamID = streamID
|
2019-08-04 09:38:49 +00:00
|
|
|
i, _ := sesh.Obfs(f, obfsBuf)
|
2019-08-02 22:23:54 +00:00
|
|
|
streamID++
|
2019-08-04 09:38:49 +00:00
|
|
|
ch <- obfsBuf[:i]
|
2019-08-05 21:14:11 +00:00
|
|
|
time.Sleep(100 * time.Microsecond)
|
2019-08-02 22:23:54 +00:00
|
|
|
stream, _ := sesh.Accept()
|
|
|
|
stream.Close()
|
|
|
|
i, err := stream.Read(buf)
|
|
|
|
if err != nil {
|
|
|
|
t.Error("failed to read", err)
|
|
|
|
}
|
|
|
|
if i != PAYLOAD_LEN {
|
|
|
|
t.Errorf("expected read %v, got %v", PAYLOAD_LEN, i)
|
|
|
|
}
|
|
|
|
if !bytes.Equal(buf[:i], testPayload) {
|
|
|
|
t.Error("expected", testPayload,
|
|
|
|
"got", buf[:i])
|
|
|
|
}
|
|
|
|
_, err = stream.Read(buf)
|
|
|
|
if err == nil {
|
|
|
|
t.Error("expecting error", ErrBrokenStream,
|
|
|
|
"got nil error")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
t.Run("Read after session close", func(t *testing.T) {
|
|
|
|
f.StreamID = streamID
|
2019-08-04 09:38:49 +00:00
|
|
|
i, _ := sesh.Obfs(f, obfsBuf)
|
2019-08-02 22:23:54 +00:00
|
|
|
streamID++
|
2019-08-04 09:38:49 +00:00
|
|
|
ch <- obfsBuf[:i]
|
2019-08-05 21:14:11 +00:00
|
|
|
time.Sleep(100 * time.Microsecond)
|
2019-08-02 22:23:54 +00:00
|
|
|
stream, _ := sesh.Accept()
|
|
|
|
sesh.Close()
|
|
|
|
i, err := stream.Read(buf)
|
|
|
|
if err != nil {
|
|
|
|
t.Error("failed to read", err)
|
|
|
|
}
|
|
|
|
if i != PAYLOAD_LEN {
|
|
|
|
t.Errorf("expected read %v, got %v", PAYLOAD_LEN, i)
|
|
|
|
}
|
|
|
|
if !bytes.Equal(buf[:i], testPayload) {
|
|
|
|
t.Error("expected", testPayload,
|
|
|
|
"got", buf[:i])
|
|
|
|
}
|
|
|
|
_, err = stream.Read(buf)
|
|
|
|
if err == nil {
|
|
|
|
t.Error("expecting error", ErrBrokenStream,
|
|
|
|
"got nil error")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|