Commit f2d85676 authored by Joel Martin's avatar Joel Martin

websockify: better multi-python version support.

Pull from websockify: 008a5118e728.

Should address issue https://github.com/kanaka/noVNC/issues/107

- Also add ability to force use of web-socket-js using
  window.WEB_SOCKET_FORCE_FLASH

- in websock.js, for rQshift*, assume length is the full length if not
  specified.
parent b688a909
...@@ -17,9 +17,9 @@ ...@@ -17,9 +17,9 @@
// Load Flash WebSocket emulator if needed // Load Flash WebSocket emulator if needed
if (window.WebSocket) { if (window.WebSocket && !window.WEB_SOCKET_FORCE_FLASH) {
Websock_native = true; Websock_native = true;
} else if (window.MozWebSocket) { } else if (window.MozWebSocket && !window.WEB_SOCKET_FORCE_FLASH) {
Websock_native = true; Websock_native = true;
window.WebSocket = window.MozWebSocket; window.WebSocket = window.MozWebSocket;
} else { } else {
...@@ -119,6 +119,7 @@ function rQshift32() { ...@@ -119,6 +119,7 @@ function rQshift32() {
(rQ[rQi++] ); (rQ[rQi++] );
} }
function rQshiftStr(len) { function rQshiftStr(len) {
if (typeof(len) === 'undefined') { len = rQlen(); }
var arr = rQ.slice(rQi, rQi + len); var arr = rQ.slice(rQi, rQi + len);
rQi += len; rQi += len;
return arr.map(function (num) { return arr.map(function (num) {
...@@ -126,6 +127,7 @@ function rQshiftStr(len) { ...@@ -126,6 +127,7 @@ function rQshiftStr(len) {
} }
function rQshiftBytes(len) { function rQshiftBytes(len) {
if (typeof(len) === 'undefined') { len = rQlen(); }
rQi += len; rQi += len;
return rQ.slice(rQi-len, rQi); return rQ.slice(rQi-len, rQi);
} }
......
...@@ -17,48 +17,54 @@ as taken from http://docs.python.org/dev/library/ssl.html#certificates ...@@ -17,48 +17,54 @@ as taken from http://docs.python.org/dev/library/ssl.html#certificates
''' '''
import os, sys, time, errno, signal, socket, traceback, select import os, sys, time, errno, signal, socket, traceback, select
import struct, array import array, struct
from cgi import parse_qsl from cgi import parse_qsl
from base64 import b64encode, b64decode from base64 import b64encode, b64decode
# Imports that vary by python version # Imports that vary by python version
# python 3.0 differences
if sys.hexversion > 0x3000000: if sys.hexversion > 0x3000000:
# python >= 3.0
from io import StringIO
from http.server import SimpleHTTPRequestHandler
from urllib.parse import urlsplit
b2s = lambda buf: buf.decode('latin_1') b2s = lambda buf: buf.decode('latin_1')
s2b = lambda s: s.encode('latin_1') s2b = lambda s: s.encode('latin_1')
s2a = lambda s: s s2a = lambda s: s
else: else:
# python 2.X b2s = lambda buf: buf # No-op
from cStringIO import StringIO s2b = lambda s: s # No-op
from SimpleHTTPServer import SimpleHTTPRequestHandler
from urlparse import urlsplit
# No-ops
b2s = lambda buf: buf
s2b = lambda s: s
s2a = lambda s: [ord(c) for c in s] s2a = lambda s: [ord(c) for c in s]
try: from io import StringIO
if sys.hexversion >= 0x2060000: except: from cStringIO import StringIO
# python >= 2.6 try: from http.server import SimpleHTTPRequestHandler
from multiprocessing import Process except: from SimpleHTTPServer import SimpleHTTPRequestHandler
from hashlib import md5, sha1 try: from urllib.parse import urlsplit
else: except: from urlparse import urlsplit
# python < 2.6
Process = None # python 2.6 differences
from md5 import md5 try: from hashlib import md5, sha1
from sha import sha as sha1 except: from md5 import md5; from sha import sha as sha1
# python 2.5 differences
try:
from struct import pack, unpack_from
except:
from struct import pack
def unpack_from(fmt, buf, offset=0):
slice = buffer(buf, offset, struct.calcsize(fmt))
return struct.unpack(fmt, slice)
# Degraded functionality if these imports are missing # Degraded functionality if these imports are missing
for mod, sup in [('numpy', 'HyBi protocol'), for mod, sup in [('numpy', 'HyBi protocol'), ('ssl', 'TLS/SSL/wss'),
('ssl', 'TLS/SSL/wss'), ('resource', 'daemonizing')]: ('multiprocessing', 'Multi-Processing'),
('resource', 'daemonizing')]:
try: try:
globals()[mod] = __import__(mod) globals()[mod] = __import__(mod)
except ImportError: except ImportError:
globals()[mod] = None globals()[mod] = None
print("WARNING: no '%s' module, %s decode may be slower" % ( print("WARNING: no '%s' module, %s is slower or disabled" % (
mod, sup)) mod, sup))
if multiprocessing and sys.platform == 'win32':
# make sockets pickle-able/inheritable
import multiprocessing.reduction
class WebSocketServer(object): class WebSocketServer(object):
...@@ -265,11 +271,11 @@ Sec-WebSocket-Accept: %s\r ...@@ -265,11 +271,11 @@ Sec-WebSocket-Accept: %s\r
b1 = 0x80 | (opcode & 0x0f) # FIN + opcode b1 = 0x80 | (opcode & 0x0f) # FIN + opcode
payload_len = len(buf) payload_len = len(buf)
if payload_len <= 125: if payload_len <= 125:
header = struct.pack('>BB', b1, payload_len) header = pack('>BB', b1, payload_len)
elif payload_len > 125 and payload_len < 65536: elif payload_len > 125 and payload_len < 65536:
header = struct.pack('>BBH', b1, 126, payload_len) header = pack('>BBH', b1, 126, payload_len)
elif payload_len >= 65536: elif payload_len >= 65536:
header = struct.pack('>BBQ', b1, 127, payload_len) header = pack('>BBQ', b1, 127, payload_len)
#print("Encoded: %s" % repr(header + buf)) #print("Encoded: %s" % repr(header + buf))
...@@ -306,7 +312,7 @@ Sec-WebSocket-Accept: %s\r ...@@ -306,7 +312,7 @@ Sec-WebSocket-Accept: %s\r
if blen < f['hlen']: if blen < f['hlen']:
return f # Incomplete frame header return f # Incomplete frame header
b1, b2 = struct.unpack_from(">BB", buf) b1, b2 = unpack_from(">BB", buf)
f['opcode'] = b1 & 0x0f f['opcode'] = b1 & 0x0f
f['fin'] = (b1 & 0x80) >> 7 f['fin'] = (b1 & 0x80) >> 7
has_mask = (b2 & 0x80) >> 7 has_mask = (b2 & 0x80) >> 7
...@@ -317,12 +323,12 @@ Sec-WebSocket-Accept: %s\r ...@@ -317,12 +323,12 @@ Sec-WebSocket-Accept: %s\r
f['hlen'] = 4 f['hlen'] = 4
if blen < f['hlen']: if blen < f['hlen']:
return f # Incomplete frame header return f # Incomplete frame header
(f['length'],) = struct.unpack_from('>xxH', buf) (f['length'],) = unpack_from('>xxH', buf)
elif f['length'] == 127: elif f['length'] == 127:
f['hlen'] = 10 f['hlen'] = 10
if blen < f['hlen']: if blen < f['hlen']:
return f # Incomplete frame header return f # Incomplete frame header
(f['length'],) = struct.unpack_from('>xxQ', buf) (f['length'],) = unpack_from('>xxQ', buf)
full_len = f['hlen'] + has_mask * 4 + f['length'] full_len = f['hlen'] + has_mask * 4 + f['length']
...@@ -351,7 +357,7 @@ Sec-WebSocket-Accept: %s\r ...@@ -351,7 +357,7 @@ Sec-WebSocket-Accept: %s\r
if f['opcode'] == 0x08: if f['opcode'] == 0x08:
if f['length'] >= 2: if f['length'] >= 2:
f['close_code'] = struct.unpack_from(">H", f['payload']) f['close_code'] = unpack_from(">H", f['payload'])
if f['length'] > 3: if f['length'] > 3:
f['close_reason'] = f['payload'][2:] f['close_reason'] = f['payload'][2:]
...@@ -381,7 +387,7 @@ Sec-WebSocket-Accept: %s\r ...@@ -381,7 +387,7 @@ Sec-WebSocket-Accept: %s\r
num1 = int("".join([c for c in key1 if c.isdigit()])) / spaces1 num1 = int("".join([c for c in key1 if c.isdigit()])) / spaces1
num2 = int("".join([c for c in key2 if c.isdigit()])) / spaces2 num2 = int("".join([c for c in key2 if c.isdigit()])) / spaces2
return b2s(md5(struct.pack('>II8s', return b2s(md5(pack('>II8s',
int(num1), int(num2), key3)).digest()) int(num1), int(num2), key3)).digest())
# #
...@@ -532,7 +538,7 @@ Sec-WebSocket-Accept: %s\r ...@@ -532,7 +538,7 @@ Sec-WebSocket-Accept: %s\r
if self.version.startswith("hybi"): if self.version.startswith("hybi"):
msg = s2b('') msg = s2b('')
if code != None: if code != None:
msg = struct.pack(">H%ds" % (len(reason)), code) msg = pack(">H%ds" % (len(reason)), code)
buf, h, t = self.encode_hybi(msg, opcode=0x08, base64=False) buf, h, t = self.encode_hybi(msg, opcode=0x08, base64=False)
self.client.send(buf) self.client.send(buf)
...@@ -791,7 +797,7 @@ Sec-WebSocket-Accept: %s\r ...@@ -791,7 +797,7 @@ Sec-WebSocket-Accept: %s\r
# Allow override of SIGINT # Allow override of SIGINT
signal.signal(signal.SIGINT, self.do_SIGINT) signal.signal(signal.SIGINT, self.do_SIGINT)
if not Process: if not multiprocessing:
# os.fork() (python 2.4) child reaper # os.fork() (python 2.4) child reaper
signal.signal(signal.SIGCHLD, self.fallback_SIGCHLD) signal.signal(signal.SIGCHLD, self.fallback_SIGCHLD)
...@@ -837,9 +843,10 @@ Sec-WebSocket-Accept: %s\r ...@@ -837,9 +843,10 @@ Sec-WebSocket-Accept: %s\r
self.msg('%s: exiting due to --run-once' self.msg('%s: exiting due to --run-once'
% address[0]) % address[0])
break break
elif Process: elif multiprocessing:
self.vmsg('%s: new handler Process' % address[0]) self.vmsg('%s: new handler Process' % address[0])
p = Process(target=self.top_new_client, p = multiprocessing.Process(
target=self.top_new_client,
args=(startsock, address)) args=(startsock, address))
p.start() p.start()
# child will not return # child will not return
......
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