Commit 486cd527 authored by Joel Martin's avatar Joel Martin

Support WebSockets 76 (hixie-76, hybi-00).

Looks like disabling web-socket-js debug messages by default that we
get a minor speedup.

Python proxy should support both 75 and 76 (00) modes. Also, update ws
test to more reliably hit the WebSockets ordering/drop issue.
parent 7dfa20b8
...@@ -2,8 +2,6 @@ Short Term: ...@@ -2,8 +2,6 @@ Short Term:
- Test on IE 9 preview 3. - Test on IE 9 preview 3.
- Support WebSockets version 76 in proxy (Chrome 6 and Safari 5).
- Support Opera 10.60. - Support Opera 10.60.
- Possibly support IE <= 8.0 using excanvas: - Possibly support IE <= 8.0 using excanvas:
......
...@@ -36,3 +36,9 @@ WebSocket gets converted to UTF-8 and vice-versa. So, one additional ...@@ -36,3 +36,9 @@ WebSocket gets converted to UTF-8 and vice-versa. So, one additional
(and necessary) function of the proxy is base64 encoding/decoding what (and necessary) function of the proxy is base64 encoding/decoding what
is sent to/from the browser. Another option that I want to explore is is sent to/from the browser. Another option that I want to explore is
UTF-8 encoding in the proxy. UTF-8 encoding in the proxy.
Building web-socket-js emulator:
cd include/web-socket-js/flash-src
mxmlc -static-link-runtime-shared-libraries WebSocketMain.as
<html> <html>
<head><title>WebSockets Test</title></head> <head>
<title>WebSockets Test</title>
<script src="include/mootools.js"></script>
<script src="include/base64.js"></script>
<script src="include/util.js"></script>
<!-- Uncomment to activate firebug lite -->
<!--
<script type='text/javascript'
src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'></script>
-->
</head>
<body> <body>
...@@ -31,16 +43,6 @@ ...@@ -31,16 +43,6 @@
</body> </body>
<!-- Uncomment to activate firebug lite -->
<!--
<script type='text/javascript'
src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'></script>
-->
<script src="include/mootools.js"></script>
<script src="include/base64.js"></script>
<script src="include/util.js"></script>
<script> <script>
function error(str) { function error(str) {
...@@ -226,7 +228,10 @@ ...@@ -226,7 +228,10 @@
/* If no builtin websockets then load web_socket.js */ /* If no builtin websockets then load web_socket.js */
if (! window.WebSocket) { if (window.WebSocket) {
VNC_native_ws = true;
} else {
VNC_native_ws = false;
console.log("Loading web-socket-js flash bridge"); console.log("Loading web-socket-js flash bridge");
var extra = "<script src='include/web-socket-js/swfobject.js'><\/script>"; var extra = "<script src='include/web-socket-js/swfobject.js'><\/script>";
extra += "<script src='include/web-socket-js/FABridge.js'><\/script>"; extra += "<script src='include/web-socket-js/FABridge.js'><\/script>";
...@@ -236,7 +241,11 @@ ...@@ -236,7 +241,11 @@
window.onload = function() { window.onload = function() {
console.log("onload"); console.log("onload");
if (!VNC_native_ws) {
console.log("initializing web-socket-js flash bridge");
WebSocket.__swfLocation = "include/web-socket-js/WebSocketMain.swf"; WebSocket.__swfLocation = "include/web-socket-js/WebSocketMain.swf";
WebSocket.__initialize();
}
var url = document.location.href; var url = document.location.href;
$('host').value = (url.match(/host=([^&#]*)/) || ['',''])[1]; $('host').value = (url.match(/host=([^&#]*)/) || ['',''])[1];
$('port').value = (url.match(/port=([^&#]*)/) || ['',''])[1]; $('port').value = (url.match(/port=([^&#]*)/) || ['',''])[1];
......
...@@ -15,6 +15,7 @@ sys.path.insert(0,os.path.dirname(__file__) + "/../utils/") ...@@ -15,6 +15,7 @@ sys.path.insert(0,os.path.dirname(__file__) + "/../utils/")
from websocket import * from websocket import *
buffer_size = 65536 buffer_size = 65536
max_packet_size = 10000
recv_cnt = send_cnt = 0 recv_cnt = send_cnt = 0
...@@ -76,8 +77,8 @@ def check(buf): ...@@ -76,8 +77,8 @@ def check(buf):
def generate(): def generate():
global send_cnt, rand_array global send_cnt, rand_array
length = random.randint(10, 100000) length = random.randint(10, max_packet_size)
numlist = rand_array[100000-length:] numlist = rand_array[max_packet_size-length:]
# Error in length # Error in length
#numlist.append(5) #numlist.append(5)
chksum = sum(numlist) chksum = sum(numlist)
...@@ -156,7 +157,7 @@ if __name__ == '__main__': ...@@ -156,7 +157,7 @@ if __name__ == '__main__':
print "Prepopulating random array" print "Prepopulating random array"
rand_array = [] rand_array = []
for i in range(0, 100000): for i in range(0, max_packet_size):
rand_array.append(random.randint(0, 9)) rand_array.append(random.randint(0, 9))
settings['listen_port'] = listen_port settings['listen_port'] = listen_port
......
...@@ -9,9 +9,10 @@ as taken from http://docs.python.org/dev/library/ssl.html#certificates ...@@ -9,9 +9,10 @@ as taken from http://docs.python.org/dev/library/ssl.html#certificates
''' '''
import sys, socket, ssl, traceback import sys, socket, ssl, struct, traceback
import os, resource, errno, signal # daemonizing import os, resource, errno, signal # daemonizing
from base64 import b64encode, b64decode from base64 import b64encode, b64decode
from hashlib import md5
settings = { settings = {
'listen_host' : '', 'listen_host' : '',
...@@ -30,11 +31,11 @@ send_seq = 0 ...@@ -30,11 +31,11 @@ send_seq = 0
server_handshake = """HTTP/1.1 101 Web Socket Protocol Handshake\r server_handshake = """HTTP/1.1 101 Web Socket Protocol Handshake\r
Upgrade: WebSocket\r Upgrade: WebSocket\r
Connection: Upgrade\r Connection: Upgrade\r
WebSocket-Origin: %s\r %sWebSocket-Origin: %s\r
WebSocket-Location: %s://%s%s\r %sWebSocket-Location: %s://%s%s\r
WebSocket-Protocol: sample\r %sWebSocket-Protocol: sample\r
\r \r
""" %s"""
policy_response = """<cross-domain-policy><allow-access-from domain="*" to-ports="*" /></cross-domain-policy>\n""" policy_response = """<cross-domain-policy><allow-access-from domain="*" to-ports="*" /></cross-domain-policy>\n"""
...@@ -104,13 +105,11 @@ def do_handshake(sock): ...@@ -104,13 +105,11 @@ def do_handshake(sock):
scheme = "ws" scheme = "ws"
print " using plain (not SSL) socket" print " using plain (not SSL) socket"
handshake = retsock.recv(4096) handshake = retsock.recv(4096)
req_lines = handshake.split("\r\n") print "handshake: " + repr(handshake)
_, path, _ = req_lines[0].split(" ") h = parse_handshake(handshake)
_, origin = req_lines[4].split(" ")
_, host = req_lines[3].split(" ")
# Parse client settings from the GET path # Parse client settings from the GET path
cvars = path.partition('?')[2].partition('#')[0].split('&') cvars = h['path'].partition('?')[2].partition('#')[0].split('&')
for cvar in [c for c in cvars if c]: for cvar in [c for c in cvars if c]:
name, _, val = cvar.partition('=') name, _, val = cvar.partition('=')
if name not in ['b64encode', 'seq_num']: continue if name not in ['b64encode', 'seq_num']: continue
...@@ -118,9 +117,56 @@ def do_handshake(sock): ...@@ -118,9 +117,56 @@ def do_handshake(sock):
client_settings[name] = value client_settings[name] = value
print " %s=%s" % (name, value) print " %s=%s" % (name, value)
retsock.send(server_handshake % (origin, scheme, host, path)) if h.get('key3'):
trailer = gen_md5(h)
pre = "Sec-"
else:
trailer = ""
pre = ""
response = server_handshake % (pre, h['Origin'], pre, scheme,
h['Host'], h['path'], pre, trailer)
print "sending response:", repr(response)
retsock.send(response)
return retsock return retsock
def parse_handshake(handshake):
ret = {}
req_lines = handshake.split("\r\n")
if not req_lines[0].startswith("GET "):
raise "Invalid handshake: no GET request line"
ret['path'] = req_lines[0].split(" ")[1]
for line in req_lines[1:]:
if line == "": break
var, delim, val = line.partition(": ")
ret[var] = val
if req_lines[-2] == "":
ret['key3'] = req_lines[-1]
return ret
def gen_md5(keys):
key1 = keys['Sec-WebSocket-Key1']
key2 = keys['Sec-WebSocket-Key2']
key3 = keys['key3']
spaces1 = key1.count(" ")
spaces2 = key2.count(" ")
num1 = int("".join([c for c in key1 if c.isdigit()])) / spaces1
num2 = int("".join([c for c in key2 if c.isdigit()])) / spaces2
packed = struct.pack('>II8s', num1, num2, key3)
digest = md5(packed).digest()
print "num1:", num1
print "num2:", num2
print "key3:", repr(key3)
print "packed:", packed
print "digest:", repr(digest)
return digest
def daemonize(): def daemonize():
os.umask(0) os.umask(0)
os.chdir('/') os.chdir('/')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment