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

Skip to content

Commit 847ec75

Browse files
author
Kristján Valur Jónsson
committed
http://bugs.python.org/issue6971
Porting revision 75054 from trunk
1 parent 7d3d209 commit 847ec75

2 files changed

Lines changed: 43 additions & 15 deletions

File tree

Lib/test/test_socket.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,10 @@ def test_sock_ioctl(self):
553553
self.assertTrue(hasattr(socket, 'SIO_RCVALL'))
554554
self.assertTrue(hasattr(socket, 'RCVALL_ON'))
555555
self.assertTrue(hasattr(socket, 'RCVALL_OFF'))
556+
self.assertTrue(hasattr(socket, 'SIO_KEEPALIVE_VALS'))
557+
s = socket.socket()
558+
self.assertRaises(ValueError, s.ioctl, -1, None)
559+
s.ioctl(socket.SIO_KEEPALIVE_VALS, (1, 100, 100))
556560

557561

558562
class BasicTCPTest(SocketConnectedTest):

Modules/socketmodule.c

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2686,24 +2686,43 @@ static PyObject*
26862686
sock_ioctl(PySocketSockObject *s, PyObject *arg)
26872687
{
26882688
unsigned long cmd = SIO_RCVALL;
2689-
unsigned int option = RCVALL_ON;
2690-
DWORD recv;
2689+
PyObject *argO;
2690+
DWORD recv;
26912691

2692-
if (!PyArg_ParseTuple(arg, "kI:ioctl", &cmd, &option))
2692+
if (!PyArg_ParseTuple(arg, "kO:ioctl", &cmd, &argO))
26932693
return NULL;
26942694

2695-
if (WSAIoctl(s->sock_fd, cmd, &option, sizeof(option),
2696-
NULL, 0, &recv, NULL, NULL) == SOCKET_ERROR) {
2697-
return set_error();
2695+
switch (cmd) {
2696+
case SIO_RCVALL: {
2697+
unsigned int option = RCVALL_ON;
2698+
if (!PyArg_ParseTuple(arg, "kI:ioctl", &cmd, &option))
2699+
return NULL;
2700+
if (WSAIoctl(s->sock_fd, cmd, &option, sizeof(option),
2701+
NULL, 0, &recv, NULL, NULL) == SOCKET_ERROR) {
2702+
return set_error();
2703+
}
2704+
return PyLong_FromUnsignedLong(recv); }
2705+
case SIO_KEEPALIVE_VALS: {
2706+
struct tcp_keepalive ka;
2707+
if (!PyArg_ParseTuple(arg, "k(kkk):ioctl", &cmd,
2708+
&ka.onoff, &ka.keepalivetime, &ka.keepaliveinterval))
2709+
return NULL;
2710+
if (WSAIoctl(s->sock_fd, cmd, &ka, sizeof(ka),
2711+
NULL, 0, &recv, NULL, NULL) == SOCKET_ERROR) {
2712+
return set_error();
2713+
}
2714+
return PyLong_FromUnsignedLong(recv); }
2715+
default:
2716+
PyErr_Format(PyExc_ValueError, "invalid ioctl command %d", cmd);
2717+
return NULL;
26982718
}
2699-
return PyLong_FromUnsignedLong(recv);
27002719
}
27012720
PyDoc_STRVAR(sock_ioctl_doc,
27022721
"ioctl(cmd, option) -> long\n\
27032722
\n\
2704-
Control the socket with WSAIoctl syscall. Currently only socket.SIO_RCVALL\n\
2705-
is supported as control. Options must be one of the socket.RCVALL_*\n\
2706-
constants.");
2723+
Control the socket with WSAIoctl syscall. Currently supported 'cmd' values are\n\
2724+
SIO_RCVALL: 'option' must be one of the socket.RCVALL_* constants.\n\
2725+
SIO_KEEPALIVE_VALS: 'option' is a tuple of (onoff, timeout, interval).");
27072726

27082727
#endif
27092728

@@ -5058,11 +5077,16 @@ PyInit__socket(void)
50585077

50595078
#ifdef SIO_RCVALL
50605079
{
5061-
PyObject *tmp;
5062-
tmp = PyLong_FromUnsignedLong(SIO_RCVALL);
5063-
if (tmp == NULL)
5064-
return NULL;
5065-
PyModule_AddObject(m, "SIO_RCVALL", tmp);
5080+
DWORD codes[] = {SIO_RCVALL, SIO_KEEPALIVE_VALS};
5081+
const char *names[] = {"SIO_RCVALL", "SIO_KEEPALIVE_VALS"};
5082+
int i;
5083+
for(i = 0; i<sizeof(codes)/sizeof(*codes); ++i) {
5084+
PyObject *tmp;
5085+
tmp = PyLong_FromUnsignedLong(codes[i]);
5086+
if (tmp == NULL)
5087+
return NULL;
5088+
PyModule_AddObject(m, names[i], tmp);
5089+
}
50665090
}
50675091
PyModule_AddIntConstant(m, "RCVALL_OFF", RCVALL_OFF);
50685092
PyModule_AddIntConstant(m, "RCVALL_ON", RCVALL_ON);

0 commit comments

Comments
 (0)