[tor-commits] [snowflake/master] Complete broker spec cases
serene at torproject.org
serene at torproject.org
Wed Feb 10 22:04:10 UTC 2016
commit 4f18340c163c18d4bcad249b4e4976d3106cd014
Author: Serene Han <keroserene+git at gmail.com>
Date: Wed Feb 10 13:05:21 2016 -0800
Complete broker spec cases
---
proxy/broker.coffee | 67 +++++++++++++++---------------
proxy/spec/broker.spec.coffee | 94 +++++++++++++++++++++++++++++++------------
2 files changed, 102 insertions(+), 59 deletions(-)
diff --git a/proxy/broker.coffee b/proxy/broker.coffee
index 71fe6eb..e989d57 100644
--- a/proxy/broker.coffee
+++ b/proxy/broker.coffee
@@ -9,6 +9,9 @@ STATUS_OK = 200
STATUS_GONE = 410
STATUS_GATEWAY_TIMEOUT = 504
+MESSAGE_TIMEOUT = 'Timed out waiting for a client offer.'
+MESSAGE_UNEXPECTED = 'Unexpected status.'
+
genSnowflakeID = ->
Math.random().toString(36).substring(2)
@@ -17,7 +20,6 @@ class Broker
clients: 0
id: null
- request: null
# When interacting with the Broker, snowflake must generate a unique session
# ID so the Broker can keep track of which signalling channel it's speaking
@@ -29,53 +31,35 @@ class Broker
@url = 'https://' + @url if 0 != @url.indexOf('https://', 0)
@url += '/' if '/' != @url.substr -1
- # Snowflake registers with the broker using an HTTP POST request, and expects
- # a response from the broker containing some client offer.
+ # Promises some client SDP Offer.
+ # Registers this Snowfalke with the broker using an HTTP POST request, and
+ # waits for a response containing some client offer that the Broker chooses
+ # for this proxy..
# TODO: Actually support multiple clients.
getClientOffer: =>
new Promise (fulfill, reject) =>
xhr = new XMLHttpRequest()
- @request = xhr
- @fulfill = fulfill
- # @request.onreadystatechange = @processOffer
- xhr.onreadystatechange = =>
+ xhr.onreadystatechange = ->
return if xhr.DONE != xhr.readyState
switch xhr.status
when STATUS_OK
fulfill xhr.responseText # Should contain offer.
when STATUS_GATEWAY_TIMEOUT
- reject 'Timed out waiting for a client to serve.'
+ reject MESSAGE_TIMEOUT
else
log 'Broker ERROR: Unexpected ' + xhr.status +
' - ' + xhr.statusText
- Status.set ' failure. Please refresh.'
- @sendRequest()
-
- sendRequest: =>
- try
- @request.open 'POST', @url + 'proxy'
- @request.setRequestHeader('X-Session-ID', @id)
- catch err
- ###
- An exception happens here when, for example, NoScript allows the domain
- on which the proxy badge runs, but not the domain to which it's trying
- to make the HTTP request. The exception message is like "Component
- returned failure code: 0x805e0006 [nsIXMLHttpRequest.open]" on Firefox.
- ###
- log 'Broker: exception while connecting: ' + err.message
- return
- @request.send @id
+ snowflake.ui.setStatus ' failure. Please refresh.'
+ reject MESSAGE_UNEXPECTED
+ @_xhr = xhr # Used by spec to fake async Broker interaction
+ @_postRequest xhr, 'proxy', @id
+ # Assumes getClientOffer happened, and a WebRTC SDP answer has been generated.
+ # Sends it back to the broker, which passes it to back to the original client.
sendAnswer: (answer) ->
dbg @id + ' - Sending answer back to broker...\n'
dbg answer.sdp
xhr = new XMLHttpRequest()
- try
- xhr.open 'POST', @url + 'answer'
- xhr.setRequestHeader('X-Session-ID', @id)
- catch err
- log 'Broker: exception while connecting: ' + err.message
- return
xhr.onreadystatechange = ->
return if xhr.DONE != xhr.readyState
switch xhr.status
@@ -87,5 +71,22 @@ class Broker
else
dbg 'Broker ERROR: Unexpected ' + xhr.status +
' - ' + xhr.statusText
- Status.set ' failure. Please refresh.'
- xhr.send JSON.stringify(answer)
+ snowflake.ui.setStatus ' failure. Please refresh.'
+ @_postRequest xhr, 'answer', JSON.stringify(answer)
+
+ # urlSuffix for the broker is different depending on what action
+ # is desired.
+ _postRequest: (xhr, urlSuffix, payload) =>
+ try
+ xhr.open 'POST', @url + urlSuffix
+ xhr.setRequestHeader('X-Session-ID', @id)
+ catch err
+ ###
+ An exception happens here when, for example, NoScript allows the domain
+ on which the proxy badge runs, but not the domain to which it's trying
+ to make the HTTP xhr. The exception message is like "Component
+ returned failure code: 0x805e0006 [nsIXMLHttpRequest.open]" on Firefox.
+ ###
+ log 'Broker: exception while connecting: ' + err.message
+ return
+ xhr.send payload
diff --git a/proxy/spec/broker.spec.coffee b/proxy/spec/broker.spec.coffee
index 3b47cd3..db936c1 100644
--- a/proxy/spec/broker.spec.coffee
+++ b/proxy/spec/broker.spec.coffee
@@ -19,32 +19,74 @@ describe 'Broker', ->
expect(b.url).toEqual 'https://fake/'
expect(b.id).not.toBeNull()
- it 'polls and promises a client offer', (done) ->
- b = new Broker 'fake'
- # fake successful request
- spyOn(b, 'sendRequest').and.callFake ->
- b.request.readyState = b.request.DONE
- b.request.status = STATUS_OK
- b.request.responseText = 'test'
- b.request.onreadystatechange()
- poll = b.getClientOffer()
- expect(poll).not.toBeNull()
- poll.then (desc) =>
- expect(desc).toEqual 'test'
- done()
-
- it 'requests correctly', ->
- b = new Broker 'fake'
- b.request = new XMLHttpRequest()
- spyOn(b.request, 'open')
- spyOn(b.request, 'setRequestHeader')
- spyOn(b.request, 'send')
- b.sendRequest()
- expect(b.request.open).toHaveBeenCalled()
- expect(b.request.setRequestHeader).toHaveBeenCalled()
- expect(b.request.send).toHaveBeenCalled()
+ describe 'getClientOffer', ->
+ it 'polls and promises a client offer', (done) ->
+ b = new Broker 'fake'
+ # fake successful request and response from broker.
+ spyOn(b, '_postRequest').and.callFake ->
+ b._xhr.readyState = b._xhr.DONE
+ b._xhr.status = STATUS_OK
+ b._xhr.responseText = 'fake offer'
+ b._xhr.onreadystatechange()
+ poll = b.getClientOffer()
+ expect(poll).not.toBeNull()
+ expect(b._postRequest).toHaveBeenCalled()
+ poll.then (desc) ->
+ expect(desc).toEqual 'fake offer'
+ done()
+ .catch ->
+ fail 'should not reject on STATUS_OK'
+ done()
+
+ it 'rejects if the broker timed-out', (done) ->
+ b = new Broker 'fake'
+ # fake timed-out request from broker
+ spyOn(b, '_postRequest').and.callFake ->
+ b._xhr.readyState = b._xhr.DONE
+ b._xhr.status = STATUS_GATEWAY_TIMEOUT
+ b._xhr.onreadystatechange()
+ poll = b.getClientOffer()
+ expect(poll).not.toBeNull()
+ expect(b._postRequest).toHaveBeenCalled()
+ poll.then (desc) ->
+ fail 'should not fulfill on GATEWAY_TIMEOUT'
+ done()
+ , (err) ->
+ expect(err).toBe MESSAGE_TIMEOUT
+ done()
+
+ it 'rejects on any other status', (done) ->
+ b = new Broker 'fake'
+ # fake timed-out request from broker
+ spyOn(b, '_postRequest').and.callFake ->
+ b._xhr.readyState = b._xhr.DONE
+ b._xhr.status = 1337
+ b._xhr.onreadystatechange()
+ poll = b.getClientOffer()
+ expect(poll).not.toBeNull()
+ expect(b._postRequest).toHaveBeenCalled()
+ poll.then (desc) ->
+ fail 'should not fulfill on non-OK status'
+ done()
+ , (err) ->
+ expect(err).toBe MESSAGE_UNEXPECTED
+ expect(b._xhr.status).toBe 1337
+ done()
it 'responds to the broker with answer', ->
- # TODO: fix
b = new Broker 'fake'
- b.sendAnswer 'foo'
+ spyOn(b, '_postRequest')
+ b.sendAnswer 123
+ expect(b._postRequest).toHaveBeenCalledWith(
+ jasmine.any(Object), 'answer', '123')
+
+ it 'POST XMLHttpRequests to the broker', ->
+ b = new Broker 'fake'
+ b._xhr = new XMLHttpRequest()
+ spyOn(b._xhr, 'open')
+ spyOn(b._xhr, 'setRequestHeader')
+ spyOn(b._xhr, 'send')
+ b._postRequest b._xhr, 'test', 'data'
+ expect(b._xhr.open).toHaveBeenCalled()
+ expect(b._xhr.setRequestHeader).toHaveBeenCalled()
+ expect(b._xhr.send).toHaveBeenCalled()
More information about the tor-commits
mailing list