Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions broker/broker.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@ import (
)

const (
ClientTimeout = 10
ProxyTimeout = 10
readLimit = 100000 //Maximum number of bytes to be read from an HTTP request
LatestProxyVersion = "1.0"
ClientTimeout = 10
ProxyTimeout = 10
readLimit = 100000 //Maximum number of bytes to be read from an HTTP request
)

type BrokerContext struct {
Expand Down Expand Up @@ -170,12 +171,14 @@ func proxyPolls(ctx *BrokerContext, w http.ResponseWriter, r *http.Request) {
return
}

sid, proxyType, err := messages.DecodePollRequest(body)
sid, proxyType, proxyVersion, err := messages.DecodePollRequest(body)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}

update := (proxyVersion != LatestProxyVersion)

// Log geoip stats
remoteIP, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil {
Expand All @@ -194,7 +197,7 @@ func proxyPolls(ctx *BrokerContext, w http.ResponseWriter, r *http.Request) {
ctx.metrics.proxyIdleCount++
ctx.metrics.lock.Unlock()

b, err = messages.EncodePollResponse("", false)
b, err = messages.EncodePollResponse("", false, update)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
Expand All @@ -203,7 +206,7 @@ func proxyPolls(ctx *BrokerContext, w http.ResponseWriter, r *http.Request) {
w.Write(b)
return
}
b, err = messages.EncodePollResponse(string(offer), true)
b, err = messages.EncodePollResponse(string(offer), true, update)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
Expand Down
6 changes: 3 additions & 3 deletions broker/snowflake-broker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ func TestBroker(t *testing.T) {
p.offerChannel <- []byte("fake offer")
<-done
So(w.Code, ShouldEqual, http.StatusOK)
So(w.Body.String(), ShouldEqual, `{"Status":"client match","Offer":"fake offer"}`)
So(w.Body.String(), ShouldEqual, `{"Status":"client match","Update":true,"Offer":"fake offer"}`)
})

Convey("return empty 200 OK when no client offer is available.", func() {
Expand All @@ -141,7 +141,7 @@ func TestBroker(t *testing.T) {
// nil means timeout
p.offerChannel <- nil
<-done
So(w.Body.String(), ShouldEqual, `{"Status":"no match","Offer":""}`)
So(w.Body.String(), ShouldEqual, `{"Status":"no match","Update":true,"Offer":""}`)
So(w.Code, ShouldEqual, http.StatusOK)
})
})
Expand Down Expand Up @@ -279,7 +279,7 @@ func TestBroker(t *testing.T) {

<-polled
So(wP.Code, ShouldEqual, http.StatusOK)
So(wP.Body.String(), ShouldResemble, `{"Status":"client match","Offer":"fake offer"}`)
So(wP.Body.String(), ShouldResemble, `{"Status":"client match","Update":true,"Offer":"fake offer"}`)
So(ctx.idToSnowflake["ymbcCMto7KHNGYlp"], ShouldNotBeNil)
// Follow up with the answer request afterwards
wA := httptest.NewRecorder()
Expand Down
56 changes: 32 additions & 24 deletions common/messages/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ import (
"strings"
)

const version = "1.1"
const version = "1.2"

/* Version 1.1 specification:
/* Version 1.2 specification:

== ProxyPollRequest ==
{
Sid: [generated session id of proxy],
Version: 1.1,
Version: 1.2,
ProxyVersion: Major.Minor,
Type: ["badge"|"webext"|"standalone"]
}

Expand All @@ -29,13 +30,15 @@ HTTP 200 OK
type: offer,
sdp: [WebRTC SDP]
}
Update: [true|false]
}

2) If a client is not matched:
HTTP 200 OK

{
Status: "no match"
Status: "no match",
Update: [true|false]
}

3) If the request is malformed:
Expand All @@ -44,7 +47,7 @@ HTTP 400 BadRequest
== ProxyAnswerRequest ==
{
Sid: [generated session id of proxy],
Version: 1.1,
Version: 1.2,
Answer:
{
type: answer,
Expand Down Expand Up @@ -73,82 +76,87 @@ HTTP 400 BadRequest
*/

type ProxyPollRequest struct {
Sid string
Version string
Type string
Sid string
Version string
ProxyVersion string
Type string
}

func EncodePollRequest(sid string, proxyType string) ([]byte, error) {
func EncodePollRequest(sid string, proxyType string, proxyVersion string) ([]byte, error) {
return json.Marshal(ProxyPollRequest{
Sid: sid,
Version: version,
Type: proxyType,
Sid: sid,
Version: version,
ProxyVersion: proxyVersion,
Type: proxyType,
})
}

// Decodes a poll message from a snowflake proxy and returns the
// sid and proxy type of the proxy on success and an error if it failed
func DecodePollRequest(data []byte) (string, string, error) {
func DecodePollRequest(data []byte) (string, string, string, error) {
var message ProxyPollRequest

err := json.Unmarshal(data, &message)
if err != nil {
return "", "", err
return "", "", "", err
}

majorVersion := strings.Split(message.Version, ".")[0]
if majorVersion != "1" {
return "", "", fmt.Errorf("using unknown version")
return "", "", "", fmt.Errorf("using unknown version")
}

// Version 1.x requires an Sid
if message.Sid == "" {
return "", "", fmt.Errorf("no supplied session id")
return "", "", "", fmt.Errorf("no supplied session id")
}

return message.Sid, message.Type, nil
return message.Sid, message.Type, message.ProxyVersion, nil
}

type ProxyPollResponse struct {
Status string
Update bool
Offer string
}

func EncodePollResponse(offer string, success bool) ([]byte, error) {
func EncodePollResponse(offer string, success bool, update bool) ([]byte, error) {
if success {
return json.Marshal(ProxyPollResponse{
Status: "client match",
Offer: offer,
Update: update,
})

}
return json.Marshal(ProxyPollResponse{
Status: "no match",
Update: update,
})
}

// Decodes a poll response from the broker and returns an offer
// If there is a client match, the returned offer string will be non-empty
func DecodePollResponse(data []byte) (string, error) {
func DecodePollResponse(data []byte) (string, bool, error) {
var message ProxyPollResponse

err := json.Unmarshal(data, &message)
if err != nil {
return "", err
return "", false, err
}
if message.Status == "" {
return "", fmt.Errorf("received invalid data")
return "", false, fmt.Errorf("received invalid data")
}

if message.Status == "client match" {
if message.Offer == "" {
return "", fmt.Errorf("no supplied offer")
return "", false, fmt.Errorf("no supplied offer")
}
} else {
message.Offer = ""
}

return message.Offer, nil
return message.Offer, message.Update, nil
}

type ProxyAnswerRequest struct {
Expand All @@ -159,7 +167,7 @@ type ProxyAnswerRequest struct {

func EncodeAnswerRequest(answer string, sid string) ([]byte, error) {
return json.Marshal(ProxyAnswerRequest{
Version: "1.1",
Version: "1.2",
Sid: sid,
Answer: answer,
})
Expand Down
Loading