mirror of
https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake.git
synced 2025-10-14 05:11:19 -04:00
Make a WS class to eliminate globals
This commit is contained in:
parent
f3254e3402
commit
bd5887a876
5 changed files with 90 additions and 85 deletions
|
@ -18,6 +18,7 @@ FILES_SPEC = [
|
||||||
'spec/broker.spec.coffee'
|
'spec/broker.spec.coffee'
|
||||||
'spec/proxypair.spec.coffee'
|
'spec/proxypair.spec.coffee'
|
||||||
'spec/snowflake.spec.coffee'
|
'spec/snowflake.spec.coffee'
|
||||||
|
'spec/websocket.spec.coffee'
|
||||||
]
|
]
|
||||||
FILES_ALL = FILES.concat FILES_SPEC
|
FILES_ALL = FILES.concat FILES_SPEC
|
||||||
OUTFILE = 'build/snowflake.js'
|
OUTFILE = 'build/snowflake.js'
|
||||||
|
|
|
@ -103,7 +103,7 @@ class ProxyPair
|
||||||
if peer_ip?
|
if peer_ip?
|
||||||
params.push(["client_ip", peer_ip])
|
params.push(["client_ip", peer_ip])
|
||||||
|
|
||||||
@relay = makeWebsocket @relayAddr, params
|
@relay = WS.makeWebsocket @relayAddr, params
|
||||||
@relay.label = 'websocket-relay'
|
@relay.label = 'websocket-relay'
|
||||||
@relay.onopen = =>
|
@relay.onopen = =>
|
||||||
if @timer
|
if @timer
|
||||||
|
|
|
@ -2,41 +2,6 @@
|
||||||
jasmine tests for Snowflake utils
|
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://[1: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 'Parse', ->
|
||||||
|
|
||||||
describe 'cookie', ->
|
describe 'cookie', ->
|
||||||
|
|
38
proxy/spec/websocket.spec.coffee
Normal file
38
proxy/spec/websocket.spec.coffee
Normal file
|
@ -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://[1: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'
|
|
@ -2,58 +2,59 @@
|
||||||
Only websocket-specific stuff.
|
Only websocket-specific stuff.
|
||||||
###
|
###
|
||||||
|
|
||||||
WSS_ENABLED = true
|
class WS
|
||||||
DEFAULT_PORTS =
|
@WSS_ENABLED: true
|
||||||
http: 80
|
@DEFAULT_PORTS:
|
||||||
https: 443
|
http: 80
|
||||||
|
https: 443
|
||||||
|
|
||||||
# Build an escaped URL string from unescaped components. Only scheme and host
|
# Build an escaped URL string from unescaped components. Only scheme and host
|
||||||
# are required. See RFC 3986, section 3.
|
# are required. See RFC 3986, section 3.
|
||||||
buildUrl = (scheme, host, port, path, params) ->
|
@buildUrl: (scheme, host, port, path, params) ->
|
||||||
parts = []
|
parts = []
|
||||||
parts.push(encodeURIComponent scheme)
|
parts.push(encodeURIComponent scheme)
|
||||||
parts.push '://'
|
parts.push '://'
|
||||||
|
|
||||||
# If it contains a colon but no square brackets, treat it as IPv6.
|
# If it contains a colon but no square brackets, treat it as IPv6.
|
||||||
if host.match(/:/) && !host.match(/[[\]]/)
|
if host.match(/:/) && !host.match(/[[\]]/)
|
||||||
parts.push '['
|
parts.push '['
|
||||||
parts.push host
|
parts.push host
|
||||||
parts.push ']'
|
parts.push ']'
|
||||||
else
|
else
|
||||||
parts.push(encodeURIComponent host)
|
parts.push(encodeURIComponent host)
|
||||||
|
|
||||||
if undefined != port && DEFAULT_PORTS[scheme] != port
|
if undefined != port && @DEFAULT_PORTS[scheme] != port
|
||||||
parts.push ':'
|
parts.push ':'
|
||||||
parts.push(encodeURIComponent port.toString())
|
parts.push(encodeURIComponent port.toString())
|
||||||
|
|
||||||
if undefined != path && '' != path
|
if undefined != path && '' != path
|
||||||
if !path.match(/^\//)
|
if !path.match(/^\//)
|
||||||
path = '/' + path
|
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
|
'User agents can use this as a hint for how to handle incoming binary data: if
|
||||||
still encoding question mark and number sign. RFC 3986, section 3.3: 'The
|
the attribute is set to 'blob', it is safe to spool it to disk, and if it is
|
||||||
path is terminated by the first question mark ('?') or number sign ('#')
|
set to 'arraybuffer', it is likely more efficient to keep the data in memory.'
|
||||||
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) ->
|
ws.binaryType = 'arraybuffer'
|
||||||
encodeURIComponent m
|
ws
|
||||||
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
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue