[tor-commits] [snowflake/master] broker successfully passing client offers to snowflake proxy (#1)

arlo at torproject.org arlo at torproject.org
Thu Jan 21 22:15:14 UTC 2016


commit 7081e6328c34db31fec437aabaac829a9280e0f9
Author: Serene Han <keroserene+git at gmail.com>
Date:   Thu Jan 21 11:40:42 2016 -0800

    broker successfully passing client offers to snowflake proxy (#1)
---
 broker/snowflake-broker.go |   11 ++++----
 proxy/broker.coffee        |   64 +++++++++++++++++++++++++-------------------
 proxy/snowflake.coffee     |   48 +++++++++++++++++++++++----------
 3 files changed, 76 insertions(+), 47 deletions(-)

diff --git a/broker/snowflake-broker.go b/broker/snowflake-broker.go
index 279b2b6..1d26eb1 100644
--- a/broker/snowflake-broker.go
+++ b/broker/snowflake-broker.go
@@ -2,7 +2,7 @@ package snowflake_broker
 
 import (
 	"container/heap"
-	"fmt"
+	// "fmt"
 	"io/ioutil"
 	"log"
 	"net"
@@ -104,8 +104,8 @@ func clientHandler(w http.ResponseWriter, r *http.Request) {
 	// TODO: Make this much better.
 	snowflake := heap.Pop(snowflakes).(*Snowflake)
 	if nil == snowflake {
+		// w.Header().Set("Status", http.StatusServiceUnavailable)
 		w.Write([]byte("no snowflake proxies available"))
-		// w.WriteHeader(http.StatusServiceUnavailable)
 		return
 	}
 	// snowflakes = snowflakes[1:]
@@ -135,10 +135,11 @@ func proxyHandler(w http.ResponseWriter, r *http.Request) {
 		log.Println("Passing client offer to snowflake.")
 		w.Write(offer)
 	case <-time.After(time.Second * 10):
-		s := fmt.Sprintf("%d snowflakes left.", snowflakes.Len())
-		w.Write([]byte("timed out. " + s))
+		// s := fmt.Sprintf("%d snowflakes left.", snowflakes.Len())
+		// w.Write([]byte("timed out. " + s))
+		// w.Header().Set("Status", http.StatusRequestTimeout)
+		w.WriteHeader(http.StatusGatewayTimeout)
 		heap.Remove(snowflakes, snowflake.index)
-		// w.WriteHeader(http.StatusRequestTimeout)
 	}
 }
 
diff --git a/proxy/broker.coffee b/proxy/broker.coffee
index 9432e5c..688d45d 100644
--- a/proxy/broker.coffee
+++ b/proxy/broker.coffee
@@ -5,43 +5,51 @@ Browser snowflakes must register with the broker in order
 to get assigned to clients.
 ###
 
+STATUS_OK = 200
+STATUS_GATEWAY_TIMEOUT = 504
+
 # Represents a broker running remotely.
 class Broker
+
+  clients: 0
+
   # 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
   # to.
   constructor: (@url) ->
     log 'Using Broker at ' + @url
+    clients = 0
 
   # Snowflake registers with the broker using an HTTP POST request, and expects
-  # a response from the broker containing some client offer
-  register: ->
-    # base_url = this.fac_url.replace(/\?.*/, "");
-    # url = base_url + "?" + build_query_string(params);
-    xhr = new XMLHttpRequest()
-    try
-      xhr.open 'POST', @url
-    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
-
-    # xhr.responseType = 'text'
-    xhr.onreadystatechange = ->
-      if xhr.DONE == xhr.readyState
-        log 'Broker: ' + xhr.status
-        if 200 == xhr.status
-          log 'Response: ' + xhr.responseText
-          log xhr
-        else
-          log 'Broker error ' + xhr.status + ' - ' + xhr.statusText
-    xhr.send 'snowflake-testing'
-    log "Broker: sent a registration message, waiting for reply..."
+  # a response from the broker containing some client offer.
+  # TODO: Actually support multiple clients.
+  getClientOffer: ->
+    new Promise (fulfill, reject) =>
+      xhr = new XMLHttpRequest()
+      try
+        xhr.open 'POST', @url
+      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
+      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. Retrying...'
+          else
+            log 'Broker ERROR: Unexpected ' + xhr.status +
+                ' - ' + xhr.statusText
+
+      xhr.send 'snowflake-testing'
+      log "Broker: polling for client offer..."
 
   sendAnswer: (answer) ->
     log 'Sending answer to broker.'
diff --git a/proxy/snowflake.coffee b/proxy/snowflake.coffee
index 1b837d5..646b9b4 100644
--- a/proxy/snowflake.coffee
+++ b/proxy/snowflake.coffee
@@ -9,6 +9,7 @@ this must always act as the answerer.
 ###
 DEFAULT_WEBSOCKET = '192.81.135.242:9901'
 DEFAULT_BROKER = 'https://snowflake-reg.appspot.com/proxy'
+COPY_PASTE_ENABLED = false
 DEFAULT_PORTS =
   http:  80
   https: 443
@@ -58,7 +59,7 @@ class Snowflake
   $badge: null
   state: MODE.INIT
 
-  constructor: ->
+  constructor: (@broker) ->
     if HEADLESS
       # No badge
     else if DEBUG
@@ -98,6 +99,27 @@ class Snowflake
       @makeProxyPair @relayAddr
     @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.
   receiveOffer: (desc) =>
     sdp = new RTCSessionDescription desc
@@ -117,14 +139,6 @@ class Snowflake
     promise = @proxyPair.pc.createAnswer next
     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) ->
     pair = new ProxyPair null, relay, @rateLimit
@@ -156,6 +170,7 @@ class Snowflake
     @badge.die() if @badge
 
 snowflake = null
+broker = null
 
 #
 ## -- DOM & Inputs -- #
@@ -170,7 +185,9 @@ Interface =
   # Local input from keyboard into message window.
   acceptInput: ->
     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
         # Set target relay.
         if !(snowflake.setRelayAddr msg)
@@ -224,10 +241,13 @@ init = ->
   $input.onkeydown = (e) -> $send.onclick() if 13 == e.keyCode  # enter
 
   log '== snowflake browser proxy =='
-  snowflake = new Snowflake()
-  window.snowflake = snowflake
   broker = new Broker DEFAULT_BROKER
-  broker.register()
-  log 'Input desired relay address:'
+  snowflake = new Snowflake(broker)
+  window.snowflake = snowflake
+  if COPY_PASTE_ENABLED
+    log 'Input desired relay address:'
+  else
+    snowflake.setRelayAddr DEFAULT_WEBSOCKET
+    snowflake.findClients()
 
 window.onload = init if window





More information about the tor-commits mailing list