[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