[tor-commits] [snowflake/master] Remove copy/paste signalling

arlo at torproject.org arlo at torproject.org
Wed May 8 15:22:16 UTC 2019


commit 622005c79ed2e9f444d75dba90b3ee52fdc82a37
Author: Arlo Breault <arlolra at gmail.com>
Date:   Tue Apr 30 22:05:40 2019 -0400

    Remove copy/paste signalling
---
 README.md                   | 25 +--------------
 client/README.md            |  5 +--
 client/lib/rendezvous.go    | 78 ++-------------------------------------------
 client/lib/webrtc.go        |  9 +-----
 client/snowflake.go         | 13 +++-----
 client/torrc-manual         |  7 ----
 proxy/README.md             |  5 ---
 proxy/proxypair.coffee      |  7 +---
 proxy/snowflake.coffee      | 35 ++------------------
 proxy/spec/ui.spec.coffee   | 10 ++----
 proxy/static/snowflake.html | 28 ----------------
 proxy/ui.coffee             | 25 ---------------
 server-webrtc/snowflake.go  | 54 ++-----------------------------
 13 files changed, 18 insertions(+), 283 deletions(-)

diff --git a/README.md b/README.md
index f5807a2..c031213 100644
--- a/README.md
+++ b/README.md
@@ -24,7 +24,6 @@ Pluggable Transport using WebRTC, inspired by Flashproxy.
   - [Test Environment](#test-environment)
 - [FAQ](#faq)
 - [Appendix](#appendix)
-    - [-- Testing Copy-Paste Via Browser Proxy --](#---testing-copy-paste-via-browser-proxy---)
     - [-- Testing directly via WebRTC Server --](#---testing-directly-via-webrtc-server---)
 
 <!-- END doctoc generated TOC please keep comment here to allow auto update -->
@@ -69,9 +68,7 @@ comma-separated list of ICE servers, which are required for NAT traversal.
 
 For logging, run `tail -F snowflake.log` in a second terminal.
 
-You can modify the `torrc` to use your own broker,
-or remove the options entirely which will default to the old copy paste
-method (see `torrc-manual`):
+You can modify the `torrc` to use your own broker:
 
 ```
 ClientTransportPlugin snowflake exec ./client --meek
@@ -155,26 +152,6 @@ go build
 ./proxy-go
 ```
 
-##### -- Testing Copy-Paste Via Browser Proxy --
-
-Open a browser proxy, passing the `manual` parameter; e.g.
-`http://127.0.0.1:8000/snowflake.html?manual=1`,
-
-Open up three terminals for the **client:**
-
-A: `tor -f torrc-manual SOCKSPort auto`
-
-B: `cat > signal`
-
-C: `tail -F snowflake.log`
-
-Then, in the browser proxy:
-
-- Look for the offer in terminal C; copy and paste it into the browser.
-- Copy and paste the answer generated in the browser back to terminal B.
-- Once WebRTC successfully connects, the browser terminal should turn green.
-  Shortly after, the tor client should bootstrap to 100%.
-
 ##### -- Testing directly via WebRTC Server --
 
 See server-webrtc/README.md for information on connecting directly to a
diff --git a/client/README.md b/client/README.md
index 96f3276..50bdba3 100644
--- a/client/README.md
+++ b/client/README.md
@@ -12,12 +12,9 @@ ClientTransportPlugin snowflake exec ./client \
 -ice stun:stun.l.google.com:19302
 ```
 
-`-url` should be the URL of a Broker instance. This is required to have
-automated signalling (which is desired in most use cases).
-When omitted, the client uses copy-paste signalling instead.
+`-url` should be the URL of a Broker instance.
 
 `-front` is an optional front domain for the Broker request.
 
 `-ice` is a comma-separated list of ICE servers. These can be STUN or TURN
 servers.
-
diff --git a/client/lib/rendezvous.go b/client/lib/rendezvous.go
index 7436f54..d04b0b1 100644
--- a/client/lib/rendezvous.go
+++ b/client/lib/rendezvous.go
@@ -1,26 +1,20 @@
 // 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:
+// This file contains the one method 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 lib
 
 import (
-	"bufio"
 	"bytes"
 	"errors"
 	"io/ioutil"
 	"log"
 	"net/http"
 	"net/url"
-	"os"
-	"syscall"
 
 	"github.com/keroserene/go-webrtc"
 )
@@ -143,71 +137,3 @@ func (w WebRTCDialer) Catch() (Snowflake, error) {
 	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      *WebRTCPeer
-}
-
-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 Peer via manual copy-paste.
-func (d *CopyPasteDialer) Catch() (Snowflake, error) {
-	if nil == d.signal {
-		return nil, errors.New("Cannot copy-paste dial without signal pipe.")
-	}
-	connection := NewWebRTCPeer(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/lib/webrtc.go b/client/lib/webrtc.go
index fe8b44c..71c96ab 100644
--- a/client/lib/webrtc.go
+++ b/client/lib/webrtc.go
@@ -284,14 +284,7 @@ func (c *WebRTCPeer) sendOfferToBroker() {
 // the Broker or signal pipe, then await for the SDP answer.
 func (c *WebRTCPeer) exchangeSDP() error {
 	select {
-	case offer := <-c.offerChannel:
-		// 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\n" + offer.Serialize() + "\n\n")
-			log.Printf("----------------")
-		}
+	case <-c.offerChannel:
 	case err := <-c.errorChannel:
 		log.Println("Failed to prepare offer", err)
 		c.Close()
diff --git a/client/snowflake.go b/client/snowflake.go
index 715f83f..9098de7 100644
--- a/client/snowflake.go
+++ b/client/snowflake.go
@@ -113,14 +113,11 @@ func main() {
 
 	// Prepare to collect remote WebRTC peers.
 	snowflakes := sf.NewPeers(*max)
-	if "" != *brokerURL {
-		// Use potentially domain-fronting broker to rendezvous.
-		broker := sf.NewBrokerChannel(*brokerURL, *frontDomain, sf.CreateBrokerTransport())
-		snowflakes.Tongue = sf.NewWebRTCDialer(broker, iceServers)
-	} else {
-		// Otherwise, use manual copy and pasting of SDP messages.
-		snowflakes.Tongue = sf.NewCopyPasteDialer(iceServers)
-	}
+
+	// Use potentially domain-fronting broker to rendezvous.
+	broker := sf.NewBrokerChannel(*brokerURL, *frontDomain, sf.CreateBrokerTransport())
+	snowflakes.Tongue = sf.NewWebRTCDialer(broker, iceServers)
+
 	if nil == snowflakes.Tongue {
 		log.Fatal("Unable to prepare rendezvous method.")
 		return
diff --git a/client/torrc-manual b/client/torrc-manual
deleted file mode 100644
index c043924..0000000
--- a/client/torrc-manual
+++ /dev/null
@@ -1,7 +0,0 @@
-UseBridges 1
-DataDirectory datadir
-
-ClientTransportPlugin snowflake exec ./client \
--log snowflake.log
-
-Bridge snowflake 0.0.3.0:1
diff --git a/proxy/README.md b/proxy/README.md
index 856b30c..634e13c 100644
--- a/proxy/README.md
+++ b/proxy/README.md
@@ -33,8 +33,3 @@ With no parameters,
 snowflake uses the default relay `snowflake.bamsoftware.com:443` and
 uses automatic signaling with the default broker at
 `https://snowflake-broker.bamsoftware.com/`.
-
-Here are optional parameters to include in the query string.
-```
-manual - enables copy-paste signalling mode.
-```
diff --git a/proxy/proxypair.coffee b/proxy/proxypair.coffee
index d3340ed..ee2f3e7 100644
--- a/proxy/proxypair.coffee
+++ b/proxy/proxypair.coffee
@@ -40,15 +40,11 @@ class ProxyPair
       ] }
     @pc.onicecandidate = (evt) =>
       # Browser sends a null candidate once the ICE gathering completes.
-      # In this case, it makes sense to send one copy-paste blob.
       if null == evt.candidate
         # TODO: Use a promise.all to tell Snowflake about all offers at once,
         # once multiple proxypairs are supported.
         dbg 'Finished gathering ICE candidates.'
-        if COPY_PASTE_ENABLED
-          Signalling.send @pc.localDescription
-        else
-          snowflake.broker.sendAnswer @id, @pc.localDescription
+        snowflake.broker.sendAnswer @id, @pc.localDescription
     # OnDataChannel triggered remotely from the client when connection succeeds.
     @pc.ondatachannel = (dc) =>
       channel = dc.channel
@@ -193,4 +189,3 @@ class ProxyPair
   webrtcIsReady: -> null != @client && 'open' == @client.readyState
   relayIsReady: -> (null != @relay) && (WebSocket.OPEN == @relay.readyState)
   isClosed: (ws) -> undefined == ws || WebSocket.CLOSED == ws.readyState
-
diff --git a/proxy/snowflake.coffee b/proxy/snowflake.coffee
index 8cb4d46..a8fc183 100644
--- a/proxy/snowflake.coffee
+++ b/proxy/snowflake.coffee
@@ -18,13 +18,11 @@ RELAY =
   # Original non-wss relay:
   # host: '192.81.135.242'
   # port: 9902
-COPY_PASTE_ENABLED = false
 COOKIE_NAME = "snowflake-allow"
 
 silenceNotifications = false
 query = Query.parse(location)
 DEBUG = Params.getBool(query, 'debug', false)
-COPY_PASTE_ENABLED = Params.getBool(query, 'manual', false)
 
 # Bytes per second. Set to undefined to disable limit.
 DEFAULT_RATE_LIMIT = DEFAULT_RATE_LIMIT || undefined
@@ -78,17 +76,14 @@ class Snowflake
   setRelayAddr: (relayAddr) ->
     @relayAddr = relayAddr
     log 'Using ' + relayAddr.host + ':' + relayAddr.port + ' as Relay.'
-    log 'Input offer from the snowflake client:' if COPY_PASTE_ENABLED
     return true
 
   # Initialize WebRTC PeerConnection, which requires beginning the signalling
-  # process. If in copy paste mode, the user will need to copy and paste the SDP
-  # blobs. Otherwise, |pollBroker| automatically arranges signalling.
+  # process. |pollBroker| automatically arranges signalling.
   beginWebRTC: ->
     @state = MODE.WEBRTC_CONNECTING
     for i in [1..CONNECTIONS_PER_CLIENT]
       @makeProxyPair @relayAddr
-    return if COPY_PASTE_ENABLED
     log 'ProxyPair Slots: ' + @proxyPairs.length
     log 'Snowflake IDs: ' + (@proxyPairs.map (p) -> p.id).join ' | '
     @pollBroker()
@@ -182,31 +177,6 @@ class Snowflake
 
 snowflake = null
 
-# Signalling channel - just tells user to copy paste to the peer.
-# When copy-paste mode is not enabled, this is handled automatically by Broker.
-Signalling =
-  send: (msg) ->
-    log '---- Please copy the below to peer ----\n'
-    log JSON.stringify msg
-    log '\n'
-
-  receive: (msg) ->
-    recv = ''
-    try
-      recv = JSON.parse msg
-    catch e
-      log 'Invalid JSON.'
-      return
-    desc = recv['sdp']
-    if !desc
-      log 'Invalid SDP.'
-      return false
-    pair = snowflake.nextAvailableProxyPair()
-    if !pair
-      log 'At client capacity.'
-      return false
-    snowflake.receiveOffer pair, msg
-
 # Log to both console and UI if applicable.
 # Requires that the snowflake and UI objects are hooked up in order to
 # log to console.
@@ -246,8 +216,7 @@ init = (isNode) ->
     return
 
   # Otherwise, begin setting up WebRTC and acting as a proxy.
-  log 'Copy-Paste mode detected.' if COPY_PASTE_ENABLED
-  dbg 'Contacting Broker at ' + broker.url if not COPY_PASTE_ENABLED
+  dbg 'Contacting Broker at ' + broker.url
   snowflake.setRelayAddr RELAY
   snowflake.beginWebRTC()
 
diff --git a/proxy/spec/ui.spec.coffee b/proxy/spec/ui.spec.coffee
index 1628d83..8229169 100644
--- a/proxy/spec/ui.spec.coffee
+++ b/proxy/spec/ui.spec.coffee
@@ -10,16 +10,12 @@ describe 'UI', ->
   it 'activates debug mode when badge does not exist', ->
     spyOn(document, 'getElementById').and.callFake (id) ->
       return null if 'badge' == id
-      return {
-        focus: ->
-      }
+      return {}
     u = new UI()
     expect(u.debug).toBe true
-    expect(document.getElementById.calls.count()).toEqual 5
+    expect(document.getElementById.calls.count()).toEqual 3
     expect(u.$status).not.toBeNull()
     expect(u.$msglog).not.toBeNull()
-    expect(u.$send).not.toBeNull()
-    expect(u.$input).not.toBeNull()
 
   it 'is not debug mode when badge exists', ->
     spyOn(document, 'getElementById').and.callFake (id) ->
@@ -31,8 +27,6 @@ describe 'UI', ->
     expect(document.getElementById.calls.count()).toEqual 1
     expect(u.$status).toBeNull()
     expect(u.$msglog).toBeNull()
-    expect(u.$send).toBeNull()
-    expect(u.$input).toBeNull()
 
   it 'sets status message only when in debug mode', ->
     u = new UI()
diff --git a/proxy/static/snowflake.html b/proxy/static/snowflake.html
index 4b42bae..fb2c0e5 100644
--- a/proxy/static/snowflake.html
+++ b/proxy/static/snowflake.html
@@ -40,30 +40,6 @@
     margin-bottom: 1em;
     padding: 8px;
   }
-  .inputarea {
-    position: relative;
-    width: 100%;
-    height: 3em;
-    display: block;
-  }
-  #input {
-    display: inline-block;
-    position: absolute; left: 0;
-    width: 89%; height: 100%;
-    padding: 8px 30px;
-    font-size: 80%;
-    color: #fff;
-    background-color: rgba(0,0,0,0.9);
-    border: 1px solid #999;
-  }
-  #send {
-    display: inline-block; position: absolute;
-    right: 0; top: 0;  height: 100%; width: 10%;
-    background-color: #202; color: #f8f;
-    font-variant: small-caps; font-size: 100%;
-    border: none; /* box-shadow: 0 2px 5px #000; */
-  }
-  #send:hover { background-color: #636; }
   #status {
     background-color: rgba(0,0,0,0.9);  color: #999;
     margin: 8px 0; padding: 8px 1em; cursor: default;
@@ -79,10 +55,6 @@
     </div>
     <textarea id="msglog" readonly>
     </textarea>
-    <div class="inputarea">
-      <input type="text" id="input">
-      <input type="submit" id="send" value="send">
-    </div>
   </div>
 
 </body>
diff --git a/proxy/ui.coffee b/proxy/ui.coffee
index 1603ec3..fb13aa4 100644
--- a/proxy/ui.coffee
+++ b/proxy/ui.coffee
@@ -7,8 +7,6 @@ class UI
 
   # DOM elements references.
   $msglog: null
-  $send:   null
-  $input:  null
   $status: null
 
   constructor: ->
@@ -21,14 +19,6 @@ class UI
     @$msglog = document.getElementById('msglog')
     @$msglog.value = ''
 
-    @$send = document.getElementById('send')
-    @$send.onclick = @acceptInput
-
-    @$input = document.getElementById('input')
-    @$input.focus()
-    @$input.onkeydown = (e) =>
-      @$send.onclick() if 13 == e.keyCode  # enter
-
   # Status bar
   setStatus: (msg) =>
     return if !@debug
@@ -40,21 +30,6 @@ class UI
     else
       @$badge.className = if connected then 'active' else ''
 
-  # Local input from keyboard into message window.
-  acceptInput: =>
-    msg = @$input.value
-    if !COPY_PASTE_ENABLED
-      @log 'No input expected - Copy Paste Signalling disabled.'
-    else switch snowflake.state
-      when MODE.WEBRTC_CONNECTING
-        Signalling.receive msg
-      when MODE.WEBRTC_READY
-        @log 'No input expected - WebRTC connected.'
-      else
-        @log 'ERROR: ' + msg
-    @$input.value = ''
-    @$input.focus()
-
   log: (msg) =>
     return if !@debug
     # Scroll to latest
diff --git a/server-webrtc/snowflake.go b/server-webrtc/snowflake.go
index 4d6641a..be9f012 100644
--- a/server-webrtc/snowflake.go
+++ b/server-webrtc/snowflake.go
@@ -1,7 +1,6 @@
 package main
 
 import (
-	"bufio"
 	"flag"
 	"fmt"
 	"io"
@@ -194,43 +193,6 @@ func makePeerConnectionFromOffer(sdp *webrtc.SessionDescription, config *webrtc.
 	return pc, nil
 }
 
-// Create a signaling named pipe and feed offers from it into
-// makePeerConnectionFromOffer.
-func receiveSignalsFIFO(filename string, config *webrtc.Configuration) error {
-	err := syscall.Mkfifo(filename, 0600)
-	if err != nil {
-		if err.(syscall.Errno) != syscall.EEXIST {
-			return err
-		}
-	}
-	signalFile, err := os.OpenFile(filename, os.O_RDONLY, 0600)
-	if err != nil {
-		return err
-	}
-	defer signalFile.Close()
-
-	s := bufio.NewScanner(signalFile)
-	for s.Scan() {
-		msg := s.Text()
-		sdp := webrtc.DeserializeSessionDescription(msg)
-		if sdp == nil {
-			log.Printf("ignoring invalid signal message %+q", msg)
-			continue
-		}
-
-		pc, err := makePeerConnectionFromOffer(sdp, config)
-		if err != nil {
-			log.Printf("makePeerConnectionFromOffer: %s", err)
-			continue
-		}
-		// Write offer to log for manual signaling.
-		log.Printf("----------------")
-		fmt.Fprintln(logFile, pc.LocalDescription().Serialize())
-		log.Printf("----------------")
-	}
-	return s.Err()
-}
-
 func main() {
 	var err error
 	var httpAddr string
@@ -260,24 +222,14 @@ func main() {
 
 	webRTCConfig := webrtc.NewConfiguration(webrtc.OptionIceServer("stun:stun.l.google.com:19302"))
 
-	// Start FIFO-based signaling receiver.
+	// Start HTTP-based signaling receiver.
 	go func() {
-		err := receiveSignalsFIFO("signal", webRTCConfig)
+		err := receiveSignalsHTTP(httpAddr, webRTCConfig)
 		if err != nil {
-			log.Printf("receiveSignalsFIFO: %s", err)
+			log.Printf("receiveSignalsHTTP: %s", err)
 		}
 	}()
 
-	// Start HTTP-based signaling receiver.
-	if httpAddr != "" {
-		go func() {
-			err := receiveSignalsHTTP(httpAddr, webRTCConfig)
-			if err != nil {
-				log.Printf("receiveSignalsHTTP: %s", err)
-			}
-		}()
-	}
-
 	for _, bindaddr := range ptInfo.Bindaddrs {
 		switch bindaddr.MethodName {
 		case ptMethodName:



More information about the tor-commits mailing list