diff --git a/eventlet/convenience.py b/eventlet/convenience.py index 887ca3b..f199fbc 100644 --- a/eventlet/convenience.py +++ b/eventlet/convenience.py @@ -96,9 +96,7 @@ def serve(sock, handle, concurrency=1000): return -def wrap_ssl(sock, keyfile=None, certfile=None, server_side=False, - cert_reqs=0, ssl_version=2, ca_certs=None, - do_handshake_on_connect=True, suppress_ragged_eofs=True): +def wrap_ssl(sock, *a, **kw): """Convenience function for converting a regular socket into an SSL socket. Has the same interface as :func:`ssl.wrap_socket`, but works on 2.5 or earlier, using PyOpenSSL (though note that it @@ -114,13 +112,7 @@ def wrap_ssl(sock, keyfile=None, certfile=None, server_side=False, :return Green SSL object. """ - return wrap_ssl_impl(sock, keyfile=keyfile, certfile=certfile, - server_side=server_side, - cert_reqs=cert_reqs, - ssl_version=ssl_version, - ca_certs=ca_certs, - do_handshake_on_connect=do_handshake_on_connect, - suppress_ragged_eofs=suppress_ragged_eofs) + return wrap_ssl_impl(sock, *a, **kw) try: from eventlet.green import ssl @@ -131,7 +123,8 @@ except ImportError: try: def wrap_ssl_impl(sock, keyfile=None, certfile=None, server_side=False, cert_reqs=None, ssl_version=None, ca_certs=None, - do_handshake_on_connect=True, suppress_ragged_eofs=True): + do_handshake_on_connect=True, + suppress_ragged_eofs=True, ciphers=None): # theoretically the ssl_version could be respected in this # next line context = SSL.Context(SSL.SSLv23_METHOD) diff --git a/eventlet/green/_socket_nodns.py b/eventlet/green/_socket_nodns.py index 3a17fbb..b200aea 100644 --- a/eventlet/green/_socket_nodns.py +++ b/eventlet/green/_socket_nodns.py @@ -31,7 +31,9 @@ except AttributeError: -def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT): +def create_connection(address, + timeout=_GLOBAL_DEFAULT_TIMEOUT, + source_address=None): """Connect to *address* and return the socket object. Convenience function. Connect to *address* (a 2-tuple ``(host, @@ -51,6 +53,8 @@ def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT): sock = socket(af, socktype, proto) if timeout is not _GLOBAL_DEFAULT_TIMEOUT: sock.settimeout(timeout) + if source_address: + sock.bind(source_address) sock.connect(sa) return sock diff --git a/eventlet/green/ssl.py b/eventlet/green/ssl.py index b2a1296..fd60ba7 100644 --- a/eventlet/green/ssl.py +++ b/eventlet/green/ssl.py @@ -1,7 +1,8 @@ __ssl = __import__('ssl') -exec "\n".join(["%s = __ssl.%s" % (attr, attr) for attr in dir(__ssl)]) +exec "\n".join("%s = __ssl.%s" % (attr, attr) for attr in dir(__ssl)) +import sys import errno time = __import__('time') @@ -10,7 +11,12 @@ from eventlet.hubs import trampoline from eventlet.greenio import set_nonblocking, GreenSocket, SOCKET_CLOSED, CONNECT_ERR, CONNECT_SUCCESS orig_socket = __import__('socket') socket = orig_socket.socket -timeout_exc = orig_socket.timeout +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'] @@ -38,9 +44,14 @@ class GreenSSLSocket(__ssl.SSLSocket): self._timeout = sock.gettimeout() super(GreenSSLSocket, self).__init__(sock.fd, *args, **kw) - # the superclass initializer trashes the methods so... - for fn in orig_socket._delegate_methods: - delattr(self, fn) + # the superclass initializer trashes the methods so we remove + # the local-object versions of them and let the actual class + # methods shine through + try: + for fn in orig_socket._delegate_methods: + delattr(self, fn) + except AttributeError: + pass def settimeout(self, timeout): self._timeout = timeout @@ -247,9 +258,14 @@ class GreenSSLSocket(__ssl.SSLSocket): if self._sslobj: raise ValueError("attempt to connect already-connected SSLSocket!") self._socket_connect(addr) - self._sslobj = _ssl.sslwrap(self._sock, False, self.keyfile, self.certfile, - self.cert_reqs, self.ssl_version, - self.ca_certs) + if has_ciphers: + self._sslobj = _ssl.sslwrap(self._sock, False, self.keyfile, self.certfile, + self.cert_reqs, self.ssl_version, + self.ca_certs, self.ciphers) + else: + self._sslobj = _ssl.sslwrap(self._sock, False, self.keyfile, self.certfile, + self.cert_reqs, self.ssl_version, + self.ca_certs) if self.do_handshake_on_connect: self.do_handshake() @@ -286,16 +302,8 @@ class GreenSSLSocket(__ssl.SSLSocket): SSLSocket = GreenSSLSocket -def wrap_socket(sock, keyfile=None, certfile=None, - server_side=False, cert_reqs=CERT_NONE, - ssl_version=PROTOCOL_SSLv23, ca_certs=None, - do_handshake_on_connect=True, - suppress_ragged_eofs=True): - return GreenSSLSocket(sock, keyfile=keyfile, certfile=certfile, - server_side=server_side, cert_reqs=cert_reqs, - ssl_version=ssl_version, ca_certs=ca_certs, - do_handshake_on_connect=do_handshake_on_connect, - suppress_ragged_eofs=suppress_ragged_eofs) +def wrap_socket(sock, *a, **kw): + return GreenSSLSocket(sock, *a, **kw) if hasattr(__ssl, 'sslwrap_simple'): diff --git a/eventlet/green/thread.py b/eventlet/green/thread.py index 9e003f9..126651a 100644 --- a/eventlet/green/thread.py +++ b/eventlet/green/thread.py @@ -5,9 +5,14 @@ from eventlet import greenthread from eventlet.semaphore import Semaphore as LockType __patched__ = ['get_ident', 'start_new_thread', 'start_new', 'allocate_lock', - 'allocate', 'exit', 'interrupt_main', 'stack_size', '_local', 'LockType'] + 'allocate', 'exit', 'interrupt_main', 'stack_size', '_local', + 'LockType', '_count'] error = __thread.error +__threadcount = 0 + +def _count(): + return __threadcount def get_ident(gr=None): if gr is None: @@ -15,13 +20,21 @@ def get_ident(gr=None): else: return id(gr) +def __thread_body(func, args, kwargs): + global __threadcount + __threadcount += 1 + try: + func(*args, **kwargs) + finally: + __threadcount -= 1 + def start_new_thread(function, args=(), kwargs={}): - g = greenthread.spawn_n(function, *args, **kwargs) + g = greenthread.spawn_n(__thread_body, function, args, kwargs) return get_ident(g) start_new = start_new_thread -def allocate_lock(): +def allocate_lock(*a): return LockType(1) allocate = allocate_lock diff --git a/tests/stdlib/test_ftplib.py b/tests/stdlib/test_ftplib.py index 0bff132..3563738 100644 --- a/tests/stdlib/test_ftplib.py +++ b/tests/stdlib/test_ftplib.py @@ -5,11 +5,7 @@ from eventlet.green import threading from eventlet.green import socket patcher.inject('test.test_ftplib', - globals(), - ('asyncore', asyncore), - ('ftplib', ftplib), - ('socket', socket), - ('threading', threading)) + globals()) if __name__ == "__main__": - test_main() \ No newline at end of file + test_main()