[Python-checkins] python/dist/src/Modules _ssl.c,1.9,1.10

gvanrossum@users.sourceforge.net gvanrossum@users.sourceforge.net
Fri, 31 Jan 2003 10:13:21 -0800


Update of /cvsroot/python/python/dist/src/Modules
In directory sc8-pr-cvs1:/tmp/cvs-serv5789

Modified Files:
	_ssl.c 
Log Message:
SF patch 676472 by Geoff Talvola, reviewed by Ben Laurie.

Geoff writes:
  This is yet another patch to _ssl.c that sets the
  underlying BIO to non-blocking if the socket being
  wrapped is non-blocking. It also correctly loops when
  SSL_connect, SSL_write, or SSL_read indicates that it
  needs to read or write more bytes.

  This seems to fix bug #673797 which was not fixed by my
  previous patch.


Index: _ssl.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/_ssl.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -C2 -d -r1.9 -r1.10
*** _ssl.c	27 Jan 2003 22:19:21 -0000	1.9
--- _ssl.c	31 Jan 2003 18:13:18 -0000	1.10
***************
*** 169,172 ****
--- 169,174 ----
  	char *errstr = NULL;
  	int ret;
+ 	int err;
+ 	int timedout;
  
  	self = PyObject_New(PySSLObject, &PySSL_Type); /* Create new object */
***************
*** 221,232 ****
  	Py_END_ALLOW_THREADS
  	SSL_set_fd(self->ssl, Sock->sock_fd);	/* Set the socket for SSL */
  	Py_BEGIN_ALLOW_THREADS
  	SSL_set_connect_state(self->ssl);
! 
  
  	/* Actually negotiate SSL connection */
  	/* XXX If SSL_connect() returns 0, it's also a failure. */
! 	ret = SSL_connect(self->ssl);
! 	Py_END_ALLOW_THREADS
  	if (ret <= 0) {
  		PySSL_SetError(self, ret);
--- 223,258 ----
  	Py_END_ALLOW_THREADS
  	SSL_set_fd(self->ssl, Sock->sock_fd);	/* Set the socket for SSL */
+ 
+ 	/* If the socket is is non-blocking mode or timeout mode, set the BIO
+ 	 * to non-blocking mode (blocking is the default)
+ 	 */
+ 	if (Sock->sock_timeout >= 0.0) {
+ 		/* Set both the read and write BIO's to non-blocking mode */
+ 		BIO_set_nbio(SSL_get_rbio(self->ssl), 1);
+ 		BIO_set_nbio(SSL_get_wbio(self->ssl), 1);
+ 	}
+ 
  	Py_BEGIN_ALLOW_THREADS
  	SSL_set_connect_state(self->ssl);
! 	Py_END_ALLOW_THREADS
  
  	/* Actually negotiate SSL connection */
  	/* XXX If SSL_connect() returns 0, it's also a failure. */
! 	timedout = 0;
! 	do {
! 		Py_BEGIN_ALLOW_THREADS
! 		ret = SSL_connect(self->ssl);
! 		err = SSL_get_error(self->ssl, ret);
! 		Py_END_ALLOW_THREADS
! 		if (err == SSL_ERROR_WANT_READ) {
! 			timedout = wait_for_timeout(Sock, 0);
! 		} else if (err == SSL_ERROR_WANT_WRITE) {
! 			timedout = wait_for_timeout(Sock, 1);
! 		}
! 		if (timedout) {
! 			PyErr_SetString(PySSLErrorObject, "The connect operation timed out");
! 			return NULL;
! 		}
! 	} while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE);
  	if (ret <= 0) {
  		PySSL_SetError(self, ret);
***************
*** 329,336 ****
--- 355,364 ----
  
  	/* See if the socket is ready */
+ 	Py_BEGIN_ALLOW_THREADS
  	if (writing)
  		rc = select(s->sock_fd+1, NULL, &fds, NULL, &tv);
  	else
  		rc = select(s->sock_fd+1, &fds, NULL, NULL, &tv);
+ 	Py_END_ALLOW_THREADS
  
  	/* Return 1 on timeout, 0 otherwise */
***************
*** 343,360 ****
  	int len;
  	int timedout;
  
  	if (!PyArg_ParseTuple(args, "s#:write", &data, &len))
  		return NULL;
  
- 	Py_BEGIN_ALLOW_THREADS
  	timedout = wait_for_timeout(self->Socket, 1);
- 	Py_END_ALLOW_THREADS
  	if (timedout) {
  		PyErr_SetString(PySSLErrorObject, "The write operation timed out");
  		return NULL;
  	}
! 	Py_BEGIN_ALLOW_THREADS
! 	len = SSL_write(self->ssl, data, len);
! 	Py_END_ALLOW_THREADS
  	if (len > 0)
  		return PyInt_FromLong(len);
--- 371,400 ----
  	int len;
  	int timedout;
+ 	int err;
  
  	if (!PyArg_ParseTuple(args, "s#:write", &data, &len))
  		return NULL;
  
  	timedout = wait_for_timeout(self->Socket, 1);
  	if (timedout) {
  		PyErr_SetString(PySSLErrorObject, "The write operation timed out");
  		return NULL;
  	}
! 	do {
! 		err = 0;
! 		Py_BEGIN_ALLOW_THREADS
! 		len = SSL_write(self->ssl, data, len);
! 		err = SSL_get_error(self->ssl, len);
! 		Py_END_ALLOW_THREADS
! 		if (err == SSL_ERROR_WANT_READ) {
! 			timedout = wait_for_timeout(self->Socket, 0);
! 		} else if (err == SSL_ERROR_WANT_WRITE) {
! 			timedout = wait_for_timeout(self->Socket, 1);
! 		}
! 		if (timedout) {
! 			PyErr_SetString(PySSLErrorObject, "The write operation timed out");
! 			return NULL;
! 		}
! 	} while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE);
  	if (len > 0)
  		return PyInt_FromLong(len);
***************
*** 375,378 ****
--- 415,419 ----
  	int len = 1024;
  	int timedout;
+ 	int err;
  
  	if (!PyArg_ParseTuple(args, "|i:read", &len))
***************
*** 382,395 ****
  		return NULL;
  
- 	Py_BEGIN_ALLOW_THREADS
  	timedout = wait_for_timeout(self->Socket, 0);
- 	Py_END_ALLOW_THREADS
  	if (timedout) {
  		PyErr_SetString(PySSLErrorObject, "The read operation timed out");
  		return NULL;
  	}
! 	Py_BEGIN_ALLOW_THREADS
! 	count = SSL_read(self->ssl, PyString_AsString(buf), len);
! 	Py_END_ALLOW_THREADS
   	if (count <= 0) {
  		Py_DECREF(buf);
--- 423,447 ----
  		return NULL;
  
  	timedout = wait_for_timeout(self->Socket, 0);
  	if (timedout) {
  		PyErr_SetString(PySSLErrorObject, "The read operation timed out");
  		return NULL;
  	}
! 	do {
! 		err = 0;
! 		Py_BEGIN_ALLOW_THREADS
! 		count = SSL_read(self->ssl, PyString_AsString(buf), len);
! 		err = SSL_get_error(self->ssl, count);
! 		Py_END_ALLOW_THREADS
! 		if (err == SSL_ERROR_WANT_READ) {
! 			timedout = wait_for_timeout(self->Socket, 0);
! 		} else if (err == SSL_ERROR_WANT_WRITE) {
! 			timedout = wait_for_timeout(self->Socket, 1);
! 		}
! 		if (timedout) {
! 			PyErr_SetString(PySSLErrorObject, "The read operation timed out");
! 			return NULL;
! 		}
! 	} while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE);
   	if (count <= 0) {
  		Py_DECREF(buf);