[tor-commits] [snowflake/master] Create new smux session for each SOCKS connection

cohosh at torproject.org cohosh at torproject.org
Fri Dec 4 16:24:10 UTC 2020


commit 114df695ceff25d0213200a3368ed7a1bb1c7668
Author: Cecylia Bocovich <cohosh at torproject.org>
Date:   Mon Nov 23 14:02:54 2020 -0500

    Create new smux session for each SOCKS connection
    
    Each SOCKS connection has its own set of snowflakes and broker poll
    loop. Since the session manager was tied to a single set of snowflakes,
    this resulted in a bug where RedialPacketConn would sometimes try to
    pull snowflakes from a previously melted pool. The fix is to maintain
    separate smux sessions for each SOCKS connection, tied to its own
    snowflake pool.
---
 client/lib/snowflake.go | 57 ++++++-------------------------------------------
 1 file changed, 6 insertions(+), 51 deletions(-)

diff --git a/client/lib/snowflake.go b/client/lib/snowflake.go
index e888160..171e173 100644
--- a/client/lib/snowflake.go
+++ b/client/lib/snowflake.go
@@ -6,7 +6,6 @@ import (
 	"io"
 	"log"
 	"net"
-	"sync"
 	"time"
 
 	"git.torproject.org/pluggable-transports/snowflake.git/common/turbotunnel"
@@ -92,54 +91,6 @@ func newSession(snowflakes SnowflakeCollector) (net.PacketConn, *smux.Session, e
 	return pconn, sess, err
 }
 
-// sessionManager_ maintains a single global smux.Session that is shared among
-// incoming SOCKS connections.
-type sessionManager_ struct {
-	mutex sync.Mutex
-	sess  *smux.Session
-}
-
-// Get creates and returns a new global smux.Session if none exists yet. If one
-// already exists, it returns the existing one. It monitors the returned session
-// and if it ever fails, sets things up so the next call to Get will create a
-// new session.
-func (manager *sessionManager_) Get(snowflakes SnowflakeCollector) (*smux.Session, error) {
-	manager.mutex.Lock()
-	defer manager.mutex.Unlock()
-
-	if manager.sess == nil {
-		log.Printf("starting a new session")
-		pconn, sess, err := newSession(snowflakes)
-		if err != nil {
-			return nil, err
-		}
-		manager.sess = sess
-		go func() {
-			// If the session dies, set it to be recreated.
-			for {
-				<-time.After(5 * time.Second)
-				if sess.IsClosed() {
-					break
-				}
-			}
-			log.Printf("discarding finished session")
-			// Close the underlying to force any ongoing WebRTC
-			// connection to close as well, and relinquish the
-			// SnowflakeCollector.
-			pconn.Close()
-			manager.mutex.Lock()
-			manager.sess = nil
-			manager.mutex.Unlock()
-		}()
-	} else {
-		log.Printf("reusing the existing session")
-	}
-
-	return manager.sess, nil
-}
-
-var sessionManager = sessionManager_{}
-
 // Given an accepted SOCKS connection, establish a WebRTC connection to the
 // remote peer and exchange traffic.
 func Handler(socks net.Conn, tongue Tongue) error {
@@ -155,8 +106,9 @@ func Handler(socks net.Conn, tongue Tongue) error {
 	log.Printf("---- Handler: begin collecting snowflakes ---")
 	go connectLoop(snowflakes)
 
-	// Return the global smux.Session.
-	sess, err := sessionManager.Get(snowflakes)
+	// Create a new smux session
+	log.Printf("---- Handler: starting a new session ---")
+	pconn, sess, err := newSession(snowflakes)
 	if err != nil {
 		return err
 	}
@@ -174,6 +126,9 @@ func Handler(socks net.Conn, tongue Tongue) error {
 	log.Printf("---- Handler: closed stream %v ---", stream.ID())
 	snowflakes.End()
 	log.Printf("---- Handler: end collecting snowflakes ---")
+	pconn.Close()
+	sess.Close()
+	log.Printf("---- Handler: discarding finished session ---")
 	return nil
 }
 



More information about the tor-commits mailing list