@@ -2686,24 +2686,43 @@ static PyObject*
26862686sock_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}
27012720PyDoc_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