summaryrefslogtreecommitdiffstats
path: root/Modules/socketmodule.c
diff options
context:
space:
mode:
authorKristján Valur Jónsson <kristjan@ccpgames.com>2012-04-07 11:23:31 (GMT)
committerKristján Valur Jónsson <kristjan@ccpgames.com>2012-04-07 11:23:31 (GMT)
commit10f383a9376df13635bb53d5885d43297d0022cd (patch)
treec6ffb4eee7fabdaa0ffa87e5f6282e6b7a2e6f37 /Modules/socketmodule.c
parent0f9eec19ee1652a61d4b2e860e599c617d88b707 (diff)
downloadcpython-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.c73
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 {