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:
@@ -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)
|
||||
|
@@ -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:
|
||||
|
@@ -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):
|
||||
|
Reference in New Issue
Block a user