[tor-commits] [snowflake/master] initial client roundtrip estimate on broker

serene at torproject.org serene at torproject.org
Tue Sep 20 13:28:30 UTC 2016


commit 47e1338290359755308825ca66008e2df94cab60
Author: Serene H <git at keroserene.net>
Date:   Tue Sep 20 06:26:21 2016 -0700

    initial client roundtrip estimate on broker
---
 broker/broker.go       | 25 ++++++++++++++++++-------
 broker/metrics.go      | 17 +++++++++++++++++
 client/torrc           |  2 +-
 proxy/snowflake.coffee |  1 +
 4 files changed, 37 insertions(+), 8 deletions(-)

diff --git a/broker/broker.go b/broker/broker.go
index 3c50ac9..3561141 100644
--- a/broker/broker.go
+++ b/broker/broker.go
@@ -26,6 +26,7 @@ type BrokerContext struct {
 	// the second http POST.
 	idToSnowflake map[string]*Snowflake
 	proxyPolls    chan *ProxyPoll
+	metrics       *Metrics
 }
 
 func NewBrokerContext() *BrokerContext {
@@ -35,6 +36,7 @@ func NewBrokerContext() *BrokerContext {
 		snowflakes:    snowflakes,
 		idToSnowflake: make(map[string]*Snowflake),
 		proxyPolls:    make(chan *ProxyPoll),
+		metrics:       new(Metrics),
 	}
 }
 
@@ -67,7 +69,7 @@ func (ctx *BrokerContext) RequestOffer(id string) []byte {
 	request.id = id
 	request.offerChannel = make(chan []byte)
 	ctx.proxyPolls <- request
-	// Block until an offer is available...
+	// Block until an offer is available, or timeout which sends a nil offer.
 	offer := <-request.offerChannel
 	return offer
 }
@@ -96,6 +98,8 @@ func (ctx *BrokerContext) Broker() {
 }
 
 // Create and add a Snowflake to the heap.
+// Required to keep track of proxies between providing them
+// with an offer and awaiting their second POST with an answer.
 func (ctx *BrokerContext) AddSnowflake(id string) *Snowflake {
 	snowflake := new(Snowflake)
 	snowflake.id = id
@@ -141,29 +145,32 @@ snowflake proxy, which responds with the SDP answer to be sent in
 the HTTP response back to the client.
 */
 func clientOffers(ctx *BrokerContext, w http.ResponseWriter, r *http.Request) {
+	startTime := time.Now()
 	offer, err := ioutil.ReadAll(r.Body)
 	if nil != err {
 		log.Println("Invalid data.")
 		w.WriteHeader(http.StatusBadRequest)
 		return
 	}
-
-	// Find the most available snowflake proxy, and pass the offer to it.
-	// TODO: Needs improvement - maybe shouldn't immediately fail?
+	// Immediately fail if there are no snowflakes available.
 	if ctx.snowflakes.Len() <= 0 {
 		log.Println("Client: No snowflake proxies available.")
 		w.WriteHeader(http.StatusServiceUnavailable)
 		return
 	}
+	// Otherwise, find the most available snowflake proxy, and pass the offer to it.
 	snowflake := heap.Pop(ctx.snowflakes).(*Snowflake)
-	defer delete(ctx.idToSnowflake, snowflake.id)
+	delete(ctx.idToSnowflake, snowflake.id)
 	snowflake.offerChannel <- offer
 
-	// Wait for the answer to be returned on the channel.
+	// Wait for the answer to be returned on the channel or timeout.
 	select {
 	case answer := <-snowflake.answerChannel:
 		log.Println("Client: Retrieving answer")
 		w.Write(answer)
+		// Initial tracking of elapsed time.
+		ctx.metrics.clientRoundtripEstimate = time.Since(startTime) /
+			time.Millisecond
 	case <-time.After(time.Second * ClientTimeout):
 		log.Println("Client: Timed out.")
 		w.WriteHeader(http.StatusGatewayTimeout)
@@ -196,7 +203,11 @@ func proxyAnswers(ctx *BrokerContext, w http.ResponseWriter, r *http.Request) {
 }
 
 func debugHandler(ctx *BrokerContext, w http.ResponseWriter, r *http.Request) {
-	s := fmt.Sprintf("current: %d", ctx.snowflakes.Len())
+	s := fmt.Sprintf("current snowflakes available: %d\n", ctx.snowflakes.Len())
+	for _, snowflake := range ctx.idToSnowflake {
+		s += fmt.Sprintf("\nsnowflake %d: %s", snowflake.index, snowflake.id)
+	}
+	s += fmt.Sprintf("\n\nroundtrip avg: %d", ctx.metrics.clientRoundtripEstimate)
 	w.Write([]byte(s))
 }
 
diff --git a/broker/metrics.go b/broker/metrics.go
new file mode 100644
index 0000000..f64d1cc
--- /dev/null
+++ b/broker/metrics.go
@@ -0,0 +1,17 @@
+package snowflake_broker
+
+import (
+	// "golang.org/x/net/internal/timeseries"
+	"time"
+)
+
+// Implements Observable
+type Metrics struct {
+	// snowflakes	timeseries.Float
+	clientRoundtripEstimate time.Duration
+}
+
+func NewMetrics() *Metrics {
+	m := new(Metrics)
+	return m
+}
diff --git a/client/torrc b/client/torrc
index d066454..6912760 100644
--- a/client/torrc
+++ b/client/torrc
@@ -5,6 +5,6 @@ ClientTransportPlugin snowflake exec ./client \
 -url https://snowflake-reg.appspot.com/ \
 -front www.google.com \
 -ice stun:stun.l.google.com:19302 \
--max 1
+-max 3
 
 Bridge snowflake 0.0.3.0:1
diff --git a/proxy/snowflake.coffee b/proxy/snowflake.coffee
index c16694c..8877470 100644
--- a/proxy/snowflake.coffee
+++ b/proxy/snowflake.coffee
@@ -125,6 +125,7 @@ class Snowflake
     try
       offer = JSON.parse desc
       dbg 'Received:\n\n' + offer.sdp + '\n'
+      console.log offer
       sdp = new SessionDescription offer
       @sendAnswer pair if pair.receiveWebRTCOffer sdp
     catch e



More information about the tor-commits mailing list