[tor-commits] [snowflake/master] fix datachannel remote vs. local closing during client's peerconnection cleanup

serene at torproject.org serene at torproject.org
Tue Mar 8 07:05:38 UTC 2016


commit 91673a4abe85e61cc397c5c4c359c80382958e46
Author: Serene Han <keroserene+git at gmail.com>
Date:   Sun Mar 6 11:40:00 2016 -0800

    fix datachannel remote vs. local closing during client's peerconnection cleanup
---
 client/webrtc.go | 46 +++++++++++++++++++++++++++++-----------------
 1 file changed, 29 insertions(+), 17 deletions(-)

diff --git a/client/webrtc.go b/client/webrtc.go
index 2388e9a..e2e8280 100644
--- a/client/webrtc.go
+++ b/client/webrtc.go
@@ -48,17 +48,7 @@ func (c *webRTCConn) Write(b []byte) (int, error) {
 func (c *webRTCConn) Close() error {
 	var err error = nil
 	log.Printf("WebRTC: Closing")
-	if nil != c.snowflake {
-		s := c.snowflake
-		c.snowflake = nil
-		log.Printf("WebRTC: closing DataChannel")
-		s.Close()
-	}
-	if nil != c.pc {
-		log.Printf("WebRTC: closing PeerConnection")
-		err = c.pc.Close()
-		c.pc = nil
-	}
+	c.cleanup()
 	close(c.offerChannel)
 	close(c.answerChannel)
 	close(c.errorChannel)
@@ -127,9 +117,12 @@ func (c *webRTCConn) ConnectLoop() {
 			<-c.reset
 			log.Println(" --- snowflake connection reset ---")
 		}
+		<-time.After(time.Second * 1)
+		c.cleanup()
 	}
 }
 
+// Create and prepare callbacks on a new WebRTC PeerConnection.
 func (c *webRTCConn) preparePeerConnection() {
 	if nil != c.pc {
 		c.pc.Close()
@@ -178,6 +171,9 @@ func (c *webRTCConn) preparePeerConnection() {
 
 // Create a WebRTC DataChannel locally.
 func (c *webRTCConn) establishDataChannel() error {
+	if c.snowflake != nil {
+		panic("Unexpected datachannel already exists!")
+	}
 	dc, err := c.pc.CreateDataChannel("snowflake", webrtc.Init{})
 	// Triggers "OnNegotiationNeeded" on the PeerConnection, which will prepare
 	// an SDP offer while other goroutines operating on this struct handle the
@@ -201,20 +197,20 @@ func (c *webRTCConn) establishDataChannel() error {
 		c.snowflake = dc
 	}
 	dc.OnClose = func() {
-		// Disable the DataChannel as a write destination.
 		// Future writes will go to the buffer until a new DataChannel is available.
-		log.Println("WebRTC: DataChannel.OnClose")
-		// Only reset if this OnClose was triggered remotely.
 		if nil == c.snowflake {
-			panic("Should not have nil snowflake before closing. ")
+			// Closed locally, as part of a reset.
+			log.Println("WebRTC: DataChannel.OnClose [locally]")
+			return
 		}
+		// Closed remotely, need to reset everything.
+		// Disable the DataChannel as a write destination.
+		log.Println("WebRTC: DataChannel.OnClose [remotely]")
 		c.snowflake = nil
 		// TODO: Need a way to update the circuit so that when a new WebRTC
 		// data channel is available, the relay actually recognizes the new
 		// snowflake?
 		c.Reset()
-		// c.Close()
-		// c.endChannel <- struct{}{}
 	}
 	dc.OnMessage = func(msg []byte) {
 		// log.Println("ONMESSAGE: ", len(msg))
@@ -290,3 +286,19 @@ func (c *webRTCConn) Reset() {
 		log.Println("WebRTC resetting...")
 	}()
 }
+
+func (c *webRTCConn) cleanup() {
+	if nil != c.snowflake {
+		s := c.snowflake
+		log.Printf("WebRTC: closing DataChannel")
+		// Setting snowflak to nil *before* Close indicates to OnClose that it
+		// was locally triggered.
+		c.snowflake = nil
+		s.Close()
+	}
+	if nil != c.pc {
+		log.Printf("WebRTC: closing PeerConnection")
+		c.pc.Close()
+		c.pc = nil
+	}
+}





More information about the tor-commits mailing list