diff --git a/NEWS b/NEWS index acb70b3..ae64b3a 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,9 @@ +0.7.x +===== +Fix a major memory leak when using the libevent or libev hubs. Timers were not being removed from the hub after they fired. (Thanks Agusto Becciu and the grugq). Also, make it possible to call wrap_socket_with_coroutine_socket without using the threadpool to make dns operations non-blocking (Thanks the grugq). + +It's now possible to use eventlet's SSL client to talk to eventlet's SSL server. (Thanks to Ryan Williams) + 0.6.x ===== @@ -5,8 +11,6 @@ Fixes some long-standing bugs where sometimes failures in accept() or connect() 0.6.1: Added eventlet.tpool.killall. Blocks until all of the threadpool threads have been told to exit and join()ed. Meant to be used to clean up the threadpool on exit or if calling execv. Used by Spawning. -0.6.2: Fix a major memory leak when using the libevent or libev hubs. Timers were not being removed from the hub after they fired. (Thanks Agusto Becciu). Also, make it possible to call wrap_socket_with_coroutine_socket without using the threadpool to make dns operations non-blocking (Thanks the grugq). - 0.5.x ===== diff --git a/README b/README index 3b73486..0d05178 100644 --- a/README +++ b/README @@ -21,9 +21,6 @@ Eventlet runs on Python version 2.3 or greater, with the following dependenceis: * Not enough test coverage -- the goal is 100%, but we are not there yet. * Eventlet does not currently run on stackless using tasklets, though it is a goal to do so in the future. -* The SSL client does not properly connect to the SSL server, though -both client and server interoperate with other SSL implementations -(e.g. curl and apache). == getting started == diff --git a/eventlet/api_test.py b/eventlet/api_test.py index 53c5501..0e45f8f 100644 --- a/eventlet/api_test.py +++ b/eventlet/api_test.py @@ -22,10 +22,14 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ -from eventlet import tests -from eventlet import api, greenio, util +import os import socket +from eventlet import api +from eventlet import greenio +from eventlet import tests +from eventlet import util + def check_hub(): # Clear through the descriptor queue @@ -43,6 +47,10 @@ def check_hub(): class TestApi(tests.TestCase): mode = 'static' + + certificate_file = os.path.join(os.path.dirname(__file__), 'test_server.crt') + private_key_file = os.path.join(os.path.dirname(__file__), 'test_server.key') + def test_tcp_listener(self): socket = api.tcp_listener(('0.0.0.0', 0)) assert socket.getsockname()[0] == '0.0.0.0' @@ -74,6 +82,30 @@ class TestApi(tests.TestCase): check_hub() + def test_connect_ssl(self): + def accept_once(listenfd): + try: + conn, addr = listenfd.accept() + fl = conn.makefile('w') + fl.write('hello\r\n') + fl.close() + conn.close() + finally: + listenfd.close() + + server = api.ssl_listener(('0.0.0.0', 0), + self.certificate_file, + self.private_key_file) + api.spawn(accept_once, server) + + client = util.wrap_ssl( + api.connect_tcp(('127.0.0.1', server.getsockname()[1]))) + client = client.makefile() + + assert client.readline() == 'hello\r\n' + assert client.read() == '' + client.close() + def test_server(self): connected = [] server = api.tcp_listener(('0.0.0.0', 0)) diff --git a/eventlet/greenio.py b/eventlet/greenio.py index f214f75..c2faca6 100644 --- a/eventlet/greenio.py +++ b/eventlet/greenio.py @@ -137,7 +137,7 @@ def socket_recv(descriptor, buflen): return '' except util.SSL.SysCallError, e: if e[0] == -1 or e[0] > 0: - raise socket.error(errno.ECONNRESET, errno.errorcode[errno.ECONNRESET]) + return '' raise finally: if cancel: @@ -213,6 +213,12 @@ class GreenSocket(object): if self.closed: return self.closed = True + if self.is_secure: + # *NOTE: This is not quite the correct SSL shutdown sequence. + # We should actually be checking the return value of shutdown. + # Note also that this is not the same as calling self.shutdown(). + self.fd.shutdown() + fn = self.close = self.fd.close try: res = fn(*args, **kw) @@ -296,7 +302,10 @@ class GreenSocket(object): return fn(*args, **kw) def shutdown(self, *args, **kw): - fn = self.shutdown = self.fd.shutdown + if self.is_secure: + fn = self.shutdown = self.fd.sock_shutdown + else: + fn = self.shutdown = self.fd.shutdown return fn(*args, **kw) def settimeout(self, howlong): diff --git a/setup.py b/setup.py index 3e82c55..971084c 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ from setuptools import find_packages, setup setup( name='eventlet', - version='0.6.2pre', + version='0.7pre', description='Coroutine-based networking library', author='Linden Lab', author_email='eventletdev@lists.secondlife.com',