broker successfully passing client offers to snowflake proxy (#1)

This commit is contained in:
Serene Han 2016-01-21 11:40:42 -08:00
parent 0cd6852ad0
commit 7081e6328c
3 changed files with 75 additions and 46 deletions

View file

@ -2,7 +2,7 @@ package snowflake_broker
import ( import (
"container/heap" "container/heap"
"fmt" // "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"net" "net"
@ -104,8 +104,8 @@ func clientHandler(w http.ResponseWriter, r *http.Request) {
// TODO: Make this much better. // TODO: Make this much better.
snowflake := heap.Pop(snowflakes).(*Snowflake) snowflake := heap.Pop(snowflakes).(*Snowflake)
if nil == snowflake { if nil == snowflake {
// w.Header().Set("Status", http.StatusServiceUnavailable)
w.Write([]byte("no snowflake proxies available")) w.Write([]byte("no snowflake proxies available"))
// w.WriteHeader(http.StatusServiceUnavailable)
return return
} }
// snowflakes = snowflakes[1:] // snowflakes = snowflakes[1:]
@ -135,10 +135,11 @@ func proxyHandler(w http.ResponseWriter, r *http.Request) {
log.Println("Passing client offer to snowflake.") log.Println("Passing client offer to snowflake.")
w.Write(offer) w.Write(offer)
case <-time.After(time.Second * 10): case <-time.After(time.Second * 10):
s := fmt.Sprintf("%d snowflakes left.", snowflakes.Len()) // s := fmt.Sprintf("%d snowflakes left.", snowflakes.Len())
w.Write([]byte("timed out. " + s)) // w.Write([]byte("timed out. " + s))
// w.Header().Set("Status", http.StatusRequestTimeout)
w.WriteHeader(http.StatusGatewayTimeout)
heap.Remove(snowflakes, snowflake.index) heap.Remove(snowflakes, snowflake.index)
// w.WriteHeader(http.StatusRequestTimeout)
} }
} }

View file

@ -5,43 +5,51 @@ Browser snowflakes must register with the broker in order
to get assigned to clients. to get assigned to clients.
### ###
STATUS_OK = 200
STATUS_GATEWAY_TIMEOUT = 504
# Represents a broker running remotely. # Represents a broker running remotely.
class Broker class Broker
clients: 0
# When interacting with the Broker, snowflake must generate a unique session # 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 # ID so the Broker can keep track of which signalling channel it's speaking
# to. # to.
constructor: (@url) -> constructor: (@url) ->
log 'Using Broker at ' + @url log 'Using Broker at ' + @url
clients = 0
# Snowflake registers with the broker using an HTTP POST request, and expects # Snowflake registers with the broker using an HTTP POST request, and expects
# a response from the broker containing some client offer # a response from the broker containing some client offer.
register: -> # TODO: Actually support multiple clients.
# base_url = this.fac_url.replace(/\?.*/, ""); getClientOffer: ->
# url = base_url + "?" + build_query_string(params); new Promise (fulfill, reject) =>
xhr = new XMLHttpRequest() xhr = new XMLHttpRequest()
try try
xhr.open 'POST', @url xhr.open 'POST', @url
catch err catch err
### ###
An exception happens here when, for example, NoScript allows the domain on An exception happens here when, for example, NoScript allows the domain
which the proxy badge runs, but not the domain to which it's trying to on which the proxy badge runs, but not the domain to which it's trying
make the HTTP request. The exception message is like "Component returned to make the HTTP request. The exception message is like "Component
failure code: 0x805e0006 [nsIXMLHttpRequest.open]" on Firefox. returned failure code: 0x805e0006 [nsIXMLHttpRequest.open]" on Firefox.
### ###
log 'Broker: exception while connecting: ' + err.message log 'Broker: exception while connecting: ' + err.message
return return
# xhr.responseType = 'text'
xhr.onreadystatechange = -> xhr.onreadystatechange = ->
if xhr.DONE == xhr.readyState return if xhr.DONE != xhr.readyState
log 'Broker: ' + xhr.status switch xhr.status
if 200 == xhr.status when STATUS_OK
log 'Response: ' + xhr.responseText fulfill xhr.responseText # Should contain offer.
log xhr when STATUS_GATEWAY_TIMEOUT
reject 'Timed out waiting for a client to serve. Retrying...'
else else
log 'Broker error ' + xhr.status + ' - ' + xhr.statusText log 'Broker ERROR: Unexpected ' + xhr.status +
' - ' + xhr.statusText
xhr.send 'snowflake-testing' xhr.send 'snowflake-testing'
log "Broker: sent a registration message, waiting for reply..." log "Broker: polling for client offer..."
sendAnswer: (answer) -> sendAnswer: (answer) ->
log 'Sending answer to broker.' log 'Sending answer to broker.'

View file

@ -9,6 +9,7 @@ this must always act as the answerer.
### ###
DEFAULT_WEBSOCKET = '192.81.135.242:9901' DEFAULT_WEBSOCKET = '192.81.135.242:9901'
DEFAULT_BROKER = 'https://snowflake-reg.appspot.com/proxy' DEFAULT_BROKER = 'https://snowflake-reg.appspot.com/proxy'
COPY_PASTE_ENABLED = false
DEFAULT_PORTS = DEFAULT_PORTS =
http: 80 http: 80
https: 443 https: 443
@ -58,7 +59,7 @@ class Snowflake
$badge: null $badge: null
state: MODE.INIT state: MODE.INIT
constructor: -> constructor: (@broker) ->
if HEADLESS if HEADLESS
# No badge # No badge
else if DEBUG else if DEBUG
@ -98,6 +99,27 @@ class Snowflake
@makeProxyPair @relayAddr @makeProxyPair @relayAddr
@proxyPair = @proxyPairs[0] @proxyPair = @proxyPairs[0]
# Poll broker for clients.
findClients: ->
poll = =>
recv = broker.getClientOffer()
recv.then((desc) =>
log 'Received:\n\n' + desc + '\n'
offer = JSON.parse desc
@receiveOffer offer
, (err) ->
log err
setTimeout(poll, 1000)
)
poll()
# if @proxyPairs.length >= MAX_NUM_CLIENTS * CONNECTIONS_PER_CLIENT
# setTimeout(@proxyMain, @broker_poll_interval * 1000)
# return
# params = [['r', '1']]
# params.push ['transport', 'websocket']
# params.push ['transport', 'webrtc']
# Receive an SDP offer from client plugin. # Receive an SDP offer from client plugin.
receiveOffer: (desc) => receiveOffer: (desc) =>
sdp = new RTCSessionDescription desc sdp = new RTCSessionDescription desc
@ -117,14 +139,6 @@ class Snowflake
promise = @proxyPair.pc.createAnswer next promise = @proxyPair.pc.createAnswer next
promise.then next if promise promise.then next if promise
# Poll broker when this snowflake can support more clients.
proxyMain: ->
if @proxyPairs.length >= MAX_NUM_CLIENTS * CONNECTIONS_PER_CLIENT
setTimeout(@proxyMain, @broker_poll_interval * 1000)
return
params = [['r', '1']]
params.push ['transport', 'websocket']
params.push ['transport', 'webrtc']
makeProxyPair: (relay) -> makeProxyPair: (relay) ->
pair = new ProxyPair null, relay, @rateLimit pair = new ProxyPair null, relay, @rateLimit
@ -156,6 +170,7 @@ class Snowflake
@badge.die() if @badge @badge.die() if @badge
snowflake = null snowflake = null
broker = null
# #
## -- DOM & Inputs -- # ## -- DOM & Inputs -- #
@ -170,7 +185,9 @@ Interface =
# Local input from keyboard into message window. # Local input from keyboard into message window.
acceptInput: -> acceptInput: ->
msg = $input.value msg = $input.value
switch snowflake.state if !COPY_PASTE_ENABLED
log 'No input expected - Copy Paste Signalling disabled.'
else switch snowflake.state
when MODE.INIT when MODE.INIT
# Set target relay. # Set target relay.
if !(snowflake.setRelayAddr msg) if !(snowflake.setRelayAddr msg)
@ -224,10 +241,13 @@ init = ->
$input.onkeydown = (e) -> $send.onclick() if 13 == e.keyCode # enter $input.onkeydown = (e) -> $send.onclick() if 13 == e.keyCode # enter
log '== snowflake browser proxy ==' log '== snowflake browser proxy =='
snowflake = new Snowflake()
window.snowflake = snowflake
broker = new Broker DEFAULT_BROKER broker = new Broker DEFAULT_BROKER
broker.register() snowflake = new Snowflake(broker)
window.snowflake = snowflake
if COPY_PASTE_ENABLED
log 'Input desired relay address:' log 'Input desired relay address:'
else
snowflake.setRelayAddr DEFAULT_WEBSOCKET
snowflake.findClients()
window.onload = init if window window.onload = init if window