diff --git a/include/websock.js b/include/websock.js index f293ce8b7622b7f3a8643e32f23383bc3b279506..ca17668c536825276e75374d41477deb0347f352 100644 --- a/include/websock.js +++ b/include/websock.js @@ -17,9 +17,9 @@ // Load Flash WebSocket emulator if needed -if (window.WebSocket) { +if (window.WebSocket && !window.WEB_SOCKET_FORCE_FLASH) { Websock_native = true; -} else if (window.MozWebSocket) { +} else if (window.MozWebSocket && !window.WEB_SOCKET_FORCE_FLASH) { Websock_native = true; window.WebSocket = window.MozWebSocket; } else { @@ -119,6 +119,7 @@ function rQshift32() { (rQ[rQi++] ); } function rQshiftStr(len) { + if (typeof(len) === 'undefined') { len = rQlen(); } var arr = rQ.slice(rQi, rQi + len); rQi += len; return arr.map(function (num) { @@ -126,6 +127,7 @@ function rQshiftStr(len) { } function rQshiftBytes(len) { + if (typeof(len) === 'undefined') { len = rQlen(); } rQi += len; return rQ.slice(rQi-len, rQi); } diff --git a/utils/websocket.py b/utils/websocket.py index 37b69c868a59e50ba95ed28c86dbcf05efea68c0..2b3bacc529739318e14a776f86bc01bc3bf74583 100644 --- a/utils/websocket.py +++ b/utils/websocket.py @@ -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 struct, array +import array, struct from cgi import parse_qsl from base64 import b64encode, b64decode # Imports that vary by python version + +# python 3.0 differences 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') s2b = lambda s: s.encode('latin_1') s2a = lambda s: s else: - # python 2.X - from cStringIO import StringIO - from SimpleHTTPServer import SimpleHTTPRequestHandler - from urlparse import urlsplit - # No-ops - b2s = lambda buf: buf - s2b = lambda s: s + b2s = lambda buf: buf # No-op + s2b = lambda s: s # No-op s2a = lambda s: [ord(c) for c in s] - -if sys.hexversion >= 0x2060000: - # python >= 2.6 - from multiprocessing import Process - from hashlib import md5, sha1 -else: - # python < 2.6 - Process = None - from md5 import md5 - from sha import sha as sha1 +try: from io import StringIO +except: from cStringIO import StringIO +try: from http.server import SimpleHTTPRequestHandler +except: from SimpleHTTPServer import SimpleHTTPRequestHandler +try: from urllib.parse import urlsplit +except: from urlparse import urlsplit + +# python 2.6 differences +try: from hashlib import md5, 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 -for mod, sup in [('numpy', 'HyBi protocol'), - ('ssl', 'TLS/SSL/wss'), ('resource', 'daemonizing')]: +for mod, sup in [('numpy', 'HyBi protocol'), ('ssl', 'TLS/SSL/wss'), + ('multiprocessing', 'Multi-Processing'), + ('resource', 'daemonizing')]: try: globals()[mod] = __import__(mod) except ImportError: 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)) +if multiprocessing and sys.platform == 'win32': + # make sockets pickle-able/inheritable + import multiprocessing.reduction class WebSocketServer(object): @@ -265,11 +271,11 @@ Sec-WebSocket-Accept: %s\r b1 = 0x80 | (opcode & 0x0f) # FIN + opcode payload_len = len(buf) 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: - header = struct.pack('>BBH', b1, 126, payload_len) + header = pack('>BBH', b1, 126, payload_len) 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)) @@ -306,7 +312,7 @@ Sec-WebSocket-Accept: %s\r if blen < f['hlen']: return f # Incomplete frame header - b1, b2 = struct.unpack_from(">BB", buf) + b1, b2 = unpack_from(">BB", buf) f['opcode'] = b1 & 0x0f f['fin'] = (b1 & 0x80) >> 7 has_mask = (b2 & 0x80) >> 7 @@ -317,12 +323,12 @@ Sec-WebSocket-Accept: %s\r f['hlen'] = 4 if blen < f['hlen']: return f # Incomplete frame header - (f['length'],) = struct.unpack_from('>xxH', buf) + (f['length'],) = unpack_from('>xxH', buf) elif f['length'] == 127: f['hlen'] = 10 if blen < f['hlen']: 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'] @@ -351,7 +357,7 @@ Sec-WebSocket-Accept: %s\r if f['opcode'] == 0x08: 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: f['close_reason'] = f['payload'][2:] @@ -381,7 +387,7 @@ Sec-WebSocket-Accept: %s\r num1 = int("".join([c for c in key1 if c.isdigit()])) / spaces1 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()) # @@ -532,7 +538,7 @@ Sec-WebSocket-Accept: %s\r if self.version.startswith("hybi"): msg = s2b('') 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) self.client.send(buf) @@ -791,7 +797,7 @@ Sec-WebSocket-Accept: %s\r # Allow override of SIGINT signal.signal(signal.SIGINT, self.do_SIGINT) - if not Process: + if not multiprocessing: # os.fork() (python 2.4) child reaper signal.signal(signal.SIGCHLD, self.fallback_SIGCHLD) @@ -837,9 +843,10 @@ Sec-WebSocket-Accept: %s\r self.msg('%s: exiting due to --run-once' % address[0]) break - elif Process: + elif multiprocessing: 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)) p.start() # child will not return