Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 99d4abf

Browse files
committed
Support socket timeout in SSL, by Geoff Talvola.
(SF patch #675750, to fix SF bug #675552.)
1 parent 5a2d8f5 commit 99d4abf

3 files changed

Lines changed: 55 additions & 0 deletions

File tree

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,7 @@ Michael Stone
516516
Ken Stox
517517
Daniel Stutzbach
518518
Paul Swartz
519+
Geoff Talvola
519520
William Tanksley
520521
Christian Tanzer
521522
Amy Taylor

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ Core and builtins
2626
Extension modules
2727
-----------------
2828

29+
- The SSL module now handles sockets with a timeout set correctly (SF
30+
patch #675750, fixing SF bug #675552).
31+
2932
- A new module _iconv_codec has been added, to expose the iconv(3)
3033
library.
3134

Modules/_ssl.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
305340
static 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

Comments
 (0)