@@ -302,14 +302,57 @@ static void PySSL_dealloc(PySSLObject *self)
302302 PyObject_Del (self );
303303}
304304
305+ /* If the socket has a timeout, do a select() on the socket.
306+ The argument writing indicates the direction.
307+ Return non-zero if the socket timed out, zero otherwise.
308+ */
309+ static int
310+ wait_for_timeout (PySocketSockObject * s , int writing )
311+ {
312+ fd_set fds ;
313+ struct timeval tv ;
314+ int rc ;
315+
316+ /* Nothing to do unless we're in timeout mode (not non-blocking) */
317+ if (s -> sock_timeout <= 0.0 )
318+ return 0 ;
319+
320+ /* Guard against closed socket */
321+ if (s -> sock_fd < 0 )
322+ return 0 ;
323+
324+ /* Construct the arguments to select */
325+ tv .tv_sec = (int )s -> sock_timeout ;
326+ tv .tv_usec = (int )((s -> sock_timeout - tv .tv_sec ) * 1e6 );
327+ FD_ZERO (& fds );
328+ FD_SET (s -> sock_fd , & fds );
329+
330+ /* See if the socket is ready */
331+ if (writing )
332+ rc = select (s -> sock_fd + 1 , NULL , & fds , NULL , & tv );
333+ else
334+ rc = select (s -> sock_fd + 1 , & fds , NULL , NULL , & tv );
335+
336+ /* Return 1 on timeout, 0 otherwise */
337+ return rc == 0 ;
338+ }
339+
305340static PyObject * PySSL_SSLwrite (PySSLObject * self , PyObject * args )
306341{
307342 char * data ;
308343 int len ;
344+ int timedout ;
309345
310346 if (!PyArg_ParseTuple (args , "s#:write" , & data , & len ))
311347 return NULL ;
312348
349+ Py_BEGIN_ALLOW_THREADS
350+ timedout = wait_for_timeout (self -> Socket , 1 );
351+ Py_END_ALLOW_THREADS
352+ if (timedout ) {
353+ PyErr_SetString (PySSLErrorObject , "The write operation timed out" );
354+ return NULL ;
355+ }
313356 Py_BEGIN_ALLOW_THREADS
314357 len = SSL_write (self -> ssl , data , len );
315358 Py_END_ALLOW_THREADS
@@ -330,13 +373,21 @@ static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args)
330373 PyObject * buf ;
331374 int count = 0 ;
332375 int len = 1024 ;
376+ int timedout ;
333377
334378 if (!PyArg_ParseTuple (args , "|i :read ", & len ))
335379 return NULL ;
336380
337381 if (!(buf = PyString_FromStringAndSize ((char * ) 0 , len )))
338382 return NULL;
339383
384+ Py_BEGIN_ALLOW_THREADS
385+ timedout = wait_for_timeout (self -> Socket , 0 );
386+ Py_END_ALLOW_THREADS
387+ if (timedout ) {
388+ PyErr_SetString (PySSLErrorObject , "The read operation timed out" );
389+ return NULL ;
390+ }
340391 Py_BEGIN_ALLOW_THREADS
341392 count = SSL_read (self -> ssl , PyString_AsString (buf ), len );
342393 Py_END_ALLOW_THREADS
0 commit comments