diff options
author | Kristján Valur Jónsson <kristjan@ccpgames.com> | 2012-04-07 11:23:31 (GMT) |
---|---|---|
committer | Kristján Valur Jónsson <kristjan@ccpgames.com> | 2012-04-07 11:23:31 (GMT) |
commit | 10f383a9376df13635bb53d5885d43297d0022cd (patch) | |
tree | c6ffb4eee7fabdaa0ffa87e5f6282e6b7a2e6f37 /Modules/socketmodule.c | |
parent | 0f9eec19ee1652a61d4b2e860e599c617d88b707 (diff) | |
download | cpython-10f383a9376df13635bb53d5885d43297d0022cd.zip cpython-10f383a9376df13635bb53d5885d43297d0022cd.tar.gz cpython-10f383a9376df13635bb53d5885d43297d0022cd.tar.bz2 |
Issue #14310: inter-process socket duplication for windows
Diffstat (limited to 'Modules/socketmodule.c')
-rw-r--r-- | Modules/socketmodule.c | 73 |
1 files changed, 66 insertions, 7 deletions
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 59a2f28..936e930 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -3771,6 +3771,34 @@ PyDoc_STRVAR(sock_ioctl_doc, 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 + +#if defined(MS_WINDOWS) +static PyObject* +sock_share(PySocketSockObject *s, PyObject *arg) +{ + WSAPROTOCOL_INFO info; + DWORD processId; + int result; + + if (!PyArg_ParseTuple(arg, "I", &processId)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + result = WSADuplicateSocket(s->sock_fd, processId, &info); + Py_END_ALLOW_THREADS + if (result == SOCKET_ERROR) + return set_error(); + return PyBytes_FromStringAndSize((const char*)&info, sizeof(info)); +} +PyDoc_STRVAR(sock_share_doc, +"share(process_id) -> bytes\n\ +\n\ +Share the socket with another process. The target process id\n\ +must be provided and the resulting bytes object passed to the target\n\ +process. There the shared socket can be instantiated by calling\n\ +socket.fromshare()."); + #endif @@ -3803,6 +3831,10 @@ static PyMethodDef sock_methods[] = { {"ioctl", (PyCFunction)sock_ioctl, METH_VARARGS, sock_ioctl_doc}, #endif +#if defined(MS_WINDOWS) + {"share", (PyCFunction)sock_share, METH_VARARGS, + sock_share_doc}, +#endif {"listen", (PyCFunction)sock_listen, METH_O, listen_doc}, {"recv", (PyCFunction)sock_recv, METH_VARARGS, @@ -3930,13 +3962,40 @@ sock_initobj(PyObject *self, PyObject *args, PyObject *kwds) return -1; if (fdobj != NULL && fdobj != Py_None) { - fd = PyLong_AsSocket_t(fdobj); - if (fd == (SOCKET_T)(-1) && PyErr_Occurred()) - return -1; - if (fd == INVALID_SOCKET) { - PyErr_SetString(PyExc_ValueError, - "can't use invalid socket value"); - return -1; +#ifdef MS_WINDOWS + /* recreate a socket that was duplicated */ + if (PyBytes_Check(fdobj)) { + WSAPROTOCOL_INFO info; + if (PyBytes_GET_SIZE(fdobj) != sizeof(info)) { + PyErr_Format(PyExc_ValueError, + "socket descriptor string has wrong size, " + "should be %zu bytes.", sizeof(info)); + return -1; + } + memcpy(&info, PyBytes_AS_STRING(fdobj), sizeof(info)); + Py_BEGIN_ALLOW_THREADS + fd = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, + FROM_PROTOCOL_INFO, &info, 0, WSA_FLAG_OVERLAPPED); + Py_END_ALLOW_THREADS + if (fd == INVALID_SOCKET) { + set_error(); + return -1; + } + family = info.iAddressFamily; + type = info.iSocketType; + proto = info.iProtocol; + } + else +#endif + { + fd = PyLong_AsSocket_t(fdobj); + if (fd == (SOCKET_T)(-1) && PyErr_Occurred()) + return -1; + if (fd == INVALID_SOCKET) { + PyErr_SetString(PyExc_ValueError, + "can't use invalid socket value"); + return -1; + } } } else { |