From 33a9ab48f994f7ff6380cecd6a723aa70b9fdc11 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Sun, 19 Jul 2009 01:44:46 -0700 Subject: [PATCH] Removed RefCount so that GreenSSL behaves more like SSL.Connection, fixed wsgi.py so that it handles this gracefully, and cleaned up all those TODOs --- eventlet/greenio.py | 57 +++++++++--------------------------------- eventlet/wsgi.py | 17 +++++++++++++ greentest/wsgi_test.py | 10 +++----- 3 files changed, 33 insertions(+), 51 deletions(-) diff --git a/eventlet/greenio.py b/eventlet/greenio.py index e98dd86..139bc04 100644 --- a/eventlet/greenio.py +++ b/eventlet/greenio.py @@ -530,35 +530,19 @@ class GreenPipe(GreenFile): self.fd.fd.flush() - -class RefCount(object): - """ Reference counting class only to be used with GreenSSL objects """ - def __init__(self): - self._count = 1 - - def increment(self): - self._count += 1 - - def decrement(self): - self._count -= 1 - assert self._count >= 0 - - def is_referenced(self): - return self._count > 0 - - class GreenSSL(GreenSocket): """ Nonblocking wrapper for SSL.Connection objects. + + Note: not compatible with SSLObject + (http://www.python.org/doc/2.5.2/lib/ssl-objects.html) because it does not + implement server() or issuer(), and the read() method has a mandatory size. """ - def __init__(self, fd, refcount = None): - GreenSocket.__init__(self, fd) + def __init__(self, fd): + super(GreenSSL, self).__init__(fd) assert(isinstance(fd, (util.SSL.ConnectionType)), "GreenSSL can only be constructed with an "\ "OpenSSL Connection object") self.sock = self - self._refcount = refcount - if refcount is None: - self._refcount = RefCount() def read(self, size): """Works like a blocking call to SSL_read(), whose behavior is @@ -613,33 +597,16 @@ class GreenSSL(GreenSocket): while tail < len(data): tail += self.send(data[tail:]) - def server(self): - return self.fd.server() - - def issuer(self): - return self.fd.issuer() - def dup(self): raise NotImplementedError("Dup not supported on SSL sockets") - - # TODO: remove and fix wsgi.py so that it doesn't call makefile on - # ssl sockets (see http://code.activestate.com/recipes/442473/) - def makefile(self, *args, **kw): - self._refcount.increment() - return GreenFile(type(self)(self.fd, refcount = self._refcount)) - # TODO: remove along with makefile - makeGreenFile = makefile + def makefile(self, mode='r', bufsize=-1): + raise NotImplementedError("Makefile not supported on SSL sockets") - # TODO: remove along with makefile - def close(self): - self._refcount.decrement() - if self._refcount.is_referenced(): - return - super(GreenSSL, self).close() - - - + def pending(self, *args, **kw): + fn = self.pending = self.fd.pending + return fn(*args, **kw) + def socketpair(*args): one, two = socket.socketpair(*args) diff --git a/eventlet/wsgi.py b/eventlet/wsgi.py index 0eed2b1..d7c9579 100644 --- a/eventlet/wsgi.py +++ b/eventlet/wsgi.py @@ -135,6 +135,23 @@ class Input(object): class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler): protocol_version = 'HTTP/1.1' minimum_chunk_size = MINIMUM_CHUNK_SIZE + + def setup(self): + # overriding SocketServer.setup to correctly handle SSL.Connection objects + conn = self.connection = self.request + try: + self.rfile = conn.makefile('rb', self.rbufsize) + self.wfile = conn.makefile('wb', self.wbufsize) + print "have a regular socket", conn.makefile + except (AttributeError, NotImplementedError): + if hasattr(conn, 'send') and hasattr(conn, 'recv'): + # it's an SSL.Connection + self.rfile = socket._fileobject(conn, "rb", self.rbufsize) + self.wfile = socket._fileobject(conn, "wb", self.wbufsize) + else: + # it's a SSLObject, or a martian + raise NotImplementedError("wsgi.py doesn't support sockets "\ + "of type %s" % type(conn)) def handle_one_request(self): if self.server.max_http_version: diff --git a/greentest/wsgi_test.py b/greentest/wsgi_test.py index 590b747..50fb75c 100644 --- a/greentest/wsgi_test.py +++ b/greentest/wsgi_test.py @@ -295,9 +295,8 @@ class TestHttpd(TestCase): sock = api.connect_tcp(('127.0.0.1', 4201)) sock = util.wrap_ssl(sock) - fd = sock.makeGreenFile() - fd.write('POST /foo HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\nContent-length:3\r\n\r\nabc') - result = fd.read(8192) + sock.write('POST /foo HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\nContent-length:3\r\n\r\nabc') + result = sock.read(8192) self.assertEquals(result[-3:], 'abc') def test_013_empty_return(self): @@ -326,9 +325,8 @@ class TestHttpd(TestCase): sock = api.connect_tcp(('127.0.0.1', 4202)) sock = util.wrap_ssl(sock) - fd = sock.makeGreenFile() - fd.write('GET /foo HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n') - result = fd.read(8192) + sock.write('GET /foo HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n') + result = sock.read(8192) self.assertEquals(result[-4:], '\r\n\r\n') def test_014_chunked_post(self):