mirror of
https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake.git
synced 2025-10-13 20:11:19 -04:00
So the assignment of proxies is based on the load. The number of clients is ronded down to 8. Existing proxies that doesn't report the number of clients will be distributed equaly to new proxies until they get 8 clients, that is okish as the existing proxies do have a maximum capacity of 10. Fixes #40048
390 lines
8.4 KiB
Go
390 lines
8.4 KiB
Go
package messages
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"testing"
|
|
|
|
. "github.com/smartystreets/goconvey/convey"
|
|
)
|
|
|
|
func TestDecodeProxyPollRequest(t *testing.T) {
|
|
Convey("Context", t, func() {
|
|
for _, test := range []struct {
|
|
sid string
|
|
proxyType string
|
|
natType string
|
|
clients int
|
|
data string
|
|
err error
|
|
}{
|
|
{
|
|
//Version 1.0 proxy message
|
|
"ymbcCMto7KHNGYlp",
|
|
"",
|
|
"unknown",
|
|
0,
|
|
`{"Sid":"ymbcCMto7KHNGYlp","Version":"1.0"}`,
|
|
nil,
|
|
},
|
|
{
|
|
//Version 1.1 proxy message
|
|
"ymbcCMto7KHNGYlp",
|
|
"standalone",
|
|
"unknown",
|
|
0,
|
|
`{"Sid":"ymbcCMto7KHNGYlp","Version":"1.1","Type":"standalone"}`,
|
|
nil,
|
|
},
|
|
{
|
|
//Version 1.2 proxy message
|
|
"ymbcCMto7KHNGYlp",
|
|
"standalone",
|
|
"restricted",
|
|
0,
|
|
`{"Sid":"ymbcCMto7KHNGYlp","Version":"1.2","Type":"standalone", "NAT":"restricted"}`,
|
|
nil,
|
|
},
|
|
{
|
|
//Version 1.2 proxy message with clients
|
|
"ymbcCMto7KHNGYlp",
|
|
"standalone",
|
|
"restricted",
|
|
24,
|
|
`{"Sid":"ymbcCMto7KHNGYlp","Version":"1.2","Type":"standalone", "NAT":"restricted","Clients":24}`,
|
|
nil,
|
|
},
|
|
{
|
|
//Version 0.X proxy message:
|
|
"",
|
|
"",
|
|
"",
|
|
0,
|
|
"",
|
|
&json.SyntaxError{},
|
|
},
|
|
{
|
|
"",
|
|
"",
|
|
"",
|
|
0,
|
|
`{"Sid":"ymbcCMto7KHNGYlp"}`,
|
|
fmt.Errorf(""),
|
|
},
|
|
{
|
|
"",
|
|
"",
|
|
"",
|
|
0,
|
|
"{}",
|
|
fmt.Errorf(""),
|
|
},
|
|
{
|
|
"",
|
|
"",
|
|
"",
|
|
0,
|
|
`{"Version":"1.0"}`,
|
|
fmt.Errorf(""),
|
|
},
|
|
{
|
|
"",
|
|
"",
|
|
"",
|
|
0,
|
|
`{"Version":"2.0"}`,
|
|
fmt.Errorf(""),
|
|
},
|
|
} {
|
|
sid, proxyType, natType, clients, err := DecodePollRequest([]byte(test.data))
|
|
So(sid, ShouldResemble, test.sid)
|
|
So(proxyType, ShouldResemble, test.proxyType)
|
|
So(natType, ShouldResemble, test.natType)
|
|
So(clients, ShouldEqual, test.clients)
|
|
So(err, ShouldHaveSameTypeAs, test.err)
|
|
}
|
|
|
|
})
|
|
}
|
|
|
|
func TestEncodeProxyPollRequests(t *testing.T) {
|
|
Convey("Context", t, func() {
|
|
b, err := EncodePollRequest("ymbcCMto7KHNGYlp", "standalone", "unknown", 16)
|
|
So(err, ShouldEqual, nil)
|
|
sid, proxyType, natType, clients, err := DecodePollRequest(b)
|
|
So(sid, ShouldEqual, "ymbcCMto7KHNGYlp")
|
|
So(proxyType, ShouldEqual, "standalone")
|
|
So(natType, ShouldEqual, "unknown")
|
|
So(clients, ShouldEqual, 16)
|
|
So(err, ShouldEqual, nil)
|
|
})
|
|
}
|
|
|
|
func TestDecodeProxyPollResponse(t *testing.T) {
|
|
Convey("Context", t, func() {
|
|
for _, test := range []struct {
|
|
offer string
|
|
data string
|
|
err error
|
|
}{
|
|
{
|
|
"fake offer",
|
|
`{"Status":"client match","Offer":"fake offer","NAT":"unknown"}`,
|
|
nil,
|
|
},
|
|
{
|
|
"",
|
|
`{"Status":"no match"}`,
|
|
nil,
|
|
},
|
|
{
|
|
"",
|
|
`{"Status":"client match"}`,
|
|
fmt.Errorf("no supplied offer"),
|
|
},
|
|
{
|
|
"",
|
|
`{"Test":"test"}`,
|
|
fmt.Errorf(""),
|
|
},
|
|
} {
|
|
offer, _, err := DecodePollResponse([]byte(test.data))
|
|
So(err, ShouldHaveSameTypeAs, test.err)
|
|
So(offer, ShouldResemble, test.offer)
|
|
}
|
|
|
|
})
|
|
}
|
|
|
|
func TestEncodeProxyPollResponse(t *testing.T) {
|
|
Convey("Context", t, func() {
|
|
b, err := EncodePollResponse("fake offer", true, "restricted")
|
|
So(err, ShouldEqual, nil)
|
|
offer, natType, err := DecodePollResponse(b)
|
|
So(offer, ShouldEqual, "fake offer")
|
|
So(natType, ShouldEqual, "restricted")
|
|
So(err, ShouldEqual, nil)
|
|
|
|
b, err = EncodePollResponse("", false, "unknown")
|
|
So(err, ShouldEqual, nil)
|
|
offer, natType, err = DecodePollResponse(b)
|
|
So(offer, ShouldEqual, "")
|
|
So(natType, ShouldEqual, "unknown")
|
|
So(err, ShouldEqual, nil)
|
|
})
|
|
}
|
|
func TestDecodeProxyAnswerRequest(t *testing.T) {
|
|
Convey("Context", t, func() {
|
|
for _, test := range []struct {
|
|
answer string
|
|
sid string
|
|
data string
|
|
err error
|
|
}{
|
|
{
|
|
"test",
|
|
"test",
|
|
`{"Version":"1.0","Sid":"test","Answer":"test"}`,
|
|
nil,
|
|
},
|
|
{
|
|
"",
|
|
"",
|
|
`{"type":"offer","sdp":"v=0\r\no=- 4358805017720277108 2 IN IP4 [scrubbed]\r\ns=-\r\nt=0 0\r\na=group:BUNDLE data\r\na=msid-semantic: WMS\r\nm=application 56688 DTLS/SCTP 5000\r\nc=IN IP4 [scrubbed]\r\na=candidate:3769337065 1 udp 2122260223 [scrubbed] 56688 typ host generation 0 network-id 1 network-cost 50\r\na=candidate:2921887769 1 tcp 1518280447 [scrubbed] 35441 typ host tcptype passive generation 0 network-id 1 network-cost 50\r\na=ice-ufrag:aMAZ\r\na=ice-pwd:jcHb08Jjgrazp2dzjdrvPPvV\r\na=ice-options:trickle\r\na=fingerprint:sha-256 C8:88:EE:B9:E7:02:2E:21:37:ED:7A:D1:EB:2B:A3:15:A2:3B:5B:1C:3D:D4:D5:1F:06:CF:52:40:03:F8:DD:66\r\na=setup:actpass\r\na=mid:data\r\na=sctpmap:5000 webrtc-datachannel 1024\r\n"}`,
|
|
fmt.Errorf(""),
|
|
},
|
|
{
|
|
"",
|
|
"",
|
|
`{"Version":"1.0","Answer":"test"}`,
|
|
fmt.Errorf(""),
|
|
},
|
|
{
|
|
"",
|
|
"",
|
|
`{"Version":"1.0","Sid":"test"}`,
|
|
fmt.Errorf(""),
|
|
},
|
|
} {
|
|
answer, sid, err := DecodeAnswerRequest([]byte(test.data))
|
|
So(answer, ShouldResemble, test.answer)
|
|
So(sid, ShouldResemble, test.sid)
|
|
So(err, ShouldHaveSameTypeAs, test.err)
|
|
}
|
|
|
|
})
|
|
}
|
|
|
|
func TestEncodeProxyAnswerRequest(t *testing.T) {
|
|
Convey("Context", t, func() {
|
|
b, err := EncodeAnswerRequest("test answer", "test sid")
|
|
So(err, ShouldEqual, nil)
|
|
answer, sid, err := DecodeAnswerRequest(b)
|
|
So(answer, ShouldEqual, "test answer")
|
|
So(sid, ShouldEqual, "test sid")
|
|
So(err, ShouldEqual, nil)
|
|
})
|
|
}
|
|
|
|
func TestDecodeProxyAnswerResponse(t *testing.T) {
|
|
Convey("Context", t, func() {
|
|
for _, test := range []struct {
|
|
success bool
|
|
data string
|
|
err error
|
|
}{
|
|
{
|
|
true,
|
|
`{"Status":"success"}`,
|
|
nil,
|
|
},
|
|
{
|
|
false,
|
|
`{"Status":"client gone"}`,
|
|
nil,
|
|
},
|
|
{
|
|
false,
|
|
`{"Test":"test"}`,
|
|
fmt.Errorf(""),
|
|
},
|
|
} {
|
|
success, err := DecodeAnswerResponse([]byte(test.data))
|
|
So(success, ShouldResemble, test.success)
|
|
So(err, ShouldHaveSameTypeAs, test.err)
|
|
}
|
|
|
|
})
|
|
}
|
|
|
|
func TestEncodeProxyAnswerResponse(t *testing.T) {
|
|
Convey("Context", t, func() {
|
|
b, err := EncodeAnswerResponse(true)
|
|
So(err, ShouldEqual, nil)
|
|
success, err := DecodeAnswerResponse(b)
|
|
So(success, ShouldEqual, true)
|
|
So(err, ShouldEqual, nil)
|
|
|
|
b, err = EncodeAnswerResponse(false)
|
|
So(err, ShouldEqual, nil)
|
|
success, err = DecodeAnswerResponse(b)
|
|
So(success, ShouldEqual, false)
|
|
So(err, ShouldEqual, nil)
|
|
})
|
|
}
|
|
|
|
func TestDecodeClientPollRequest(t *testing.T) {
|
|
Convey("Context", t, func() {
|
|
for _, test := range []struct {
|
|
natType string
|
|
offer string
|
|
data string
|
|
err error
|
|
}{
|
|
{
|
|
//version 1.0 client message
|
|
"unknown",
|
|
"fake",
|
|
`{"nat":"unknown","offer":"fake"}`,
|
|
nil,
|
|
},
|
|
{
|
|
//version 1.0 client message
|
|
"unknown",
|
|
"fake",
|
|
`{"offer":"fake"}`,
|
|
nil,
|
|
},
|
|
{
|
|
//unknown version
|
|
"",
|
|
"",
|
|
`{"version":"2.0"}`,
|
|
fmt.Errorf(""),
|
|
},
|
|
{
|
|
//no offer
|
|
"",
|
|
"",
|
|
`{"nat":"unknown"}`,
|
|
fmt.Errorf(""),
|
|
},
|
|
} {
|
|
req, err := DecodeClientPollRequest([]byte(test.data))
|
|
if test.err == nil {
|
|
So(req.NAT, ShouldResemble, test.natType)
|
|
So(req.Offer, ShouldResemble, test.offer)
|
|
}
|
|
So(err, ShouldHaveSameTypeAs, test.err)
|
|
}
|
|
|
|
})
|
|
}
|
|
|
|
func TestEncodeClientPollRequests(t *testing.T) {
|
|
Convey("Context", t, func() {
|
|
req1 := &ClientPollRequest{
|
|
NAT: "unknown",
|
|
Offer: "fake",
|
|
}
|
|
b, err := req1.EncodePollRequest()
|
|
So(err, ShouldEqual, nil)
|
|
fmt.Println(string(b))
|
|
parts := bytes.SplitN(b, []byte("\n"), 2)
|
|
So(string(parts[0]), ShouldEqual, "1.0")
|
|
b = parts[1]
|
|
req2, err := DecodeClientPollRequest(b)
|
|
So(err, ShouldEqual, nil)
|
|
So(req2, ShouldResemble, req1)
|
|
})
|
|
}
|
|
|
|
func TestDecodeClientPollResponse(t *testing.T) {
|
|
Convey("Context", t, func() {
|
|
for _, test := range []struct {
|
|
answer string
|
|
msg string
|
|
data string
|
|
}{
|
|
{
|
|
"fake answer",
|
|
"",
|
|
`{"answer":"fake answer"}`,
|
|
},
|
|
{
|
|
"",
|
|
"no snowflakes",
|
|
`{"error":"no snowflakes"}`,
|
|
},
|
|
} {
|
|
resp, err := DecodeClientPollResponse([]byte(test.data))
|
|
So(err, ShouldBeNil)
|
|
So(resp.Answer, ShouldResemble, test.answer)
|
|
So(resp.Error, ShouldResemble, test.msg)
|
|
}
|
|
|
|
})
|
|
}
|
|
|
|
func TestEncodeClientPollResponse(t *testing.T) {
|
|
Convey("Context", t, func() {
|
|
resp1 := &ClientPollResponse{
|
|
Answer: "fake answer",
|
|
}
|
|
b, err := resp1.EncodePollResponse()
|
|
So(err, ShouldEqual, nil)
|
|
resp2, err := DecodeClientPollResponse(b)
|
|
So(err, ShouldEqual, nil)
|
|
So(resp1, ShouldResemble, resp2)
|
|
|
|
resp1 = &ClientPollResponse{
|
|
Error: "failed",
|
|
}
|
|
b, err = resp1.EncodePollResponse()
|
|
So(err, ShouldEqual, nil)
|
|
resp2, err = DecodeClientPollResponse(b)
|
|
So(err, ShouldEqual, nil)
|
|
So(resp1, ShouldResemble, resp2)
|
|
})
|
|
}
|