[pypy-svn] pypy default: SSLObject.read() now returns '' when the other side cleanly closes the connection.

amauryfa commits-noreply at bitbucket.org
Fri Jan 28 18:43:07 CET 2011


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: 
Changeset: r41434:7563680a9fea
Date: 2011-01-28 18:36 +0100
http://bitbucket.org/pypy/pypy/changeset/7563680a9fea/

Log:	SSLObject.read() now returns '' when the other side cleanly closes
	the connection.

	I could not come with a working test (sorry) but now test_ftplib.py
	passes.

diff --git a/pypy/module/_ssl/interp_ssl.py b/pypy/module/_ssl/interp_ssl.py
--- a/pypy/module/_ssl/interp_ssl.py
+++ b/pypy/module/_ssl/interp_ssl.py
@@ -216,6 +216,10 @@
                 raise ssl_error(self.space, "The read operation timed out")
             elif sockstate == SOCKET_TOO_LARGE_FOR_SELECT:
                 raise ssl_error(self.space, "Underlying socket too large for select().")
+            elif sockstate == SOCKET_HAS_BEEN_CLOSED:
+                if libssl_SSL_get_shutdown(self.ssl) == SSL_RECEIVED_SHUTDOWN:
+                    return self.space.wrap('')
+                raise ssl_error(self.space, "Socket closed without SSL shutdown handshake")
 
         raw_buf, gc_buf = rffi.alloc_buffer(num_bytes)
         while True:
@@ -230,6 +234,9 @@
             elif err == SSL_ERROR_WANT_WRITE:
                 sockstate = check_socket_and_wait_for_timeout(self.space,
                     self.w_socket, True)
+            elif (err == SSL_ERROR_ZERO_RETURN and
+                  libssl_SSL_get_shutdown(self.ssl) == SSL_RECEIVED_SHUTDOWN):
+                return self.space.wrap("")
             else:
                 sockstate = SOCKET_OPERATION_OK
         

diff --git a/pypy/rlib/ropenssl.py b/pypy/rlib/ropenssl.py
--- a/pypy/rlib/ropenssl.py
+++ b/pypy/rlib/ropenssl.py
@@ -65,6 +65,8 @@
         "SSL_ERROR_WANT_CONNECT")
     SSL_ERROR_SYSCALL = rffi_platform.ConstantInteger("SSL_ERROR_SYSCALL")
     SSL_ERROR_SSL = rffi_platform.ConstantInteger("SSL_ERROR_SSL")
+    SSL_RECEIVED_SHUTDOWN = rffi_platform.ConstantInteger(
+        "SSL_RECEIVED_SHUTDOWN")
     SSL_CTRL_OPTIONS = rffi_platform.ConstantInteger("SSL_CTRL_OPTIONS")
     SSL_CTRL_MODE = rffi_platform.ConstantInteger("SSL_CTRL_MODE")
     BIO_C_SET_NBIO = rffi_platform.ConstantInteger("BIO_C_SET_NBIO")
@@ -117,6 +119,7 @@
 ssl_external('SSL_do_handshake', [SSL], rffi.INT)
 ssl_external('SSL_shutdown', [SSL], rffi.INT)
 ssl_external('SSL_get_error', [SSL, rffi.INT], rffi.INT)
+ssl_external('SSL_get_shutdown', [SSL], rffi.INT)
 ssl_external('SSL_set_read_ahead', [SSL, rffi.INT], lltype.Void)
 
 ssl_external('ERR_get_error', [], rffi.INT)


More information about the Pypy-commit mailing list