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

This commit is contained in:
Ryan Williams
2009-07-19 01:44:46 -07:00
parent d6d05c936f
commit 33a9ab48f9
3 changed files with 33 additions and 51 deletions

View File

@@ -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,32 +597,15 @@ 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
# TODO: remove along with makefile
def close(self):
self._refcount.decrement()
if self._refcount.is_referenced():
return
super(GreenSSL, self).close()
def makefile(self, mode='r', bufsize=-1):
raise NotImplementedError("Makefile not supported on SSL sockets")
def pending(self, *args, **kw):
fn = self.pending = self.fd.pending
return fn(*args, **kw)
def socketpair(*args):

View File

@@ -136,6 +136,23 @@ 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:
self.protocol_version = self.server.max_http_version

View File

@@ -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):