Use detection rather than python version checking.
Try importing from the newest location/name and then fallback if that fails instead of using python version switches. Still use version switch for the buffer/bytes to string wrapper routines since python 2.6 has intermediate support for buffer/bytes and I want to know if full support (ala python 3.0) is there.
This commit is contained in:
parent
1658649d0c
commit
eac2c9fadd
85
websocket.py
85
websocket.py
|
@ -17,60 +17,54 @@ as taken from http://docs.python.org/dev/library/ssl.html#certificates
|
|||
'''
|
||||
|
||||
import os, sys, time, errno, signal, socket, traceback, select
|
||||
import 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]
|
||||
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
|
||||
|
||||
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
|
||||
# python 2.6 differences
|
||||
try: from hashlib import md5, sha1
|
||||
except: from md5 import md5; from sha import sha as sha1
|
||||
|
||||
if sys.hexversion >= 0x2050000:
|
||||
# python >= 2.5
|
||||
import struct
|
||||
else:
|
||||
# python < 2.5
|
||||
import struct
|
||||
# unpack_from was introduced in python 2.5
|
||||
def _unpack_from(fmt, buf, offset=0):
|
||||
# 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)
|
||||
struct.unpack_from = _unpack_from
|
||||
|
||||
# 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):
|
||||
|
@ -277,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))
|
||||
|
||||
|
@ -318,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
|
||||
|
@ -329,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']
|
||||
|
||||
|
@ -363,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:]
|
||||
|
||||
|
@ -393,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())
|
||||
|
||||
#
|
||||
|
@ -544,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)
|
||||
|
@ -803,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)
|
||||
|
||||
|
@ -849,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
|
||||
|
|
Loading…
Reference in New Issue