12da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# Copyright 2011, Google Inc. 22da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# All rights reserved. 32da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# 42da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# Redistribution and use in source and binary forms, with or without 52da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# modification, are permitted provided that the following conditions are 62da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# met: 72da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# 82da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# * Redistributions of source code must retain the above copyright 92da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# notice, this list of conditions and the following disclaimer. 102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# * Redistributions in binary form must reproduce the above 112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# copyright notice, this list of conditions and the following disclaimer 122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# in the documentation and/or other materials provided with the 132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# distribution. 142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# * Neither the name of Google Inc. nor the names of its 152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# contributors may be used to endorse or promote products derived from 162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# this software without specific prior written permission. 172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# 182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis"""WebSocket utilities. 322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis""" 332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 352da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport array 362da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport errno 372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# Import hash classes from a module available and recommended for each Python 392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# version and re-export those symbol. Use sha and md5 module in Python 2.4, and 402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# hashlib module in Python 2.6. 412da489cd246702bee5938545b18a6f710ed214bcJamie Gennistry: 422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis import hashlib 432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis md5_hash = hashlib.md5 442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis sha1_hash = hashlib.sha1 452da489cd246702bee5938545b18a6f710ed214bcJamie Gennisexcept ImportError: 462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis import md5 472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis import sha 482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis md5_hash = md5.md5 492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis sha1_hash = sha.sha 502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 512da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport StringIO 522da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport logging 532da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport os 542da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport re 552da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport socket 562da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport traceback 572da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport zlib 582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 602da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef get_stack_trace(): 612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """Get the current stack trace as string. 622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis This is needed to support Python 2.3. 642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis TODO: Remove this when we only support Python 2.4 and above. 652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Use traceback.format_exc instead. 662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """ 672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis out = StringIO.StringIO() 692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis traceback.print_exc(file=out) 702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return out.getvalue() 712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 732da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef prepend_message_to_exception(message, exc): 742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """Prepend message to the exception.""" 752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis exc.args = (message + str(exc),) 772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return 782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 802da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef __translate_interp(interp, cygwin_path): 812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """Translate interp program path for Win32 python to run cygwin program 822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis (e.g. perl). Note that it doesn't support path that contains space, 832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis which is typically true for Unix, where #!-script is written. 842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis For Win32 python, cygwin_path is a directory of cygwin binaries. 852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Args: 872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis interp: interp command line 882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis cygwin_path: directory name of cygwin binary, or None 892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Returns: 902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis translated interp command line. 912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """ 922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if not cygwin_path: 932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return interp 942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis m = re.match('^[^ ]*/([^ ]+)( .*)?', interp) 952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if m: 962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis cmd = os.path.join(cygwin_path, m.group(1)) 972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return cmd + m.group(2) 982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return interp 992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1012da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef get_script_interp(script_path, cygwin_path=None): 1022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """Gets #!-interpreter command line from the script. 1032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis It also fixes command path. When Cygwin Python is used, e.g. in WebKit, 1052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis it could run "/usr/bin/perl -wT hello.pl". 1062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis When Win32 Python is used, e.g. in Chromium, it couldn't. So, fix 1072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis "/usr/bin/perl" to "<cygwin_path>\perl.exe". 1082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Args: 1102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis script_path: pathname of the script 1112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis cygwin_path: directory name of cygwin binary, or None 1122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Returns: 1132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis #!-interpreter command line, or None if it is not #!-script. 1142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """ 1152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis fp = open(script_path) 1162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis line = fp.readline() 1172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis fp.close() 1182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis m = re.match('^#!(.*)', line) 1192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if m: 1202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return __translate_interp(m.group(1), cygwin_path) 1212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return None 1222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1242da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef wrap_popen3_for_win(cygwin_path): 1252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """Wrap popen3 to support #!-script on Windows. 1262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Args: 1282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis cygwin_path: path for cygwin binary if command path is needed to be 1292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis translated. None if no translation required. 1302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """ 1312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis __orig_popen3 = os.popen3 1332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def __wrap_popen3(cmd, mode='t', bufsize=-1): 1352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis cmdline = cmd.split(' ') 1362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis interp = get_script_interp(cmdline[0], cygwin_path) 1372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if interp: 1382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis cmd = interp + ' ' + cmd 1392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return __orig_popen3(cmd, mode, bufsize) 1402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis os.popen3 = __wrap_popen3 1422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1442da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef hexify(s): 1452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return ' '.join(map(lambda x: '%02x' % ord(x), s)) 1462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1482da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef get_class_logger(o): 1492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return logging.getLogger( 1502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis '%s.%s' % (o.__class__.__module__, o.__class__.__name__)) 1512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1532da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass NoopMasker(object): 1542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """A masking object that has the same interface as RepeatedXorMasker but 1552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis just returns the string passed in without making any change. 1562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """ 1572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def __init__(self): 1592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis pass 1602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def mask(self, s): 1622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return s 1632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1652da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass RepeatedXorMasker(object): 1662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """A masking object that applies XOR on the string given to mask method 1672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis with the masking bytes given to the constructor repeatedly. This object 1682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis remembers the position in the masking bytes the last mask method call 1692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ended and resumes from that point on the next mask method call. 1702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """ 1712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def __init__(self, mask): 1732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._mask = map(ord, mask) 1742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._mask_size = len(self._mask) 1752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._count = 0 1762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def mask(self, s): 1782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis result = array.array('B') 1792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis result.fromstring(s) 1802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Use temporary local variables to eliminate the cost to access 1812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # attributes 1822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis count = self._count 1832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis mask = self._mask 1842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis mask_size = self._mask_size 1852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis for i in xrange(len(result)): 1862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis result[i] ^= mask[count] 1872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis count = (count + 1) % mask_size 1882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._count = count 1892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return result.tostring() 1912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1932da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass DeflateRequest(object): 1942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """A wrapper class for request object to intercept send and recv to perform 1952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis deflate compression and decompression transparently. 1962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """ 1972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def __init__(self, request): 1992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._request = request 2002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.connection = DeflateConnection(request.connection) 2012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def __getattribute__(self, name): 2032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if name in ('_request', 'connection'): 2042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return object.__getattribute__(self, name) 2052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return self._request.__getattribute__(name) 2062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def __setattr__(self, name, value): 2082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if name in ('_request', 'connection'): 2092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return object.__setattr__(self, name, value) 2102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return self._request.__setattr__(name, value) 2112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# By making wbits option negative, we can suppress CMF/FLG (2 octet) and 2142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# ADLER32 (4 octet) fields of zlib so that we can use zlib module just as 2152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# deflate library. DICTID won't be added as far as we don't set dictionary. 2162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# LZ77 window of 32K will be used for both compression and decompression. 2172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# For decompression, we can just use 32K to cover any windows size. For 2182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# compression, we use 32K so receivers must use 32K. 2192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# 2202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# Compression level is Z_DEFAULT_COMPRESSION. We don't have to match level 2212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# to decode. 2222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# 2232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# See zconf.h, deflate.cc, inflate.cc of zlib library, and zlibmodule.c of 2242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# Python. See also RFC1950 (ZLIB 3.3). 2252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2272da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass _Deflater(object): 2282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def __init__(self, window_bits): 2302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._logger = get_class_logger(self) 2312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._compress = zlib.compressobj( 2332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -window_bits) 2342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def compress_and_flush(self, bytes): 2362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_bytes = self._compress.compress(bytes) 2372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_bytes += self._compress.flush(zlib.Z_SYNC_FLUSH) 2382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._logger.debug('Compress input %r', bytes) 2392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._logger.debug('Compress result %r', compressed_bytes) 2402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return compressed_bytes 2412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2432da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass _Inflater(object): 2442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def __init__(self): 2462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._logger = get_class_logger(self) 2472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._unconsumed = '' 2492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.reset() 2512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def decompress(self, size): 2532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if not (size == -1 or size > 0): 2542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis raise Exception('size must be -1 or positive') 2552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data = '' 2572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis while True: 2592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if size == -1: 2602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += self._decompress.decompress(self._unconsumed) 2612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # See Python bug http://bugs.python.org/issue12050 to 2622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # understand why the same code cannot be used for updating 2632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # self._unconsumed for here and else block. 2642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._unconsumed = '' 2652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis else: 2662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += self._decompress.decompress( 2672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._unconsumed, size - len(data)) 2682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._unconsumed = self._decompress.unconsumed_tail 2692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if self._decompress.unused_data: 2702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Encountered a last block (i.e. a block with BFINAL = 1) and 2712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # found a new stream (unused_data). We cannot use the same 2722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # zlib.Decompress object for the new stream. Create a new 2732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Decompress object to decompress the new one. 2742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # 2752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # It's fine to ignore unconsumed_tail if unused_data is not 2762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # empty. 2772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._unconsumed = self._decompress.unused_data 2782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.reset() 2792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if size >= 0 and len(data) == size: 2802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # data is filled. Don't call decompress again. 2812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis break 2822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis else: 2832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Re-invoke Decompress.decompress to try to decompress all 2842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # available bytes before invoking read which blocks until 2852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # any new byte is available. 2862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis continue 2872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis else: 2882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Here, since unused_data is empty, even if unconsumed_tail is 2892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # not empty, bytes of requested length are already in data. We 2902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # don't have to "continue" here. 2912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis break 2922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if data: 2942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._logger.debug('Decompressed %r', data) 2952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return data 2962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def append(self, data): 2982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._logger.debug('Appended %r', data) 2992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._unconsumed += data 3002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def reset(self): 3022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._logger.debug('Reset') 3032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._decompress = zlib.decompressobj(-zlib.MAX_WBITS) 3042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# Compresses/decompresses given octets using the method introduced in RFC1979. 3072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3092da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass _RFC1979Deflater(object): 3102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """A compressor class that applies DEFLATE to given byte sequence and 3112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis flushes using the algorithm described in the RFC1979 section 2.1. 3122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """ 3132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def __init__(self, window_bits, no_context_takeover): 3152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._deflater = None 3162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if window_bits is None: 3172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis window_bits = zlib.MAX_WBITS 3182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._window_bits = window_bits 3192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._no_context_takeover = no_context_takeover 3202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def filter(self, bytes): 3222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if self._deflater is None or self._no_context_takeover: 3232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._deflater = _Deflater(self._window_bits) 3242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Strip last 4 octets which is LEN and NLEN field of a non-compressed 3262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # block added for Z_SYNC_FLUSH. 3272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return self._deflater.compress_and_flush(bytes)[:-4] 3282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3302da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass _RFC1979Inflater(object): 3312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """A decompressor class for byte sequence compressed and flushed following 3322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis the algorithm described in the RFC1979 section 2.1. 3332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """ 3342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def __init__(self): 3362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._inflater = _Inflater() 3372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def filter(self, bytes): 3392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Restore stripped LEN and NLEN field of a non-compressed block added 3402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # for Z_SYNC_FLUSH. 3412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._inflater.append(bytes + '\x00\x00\xff\xff') 3422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return self._inflater.decompress(-1) 3432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3452da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass DeflateSocket(object): 3462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """A wrapper class for socket object to intercept send and recv to perform 3472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis deflate compression and decompression transparently. 3482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """ 3492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Size of the buffer passed to recv to receive compressed data. 3512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis _RECV_SIZE = 4096 3522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def __init__(self, socket): 3542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._socket = socket 3552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._logger = get_class_logger(self) 3572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._deflater = _Deflater(zlib.MAX_WBITS) 3592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._inflater = _Inflater() 3602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def recv(self, size): 3622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """Receives data from the socket specified on the construction up 3632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis to the specified size. Once any data is available, returns it even 3642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if it's smaller than the specified size. 3652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """ 3662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # TODO(tyoshino): Allow call with size=0. It should block until any 3682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # decompressed data is available. 3692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if size <= 0: 3702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis raise Exception('Non-positive size passed') 3712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis while True: 3722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data = self._inflater.decompress(size) 3732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if len(data) != 0: 3742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return data 3752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis read_data = self._socket.recv(DeflateSocket._RECV_SIZE) 3772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if not read_data: 3782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return '' 3792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._inflater.append(read_data) 3802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def sendall(self, bytes): 3822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.send(bytes) 3832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def send(self, bytes): 3852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._socket.sendall(self._deflater.compress_and_flush(bytes)) 3862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return len(bytes) 3872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3892da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass DeflateConnection(object): 3902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """A wrapper class for request object to intercept write and read to 3912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis perform deflate compression and decompression transparently. 3922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """ 3932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def __init__(self, connection): 3952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._connection = connection 3962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._logger = get_class_logger(self) 3982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._deflater = _Deflater(zlib.MAX_WBITS) 4002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._inflater = _Inflater() 4012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def get_remote_addr(self): 4032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return self._connection.remote_addr 4042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis remote_addr = property(get_remote_addr) 4052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def put_bytes(self, bytes): 4072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.write(bytes) 4082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def read(self, size=-1): 4102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """Reads at most size bytes. Blocks until there's at least one byte 4112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis available. 4122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """ 4132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # TODO(tyoshino): Allow call with size=0. 4152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if not (size == -1 or size > 0): 4162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis raise Exception('size must be -1 or positive') 4172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data = '' 4192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis while True: 4202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if size == -1: 4212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += self._inflater.decompress(-1) 4222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis else: 4232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += self._inflater.decompress(size - len(data)) 4242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if size >= 0 and len(data) != 0: 4262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis break 4272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # TODO(tyoshino): Make this read efficient by some workaround. 4292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # 4302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # In 3.0.3 and prior of mod_python, read blocks until length bytes 4312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # was read. We don't know the exact size to read while using 4322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # deflate, so read byte-by-byte. 4332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # 4342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # _StandaloneRequest.read that ultimately performs 4352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # socket._fileobject.read also blocks until length bytes was read 4362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis read_data = self._connection.read(1) 4372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if not read_data: 4382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis break 4392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._inflater.append(read_data) 4402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return data 4412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def write(self, bytes): 4432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self._connection.write(self._deflater.compress_and_flush(bytes)) 4442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4462da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef _is_ewouldblock_errno(error_number): 4472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """Returns True iff error_number indicates that receive operation would 4482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis block. To make this portable, we check availability of errno and then 4492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compare them. 4502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """ 4512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis for error_name in ['WSAEWOULDBLOCK', 'EWOULDBLOCK', 'EAGAIN']: 4532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (error_name in dir(errno) and 4542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis error_number == getattr(errno, error_name)): 4552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return True 4562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return False 4572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4592da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef drain_received_data(raw_socket): 4602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Set the socket non-blocking. 4612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis original_timeout = raw_socket.gettimeout() 4622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis raw_socket.settimeout(0.0) 4632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis drained_data = [] 4652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Drain until the socket is closed or no data is immediately 4672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # available for read. 4682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis while True: 4692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis try: 4702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data = raw_socket.recv(1) 4712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if not data: 4722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis break 4732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis drained_data.append(data) 4742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis except socket.error, e: 4752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # e can be either a pair (errno, string) or just a string (or 4762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # something else) telling what went wrong. We suppress only 4772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # the errors that indicates that the socket blocks. Those 4782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # exceptions can be parsed as a pair (errno, string). 4792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis try: 4802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis error_number, message = e 4812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis except: 4822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Failed to parse socket.error. 4832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis raise e 4842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if _is_ewouldblock_errno(error_number): 4862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis break 4872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis else: 4882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis raise e 4892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Rollback timeout value. 4912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis raw_socket.settimeout(original_timeout) 4922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return ''.join(drained_data) 4942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# vi:sts=4 sw=4 et 497