mirror of
https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake.git
synced 2025-10-13 11:11:30 -04:00
Redo protocol for proxy--broker messages
Switch to containing all communication between the proxy and the broker in the HTTP response body. This will make things easier if we ever use something other than HTTP communicate between different actors in the snowflake system. Other changes to the protocol are as follows: - requests are accompanied by a version number so the broker can be backwards compatable if desired in the future - all responses are 200 OK unless the request was badly formatted
This commit is contained in:
parent
abefae1587
commit
c4ae64905b
6 changed files with 489 additions and 53 deletions
|
@ -113,9 +113,8 @@ func TestBroker(t *testing.T) {
|
|||
Convey("Responds to proxy polls...", func() {
|
||||
done := make(chan bool)
|
||||
w := httptest.NewRecorder()
|
||||
data := bytes.NewReader([]byte("test"))
|
||||
data := bytes.NewReader([]byte(`{"Sid":"ymbcCMto7KHNGYlp","Version":"1.0"}`))
|
||||
r, err := http.NewRequest("POST", "snowflake.broker/proxy", data)
|
||||
r.Header.Set("X-Session-ID", "test")
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
Convey("with a client offer if available.", func() {
|
||||
|
@ -125,57 +124,59 @@ func TestBroker(t *testing.T) {
|
|||
}(ctx)
|
||||
// Pass a fake client offer to this proxy
|
||||
p := <-ctx.proxyPolls
|
||||
So(p.id, ShouldEqual, "test")
|
||||
So(p.id, ShouldEqual, "ymbcCMto7KHNGYlp")
|
||||
p.offerChannel <- []byte("fake offer")
|
||||
<-done
|
||||
So(w.Code, ShouldEqual, http.StatusOK)
|
||||
So(w.Body.String(), ShouldEqual, "fake offer")
|
||||
So(w.Body.String(), ShouldEqual, `{"Status":"client match","Offer":"fake offer"}`)
|
||||
})
|
||||
|
||||
Convey("times out when no client offer is available.", func() {
|
||||
Convey("return empty 200 OK when no client offer is available.", func() {
|
||||
go func(ctx *BrokerContext) {
|
||||
proxyPolls(ctx, w, r)
|
||||
done <- true
|
||||
}(ctx)
|
||||
p := <-ctx.proxyPolls
|
||||
So(p.id, ShouldEqual, "test")
|
||||
So(p.id, ShouldEqual, "ymbcCMto7KHNGYlp")
|
||||
// nil means timeout
|
||||
p.offerChannel <- nil
|
||||
<-done
|
||||
So(w.Body.String(), ShouldEqual, "")
|
||||
So(w.Code, ShouldEqual, http.StatusGatewayTimeout)
|
||||
So(w.Body.String(), ShouldEqual, `{"Status":"no match","Offer":""}`)
|
||||
So(w.Code, ShouldEqual, http.StatusOK)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("Responds to proxy answers...", func() {
|
||||
s := ctx.AddSnowflake("test")
|
||||
w := httptest.NewRecorder()
|
||||
data := bytes.NewReader([]byte("fake answer"))
|
||||
data := bytes.NewReader([]byte(`{"Version":"1.0","Sid":"test","Answer":"test"}`))
|
||||
|
||||
Convey("by passing to the client if valid.", func() {
|
||||
r, err := http.NewRequest("POST", "snowflake.broker/answer", data)
|
||||
So(err, ShouldBeNil)
|
||||
r.Header.Set("X-Session-ID", "test")
|
||||
go func(ctx *BrokerContext) {
|
||||
proxyAnswers(ctx, w, r)
|
||||
}(ctx)
|
||||
answer := <-s.answerChannel
|
||||
So(w.Code, ShouldEqual, http.StatusOK)
|
||||
So(answer, ShouldResemble, []byte("fake answer"))
|
||||
So(answer, ShouldResemble, []byte("test"))
|
||||
})
|
||||
|
||||
Convey("with error if the proxy is not recognized", func() {
|
||||
r, err := http.NewRequest("POST", "snowflake.broker/answer", nil)
|
||||
Convey("with client gone status if the proxy is not recognized", func() {
|
||||
data = bytes.NewReader([]byte(`{"Version":"1.0","Sid":"invalid","Answer":"test"}`))
|
||||
r, err := http.NewRequest("POST", "snowflake.broker/answer", data)
|
||||
So(err, ShouldBeNil)
|
||||
r.Header.Set("X-Session-ID", "invalid")
|
||||
proxyAnswers(ctx, w, r)
|
||||
So(w.Code, ShouldEqual, http.StatusGone)
|
||||
So(w.Code, ShouldEqual, http.StatusOK)
|
||||
b, err := ioutil.ReadAll(w.Body)
|
||||
So(err, ShouldBeNil)
|
||||
So(b, ShouldResemble, []byte(`{"Status":"client gone"}`))
|
||||
|
||||
})
|
||||
|
||||
Convey("with error if the proxy gives invalid answer", func() {
|
||||
data := bytes.NewReader(nil)
|
||||
r, err := http.NewRequest("POST", "snowflake.broker/answer", data)
|
||||
r.Header.Set("X-Session-ID", "test")
|
||||
So(err, ShouldBeNil)
|
||||
proxyAnswers(ctx, w, r)
|
||||
So(w.Code, ShouldEqual, http.StatusBadRequest)
|
||||
|
@ -184,7 +185,6 @@ func TestBroker(t *testing.T) {
|
|||
Convey("with error if the proxy writes too much data", func() {
|
||||
data := bytes.NewReader(make([]byte, 100001))
|
||||
r, err := http.NewRequest("POST", "snowflake.broker/answer", data)
|
||||
r.Header.Set("X-Session-ID", "test")
|
||||
So(err, ShouldBeNil)
|
||||
proxyAnswers(ctx, w, r)
|
||||
So(w.Code, ShouldEqual, http.StatusBadRequest)
|
||||
|
@ -199,11 +199,10 @@ func TestBroker(t *testing.T) {
|
|||
ctx := NewBrokerContext(NullLogger())
|
||||
|
||||
// Proxy polls with its ID first...
|
||||
dataP := bytes.NewReader([]byte("test"))
|
||||
dataP := bytes.NewReader([]byte(`{"Sid":"ymbcCMto7KHNGYlp","Version":"1.0"}`))
|
||||
wP := httptest.NewRecorder()
|
||||
rP, err := http.NewRequest("POST", "snowflake.broker/proxy", dataP)
|
||||
So(err, ShouldBeNil)
|
||||
rP.Header.Set("X-Session-ID", "test")
|
||||
go func() {
|
||||
proxyPolls(ctx, wP, rP)
|
||||
polled <- true
|
||||
|
@ -211,13 +210,13 @@ func TestBroker(t *testing.T) {
|
|||
|
||||
// Manually do the Broker goroutine action here for full control.
|
||||
p := <-ctx.proxyPolls
|
||||
So(p.id, ShouldEqual, "test")
|
||||
So(p.id, ShouldEqual, "ymbcCMto7KHNGYlp")
|
||||
s := ctx.AddSnowflake(p.id)
|
||||
go func() {
|
||||
offer := <-s.offerChannel
|
||||
p.offerChannel <- offer
|
||||
}()
|
||||
So(ctx.idToSnowflake["test"], ShouldNotBeNil)
|
||||
So(ctx.idToSnowflake["ymbcCMto7KHNGYlp"], ShouldNotBeNil)
|
||||
|
||||
// Client request blocks until proxy answer arrives.
|
||||
dataC := bytes.NewReader([]byte("fake offer"))
|
||||
|
@ -231,20 +230,19 @@ func TestBroker(t *testing.T) {
|
|||
|
||||
<-polled
|
||||
So(wP.Code, ShouldEqual, http.StatusOK)
|
||||
So(wP.Body.String(), ShouldResemble, "fake offer")
|
||||
So(ctx.idToSnowflake["test"], ShouldNotBeNil)
|
||||
So(wP.Body.String(), ShouldResemble, `{"Status":"client match","Offer":"fake offer"}`)
|
||||
So(ctx.idToSnowflake["ymbcCMto7KHNGYlp"], ShouldNotBeNil)
|
||||
// Follow up with the answer request afterwards
|
||||
wA := httptest.NewRecorder()
|
||||
dataA := bytes.NewReader([]byte("fake answer"))
|
||||
rA, err := http.NewRequest("POST", "snowflake.broker/proxy", dataA)
|
||||
dataA := bytes.NewReader([]byte(`{"Version":"1.0","Sid":"ymbcCMto7KHNGYlp","Answer":"test"}`))
|
||||
rA, err := http.NewRequest("POST", "snowflake.broker/answer", dataA)
|
||||
So(err, ShouldBeNil)
|
||||
rA.Header.Set("X-Session-ID", "test")
|
||||
proxyAnswers(ctx, wA, rA)
|
||||
So(wA.Code, ShouldEqual, http.StatusOK)
|
||||
|
||||
<-done
|
||||
So(wC.Code, ShouldEqual, http.StatusOK)
|
||||
So(wC.Body.String(), ShouldEqual, "fake answer")
|
||||
So(wC.Body.String(), ShouldEqual, "test")
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -408,7 +406,7 @@ func TestMetrics(t *testing.T) {
|
|||
//Test addition of proxy polls
|
||||
Convey("for proxy polls", func() {
|
||||
w := httptest.NewRecorder()
|
||||
data := bytes.NewReader([]byte("test"))
|
||||
data := bytes.NewReader([]byte("{\"Sid\":\"ymbcCMto7KHNGYlp\",\"Version\":\"1.0\"}"))
|
||||
r, err := http.NewRequest("POST", "snowflake.broker/proxy", data)
|
||||
r.Header.Set("X-Session-ID", "test")
|
||||
r.RemoteAddr = "129.97.208.23:8888" //CA geoip
|
||||
|
@ -492,7 +490,7 @@ func TestMetrics(t *testing.T) {
|
|||
//Test unique ip
|
||||
Convey("proxy counts by unique ip", func() {
|
||||
w := httptest.NewRecorder()
|
||||
data := bytes.NewReader([]byte("test"))
|
||||
data := bytes.NewReader([]byte(`{"Sid":"ymbcCMto7KHNGYlp","Version":"1.0"}`))
|
||||
r, err := http.NewRequest("POST", "snowflake.broker/proxy", data)
|
||||
r.Header.Set("X-Session-ID", "test")
|
||||
r.RemoteAddr = "129.97.208.23:8888" //CA geoip
|
||||
|
@ -505,7 +503,7 @@ func TestMetrics(t *testing.T) {
|
|||
p.offerChannel <- nil
|
||||
<-done
|
||||
|
||||
data = bytes.NewReader([]byte("test"))
|
||||
data = bytes.NewReader([]byte(`{"Sid":"ymbcCMto7KHNGYlp","Version":"1.0"}`))
|
||||
r, err = http.NewRequest("POST", "snowflake.broker/proxy", data)
|
||||
if err != nil {
|
||||
log.Printf("unable to get NewRequest with error: %v", err)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue