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