[tor-commits] [snowflake/master] Use reconnect timeout on client (#12)

serene at torproject.org serene at torproject.org
Thu Feb 18 22:15:38 UTC 2016


commit 8a2e7a6041f367a86e3c75df39b010c34649d3b7
Author: Serene Han <keroserene+git at gmail.com>
Date:   Wed Feb 17 19:53:11 2016 -0800

    Use reconnect timeout on client (#12)
---
 client/client_test.go |  7 +++++++
 client/rendezvous.go  |  4 ++++
 client/snowflake.go   | 50 +++++++++++++++++++++++++-------------------------
 3 files changed, 36 insertions(+), 25 deletions(-)

diff --git a/client/client_test.go b/client/client_test.go
index 399549a..546382f 100644
--- a/client/client_test.go
+++ b/client/client_test.go
@@ -39,6 +39,13 @@ func TestConnect(t *testing.T) {
 				So(mock.destination.Bytes(), ShouldResemble, []byte("test"))
 			})
 
+			Convey("Receive answer fails on nil answer", func() {
+				c.reset = make(chan struct{})
+				c.ReceiveAnswer()
+				answerChannel <- nil
+				<-c.reset
+			})
+
 			Convey("Connect Loop", func() {
 				// TODO
 			})
diff --git a/client/rendezvous.go b/client/rendezvous.go
index ea0b338..fe75b09 100644
--- a/client/rendezvous.go
+++ b/client/rendezvous.go
@@ -5,6 +5,7 @@ package main
 
 import (
 	"bytes"
+	"errors"
 	"io/ioutil"
 	"log"
 	"net/http"
@@ -66,6 +67,9 @@ func (bc *BrokerChannel) Negotiate(offer *webrtc.SessionDescription) (
 	}
 	defer resp.Body.Close()
 	log.Printf("BrokerChannel Response:\n%s\n\n", resp.Status)
+	if http.StatusOK != resp.StatusCode {
+		return nil, errors.New("no answer from broker.")
+	}
 	body, err := ioutil.ReadAll(resp.Body)
 	if nil != err {
 		return nil, err
diff --git a/client/snowflake.go b/client/snowflake.go
index 907c8ae..6d612ce 100644
--- a/client/snowflake.go
+++ b/client/snowflake.go
@@ -58,7 +58,7 @@ type SnowflakeChannel interface {
 
 // Implements net.Conn interface
 type webRTCConn struct {
-	config			 *webrtc.Configuration
+	config       *webrtc.Configuration
 	pc           *webrtc.PeerConnection
 	snowflake    SnowflakeChannel // Interface holding the WebRTC DataChannel.
 	broker       *BrokerChannel
@@ -108,7 +108,6 @@ func (c *webRTCConn) SetWriteDeadline(t time.Time) error {
 
 func (c *webRTCConn) PreparePeerConnection() {
 	if nil != c.pc {
-		log.Printf("PeerConnection already exists.")
 		c.pc.Close()
 		c.pc = nil
 	}
@@ -135,12 +134,12 @@ func (c *webRTCConn) PreparePeerConnection() {
 		}()
 	}
 	pc.OnIceCandidate = func(candidate webrtc.IceCandidate) {
-		log.Printf("OnIceCandidate %s", candidate.Serialize())
+		log.Printf("WebRTC: OnIceCandidate %s", candidate.Serialize())
 		// Allow candidates to accumulate until OnIceComplete.
 	}
 	// TODO: This may soon be deprecated, consider OnIceGatheringStateChange.
 	pc.OnIceComplete = func() {
-		log.Printf("OnIceComplete")
+		log.Printf("WebRTC: OnIceComplete")
 		c.offerChannel <- pc.LocalDescription()
 	}
 	// This callback is not expected, as the Client initiates the creation
@@ -150,6 +149,7 @@ func (c *webRTCConn) PreparePeerConnection() {
 		panic("Unexpected OnDataChannel!")
 	}
 	c.pc = pc
+	log.Println("WebRTC: PeerConnection created.")
 }
 
 // Create a WebRTC DataChannel locally.
@@ -189,6 +189,7 @@ func (c *webRTCConn) EstablishDataChannel() error {
 			panic("short write")
 		}
 	}
+	log.Println("WebRTC: DataChannel created.")
 	return nil
 }
 
@@ -209,15 +210,9 @@ func (c *webRTCConn) SendOffer() error {
 			log.Println("Sending offer via BrokerChannel...\nTarget URL: ", brokerURL,
 				"\nFront URL:  ", frontDomain)
 			answer, err := c.broker.Negotiate(c.pc.LocalDescription())
-			if nil != err {
-				log.Printf("BrokerChannel signaling error: %s", err)
-				return
-			}
-			if nil == answer {
-				log.Printf("BrokerChannel: No answer received.")
-				// TODO: Should try again here.
-				c.reset <- struct{}{}
-				return
+			if nil != err || nil == answer {
+				log.Printf("BrokerChannel error: %s", err)
+				answer = nil
 			}
 			answerChannel <- answer
 		}()
@@ -228,17 +223,21 @@ func (c *webRTCConn) SendOffer() error {
 	return nil
 }
 
-func (c *webRTCConn) ReceiveAnswer() error {
-	log.Printf("waiting for answer...")
-	answer, ok := <-answerChannel
-	if !ok {
-		// TODO: Don't just fail, try again!
-		c.pc.Close()
-		// connection.errorChannel <- errors.New("Bad answer")
-		return errors.New("Bad answer")
-	}
-	log.Printf("Received Answer:\n\n%s\n", answer.Sdp)
-	return c.pc.SetRemoteDescription(answer)
+func (c *webRTCConn) ReceiveAnswer() {
+	go func() {
+		answer, ok := <-answerChannel
+		if !ok || nil == answer {
+			log.Printf("Failed to retrieve answer. Retrying in %d seconds", ReconnectTimeout)
+			<-time.After(time.Second * ReconnectTimeout)
+			c.reset <- struct{}{}
+			return
+		}
+		log.Printf("Received Answer:\n\n%s\n", answer.Sdp)
+		err := c.pc.SetRemoteDescription(answer)
+		if nil != err {
+			c.errorChannel <- err
+		}
+	}()
 }
 
 func (c *webRTCConn) sendData(data []byte) {
@@ -259,10 +258,11 @@ func (c *webRTCConn) ConnectLoop() {
 		// TODO: When go-webrtc is more stable, it's possible that a new
 		// PeerConnection won't need to be recreated each time.
 		// called once.
-  	c.PreparePeerConnection()
+		c.PreparePeerConnection()
 		c.EstablishDataChannel()
 		c.SendOffer()
 		c.ReceiveAnswer()
+
 		<-c.reset
 		log.Println(" --- snowflake connection reset ---")
 	}





More information about the tor-commits mailing list