commit 02562ba7504811659d801d06d9fdb1c3ecfa5d9b
Author: Serene Han <[email protected]>
Date:   Sun Jun 12 12:43:24 2016 -0700

    copy-paste rendezvous works again, but with new interface allowing seamless 
recovery for the first time
---
 client/rendezvous.go | 112 +++++++++++++++++++++++++++++++++++++++++++++++++--
 client/snowflake.go  |  65 +++++-------------------------
 client/webrtc.go     |  32 +--------------
 3 files changed, 122 insertions(+), 87 deletions(-)

diff --git a/client/rendezvous.go b/client/rendezvous.go
index 3b25c89..0acee80 100644
--- a/client/rendezvous.go
+++ b/client/rendezvous.go
@@ -1,15 +1,26 @@
-// WebRTC Rendezvous requires the exchange of SessionDescriptions between
-// peers. This file contains the domain-fronted HTTP signaling mechanism
-// between the client and a desired Broker.
+// WebRTC rendezvous requires the exchange of SessionDescriptions between
+// peers in order to establish a PeerConnection.
+//
+// This file contains the two methods currently available to Snowflake:
+//
+// - Domain-fronted HTTP signaling. The Broker automatically exchange offers
+//   and answers between this client and some remote WebRTC proxy.
+//   (This is the recommended default, enabled via the flags in "torrc".)
+//
+// - Manual copy-paste signaling. User must create a signaling pipe.
+//   (The flags in torrc-manual allow this)
 package main
 
 import (
+       "bufio"
        "bytes"
        "errors"
        "io/ioutil"
        "log"
        "net/http"
        "net/url"
+       "os"
+       "syscall"
 
        "github.com/keroserene/go-webrtc"
 )
@@ -100,3 +111,98 @@ func (bc *BrokerChannel) Negotiate(offer 
*webrtc.SessionDescription) (
                return nil, errors.New(BrokerErrorUnexpected)
        }
 }
+
+// Implements the |Tongue| interface to catch snowflakes, using BrokerChannel.
+type WebRTCDialer struct {
+       *BrokerChannel
+       webrtcConfig *webrtc.Configuration
+}
+
+func NewWebRTCDialer(
+       broker *BrokerChannel, iceServers IceServerList) *WebRTCDialer {
+       config := webrtc.NewConfiguration(iceServers...)
+       return &WebRTCDialer{
+               BrokerChannel: broker,
+               webrtcConfig:  config,
+       }
+}
+
+// Initialize a WebRTC Connection by signaling through the broker.
+func (w WebRTCDialer) Catch() (*webRTCConn, error) {
+       if nil == w.BrokerChannel {
+               return nil, errors.New("Cannot Dial WebRTC without a 
BrokerChannel.")
+       }
+       // TODO: [#3] Fetch ICE server information from Broker.
+       // TODO: [#18] Consider TURN servers here too.
+       connection := NewWebRTCConnection(w.webrtcConfig, w.BrokerChannel)
+       err := connection.Connect()
+       return connection, err
+}
+
+// CopyPasteDialer handles the interaction required to copy-paste the
+// offers and answers.
+// Implements |Tongue| interface to catch snowflakes manually.
+// Supports recovery of connections.
+type CopyPasteDialer struct {
+       webrtcConfig *webrtc.Configuration
+       signal       *os.File
+       current      *webRTCConn
+}
+
+func NewCopyPasteDialer(iceServers IceServerList) *CopyPasteDialer {
+       log.Println("No HTTP signaling detected. Using manual copy-paste 
signaling.")
+       log.Println("Waiting for a \"signal\" pipe...")
+       // This FIFO receives signaling messages.
+       err := syscall.Mkfifo("signal", 0600)
+       if err != nil {
+               if syscall.EEXIST != err.(syscall.Errno) {
+                       log.Fatal(err)
+               }
+       }
+       signalFile, err := os.OpenFile("signal", os.O_RDONLY, 0600)
+       if nil != err {
+               log.Fatal(err)
+               return nil
+       }
+       config := webrtc.NewConfiguration(iceServers...)
+       dialer := &CopyPasteDialer{
+               webrtcConfig: config,
+               signal:       signalFile,
+       }
+       go dialer.readSignals()
+       return dialer
+}
+
+// Initialize a WebRTC connection via manual copy-paste.
+func (d *CopyPasteDialer) Catch() (*webRTCConn, error) {
+       if nil == d.signal {
+               return nil, errors.New("Cannot copy-paste dial without signal 
pipe.")
+       }
+       connection := NewWebRTCConnection(d.webrtcConfig, nil)
+       // Must keep track of pending new connection until copy-paste completes.
+       d.current = connection
+       // Outputs SDP offer to log, expecting user to copy-paste to the remote 
Peer.
+       // Blocks until user pastes back the answer.
+       err := connection.Connect()
+       d.current = nil
+       return connection, err
+}
+
+// Manual copy-paste signalling.
+func (d *CopyPasteDialer) readSignals() {
+       defer d.signal.Close()
+       log.Printf("CopyPasteDialer: reading messages from signal pipe.")
+       s := bufio.NewScanner(d.signal)
+       for s.Scan() {
+               msg := s.Text()
+               sdp := webrtc.DeserializeSessionDescription(msg)
+               if sdp == nil {
+                       log.Printf("CopyPasteDialer: ignoring invalid signal 
message %+q", msg)
+                       continue
+               }
+               d.current.answerChannel <- sdp
+       }
+       if err := s.Err(); err != nil {
+               log.Printf("signal FIFO: %s", err)
+       }
+}
diff --git a/client/snowflake.go b/client/snowflake.go
index 948b862..7c06b17 100644
--- a/client/snowflake.go
+++ b/client/snowflake.go
@@ -2,7 +2,6 @@
 package main
 
 import (
-       "bufio"
        "errors"
        "flag"
        "io"
@@ -110,45 +109,6 @@ func handler(socks SocksConnector, snowflakes 
SnowflakeCollector) error {
        return nil
 }
 
-func setupCopyPaste() {
-       log.Println("No HTTP signaling detected. Waiting for a \"signal\" 
pipe...")
-       // This FIFO receives signaling messages.
-       err := syscall.Mkfifo("signal", 0600)
-       if err != nil {
-               if syscall.EEXIST != err.(syscall.Errno) {
-                       log.Fatal(err)
-               }
-       }
-       signalFile, err := os.OpenFile("signal", os.O_RDONLY, 0600)
-       if nil != err {
-               log.Fatal(err)
-       }
-       defer signalFile.Close()
-       go readSignalingMessages(signalFile)
-}
-
-// Manual copy-paste signalling.
-// TODO: Needs fix since multiplexing changes access to the remotes.
-func readSignalingMessages(f *os.File) {
-       log.Printf("readSignalingMessages")
-       s := bufio.NewScanner(f)
-       for s.Scan() {
-               msg := s.Text()
-               log.Printf("readSignalingMessages loop %+q", msg)
-               sdp := webrtc.DeserializeSessionDescription(msg)
-               if sdp == nil {
-                       log.Printf("ignoring invalid signal message %+q", msg)
-                       continue
-               }
-               // webrtcRemotes[0].answerChannel <- sdp
-       }
-       log.Printf("close answerChannel")
-       // close(webrtcRemotes[0].answerChannel)
-       if err := s.Err(); err != nil {
-               log.Printf("signal FIFO: %s", err)
-       }
-}
-
 func main() {
        webrtc.SetLoggingVerbosity(1)
        logFile, err := os.OpenFile("snowflake.log",
@@ -169,24 +129,24 @@ func main() {
                "capacity for number of multiplexed WebRTC peers")
        flag.Parse()
 
-       // TODO: Maybe just get rid of copy-paste option entirely.
-       if "" == *brokerURL {
-               setupCopyPaste()
-       }
-
-       // Prepare WebRTC SnowflakeCollector, Broker, then accumulate 
connections.
+       // Prepare to collect remote WebRTC peers.
        snowflakes := NewPeers(*max)
-       broker := NewBrokerChannel(*brokerURL, *frontDomain, 
CreateBrokerTransport())
-       snowflakes.Tongue = NewWebRTCDialer(broker, iceServers)
-
-       // Use a real logger for traffic.
+       if "" != *brokerURL {
+               // Use potentially domain-fronting broker to rendezvous.
+               broker := NewBrokerChannel(*brokerURL, *frontDomain, 
CreateBrokerTransport())
+               snowflakes.Tongue = NewWebRTCDialer(broker, iceServers)
+       } else {
+               // Otherwise, use manual copy and pasting of SDP messages.
+               snowflakes.Tongue = NewCopyPasteDialer(iceServers)
+       }
+       // Use a real logger to periodically output how much traffic is 
happening.
        snowflakes.BytesLogger = &BytesSyncLogger{
                inboundChan: make(chan int, 5), outboundChan: make(chan int, 5),
                inbound: 0, outbound: 0, inEvents: 0, outEvents: 0,
        }
+       go snowflakes.BytesLogger.Log()
 
        go ConnectLoop(snowflakes)
-       go snowflakes.BytesLogger.Log()
 
        // Begin goptlib client process.
        ptInfo, err := pt.ClientSetup(nil)
@@ -197,7 +157,6 @@ func main() {
                pt.ProxyError("proxy is not supported")
                os.Exit(1)
        }
-
        listeners := make([]net.Listener, 0)
        for _, methodName := range ptInfo.MethodNames {
                switch methodName {
@@ -234,9 +193,7 @@ func main() {
        for _, ln := range listeners {
                ln.Close()
        }
-
        snowflakes.End()
-
        // wait for second signal or no more handlers
        sig = nil
        for sig == nil && numHandlers != 0 {
diff --git a/client/webrtc.go b/client/webrtc.go
index 7647cf6..2d26b7a 100644
--- a/client/webrtc.go
+++ b/client/webrtc.go
@@ -11,34 +11,6 @@ import (
        "time"
 )
 
-// Implements the |Tongue| interface to catch snowflakes, using a 
BrokerChannel.
-type WebRTCDialer struct {
-       *BrokerChannel
-       webrtcConfig *webrtc.Configuration
-}
-
-func NewWebRTCDialer(
-       broker *BrokerChannel, iceServers IceServerList) *WebRTCDialer {
-
-       config := webrtc.NewConfiguration(iceServers...)
-       return &WebRTCDialer{
-               BrokerChannel: broker,
-               webrtcConfig:  config,
-       }
-}
-
-// Initialize a WebRTC Connection by signaling through the broker.
-func (w WebRTCDialer) Catch() (*webRTCConn, error) {
-       if nil == w.BrokerChannel {
-               return nil, errors.New("Cannot Dial WebRTC without a 
BrokerChannel.")
-       }
-       // TODO: [#3] Fetch ICE server information from Broker.
-       // TODO: [#18] Consider TURN servers here too.
-       connection := NewWebRTCConnection(w.webrtcConfig, w.BrokerChannel)
-       err := connection.Connect()
-       return connection, err
-}
-
 // Remote WebRTC peer.  Implements the |net.Conn| interface.
 type webRTCConn struct {
        config    *webrtc.Configuration
@@ -282,11 +254,11 @@ func (c *webRTCConn) sendOfferToBroker() {
 func (c *webRTCConn) exchangeSDP() error {
        select {
        case offer := <-c.offerChannel:
-               // Display for copy-paste, when no broker available.
+               // Display for copy-paste when no broker available.
                if nil == c.broker {
                        log.Printf("Please Copy & Paste the following to the 
peer:")
                        log.Printf("----------------")
-                       log.Printf("\n" + offer.Serialize() + "\n")
+                       log.Printf("\n\n" + offer.Serialize() + "\n\n")
                        log.Printf("----------------")
                }
        case err := <-c.errorChannel:

_______________________________________________
tor-commits mailing list
[email protected]
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits

Reply via email to