Python OpenSSL.SSL.WantWriteError() Examples

The following are 21 code examples of OpenSSL.SSL.WantWriteError(). You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may also want to check out all available functions/classes of the module OpenSSL.SSL , or try the search function .
Example #1
Source File: handlers.py    From oss-ftp with MIT License 6 votes vote down vote up
def _handle_ssl_want_rw(self):
            prev_row_pending = self._ssl_want_read or self._ssl_want_write
            try:
                yield
            except SSL.WantReadError:
                # we should never get here; it's just for extra safety
                self._ssl_want_read = True
            except SSL.WantWriteError:
                # we should never get here; it's just for extra safety
                self._ssl_want_write = True

            if self._ssl_want_read:
                self.modify_ioloop_events(
                    self._wanted_io_events | self.ioloop.READ, logdebug=True)
            elif self._ssl_want_write:
                self.modify_ioloop_events(
                    self._wanted_io_events | self.ioloop.WRITE, logdebug=True)
            else:
                if prev_row_pending:
                    self.modify_ioloop_events(self._wanted_io_events) 
Example #2
Source File: handlers.py    From oss-ftp with MIT License 6 votes vote down vote up
def recv(self, buffer_size):
            try:
                return super(SSLConnection, self).recv(buffer_size)
            except SSL.WantReadError:
                debug("call: recv(), err: want-read", inst=self)
                self._ssl_want_read = True
                raise RetryError
            except SSL.WantWriteError:
                debug("call: recv(), err: want-write", inst=self)
                self._ssl_want_write = True
                raise RetryError
            except SSL.ZeroReturnError as err:
                debug("call: recv() -> shutdown(), err: zero-return",
                      inst=self)
                super(SSLConnection, self).handle_close()
                return b''
            except SSL.SysCallError as err:
                debug("call: recv(), err: %r" % err, inst=self)
                errnum, errstr = err.args
                if (errnum in _ERRNOS_DISCONNECTED or
                        errstr == 'Unexpected EOF'):
                    super(SSLConnection, self).handle_close()
                    return b''
                else:
                    raise 
Example #3
Source File: handlers.py    From oss-ftp with MIT License 6 votes vote down vote up
def _handle_ssl_want_rw(self):
            prev_row_pending = self._ssl_want_read or self._ssl_want_write
            try:
                yield
            except SSL.WantReadError:
                # we should never get here; it's just for extra safety
                self._ssl_want_read = True
            except SSL.WantWriteError:
                # we should never get here; it's just for extra safety
                self._ssl_want_write = True

            if self._ssl_want_read:
                self.modify_ioloop_events(
                    self._wanted_io_events | self.ioloop.READ, logdebug=True)
            elif self._ssl_want_write:
                self.modify_ioloop_events(
                    self._wanted_io_events | self.ioloop.WRITE, logdebug=True)
            else:
                if prev_row_pending:
                    self.modify_ioloop_events(self._wanted_io_events) 
Example #4
Source File: tcp.py    From BitTorrent with GNU General Public License v3.0 6 votes vote down vote up
def writeSomeData(self, data):
        try:
            return Connection.writeSomeData(self, data)
        except SSL.WantWriteError:
            return 0
        except SSL.WantReadError:
            self.writeBlockedOnRead = 1
            Connection.stopWriting(self)
            Connection.startReading(self)
            return 0
        except SSL.ZeroReturnError:
            return main.CONNECTION_LOST
        except SSL.SysCallError, e:
            if e[0] == -1 and data == "":
                # errors when writing empty strings are expected
                # and can be ignored
                return 0
            else:
                return main.CONNECTION_LOST 
Example #5
Source File: handlers.py    From oss-ftp with MIT License 6 votes vote down vote up
def recv(self, buffer_size):
            try:
                return super(SSLConnection, self).recv(buffer_size)
            except SSL.WantReadError:
                debug("call: recv(), err: want-read", inst=self)
                self._ssl_want_read = True
                raise RetryError
            except SSL.WantWriteError:
                debug("call: recv(), err: want-write", inst=self)
                self._ssl_want_write = True
                raise RetryError
            except SSL.ZeroReturnError as err:
                debug("call: recv() -> shutdown(), err: zero-return",
                      inst=self)
                super(SSLConnection, self).handle_close()
                return b''
            except SSL.SysCallError as err:
                debug("call: recv(), err: %r" % err, inst=self)
                errnum, errstr = err.args
                if (errnum in _ERRNOS_DISCONNECTED or
                        errstr == 'Unexpected EOF'):
                    super(SSLConnection, self).handle_close()
                    return b''
                else:
                    raise 
Example #6
Source File: tcp.py    From BitTorrent with GNU General Public License v3.0 6 votes vote down vote up
def doRead(self):
        if self.writeBlockedOnRead:
            self.writeBlockedOnRead = 0
            self._resetReadWrite()
        try:
            return Connection.doRead(self)
        except SSL.ZeroReturnError:
            return main.CONNECTION_DONE
        except SSL.WantReadError:
            return
        except SSL.WantWriteError:
            self.readBlockedOnWrite = 1
            Connection.startWriting(self)
            Connection.stopReading(self)
            return
        except SSL.SysCallError, (retval, desc):
            if ((retval == -1 and desc == 'Unexpected EOF')
                or retval > 0):
                return main.CONNECTION_LOST
            log.err()
            return main.CONNECTION_LOST 
Example #7
Source File: tcp.py    From python-for-android with Apache License 2.0 6 votes vote down vote up
def writeSomeData(self, data):
        try:
            return Connection.writeSomeData(self, data)
        except SSL.WantWriteError:
            return 0
        except SSL.WantReadError:
            self.writeBlockedOnRead = 1
            Connection.stopWriting(self)
            Connection.startReading(self)
            return 0
        except SSL.ZeroReturnError:
            return main.CONNECTION_LOST
        except SSL.SysCallError, e:
            if e[0] == -1 and data == "":
                # errors when writing empty strings are expected
                # and can be ignored
                return 0
            else:
                return main.CONNECTION_LOST 
Example #8
Source File: ssl_pyopenssl.py    From opsbro with MIT License 5 votes vote down vote up
def _safe_call(self, is_reader, call, *args, **kwargs):
        """Wrap the given call with SSL error-trapping.

        is_reader: if False EOF errors will be raised. If True, EOF errors
        will return "" (to emulate normal sockets).
        """
        start = time.time()
        while True:
            try:
                return call(*args, **kwargs)
            except SSL.WantReadError:
                # Sleep and try again. This is dangerous, because it means
                # the rest of the stack has no way of differentiating
                # between a "new handshake" error and "client dropped".
                # Note this isn't an endless loop: there's a timeout below.
                time.sleep(self.ssl_retry)
            except SSL.WantWriteError:
                time.sleep(self.ssl_retry)
            except SSL.SysCallError, e:
                if is_reader and e.args == (-1, 'Unexpected EOF'):
                    return ""

                errnum = e.args[0]
                if is_reader and errnum in wsgiserver.socket_errors_to_ignore:
                    return ""
                raise socket.error(errnum)
            except SSL.Error, e:
                if is_reader and e.args == (-1, 'Unexpected EOF'):
                    return ""

                thirdarg = None
                try:
                    thirdarg = e.args[0][0][2]
                except IndexError:
                    pass

                if thirdarg == 'http request':
                    # The client is talking HTTP to an HTTPS server.
                    raise wsgiserver.NoSSLError()

                raise wsgiserver.FatalSSLAlert(*e.args) 
Example #9
Source File: ssl_pyopenssl.py    From moviegrabber with GNU General Public License v3.0 5 votes vote down vote up
def _safe_call(self, is_reader, call, *args, **kwargs):
        """Wrap the given call with SSL error-trapping.
        
        is_reader: if False EOF errors will be raised. If True, EOF errors
        will return "" (to emulate normal sockets).
        """
        start = time.time()
        while True:
            try:
                return call(*args, **kwargs)
            except SSL.WantReadError:
                # Sleep and try again. This is dangerous, because it means
                # the rest of the stack has no way of differentiating
                # between a "new handshake" error and "client dropped".
                # Note this isn't an endless loop: there's a timeout below.
                time.sleep(self.ssl_retry)
            except SSL.WantWriteError:
                time.sleep(self.ssl_retry)
            except SSL.SysCallError, e:
                if is_reader and e.args == (-1, 'Unexpected EOF'):
                    return ""
                
                errnum = e.args[0]
                if is_reader and errnum in wsgiserver.socket_errors_to_ignore:
                    return ""
                raise socket.error(errnum)
            except SSL.Error, e:
                if is_reader and e.args == (-1, 'Unexpected EOF'):
                    return ""
                
                thirdarg = None
                try:
                    thirdarg = e.args[0][0][2]
                except IndexError:
                    pass
                
                if thirdarg == 'http request':
                    # The client is talking HTTP to an HTTPS server.
                    raise wsgiserver.NoSSLError()
                
                raise wsgiserver.FatalSSLAlert(*e.args) 
Example #10
Source File: ssl_pyopenssl.py    From cosa-nostra with GNU General Public License v3.0 5 votes vote down vote up
def _safe_call(self, is_reader, call, *args, **kwargs):
        """Wrap the given call with SSL error-trapping.
        
        is_reader: if False EOF errors will be raised. If True, EOF errors
        will return "" (to emulate normal sockets).
        """
        start = time.time()
        while True:
            try:
                return call(*args, **kwargs)
            except SSL.WantReadError:
                # Sleep and try again. This is dangerous, because it means
                # the rest of the stack has no way of differentiating
                # between a "new handshake" error and "client dropped".
                # Note this isn't an endless loop: there's a timeout below.
                time.sleep(self.ssl_retry)
            except SSL.WantWriteError:
                time.sleep(self.ssl_retry)
            except SSL.SysCallError, e:
                if is_reader and e.args == (-1, 'Unexpected EOF'):
                    return ""
                
                errnum = e.args[0]
                if is_reader and errnum in wsgiserver.socket_errors_to_ignore:
                    return ""
                raise socket.error(errnum)
            except SSL.Error, e:
                if is_reader and e.args == (-1, 'Unexpected EOF'):
                    return ""
                
                thirdarg = None
                try:
                    thirdarg = e.args[0][0][2]
                except IndexError:
                    pass
                
                if thirdarg == 'http request':
                    # The client is talking HTTP to an HTTPS server.
                    raise wsgiserver.NoSSLError()
                
                raise wsgiserver.FatalSSLAlert(*e.args) 
Example #11
Source File: ssl_pyopenssl.py    From bokken with GNU General Public License v2.0 5 votes vote down vote up
def _safe_call(self, is_reader, call, *args, **kwargs):
        """Wrap the given call with SSL error-trapping.
        
        is_reader: if False EOF errors will be raised. If True, EOF errors
        will return "" (to emulate normal sockets).
        """
        start = time.time()
        while True:
            try:
                return call(*args, **kwargs)
            except SSL.WantReadError:
                # Sleep and try again. This is dangerous, because it means
                # the rest of the stack has no way of differentiating
                # between a "new handshake" error and "client dropped".
                # Note this isn't an endless loop: there's a timeout below.
                time.sleep(self.ssl_retry)
            except SSL.WantWriteError:
                time.sleep(self.ssl_retry)
            except SSL.SysCallError, e:
                if is_reader and e.args == (-1, 'Unexpected EOF'):
                    return ""
                
                errnum = e.args[0]
                if is_reader and errnum in wsgiserver.socket_errors_to_ignore:
                    return ""
                raise socket.error(errnum)
            except SSL.Error, e:
                if is_reader and e.args == (-1, 'Unexpected EOF'):
                    return ""
                
                thirdarg = None
                try:
                    thirdarg = e.args[0][0][2]
                except IndexError:
                    pass
                
                if thirdarg == 'http request':
                    # The client is talking HTTP to an HTTPS server.
                    raise wsgiserver.NoSSLError()
                
                raise wsgiserver.FatalSSLAlert(*e.args) 
Example #12
Source File: tcp.py    From python-for-android with Apache License 2.0 5 votes vote down vote up
def doRead(self):
        if self.disconnected:
            # See the comment in the similar check in doWrite below.
            # Additionally, in order for anything other than returning
            # CONNECTION_DONE here to make sense, it will probably be necessary
            # to implement a way to switch back to TCP from TLS (actually, if
            # we did something other than return CONNECTION_DONE, that would be
            # a big part of implementing that feature).  In other words, the
            # expectation is that doRead will be called when self.disconnected
            # is True only when the connection has been lost.  It's possible
            # that the other end could stop speaking TLS and then send us some
            # non-TLS data.  We'll end up ignoring that data and dropping the
            # connection.  There's no unit tests for this check in the cases
            # where it makes a difference.  The test suite only hits this
            # codepath when it would have otherwise hit the SSL.ZeroReturnError
            # exception handler below, which has exactly the same behavior as
            # this conditional.  Maybe that's the only case that can ever be
            # triggered, I'm not sure.  -exarkun
            return main.CONNECTION_DONE
        if self.writeBlockedOnRead:
            self.writeBlockedOnRead = 0
            self._resetReadWrite()
        try:
            return Connection.doRead(self)
        except SSL.ZeroReturnError:
            return main.CONNECTION_DONE
        except SSL.WantReadError:
            return
        except SSL.WantWriteError:
            self.readBlockedOnWrite = 1
            Connection.startWriting(self)
            Connection.stopReading(self)
            return
        except SSL.SysCallError, (retval, desc):
            if ((retval == -1 and desc == 'Unexpected EOF')
                or retval > 0):
                return main.CONNECTION_LOST
            log.err()
            return main.CONNECTION_LOST 
Example #13
Source File: ssl_pyopenssl.py    From SalesforceXyTools with Apache License 2.0 5 votes vote down vote up
def _safe_call(self, is_reader, call, *args, **kwargs):
        """Wrap the given call with SSL error-trapping.
        
        is_reader: if False EOF errors will be raised. If True, EOF errors
        will return "" (to emulate normal sockets).
        """
        start = time.time()
        while True:
            try:
                return call(*args, **kwargs)
            except SSL.WantReadError:
                # Sleep and try again. This is dangerous, because it means
                # the rest of the stack has no way of differentiating
                # between a "new handshake" error and "client dropped".
                # Note this isn't an endless loop: there's a timeout below.
                time.sleep(self.ssl_retry)
            except SSL.WantWriteError:
                time.sleep(self.ssl_retry)
            except SSL.SysCallError, e:
                if is_reader and e.args == (-1, 'Unexpected EOF'):
                    return ""
                
                errnum = e.args[0]
                if is_reader and errnum in wsgiserver.socket_errors_to_ignore:
                    return ""
                raise socket.error(errnum)
            except SSL.Error, e:
                if is_reader and e.args == (-1, 'Unexpected EOF'):
                    return ""
                
                thirdarg = None
                try:
                    thirdarg = e.args[0][0][2]
                except IndexError:
                    pass
                
                if thirdarg == 'http request':
                    # The client is talking HTTP to an HTTPS server.
                    raise wsgiserver.NoSSLError()
                
                raise wsgiserver.FatalSSLAlert(*e.args) 
Example #14
Source File: handlers.py    From oss-ftp with MIT License 5 votes vote down vote up
def send(self, data):
            if not isinstance(data, bytes):
                data = bytes(data)
            try:
                return super(SSLConnection, self).send(data)
            except SSL.WantReadError:
                debug("call: send(), err: want-read", inst=self)
                self._ssl_want_read = True
                return 0
            except SSL.WantWriteError:
                debug("call: send(), err: want-write", inst=self)
                self._ssl_want_write = True
                return 0
            except SSL.ZeroReturnError as err:
                debug(
                    "call: send() -> shutdown(), err: zero-return", inst=self)
                super(SSLConnection, self).handle_close()
                return 0
            except SSL.SysCallError as err:
                debug("call: send(), err: %r" % err, inst=self)
                errnum, errstr = err.args
                if errnum == errno.EWOULDBLOCK:
                    return 0
                elif (errnum in _ERRNOS_DISCONNECTED or
                        errstr == 'Unexpected EOF'):
                    super(SSLConnection, self).handle_close()
                    return 0
                else:
                    raise 
Example #15
Source File: handlers.py    From oss-ftp with MIT License 5 votes vote down vote up
def send(self, data):
            if not isinstance(data, bytes):
                data = bytes(data)
            try:
                return super(SSLConnection, self).send(data)
            except SSL.WantReadError:
                debug("call: send(), err: want-read", inst=self)
                self._ssl_want_read = True
                return 0
            except SSL.WantWriteError:
                debug("call: send(), err: want-write", inst=self)
                self._ssl_want_write = True
                return 0
            except SSL.ZeroReturnError as err:
                debug(
                    "call: send() -> shutdown(), err: zero-return", inst=self)
                super(SSLConnection, self).handle_close()
                return 0
            except SSL.SysCallError as err:
                debug("call: send(), err: %r" % err, inst=self)
                errnum, errstr = err.args
                if errnum == errno.EWOULDBLOCK:
                    return 0
                elif (errnum in _ERRNOS_DISCONNECTED or
                        errstr == 'Unexpected EOF'):
                    super(SSLConnection, self).handle_close()
                    return 0
                else:
                    raise 
Example #16
Source File: handlers.py    From oss-ftp with MIT License 5 votes vote down vote up
def _do_ssl_handshake(self):
            self._ssl_accepting = True
            self._ssl_want_read = False
            self._ssl_want_write = False
            try:
                self.socket.do_handshake()
            except SSL.WantReadError:
                self._ssl_want_read = True
                debug("call: _do_ssl_handshake, err: want-read", inst=self)
            except SSL.WantWriteError:
                self._ssl_want_write = True
                debug("call: _do_ssl_handshake, err: want-write", inst=self)
            except SSL.SysCallError as err:
                debug("call: _do_ssl_handshake, err: %r" % err, inst=self)
                retval, desc = err.args
                if (retval == -1 and desc == 'Unexpected EOF') or retval > 0:
                    return self.handle_close()
                raise
            except SSL.Error as err:
                debug("call: _do_ssl_handshake, err: %r" % err, inst=self)
                return self.handle_failed_ssl_handshake()
            else:
                debug("SSL connection established", self)
                self._ssl_accepting = False
                self._ssl_established = True
                self.handle_ssl_established() 
Example #17
Source File: ssl_pyopenssl.py    From nightmare with GNU General Public License v2.0 5 votes vote down vote up
def _safe_call(self, is_reader, call, *args, **kwargs):
        """Wrap the given call with SSL error-trapping.
        
        is_reader: if False EOF errors will be raised. If True, EOF errors
        will return "" (to emulate normal sockets).
        """
        start = time.time()
        while True:
            try:
                return call(*args, **kwargs)
            except SSL.WantReadError:
                # Sleep and try again. This is dangerous, because it means
                # the rest of the stack has no way of differentiating
                # between a "new handshake" error and "client dropped".
                # Note this isn't an endless loop: there's a timeout below.
                time.sleep(self.ssl_retry)
            except SSL.WantWriteError:
                time.sleep(self.ssl_retry)
            except SSL.SysCallError, e:
                if is_reader and e.args == (-1, 'Unexpected EOF'):
                    return ""
                
                errnum = e.args[0]
                if is_reader and errnum in wsgiserver.socket_errors_to_ignore:
                    return ""
                raise socket.error(errnum)
            except SSL.Error, e:
                if is_reader and e.args == (-1, 'Unexpected EOF'):
                    return ""
                
                thirdarg = None
                try:
                    thirdarg = e.args[0][0][2]
                except IndexError:
                    pass
                
                if thirdarg == 'http request':
                    # The client is talking HTTP to an HTTPS server.
                    raise wsgiserver.NoSSLError()
                
                raise wsgiserver.FatalSSLAlert(*e.args) 
Example #18
Source File: pyopenssl.py    From cheroot with BSD 3-Clause "New" or "Revised" License 4 votes vote down vote up
def _safe_call(self, is_reader, call, *args, **kwargs):
        """Wrap the given call with TLS error-trapping.

        is_reader: if False EOF errors will be raised. If True, EOF errors
        will return "" (to emulate normal sockets).
        """
        start = time.time()
        while True:
            try:
                return call(*args, **kwargs)
            except SSL.WantReadError:
                # Sleep and try again. This is dangerous, because it means
                # the rest of the stack has no way of differentiating
                # between a "new handshake" error and "client dropped".
                # Note this isn't an endless loop: there's a timeout below.
                # Ref: https://stackoverflow.com/a/5133568/595220
                time.sleep(self.ssl_retry)
            except SSL.WantWriteError:
                time.sleep(self.ssl_retry)
            except SSL.SysCallError as e:
                if is_reader and e.args == (-1, 'Unexpected EOF'):
                    return b''

                errnum = e.args[0]
                if is_reader and errnum in errors.socket_errors_to_ignore:
                    return b''
                raise socket.error(errnum)
            except SSL.Error as e:
                if is_reader and e.args == (-1, 'Unexpected EOF'):
                    return b''

                thirdarg = None
                try:
                    thirdarg = e.args[0][0][2]
                except IndexError:
                    pass

                if thirdarg == 'http request':
                    # The client is talking HTTP to an HTTPS server.
                    raise errors.NoSSLError()

                raise errors.FatalSSLAlert(*e.args)

            if time.time() - start > self.ssl_timeout:
                raise socket.timeout('timed out') 
Example #19
Source File: ssl_pyopenssl.py    From Hatkey with GNU General Public License v3.0 4 votes vote down vote up
def _safe_call(self, is_reader, call, *args, **kwargs):
        """Wrap the given call with SSL error-trapping.

        is_reader: if False EOF errors will be raised. If True, EOF errors
        will return "" (to emulate normal sockets).
        """
        start = time.time()
        while True:
            try:
                return call(*args, **kwargs)
            except SSL.WantReadError:
                # Sleep and try again. This is dangerous, because it means
                # the rest of the stack has no way of differentiating
                # between a "new handshake" error and "client dropped".
                # Note this isn't an endless loop: there's a timeout below.
                time.sleep(self.ssl_retry)
            except SSL.WantWriteError:
                time.sleep(self.ssl_retry)
            except SSL.SysCallError as e:
                if is_reader and e.args == (-1, 'Unexpected EOF'):
                    return ""

                errnum = e.args[0]
                if is_reader and errnum in wsgiserver.socket_errors_to_ignore:
                    return ""
                raise socket.error(errnum)
            except SSL.Error as e:
                if is_reader and e.args == (-1, 'Unexpected EOF'):
                    return ""

                thirdarg = None
                try:
                    thirdarg = e.args[0][0][2]
                except IndexError:
                    pass

                if thirdarg == 'http request':
                    # The client is talking HTTP to an HTTPS server.
                    raise wsgiserver.NoSSLError()

                raise wsgiserver.FatalSSLAlert(*e.args)
            except:
                raise

            if time.time() - start > self.ssl_timeout:
                raise socket.timeout("timed out") 
Example #20
Source File: ssl_pyopenssl.py    From bazarr with GNU General Public License v3.0 4 votes vote down vote up
def _safe_call(self, is_reader, call, *args, **kwargs):
        """Wrap the given call with SSL error-trapping.

        is_reader: if False EOF errors will be raised. If True, EOF errors
        will return "" (to emulate normal sockets).
        """
        start = time.time()
        while True:
            try:
                return call(*args, **kwargs)
            except SSL.WantReadError:
                # Sleep and try again. This is dangerous, because it means
                # the rest of the stack has no way of differentiating
                # between a "new handshake" error and "client dropped".
                # Note this isn't an endless loop: there's a timeout below.
                time.sleep(self.ssl_retry)
            except SSL.WantWriteError:
                time.sleep(self.ssl_retry)
            except SSL.SysCallError as e:
                if is_reader and e.args == (-1, 'Unexpected EOF'):
                    return ''

                errnum = e.args[0]
                if is_reader and errnum in wsgiserver.socket_errors_to_ignore:
                    return ''
                raise socket.error(errnum)
            except SSL.Error as e:
                if is_reader and e.args == (-1, 'Unexpected EOF'):
                    return ''

                thirdarg = None
                try:
                    thirdarg = e.args[0][0][2]
                except IndexError:
                    pass

                if thirdarg == 'http request':
                    # The client is talking HTTP to an HTTPS server.
                    raise wsgiserver.NoSSLError()

                raise wsgiserver.FatalSSLAlert(*e.args)
            except:
                raise

            if time.time() - start > self.ssl_timeout:
                raise socket.timeout('timed out') 
Example #21
Source File: pyopenssl.py    From Tautulli with GNU General Public License v3.0 4 votes vote down vote up
def _safe_call(self, is_reader, call, *args, **kwargs):
        """Wrap the given call with SSL error-trapping.

        is_reader: if False EOF errors will be raised. If True, EOF errors
        will return "" (to emulate normal sockets).
        """
        start = time.time()
        while True:
            try:
                return call(*args, **kwargs)
            except SSL.WantReadError:
                # Sleep and try again. This is dangerous, because it means
                # the rest of the stack has no way of differentiating
                # between a "new handshake" error and "client dropped".
                # Note this isn't an endless loop: there's a timeout below.
                # Ref: https://stackoverflow.com/a/5133568/595220
                time.sleep(self.ssl_retry)
            except SSL.WantWriteError:
                time.sleep(self.ssl_retry)
            except SSL.SysCallError as e:
                if is_reader and e.args == (-1, 'Unexpected EOF'):
                    return b''

                errnum = e.args[0]
                if is_reader and errnum in errors.socket_errors_to_ignore:
                    return b''
                raise socket.error(errnum)
            except SSL.Error as e:
                if is_reader and e.args == (-1, 'Unexpected EOF'):
                    return b''

                thirdarg = None
                try:
                    thirdarg = e.args[0][0][2]
                except IndexError:
                    pass

                if thirdarg == 'http request':
                    # The client is talking HTTP to an HTTPS server.
                    raise errors.NoSSLError()

                raise errors.FatalSSLAlert(*e.args)

            if time.time() - start > self.ssl_timeout:
                raise socket.timeout('timed out')