X-Git-Url: https://review.fuel-infra.org/gitweb?a=blobdiff_plain;f=eventlet%2Feventlet%2Fgreen%2Fssl.py;fp=eventlet%2Feventlet%2Fgreen%2Fssl.py;h=0000000000000000000000000000000000000000;hb=358bd9258c2b6d2ee74de4dfd07a5123107abad4;hp=963fbdb265af85483f7ff2bdcebc9a4bd98da866;hpb=376ff3bfe7071cc0793184a378c4e74508fb0d97;p=packages%2Ftrusty%2Fpython-eventlet.git diff --git a/eventlet/eventlet/green/ssl.py b/eventlet/eventlet/green/ssl.py deleted file mode 100644 index 963fbdb..0000000 --- a/eventlet/eventlet/green/ssl.py +++ /dev/null @@ -1,352 +0,0 @@ -__ssl = __import__('ssl') - -from eventlet.patcher import slurp_properties -slurp_properties(__ssl, globals(), srckeys=dir(__ssl)) - -import sys -import errno -time = __import__('time') - -from eventlet.support import get_errno, PY33, six -from eventlet.hubs import trampoline, IOClosed -from eventlet.greenio import ( - set_nonblocking, GreenSocket, SOCKET_CLOSED, CONNECT_ERR, CONNECT_SUCCESS, -) -orig_socket = __import__('socket') -socket = orig_socket.socket -if sys.version_info >= (2, 7): - has_ciphers = True - timeout_exc = SSLError -else: - has_ciphers = False - timeout_exc = orig_socket.timeout - -__patched__ = ['SSLSocket', 'wrap_socket', 'sslwrap_simple'] - -_original_sslsocket = __ssl.SSLSocket - - -class GreenSSLSocket(_original_sslsocket): - """ This is a green version of the SSLSocket class from the ssl module added - in 2.6. For documentation on it, please see the Python standard - documentation. - - Python nonblocking ssl objects don't give errors when the other end - of the socket is closed (they do notice when the other end is shutdown, - though). Any write/read operations will simply hang if the socket is - closed from the other end. There is no obvious fix for this problem; - it appears to be a limitation of Python's ssl object implementation. - A workaround is to set a reasonable timeout on the socket using - settimeout(), and to close/reopen the connection when a timeout - occurs at an unexpected juncture in the code. - """ - # we are inheriting from SSLSocket because its constructor calls - # do_handshake whose behavior we wish to override - - def __init__(self, sock, keyfile=None, certfile=None, - server_side=False, cert_reqs=CERT_NONE, - ssl_version=PROTOCOL_SSLv23, ca_certs=None, - do_handshake_on_connect=True, *args, **kw): - if not isinstance(sock, GreenSocket): - sock = GreenSocket(sock) - - self.act_non_blocking = sock.act_non_blocking - - if six.PY2: - # On Python 2 SSLSocket constructor queries the timeout, it'd break without - # this assignment - self._timeout = sock.gettimeout() - - # nonblocking socket handshaking on connect got disabled so let's pretend it's disabled - # even when it's on - super(GreenSSLSocket, self).__init__( - sock.fd, keyfile, certfile, server_side, cert_reqs, ssl_version, - ca_certs, do_handshake_on_connect and six.PY2, *args, **kw) - - # the superclass initializer trashes the methods so we remove - # the local-object versions of them and let the actual class - # methods shine through - # Note: This for Python 2 - try: - for fn in orig_socket._delegate_methods: - delattr(self, fn) - except AttributeError: - pass - - if six.PY3: - # Python 3 SSLSocket construction process overwrites the timeout so restore it - self._timeout = sock.gettimeout() - - # it also sets timeout to None internally apparently (tested with 3.4.2) - _original_sslsocket.settimeout(self, 0.0) - assert _original_sslsocket.gettimeout(self) == 0.0 - - # see note above about handshaking - self.do_handshake_on_connect = do_handshake_on_connect - if do_handshake_on_connect and self._connected: - self.do_handshake() - - def settimeout(self, timeout): - self._timeout = timeout - - def gettimeout(self): - return self._timeout - - def setblocking(self, flag): - if flag: - self.act_non_blocking = False - self._timeout = None - else: - self.act_non_blocking = True - self._timeout = 0.0 - - def _call_trampolining(self, func, *a, **kw): - if self.act_non_blocking: - return func(*a, **kw) - else: - while True: - try: - return func(*a, **kw) - except SSLError as exc: - if get_errno(exc) == SSL_ERROR_WANT_READ: - trampoline(self, - read=True, - timeout=self.gettimeout(), - timeout_exc=timeout_exc('timed out')) - elif get_errno(exc) == SSL_ERROR_WANT_WRITE: - trampoline(self, - write=True, - timeout=self.gettimeout(), - timeout_exc=timeout_exc('timed out')) - else: - raise - - def write(self, data): - """Write DATA to the underlying SSL channel. Returns - number of bytes of DATA actually transmitted.""" - return self._call_trampolining( - super(GreenSSLSocket, self).write, data) - - def read(self, *args, **kwargs): - """Read up to LEN bytes and return them. - Return zero-length string on EOF.""" - try: - return self._call_trampolining( - super(GreenSSLSocket, self).read, *args, **kwargs) - except IOClosed: - return b'' - - def send(self, data, flags=0): - if self._sslobj: - return self._call_trampolining( - super(GreenSSLSocket, self).send, data, flags) - else: - trampoline(self, write=True, timeout_exc=timeout_exc('timed out')) - return socket.send(self, data, flags) - - def sendto(self, data, addr, flags=0): - # *NOTE: gross, copied code from ssl.py becase it's not factored well enough to be used as-is - if self._sslobj: - raise ValueError("sendto not allowed on instances of %s" % - self.__class__) - else: - trampoline(self, write=True, timeout_exc=timeout_exc('timed out')) - return socket.sendto(self, data, addr, flags) - - def sendall(self, data, flags=0): - # *NOTE: gross, copied code from ssl.py becase it's not factored well enough to be used as-is - if self._sslobj: - if flags != 0: - raise ValueError( - "non-zero flags not allowed in calls to sendall() on %s" % - self.__class__) - amount = len(data) - count = 0 - while (count < amount): - v = self.send(data[count:]) - count += v - if v == 0: - trampoline(self, write=True, timeout_exc=timeout_exc('timed out')) - return amount - else: - while True: - try: - return socket.sendall(self, data, flags) - except orig_socket.error as e: - if self.act_non_blocking: - raise - if get_errno(e) == errno.EWOULDBLOCK: - trampoline(self, write=True, - timeout=self.gettimeout(), timeout_exc=timeout_exc('timed out')) - if get_errno(e) in SOCKET_CLOSED: - return '' - raise - - def recv(self, buflen=1024, flags=0): - # *NOTE: gross, copied code from ssl.py becase it's not factored well enough to be used as-is - if self._sslobj: - if flags != 0: - raise ValueError( - "non-zero flags not allowed in calls to recv() on %s" % - self.__class__) - read = self.read(buflen) - return read - else: - while True: - try: - return socket.recv(self, buflen, flags) - except orig_socket.error as e: - if self.act_non_blocking: - raise - if get_errno(e) == errno.EWOULDBLOCK: - try: - trampoline( - self, read=True, - timeout=self.gettimeout(), timeout_exc=timeout_exc('timed out')) - except IOClosed: - return b'' - if get_errno(e) in SOCKET_CLOSED: - return b'' - raise - - def recv_into(self, buffer, nbytes=None, flags=0): - if not self.act_non_blocking: - trampoline(self, read=True, timeout=self.gettimeout(), - timeout_exc=timeout_exc('timed out')) - return super(GreenSSLSocket, self).recv_into(buffer, nbytes, flags) - - def recvfrom(self, addr, buflen=1024, flags=0): - if not self.act_non_blocking: - trampoline(self, read=True, timeout=self.gettimeout(), - timeout_exc=timeout_exc('timed out')) - return super(GreenSSLSocket, self).recvfrom(addr, buflen, flags) - - def recvfrom_into(self, buffer, nbytes=None, flags=0): - if not self.act_non_blocking: - trampoline(self, read=True, timeout=self.gettimeout(), - timeout_exc=timeout_exc('timed out')) - return super(GreenSSLSocket, self).recvfrom_into(buffer, nbytes, flags) - - def unwrap(self): - return GreenSocket(self._call_trampolining( - super(GreenSSLSocket, self).unwrap)) - - def do_handshake(self): - """Perform a TLS/SSL handshake.""" - return self._call_trampolining( - super(GreenSSLSocket, self).do_handshake) - - def _socket_connect(self, addr): - real_connect = socket.connect - if self.act_non_blocking: - return real_connect(self, addr) - else: - # *NOTE: gross, copied code from greenio because it's not factored - # well enough to reuse - if self.gettimeout() is None: - while True: - try: - return real_connect(self, addr) - except orig_socket.error as exc: - if get_errno(exc) in CONNECT_ERR: - trampoline(self, write=True) - elif get_errno(exc) in CONNECT_SUCCESS: - return - else: - raise - else: - end = time.time() + self.gettimeout() - while True: - try: - real_connect(self, addr) - except orig_socket.error as exc: - if get_errno(exc) in CONNECT_ERR: - trampoline( - self, write=True, - timeout=end - time.time(), timeout_exc=timeout_exc('timed out')) - elif get_errno(exc) in CONNECT_SUCCESS: - return - else: - raise - if time.time() >= end: - raise timeout_exc('timed out') - - def connect(self, addr): - """Connects to remote ADDR, and then wraps the connection in - an SSL channel.""" - # *NOTE: grrrrr copied this code from ssl.py because of the reference - # to socket.connect which we don't want to call directly - if self._sslobj: - raise ValueError("attempt to connect already-connected SSLSocket!") - self._socket_connect(addr) - server_side = False - try: - sslwrap = _ssl.sslwrap - except AttributeError: - # sslwrap was removed in 3.x and later in 2.7.9 - if six.PY2: - sslobj = self._context._wrap_socket(self._sock, server_side, ssl_sock=self) - else: - context = self.context if PY33 else self._context - sslobj = context._wrap_socket(self, server_side) - else: - sslobj = sslwrap(self._sock, server_side, self.keyfile, self.certfile, - self.cert_reqs, self.ssl_version, - self.ca_certs, *([self.ciphers] if has_ciphers else [])) - - self._sslobj = sslobj - if self.do_handshake_on_connect: - self.do_handshake() - - def accept(self): - """Accepts a new connection from a remote client, and returns - a tuple containing that new connection wrapped with a server-side - SSL channel, and the address of the remote client.""" - # RDW grr duplication of code from greenio - if self.act_non_blocking: - newsock, addr = socket.accept(self) - else: - while True: - try: - newsock, addr = socket.accept(self) - set_nonblocking(newsock) - break - except orig_socket.error as e: - if get_errno(e) != errno.EWOULDBLOCK: - raise - trampoline(self, read=True, timeout=self.gettimeout(), - timeout_exc=timeout_exc('timed out')) - - new_ssl = type(self)( - newsock, - keyfile=self.keyfile, - certfile=self.certfile, - server_side=True, - cert_reqs=self.cert_reqs, - ssl_version=self.ssl_version, - ca_certs=self.ca_certs, - do_handshake_on_connect=self.do_handshake_on_connect, - suppress_ragged_eofs=self.suppress_ragged_eofs) - return (new_ssl, addr) - - def dup(self): - raise NotImplementedError("Can't dup an ssl object") - -SSLSocket = GreenSSLSocket - - -def wrap_socket(sock, *a, **kw): - return GreenSSLSocket(sock, *a, **kw) - - -if hasattr(__ssl, 'sslwrap_simple'): - def sslwrap_simple(sock, keyfile=None, certfile=None): - """A replacement for the old socket.ssl function. Designed - for compability with Python 2.5 and earlier. Will disappear in - Python 3.0.""" - ssl_sock = GreenSSLSocket(sock, keyfile=keyfile, certfile=certfile, - server_side=False, - cert_reqs=CERT_NONE, - ssl_version=PROTOCOL_SSLv23, - ca_certs=None) - return ssl_sock