Merge branch 'achille-roussel-wsaccel'

This commit is contained in:
liris
2015-07-16 09:27:22 +09:00
3 changed files with 70 additions and 48 deletions

View File

@@ -26,6 +26,24 @@ import os
from ._exceptions import * from ._exceptions import *
from ._utils import validate_utf8 from ._utils import validate_utf8
try:
# If wsaccel is available we use compiled routines to mask data.
from wsaccel.xormask import XorMaskerSimple
def _mask(_m, _d):
return XorMaskerSimple(_m).process(_d)
except ImportError:
# wsaccel is not available, we rely on python implementations.
def _mask(_m, _d):
for i in range(len(_d)):
_d[i] ^= _m[i % 4]
if six.PY3:
return _d.tobytes()
else:
return _d.tostring()
# closing frame status codes. # closing frame status codes.
STATUS_NORMAL = 1000 STATUS_NORMAL = 1000
STATUS_GOING_AWAY = 1001 STATUS_GOING_AWAY = 1001
@@ -208,6 +226,7 @@ class ABNF(object):
""" """
if data == None: if data == None:
data = "" data = ""
if isinstance(mask_key, six.text_type): if isinstance(mask_key, six.text_type):
mask_key = six.b(mask_key) mask_key = six.b(mask_key)
@@ -216,14 +235,7 @@ class ABNF(object):
_m = array.array("B", mask_key) _m = array.array("B", mask_key)
_d = array.array("B", data) _d = array.array("B", data)
for i in range(len(_d)): return _mask(_m, _d)
_d[i] ^= _m[i % 4]
if six.PY3:
return _d.tobytes()
else:
return _d.tostring()
class frame_buffer(object): class frame_buffer(object):
_HEADER_MASK_INDEX = 5 _HEADER_MASK_INDEX = 5

View File

@@ -119,7 +119,7 @@ def _open_socket(addrinfo_list, sockopt, timeout):
def _can_use_sni(): def _can_use_sni():
return six.Py2 and sys.version_info >= (2, 7, 9) or sys.version_info >= (3, 2) return six.PY2 and sys.version_info >= (2, 7, 9) or sys.version_info >= (3, 2)
def _wrap_sni_socket(sock, sslopt, hostname, check_hostname): def _wrap_sni_socket(sock, sslopt, hostname, check_hostname):

View File

@@ -28,43 +28,63 @@ class NoLock(object):
def __enter__(self): def __enter__(self):
pass pass
def __exit__(self,type, value, traceback): def __exit__(self, type, value, traceback):
pass pass
try:
# If wsaccel is availabe we use compiled routines to validate UTF-8
# strings.
from wsaccel.utf8validator import Utf8Validator
# UTF-8 validator def _validate_utf8(utfbytes):
# python implementation of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ return Utf8Validator().validate(utfbytes)[0]
UTF8_ACCEPT = 0 except ImportError:
UTF8_REJECT=12 # UTF-8 validator
# python implementation of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
_UTF8D = [ _UTF8_ACCEPT = 0
# The first part of the table maps bytes to character classes that _UTF8_REJECT = 12
# to reduce the size of the transition table and create bitmasks.
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
# The second part is a transition table that maps a combination _UTF8D = [
# of a state of the automaton and a character class to a state. # The first part of the table maps bytes to character classes that
0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12, # to reduce the size of the transition table and create bitmasks.
12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
12,36,12,12,12,12,12,12,12,12,12,12, ] 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
def _decode(state, codep, ch): # The second part is a transition table that maps a combination
tp = _UTF8D[ch] # of a state of the automaton and a character class to a state.
0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12,
12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12,
12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12,
12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12,
12,36,12,12,12,12,12,12,12,12,12,12, ]
codep = (ch & 0x3f ) | (codep << 6) if (state != UTF8_ACCEPT) else (0xff >> tp) & (ch) def _decode(state, codep, ch):
state = _UTF8D[256 + state + tp] tp = _UTF8D[ch]
return state, codep; codep = (ch & 0x3f ) | (codep << 6) if (state != _UTF8_ACCEPT) else (0xff >> tp) & (ch)
state = _UTF8D[256 + state + tp]
return state, codep;
def _validate_utf8(utfbytes):
state = _UTF8_ACCEPT
codep = 0
for i in utfbytes:
if six.PY2:
i = ord(i)
state, codep = _decode(state, codep, i)
if state == _UTF8_REJECT:
return False
return True
def validate_utf8(utfbytes): def validate_utf8(utfbytes):
""" """
@@ -72,17 +92,7 @@ def validate_utf8(utfbytes):
utfbytes: utf byte string to check. utfbytes: utf byte string to check.
return value: if valid utf8 string, return true. Otherwise, return false. return value: if valid utf8 string, return true. Otherwise, return false.
""" """
state = UTF8_ACCEPT return _validate_utf8(utfbytes)
codep = 0
for i in utfbytes:
if six.PY2:
i = ord(i)
state, codep = _decode(state, codep, i)
if state == UTF8_REJECT:
return False
return True
def extract_err_message(exception): def extract_err_message(exception):
if exception.args: if exception.args: