From 847ec75d3eed49b898ad69a55edaf65f3c8a7a4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristj=C3=A1n=20Valur=20J=C3=B3nsson?= Date: Sun, 27 Sep 2009 21:10:38 +0000 Subject: http://bugs.python.org/issue6971 Porting revision 75054 from trunk --- Lib/test/test_socket.py | 4 ++++ Modules/socketmodule.c | 54 +++++++++++++++++++++++++++++++++++-------------- 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 8313006..1facf0a 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -553,6 +553,10 @@ class GeneralModuleTests(unittest.TestCase): self.assertTrue(hasattr(socket, 'SIO_RCVALL')) self.assertTrue(hasattr(socket, 'RCVALL_ON')) self.assertTrue(hasattr(socket, 'RCVALL_OFF')) + self.assertTrue(hasattr(socket, 'SIO_KEEPALIVE_VALS')) + s = socket.socket() + self.assertRaises(ValueError, s.ioctl, -1, None) + s.ioctl(socket.SIO_KEEPALIVE_VALS, (1, 100, 100)) class BasicTCPTest(SocketConnectedTest): diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index de720e1..a160fee 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -2686,24 +2686,43 @@ static PyObject* sock_ioctl(PySocketSockObject *s, PyObject *arg) { unsigned long cmd = SIO_RCVALL; - unsigned int option = RCVALL_ON; - DWORD recv; + PyObject *argO; + DWORD recv; - if (!PyArg_ParseTuple(arg, "kI:ioctl", &cmd, &option)) + if (!PyArg_ParseTuple(arg, "kO:ioctl", &cmd, &argO)) return NULL; - if (WSAIoctl(s->sock_fd, cmd, &option, sizeof(option), - NULL, 0, &recv, NULL, NULL) == SOCKET_ERROR) { - return set_error(); + switch (cmd) { + case SIO_RCVALL: { + unsigned int option = RCVALL_ON; + if (!PyArg_ParseTuple(arg, "kI:ioctl", &cmd, &option)) + return NULL; + if (WSAIoctl(s->sock_fd, cmd, &option, sizeof(option), + NULL, 0, &recv, NULL, NULL) == SOCKET_ERROR) { + return set_error(); + } + return PyLong_FromUnsignedLong(recv); } + case SIO_KEEPALIVE_VALS: { + struct tcp_keepalive ka; + if (!PyArg_ParseTuple(arg, "k(kkk):ioctl", &cmd, + &ka.onoff, &ka.keepalivetime, &ka.keepaliveinterval)) + return NULL; + if (WSAIoctl(s->sock_fd, cmd, &ka, sizeof(ka), + NULL, 0, &recv, NULL, NULL) == SOCKET_ERROR) { + return set_error(); + } + return PyLong_FromUnsignedLong(recv); } + default: + PyErr_Format(PyExc_ValueError, "invalid ioctl command %d", cmd); + return NULL; } - return PyLong_FromUnsignedLong(recv); } PyDoc_STRVAR(sock_ioctl_doc, "ioctl(cmd, option) -> long\n\ \n\ -Control the socket with WSAIoctl syscall. Currently only socket.SIO_RCVALL\n\ -is supported as control. Options must be one of the socket.RCVALL_*\n\ -constants."); +Control the socket with WSAIoctl syscall. Currently supported 'cmd' values are\n\ +SIO_RCVALL: 'option' must be one of the socket.RCVALL_* constants.\n\ +SIO_KEEPALIVE_VALS: 'option' is a tuple of (onoff, timeout, interval)."); #endif @@ -5058,11 +5077,16 @@ PyInit__socket(void) #ifdef SIO_RCVALL { - PyObject *tmp; - tmp = PyLong_FromUnsignedLong(SIO_RCVALL); - if (tmp == NULL) - return NULL; - PyModule_AddObject(m, "SIO_RCVALL", tmp); + DWORD codes[] = {SIO_RCVALL, SIO_KEEPALIVE_VALS}; + const char *names[] = {"SIO_RCVALL", "SIO_KEEPALIVE_VALS"}; + int i; + for(i = 0; i