commit bd5887a8765f76b46f9203a216c6896a076dfebe Author: Arlo Breault arlolra@gmail.com Date: Wed May 1 10:11:15 2019 -0400
Make a WS class to eliminate globals --- proxy/Cakefile | 1 + proxy/proxypair.coffee | 2 +- proxy/spec/util.spec.coffee | 35 ------------- proxy/spec/websocket.spec.coffee | 38 ++++++++++++++ proxy/websocket.coffee | 107 ++++++++++++++++++++------------------- 5 files changed, 94 insertions(+), 89 deletions(-)
diff --git a/proxy/Cakefile b/proxy/Cakefile index d984c1b..7da528e 100644 --- a/proxy/Cakefile +++ b/proxy/Cakefile @@ -18,6 +18,7 @@ FILES_SPEC = [ 'spec/broker.spec.coffee' 'spec/proxypair.spec.coffee' 'spec/snowflake.spec.coffee' + 'spec/websocket.spec.coffee' ] FILES_ALL = FILES.concat FILES_SPEC OUTFILE = 'build/snowflake.js' diff --git a/proxy/proxypair.coffee b/proxy/proxypair.coffee index ee2f3e7..81ddd41 100644 --- a/proxy/proxypair.coffee +++ b/proxy/proxypair.coffee @@ -103,7 +103,7 @@ class ProxyPair if peer_ip? params.push(["client_ip", peer_ip])
- @relay = makeWebsocket @relayAddr, params + @relay = WS.makeWebsocket @relayAddr, params @relay.label = 'websocket-relay' @relay.onopen = => if @timer diff --git a/proxy/spec/util.spec.coffee b/proxy/spec/util.spec.coffee index fd5b77e..19f0041 100644 --- a/proxy/spec/util.spec.coffee +++ b/proxy/spec/util.spec.coffee @@ -2,41 +2,6 @@ jasmine tests for Snowflake utils ###
-describe 'BuildUrl', -> - it 'should parse just protocol and host', -> - expect(buildUrl('http', 'example.com')).toBe 'http://example.com' - it 'should handle different ports', -> - expect buildUrl 'http', 'example.com', 80 - .toBe 'http://example.com' - expect buildUrl 'http', 'example.com', 81 - .toBe 'http://example.com:81' - expect buildUrl 'http', 'example.com', 443 - .toBe 'http://example.com:443' - expect buildUrl 'http', 'example.com', 444 - .toBe 'http://example.com:444' - it 'should handle paths', -> - expect buildUrl 'http', 'example.com', 80, '/' - .toBe 'http://example.com/' - expect buildUrl 'http', 'example.com', 80,'/test?k=%#v' - .toBe 'http://example.com/test%3Fk%3D%25%23v' - expect buildUrl 'http', 'example.com', 80, '/test' - .toBe 'http://example.com/test' - it 'should handle params', -> - expect buildUrl 'http', 'example.com', 80, '/test', [['k', '%#v']] - .toBe 'http://example.com/test?k=%25%23v' - expect buildUrl 'http', 'example.com', 80, '/test', [['a', 'b'], ['c', 'd']] - .toBe 'http://example.com/test?a=b&c=d' - it 'should handle ips', -> - expect buildUrl 'http', '1.2.3.4' - .toBe 'http://1.2.3.4' - expect buildUrl 'http', '1:2::3:4' - .toBe 'http://%5B1:2::3:4]' - it 'should handle bogus', -> - expect buildUrl 'http', 'bog][us' - .toBe 'http://bog%5D%5Bus' - expect buildUrl 'http', 'bog:u]s' - .toBe 'http://bog%3Au%5Ds' - describe 'Parse', ->
describe 'cookie', -> diff --git a/proxy/spec/websocket.spec.coffee b/proxy/spec/websocket.spec.coffee new file mode 100644 index 0000000..178bcfd --- /dev/null +++ b/proxy/spec/websocket.spec.coffee @@ -0,0 +1,38 @@ +### +jasmine tests for Snowflake websocket +### + +describe 'BuildUrl', -> + it 'should parse just protocol and host', -> + expect(WS.buildUrl('http', 'example.com')).toBe 'http://example.com' + it 'should handle different ports', -> + expect WS.buildUrl 'http', 'example.com', 80 + .toBe 'http://example.com' + expect WS.buildUrl 'http', 'example.com', 81 + .toBe 'http://example.com:81' + expect WS.buildUrl 'http', 'example.com', 443 + .toBe 'http://example.com:443' + expect WS.buildUrl 'http', 'example.com', 444 + .toBe 'http://example.com:444' + it 'should handle paths', -> + expect WS.buildUrl 'http', 'example.com', 80, '/' + .toBe 'http://example.com/' + expect WS.buildUrl 'http', 'example.com', 80,'/test?k=%#v' + .toBe 'http://example.com/test%3Fk%3D%25%23v' + expect WS.buildUrl 'http', 'example.com', 80, '/test' + .toBe 'http://example.com/test' + it 'should handle params', -> + expect WS.buildUrl 'http', 'example.com', 80, '/test', [['k', '%#v']] + .toBe 'http://example.com/test?k=%25%23v' + expect WS.buildUrl 'http', 'example.com', 80, '/test', [['a', 'b'], ['c', 'd']] + .toBe 'http://example.com/test?a=b&c=d' + it 'should handle ips', -> + expect WS.buildUrl 'http', '1.2.3.4' + .toBe 'http://1.2.3.4' + expect WS.buildUrl 'http', '1:2::3:4' + .toBe 'http://%5B1:2::3:4]' + it 'should handle bogus', -> + expect WS.buildUrl 'http', 'bog][us' + .toBe 'http://bog%5D%5Bus' + expect WS.buildUrl 'http', 'bog:u]s' + .toBe 'http://bog%3Au%5Ds' diff --git a/proxy/websocket.coffee b/proxy/websocket.coffee index 5487df1..00a65a8 100644 --- a/proxy/websocket.coffee +++ b/proxy/websocket.coffee @@ -2,58 +2,59 @@ Only websocket-specific stuff. ###
-WSS_ENABLED = true -DEFAULT_PORTS = - http: 80 - https: 443 - -# Build an escaped URL string from unescaped components. Only scheme and host -# are required. See RFC 3986, section 3. -buildUrl = (scheme, host, port, path, params) -> - parts = [] - parts.push(encodeURIComponent scheme) - parts.push '://' - - # If it contains a colon but no square brackets, treat it as IPv6. - if host.match(/:/) && !host.match(/[[]]/) - parts.push '[' - parts.push host - parts.push ']' - else - parts.push(encodeURIComponent host) - - if undefined != port && DEFAULT_PORTS[scheme] != port - parts.push ':' - parts.push(encodeURIComponent port.toString()) - - if undefined != path && '' != path - if !path.match(/^//) - path = '/' + path +class WS + @WSS_ENABLED: true + @DEFAULT_PORTS: + http: 80 + https: 443 + + # Build an escaped URL string from unescaped components. Only scheme and host + # are required. See RFC 3986, section 3. + @buildUrl: (scheme, host, port, path, params) -> + parts = [] + parts.push(encodeURIComponent scheme) + parts.push '://' + + # If it contains a colon but no square brackets, treat it as IPv6. + if host.match(/:/) && !host.match(/[[]]/) + parts.push '[' + parts.push host + parts.push ']' + else + parts.push(encodeURIComponent host) + + if undefined != port && @DEFAULT_PORTS[scheme] != port + parts.push ':' + parts.push(encodeURIComponent port.toString()) + + if undefined != path && '' != path + if !path.match(/^//) + path = '/' + path + ### + Slash is significant so we must protect it from encodeURIComponent, while + still encoding question mark and number sign. RFC 3986, section 3.3: 'The + path is terminated by the first question mark ('?') or number sign ('#') + character, or by the end of the URI. ... A path consists of a sequence of + path segments separated by a slash ('/') character.' + ### + path = path.replace /[^/]+/, (m) -> + encodeURIComponent m + parts.push path + + if undefined != params + parts.push '?' + parts.push Query.buildString params + + parts.join '' + + @makeWebsocket: (addr, params) -> + wsProtocol = if @WSS_ENABLED then 'wss' else 'ws' + url = @buildUrl wsProtocol, addr.host, addr.port, '/', params + ws = new WebSocket url ### - Slash is significant so we must protect it from encodeURIComponent, while - still encoding question mark and number sign. RFC 3986, section 3.3: 'The - path is terminated by the first question mark ('?') or number sign ('#') - character, or by the end of the URI. ... A path consists of a sequence of - path segments separated by a slash ('/') character.' + 'User agents can use this as a hint for how to handle incoming binary data: if + the attribute is set to 'blob', it is safe to spool it to disk, and if it is + set to 'arraybuffer', it is likely more efficient to keep the data in memory.' ### - path = path.replace /[^/]+/, (m) -> - encodeURIComponent m - parts.push path - - if undefined != params - parts.push '?' - parts.push Query.buildString params - - parts.join '' - -makeWebsocket = (addr, params) -> - wsProtocol = if WSS_ENABLED then 'wss' else 'ws' - url = buildUrl wsProtocol, addr.host, addr.port, '/', params - ws = new WebSocket url - ### - 'User agents can use this as a hint for how to handle incoming binary data: if - the attribute is set to 'blob', it is safe to spool it to disk, and if it is - set to 'arraybuffer', it is likely more efficient to keep the data in memory.' - ### - ws.binaryType = 'arraybuffer' - ws + ws.binaryType = 'arraybuffer' + ws
tor-commits@lists.torproject.org