commit 622005c79ed2e9f444d75dba90b3ee52fdc82a37 Author: Arlo Breault arlolra@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%60, - -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/%60. - -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:
tor-commits@lists.torproject.org