From fb7fffba051fb13f6f32df07bc0191b761843abb Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 5 Aug 2026 21:50:16 +0300 Subject: [PATCH 1/4] gh-135748: Use Argument Clinic for more socket functions Convert all convertible functions and methods of the socket module. They now have signatures for introspection, and functions which take several arguments use METH_FASTCALL instead of METH_VARARGS. ioctl(), sendto() and setsockopt() are left as they are. Their behaviour depends on the number of the arguments or on the value of a preceding argument, which Argument Clinic cannot express. --- Modules/clinic/socketmodule.c.h | 2049 ++++++++++++++++++++++++++++++- Modules/socketmodule.c | 1429 +++++++++++---------- 2 files changed, 2734 insertions(+), 744 deletions(-) diff --git a/Modules/clinic/socketmodule.c.h b/Modules/clinic/socketmodule.c.h index b565e7516d50f33..51dbce40374ec7a 100644 --- a/Modules/clinic/socketmodule.c.h +++ b/Modules/clinic/socketmodule.c.h @@ -6,29 +6,911 @@ preserve # include "pycore_gc.h" // PyGC_Head # include "pycore_runtime.h" // _Py_ID() #endif +#include "pycore_abstract.h" // _PyNumber_Index() #include "pycore_long.h" // _PyLong_UInt16_Converter() #include "pycore_modsupport.h" // _PyArg_CheckPositional() +#if (defined(HAVE_ACCEPT) || defined(HAVE_ACCEPT4)) + +PyDoc_STRVAR(_socket_socket__accept__doc__, +"_accept($self, /)\n" +"--\n" +"\n" +"Wait for an incoming connection.\n" +"\n" +"Return a new socket file descriptor representing the connection, and\n" +"the address of the client. For IP sockets, the address info is a\n" +"pair (hostaddr, port)."); + +#define _SOCKET_SOCKET__ACCEPT_METHODDEF \ + {"_accept", (PyCFunction)_socket_socket__accept, METH_NOARGS, _socket_socket__accept__doc__}, + +static PyObject * +_socket_socket__accept_impl(PySocketSockObject *s); + +static PyObject * +_socket_socket__accept(PyObject *s, PyObject *Py_UNUSED(ignored)) +{ + return _socket_socket__accept_impl((PySocketSockObject *)s); +} + +#endif /* (defined(HAVE_ACCEPT) || defined(HAVE_ACCEPT4)) */ + +PyDoc_STRVAR(_socket_socket_setblocking__doc__, +"setblocking($self, flag, /)\n" +"--\n" +"\n" +"Set the socket to blocking (flag is true) or non-blocking (false).\n" +"\n" +"setblocking(True) is equivalent to settimeout(None);\n" +"setblocking(False) is equivalent to settimeout(0.0)."); + +#define _SOCKET_SOCKET_SETBLOCKING_METHODDEF \ + {"setblocking", (PyCFunction)_socket_socket_setblocking, METH_O, _socket_socket_setblocking__doc__}, + +static PyObject * +_socket_socket_setblocking_impl(PySocketSockObject *s, PyObject *arg); + +static PyObject * +_socket_socket_setblocking(PyObject *s, PyObject *arg) +{ + PyObject *return_value = NULL; + + return_value = _socket_socket_setblocking_impl((PySocketSockObject *)s, arg); + + return return_value; +} + +PyDoc_STRVAR(_socket_socket_getblocking__doc__, +"getblocking($self, /)\n" +"--\n" +"\n" +"Return True if socket is in blocking mode, False if in non-blocking."); + +#define _SOCKET_SOCKET_GETBLOCKING_METHODDEF \ + {"getblocking", (PyCFunction)_socket_socket_getblocking, METH_NOARGS, _socket_socket_getblocking__doc__}, + +static PyObject * +_socket_socket_getblocking_impl(PySocketSockObject *s); + +static PyObject * +_socket_socket_getblocking(PyObject *s, PyObject *Py_UNUSED(ignored)) +{ + return _socket_socket_getblocking_impl((PySocketSockObject *)s); +} + +PyDoc_STRVAR(_socket_socket_settimeout__doc__, +"settimeout($self, timeout, /)\n" +"--\n" +"\n" +"Set a timeout on socket operations.\n" +"\n" +"\'timeout\' can be a float, giving in seconds, or None. Setting a\n" +"timeout of None disables the timeout feature and is equivalent to\n" +"setblocking(1). Setting a timeout of zero is the same as\n" +"setblocking(0)."); + +#define _SOCKET_SOCKET_SETTIMEOUT_METHODDEF \ + {"settimeout", (PyCFunction)_socket_socket_settimeout, METH_O, _socket_socket_settimeout__doc__}, + +static PyObject * +_socket_socket_settimeout_impl(PySocketSockObject *s, PyObject *arg); + +static PyObject * +_socket_socket_settimeout(PyObject *s, PyObject *arg) +{ + PyObject *return_value = NULL; + + return_value = _socket_socket_settimeout_impl((PySocketSockObject *)s, arg); + + return return_value; +} + +PyDoc_STRVAR(_socket_socket_gettimeout__doc__, +"gettimeout($self, /)\n" +"--\n" +"\n" +"Return the timeout in seconds (float) of socket operations.\n" +"\n" +"A timeout of None indicates that timeouts on socket operations are\n" +"disabled."); + +#define _SOCKET_SOCKET_GETTIMEOUT_METHODDEF \ + {"gettimeout", (PyCFunction)_socket_socket_gettimeout, METH_NOARGS, _socket_socket_gettimeout__doc__}, + +static PyObject * +_socket_socket_gettimeout_impl(PySocketSockObject *self); + +static PyObject * +_socket_socket_gettimeout(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _socket_socket_gettimeout_impl((PySocketSockObject *)self); +} + +PyDoc_STRVAR(_socket_socket_getsockopt__doc__, +"getsockopt($self, level, option, buffersize=0, /)\n" +"--\n" +"\n" +"Get a socket option.\n" +"\n" +"See the Unix manual for level and option. If a nonzero buffersize\n" +"argument is given, the return value is a bytes object of that\n" +"length; otherwise it is an integer."); + +#define _SOCKET_SOCKET_GETSOCKOPT_METHODDEF \ + {"getsockopt", _PyCFunction_CAST(_socket_socket_getsockopt), METH_FASTCALL, _socket_socket_getsockopt__doc__}, + +static PyObject * +_socket_socket_getsockopt_impl(PySocketSockObject *s, int level, int optname, + int buflen); + +static PyObject * +_socket_socket_getsockopt(PyObject *s, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int level; + int optname; + int buflen = 0; + + if (!_PyArg_CheckPositional("getsockopt", nargs, 2, 3)) { + goto exit; + } + level = PyLong_AsInt(args[0]); + if (level == -1 && PyErr_Occurred()) { + goto exit; + } + optname = PyLong_AsInt(args[1]); + if (optname == -1 && PyErr_Occurred()) { + goto exit; + } + if (nargs < 3) { + goto skip_optional; + } + buflen = PyLong_AsInt(args[2]); + if (buflen == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + return_value = _socket_socket_getsockopt_impl((PySocketSockObject *)s, level, optname, buflen); + +exit: + return return_value; +} + +#if defined(HAVE_BIND) + +PyDoc_STRVAR(_socket_socket_bind__doc__, +"bind($self, address, /)\n" +"--\n" +"\n" +"Bind the socket to a local address.\n" +"\n" +"For IP sockets, the address is a pair (host, port); the host must\n" +"refer to the local host. For raw packet sockets the address is a\n" +"tuple (ifname, proto [,pkttype [,hatype [,addr]]])."); + +#define _SOCKET_SOCKET_BIND_METHODDEF \ + {"bind", (PyCFunction)_socket_socket_bind, METH_O, _socket_socket_bind__doc__}, + +static PyObject * +_socket_socket_bind_impl(PySocketSockObject *s, PyObject *addro); + +static PyObject * +_socket_socket_bind(PyObject *s, PyObject *addro) +{ + PyObject *return_value = NULL; + + return_value = _socket_socket_bind_impl((PySocketSockObject *)s, addro); + + return return_value; +} + +#endif /* defined(HAVE_BIND) */ + PyDoc_STRVAR(_socket_socket_close__doc__, "close($self, /)\n" "--\n" "\n" -"close()\n" +"close()\n" +"\n" +"Close the socket. It cannot be used after this call."); + +#define _SOCKET_SOCKET_CLOSE_METHODDEF \ + {"close", (PyCFunction)_socket_socket_close, METH_NOARGS, _socket_socket_close__doc__}, + +static PyObject * +_socket_socket_close_impl(PySocketSockObject *s); + +static PyObject * +_socket_socket_close(PyObject *s, PyObject *Py_UNUSED(ignored)) +{ + return _socket_socket_close_impl((PySocketSockObject *)s); +} + +PyDoc_STRVAR(_socket_socket_detach__doc__, +"detach($self, /)\n" +"--\n" +"\n" +"Close the socket object without closing the file descriptor.\n" +"\n" +"The object cannot be used after this call, but the file descriptor\n" +"can be reused for other purposes. The file descriptor is returned."); + +#define _SOCKET_SOCKET_DETACH_METHODDEF \ + {"detach", (PyCFunction)_socket_socket_detach, METH_NOARGS, _socket_socket_detach__doc__}, + +static PyObject * +_socket_socket_detach_impl(PySocketSockObject *s); + +static PyObject * +_socket_socket_detach(PyObject *s, PyObject *Py_UNUSED(ignored)) +{ + return _socket_socket_detach_impl((PySocketSockObject *)s); +} + +#if defined(HAVE_CONNECT) + +PyDoc_STRVAR(_socket_socket_connect__doc__, +"connect($self, address, /)\n" +"--\n" +"\n" +"Connect the socket to a remote address.\n" +"\n" +"For IP sockets, the address is a pair (host, port)."); + +#define _SOCKET_SOCKET_CONNECT_METHODDEF \ + {"connect", (PyCFunction)_socket_socket_connect, METH_O, _socket_socket_connect__doc__}, + +static PyObject * +_socket_socket_connect_impl(PySocketSockObject *s, PyObject *addro); + +static PyObject * +_socket_socket_connect(PyObject *s, PyObject *addro) +{ + PyObject *return_value = NULL; + + return_value = _socket_socket_connect_impl((PySocketSockObject *)s, addro); + + return return_value; +} + +#endif /* defined(HAVE_CONNECT) */ + +#if defined(HAVE_CONNECT) + +PyDoc_STRVAR(_socket_socket_connect_ex__doc__, +"connect_ex($self, address, /)\n" +"--\n" +"\n" +"Connect the socket to a remote address.\n" +"\n" +"This is like connect(address), but returns an error code (the errno\n" +"value) instead of raising an exception when an error occurs."); + +#define _SOCKET_SOCKET_CONNECT_EX_METHODDEF \ + {"connect_ex", (PyCFunction)_socket_socket_connect_ex, METH_O, _socket_socket_connect_ex__doc__}, + +static PyObject * +_socket_socket_connect_ex_impl(PySocketSockObject *s, PyObject *addro); + +static PyObject * +_socket_socket_connect_ex(PyObject *s, PyObject *addro) +{ + PyObject *return_value = NULL; + + return_value = _socket_socket_connect_ex_impl((PySocketSockObject *)s, addro); + + return return_value; +} + +#endif /* defined(HAVE_CONNECT) */ + +PyDoc_STRVAR(_socket_socket_fileno__doc__, +"fileno($self, /)\n" +"--\n" +"\n" +"Return the integer file descriptor of the socket."); + +#define _SOCKET_SOCKET_FILENO_METHODDEF \ + {"fileno", (PyCFunction)_socket_socket_fileno, METH_NOARGS, _socket_socket_fileno__doc__}, + +static PyObject * +_socket_socket_fileno_impl(PySocketSockObject *s); + +static PyObject * +_socket_socket_fileno(PyObject *s, PyObject *Py_UNUSED(ignored)) +{ + return _socket_socket_fileno_impl((PySocketSockObject *)s); +} + +#if defined(HAVE_GETSOCKNAME) + +PyDoc_STRVAR(_socket_socket_getsockname__doc__, +"getsockname($self, /)\n" +"--\n" +"\n" +"Return the address of the local endpoint.\n" +"\n" +"The format depends on the address family. For IPv4 sockets, the\n" +"address info is a pair (hostaddr, port). For IPv6 sockets, the\n" +"address info is a 4-tuple (hostaddr, port, flowinfo, scope_id)."); + +#define _SOCKET_SOCKET_GETSOCKNAME_METHODDEF \ + {"getsockname", (PyCFunction)_socket_socket_getsockname, METH_NOARGS, _socket_socket_getsockname__doc__}, + +static PyObject * +_socket_socket_getsockname_impl(PySocketSockObject *s); + +static PyObject * +_socket_socket_getsockname(PyObject *s, PyObject *Py_UNUSED(ignored)) +{ + return _socket_socket_getsockname_impl((PySocketSockObject *)s); +} + +#endif /* defined(HAVE_GETSOCKNAME) */ + +#if defined(HAVE_GETPEERNAME) + +PyDoc_STRVAR(_socket_socket_getpeername__doc__, +"getpeername($self, /)\n" +"--\n" +"\n" +"Return the address of the remote endpoint.\n" +"\n" +"For IP sockets, the address info is a pair (hostaddr, port)."); + +#define _SOCKET_SOCKET_GETPEERNAME_METHODDEF \ + {"getpeername", (PyCFunction)_socket_socket_getpeername, METH_NOARGS, _socket_socket_getpeername__doc__}, + +static PyObject * +_socket_socket_getpeername_impl(PySocketSockObject *s); + +static PyObject * +_socket_socket_getpeername(PyObject *s, PyObject *Py_UNUSED(ignored)) +{ + return _socket_socket_getpeername_impl((PySocketSockObject *)s); +} + +#endif /* defined(HAVE_GETPEERNAME) */ + +#if defined(HAVE_LISTEN) + +PyDoc_STRVAR(_socket_socket_listen__doc__, +"listen($self, backlog=min(SOMAXCONN, 128), /)\n" +"--\n" +"\n" +"Enable a server to accept connections.\n" +"\n" +"If backlog is specified, it must be at least 0 (if it is lower, it\n" +"is set to 0); it specifies the number of unaccepted connections that\n" +"the system will allow before refusing new connections. If not\n" +"specified, a default reasonable value is chosen."); + +#define _SOCKET_SOCKET_LISTEN_METHODDEF \ + {"listen", _PyCFunction_CAST(_socket_socket_listen), METH_FASTCALL, _socket_socket_listen__doc__}, + +static PyObject * +_socket_socket_listen_impl(PySocketSockObject *s, int backlog); + +static PyObject * +_socket_socket_listen(PyObject *s, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int backlog = Py_MIN(SOMAXCONN, 128); + + if (!_PyArg_CheckPositional("listen", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + backlog = PyLong_AsInt(args[0]); + if (backlog == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + return_value = _socket_socket_listen_impl((PySocketSockObject *)s, backlog); + +exit: + return return_value; +} + +#endif /* defined(HAVE_LISTEN) */ + +PyDoc_STRVAR(_socket_socket_recv__doc__, +"recv($self, buffersize, flags=0, /)\n" +"--\n" +"\n" +"Receive up to buffersize bytes from the socket.\n" +"\n" +"For the optional flags argument, see the Unix manual. When no data\n" +"is available, block until at least one byte is available or until\n" +"the remote end is closed. When the remote end is closed and all data\n" +"is read, return the empty string."); + +#define _SOCKET_SOCKET_RECV_METHODDEF \ + {"recv", _PyCFunction_CAST(_socket_socket_recv), METH_FASTCALL, _socket_socket_recv__doc__}, + +static PyObject * +_socket_socket_recv_impl(PySocketSockObject *s, Py_ssize_t recvlen, + int flags); + +static PyObject * +_socket_socket_recv(PyObject *s, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + Py_ssize_t recvlen; + int flags = 0; + + if (!_PyArg_CheckPositional("recv", nargs, 1, 2)) { + goto exit; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[0]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + recvlen = ival; + } + if (nargs < 2) { + goto skip_optional; + } + flags = PyLong_AsInt(args[1]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + return_value = _socket_socket_recv_impl((PySocketSockObject *)s, recvlen, flags); + +exit: + return return_value; +} + +PyDoc_STRVAR(_socket_socket_recv_into__doc__, +"recv_into($self, /, buffer, nbytes=0, flags=0)\n" +"--\n" +"\n" +"Receive up to nbytes bytes from the socket, storing into a buffer.\n" +"\n" +"A version of recv() that stores its data into a buffer rather than\n" +"creating a new bytes object. If nbytes is not specified (or 0),\n" +"receive up to the size available in the given buffer.\n" +"\n" +"See recv() for documentation about the flags."); + +#define _SOCKET_SOCKET_RECV_INTO_METHODDEF \ + {"recv_into", _PyCFunction_CAST(_socket_socket_recv_into), METH_FASTCALL|METH_KEYWORDS, _socket_socket_recv_into__doc__}, + +static PyObject * +_socket_socket_recv_into_impl(PySocketSockObject *s, Py_buffer *pbuf, + Py_ssize_t recvlen, int flags); + +static PyObject * +_socket_socket_recv_into(PyObject *s, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(buffer), &_Py_ID(nbytes), &_Py_ID(flags), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"buffer", "nbytes", "flags", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "recv_into", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + Py_buffer pbuf = {NULL, NULL}; + Py_ssize_t recvlen = 0; + int flags = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 1, /*maxpos*/ 3, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + if (PyObject_GetBuffer(args[0], &pbuf, PyBUF_WRITABLE) < 0) { + _PyArg_BadArgument("recv_into", "argument 'buffer'", "read-write bytes-like object", args[0]); + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[1]) { + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[1]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + recvlen = ival; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + flags = PyLong_AsInt(args[2]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional_pos: + return_value = _socket_socket_recv_into_impl((PySocketSockObject *)s, &pbuf, recvlen, flags); + +exit: + /* Cleanup for pbuf */ + if (pbuf.obj) { + PyBuffer_Release(&pbuf); + } + + return return_value; +} + +#if defined(HAVE_RECVFROM) + +PyDoc_STRVAR(_socket_socket_recvfrom__doc__, +"recvfrom($self, buffersize, flags=0, /)\n" +"--\n" +"\n" +"Receive up to buffersize bytes and the sender\'s address info.\n" +"\n" +"Like recv(buffersize, flags), but return a (data, address info)\n" +"pair."); + +#define _SOCKET_SOCKET_RECVFROM_METHODDEF \ + {"recvfrom", _PyCFunction_CAST(_socket_socket_recvfrom), METH_FASTCALL, _socket_socket_recvfrom__doc__}, + +static PyObject * +_socket_socket_recvfrom_impl(PySocketSockObject *s, Py_ssize_t recvlen, + int flags); + +static PyObject * +_socket_socket_recvfrom(PyObject *s, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + Py_ssize_t recvlen; + int flags = 0; + + if (!_PyArg_CheckPositional("recvfrom", nargs, 1, 2)) { + goto exit; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[0]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + recvlen = ival; + } + if (nargs < 2) { + goto skip_optional; + } + flags = PyLong_AsInt(args[1]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + return_value = _socket_socket_recvfrom_impl((PySocketSockObject *)s, recvlen, flags); + +exit: + return return_value; +} + +#endif /* defined(HAVE_RECVFROM) */ + +#if defined(HAVE_RECVFROM) + +PyDoc_STRVAR(_socket_socket_recvfrom_into__doc__, +"recvfrom_into($self, /, buffer, nbytes=0, flags=0)\n" +"--\n" +"\n" +"Receive up to nbytes bytes and the sender\'s address info.\n" +"\n" +"Like recv_into(buffer, nbytes, flags), but return a (nbytes, address\n" +"info) pair."); + +#define _SOCKET_SOCKET_RECVFROM_INTO_METHODDEF \ + {"recvfrom_into", _PyCFunction_CAST(_socket_socket_recvfrom_into), METH_FASTCALL|METH_KEYWORDS, _socket_socket_recvfrom_into__doc__}, + +static PyObject * +_socket_socket_recvfrom_into_impl(PySocketSockObject *s, Py_buffer *pbuf, + Py_ssize_t recvlen, int flags); + +static PyObject * +_socket_socket_recvfrom_into(PyObject *s, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(buffer), &_Py_ID(nbytes), &_Py_ID(flags), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"buffer", "nbytes", "flags", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "recvfrom_into", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + Py_buffer pbuf = {NULL, NULL}; + Py_ssize_t recvlen = 0; + int flags = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 1, /*maxpos*/ 3, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + if (PyObject_GetBuffer(args[0], &pbuf, PyBUF_WRITABLE) < 0) { + _PyArg_BadArgument("recvfrom_into", "argument 'buffer'", "read-write bytes-like object", args[0]); + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[1]) { + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[1]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + recvlen = ival; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + flags = PyLong_AsInt(args[2]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional_pos: + return_value = _socket_socket_recvfrom_into_impl((PySocketSockObject *)s, &pbuf, recvlen, flags); + +exit: + /* Cleanup for pbuf */ + if (pbuf.obj) { + PyBuffer_Release(&pbuf); + } + + return return_value; +} + +#endif /* defined(HAVE_RECVFROM) */ + +#if defined(CMSG_LEN) + +PyDoc_STRVAR(_socket_socket_recvmsg__doc__, +"recvmsg($self, bufsize, ancbufsize=0, flags=0, /)\n" +"--\n" +"\n" +"Receive normal data and ancillary data from the socket.\n" "\n" -"Close the socket. It cannot be used after this call."); +"Receive up to bufsize bytes of normal data. The ancbufsize argument\n" +"sets the size in bytes of the internal buffer used to receive the\n" +"ancillary data; it defaults to 0, meaning that no ancillary data\n" +"will be received. Appropriate buffer sizes for ancillary data can\n" +"be calculated using CMSG_SPACE() or CMSG_LEN(), and items which do\n" +"not fit into the buffer might be truncated or discarded. The flags\n" +"argument defaults to 0 and has the same meaning as for recv().\n" +"\n" +"The return value is a 4-tuple: (data, ancdata, msg_flags, address).\n" +"The data item is a bytes object holding the non-ancillary data\n" +"received. The ancdata item is a list of zero or more tuples\n" +"(cmsg_level, cmsg_type, cmsg_data) representing the ancillary data\n" +"(control messages) received: cmsg_level and cmsg_type are integers\n" +"specifying the protocol level and protocol-specific type\n" +"respectively, and cmsg_data is a bytes object holding the associated\n" +"data. The msg_flags item is the bitwise OR of various flags\n" +"indicating conditions on the received message; see your system\n" +"documentation for details. If the receiving socket is unconnected,\n" +"address is the address of the sending socket, if available;\n" +"otherwise, its value is unspecified.\n" +"\n" +"If recvmsg() raises an exception after the system call returns, it\n" +"will first attempt to close any file descriptors received via the\n" +"SCM_RIGHTS mechanism."); -#define _SOCKET_SOCKET_CLOSE_METHODDEF \ - {"close", (PyCFunction)_socket_socket_close, METH_NOARGS, _socket_socket_close__doc__}, +#define _SOCKET_SOCKET_RECVMSG_METHODDEF \ + {"recvmsg", _PyCFunction_CAST(_socket_socket_recvmsg), METH_FASTCALL, _socket_socket_recvmsg__doc__}, static PyObject * -_socket_socket_close_impl(PySocketSockObject *s); +_socket_socket_recvmsg_impl(PySocketSockObject *s, Py_ssize_t bufsize, + Py_ssize_t ancbufsize, int flags); static PyObject * -_socket_socket_close(PyObject *s, PyObject *Py_UNUSED(ignored)) +_socket_socket_recvmsg(PyObject *s, PyObject *const *args, Py_ssize_t nargs) { - return _socket_socket_close_impl((PySocketSockObject *)s); + PyObject *return_value = NULL; + Py_ssize_t bufsize; + Py_ssize_t ancbufsize = 0; + int flags = 0; + + if (!_PyArg_CheckPositional("recvmsg", nargs, 1, 3)) { + goto exit; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[0]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + bufsize = ival; + } + if (nargs < 2) { + goto skip_optional; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[1]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + ancbufsize = ival; + } + if (nargs < 3) { + goto skip_optional; + } + flags = PyLong_AsInt(args[2]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + return_value = _socket_socket_recvmsg_impl((PySocketSockObject *)s, bufsize, ancbufsize, flags); + +exit: + return return_value; +} + +#endif /* defined(CMSG_LEN) */ + +#if defined(CMSG_LEN) + +PyDoc_STRVAR(_socket_socket_recvmsg_into__doc__, +"recvmsg_into($self, buffers, ancbufsize=0, flags=0, /)\n" +"--\n" +"\n" +"Receive normal and ancillary data, scattering the normal data.\n" +"\n" +"The buffers argument must be an iterable of objects that export\n" +"writable buffers (e.g. bytearray objects); these will be filled\n" +"with successive chunks of the non-ancillary data until it has all\n" +"been written or there are no more buffers. The ancbufsize argument\n" +"sets the size in bytes of the internal buffer used to receive the\n" +"ancillary data; it defaults to 0, meaning that no ancillary data\n" +"will be received. Appropriate buffer sizes for ancillary data can\n" +"be calculated using CMSG_SPACE() or CMSG_LEN(), and items which do\n" +"not fit into the buffer might be truncated or discarded. The flags\n" +"argument defaults to 0 and has the same meaning as for recv().\n" +"\n" +"The return value is a 4-tuple: (nbytes, ancdata, msg_flags,\n" +"address). The nbytes item is the total number of bytes of\n" +"non-ancillary data written into the buffers. The ancdata item is a\n" +"list of zero or more tuples (cmsg_level, cmsg_type, cmsg_data)\n" +"representing the ancillary data (control messages) received:\n" +"cmsg_level and cmsg_type are integers specifying the protocol level\n" +"and protocol-specific type respectively, and cmsg_data is a bytes\n" +"object holding the associated data. The msg_flags item is the\n" +"bitwise OR of various flags indicating conditions on the received\n" +"message; see your system documentation for details. If the\n" +"receiving socket is unconnected, address is the address of the\n" +"sending socket, if available; otherwise, its value is unspecified.\n" +"\n" +"If recvmsg_into() raises an exception after the system call returns,\n" +"it will first attempt to close any file descriptors received via the\n" +"SCM_RIGHTS mechanism."); + +#define _SOCKET_SOCKET_RECVMSG_INTO_METHODDEF \ + {"recvmsg_into", _PyCFunction_CAST(_socket_socket_recvmsg_into), METH_FASTCALL, _socket_socket_recvmsg_into__doc__}, + +static PyObject * +_socket_socket_recvmsg_into_impl(PySocketSockObject *s, + PyObject *buffers_arg, + Py_ssize_t ancbufsize, int flags); + +static PyObject * +_socket_socket_recvmsg_into(PyObject *s, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *buffers_arg; + Py_ssize_t ancbufsize = 0; + int flags = 0; + + if (!_PyArg_CheckPositional("recvmsg_into", nargs, 1, 3)) { + goto exit; + } + buffers_arg = args[0]; + if (nargs < 2) { + goto skip_optional; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[1]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + ancbufsize = ival; + } + if (nargs < 3) { + goto skip_optional; + } + flags = PyLong_AsInt(args[2]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + return_value = _socket_socket_recvmsg_into_impl((PySocketSockObject *)s, buffers_arg, ancbufsize, flags); + +exit: + return return_value; } +#endif /* defined(CMSG_LEN) */ + PyDoc_STRVAR(_socket_socket_send__doc__, "send($self, data, flags=0, /)\n" "--\n" @@ -111,89 +993,290 @@ _socket_socket_sendall(PyObject *s, PyObject *const *args, Py_ssize_t nargs) if (nargs < 2) { goto skip_optional; } - flags = PyLong_AsInt(args[1]); + flags = PyLong_AsInt(args[1]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + return_value = _socket_socket_sendall_impl((PySocketSockObject *)s, &pbuf, flags); + +exit: + /* Cleanup for pbuf */ + if (pbuf.obj) { + PyBuffer_Release(&pbuf); + } + + return return_value; +} + +#if defined(CMSG_LEN) + +PyDoc_STRVAR(_socket_socket_sendmsg__doc__, +"sendmsg($self, buffers, ancdata=, flags=0,\n" +" address=, /)\n" +"--\n" +"\n" +"Send normal and ancillary data to the socket.\n" +"\n" +"It gathering the non-ancillary data from a series of buffers\n" +"and concatenating it into a single message.\n" +"The buffers argument specifies the non-ancillary\n" +"data as an iterable of bytes-like objects (e.g. bytes objects).\n" +"The ancdata argument specifies the ancillary data (control messages)\n" +"as an iterable of zero or more tuples (cmsg_level, cmsg_type,\n" +"cmsg_data), where cmsg_level and cmsg_type are integers specifying\n" +"the protocol level and protocol-specific type respectively, and\n" +"cmsg_data is a bytes-like object holding the associated data. The\n" +"flags argument defaults to 0 and has the same meaning as for send().\n" +"If address is supplied and not None, it sets a destination address\n" +"for the message. The return value is the number of bytes of\n" +"non-ancillary data sent."); + +#define _SOCKET_SOCKET_SENDMSG_METHODDEF \ + {"sendmsg", _PyCFunction_CAST(_socket_socket_sendmsg), METH_FASTCALL, _socket_socket_sendmsg__doc__}, + +static PyObject * +_socket_socket_sendmsg_impl(PySocketSockObject *s, PyObject *data_arg, + PyObject *cmsg_arg, int flags, + PyObject *addr_arg); + +static PyObject * +_socket_socket_sendmsg(PyObject *s, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *data_arg; + PyObject *cmsg_arg = NULL; + int flags = 0; + PyObject *addr_arg = NULL; + + if (!_PyArg_CheckPositional("sendmsg", nargs, 1, 4)) { + goto exit; + } + data_arg = args[0]; + if (nargs < 2) { + goto skip_optional; + } + cmsg_arg = args[1]; + if (nargs < 3) { + goto skip_optional; + } + flags = PyLong_AsInt(args[2]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } + if (nargs < 4) { + goto skip_optional; + } + addr_arg = args[3]; +skip_optional: + return_value = _socket_socket_sendmsg_impl((PySocketSockObject *)s, data_arg, cmsg_arg, flags, addr_arg); + +exit: + return return_value; +} + +#endif /* defined(CMSG_LEN) */ + +#if defined(HAVE_SOCKADDR_ALG) + +PyDoc_STRVAR(_socket_socket_sendmsg_afalg__doc__, +"sendmsg_afalg($self, /, msg=, *, op=,\n" +" iv=, assoclen=, flags=0)\n" +"--\n" +"\n" +"Set operation mode, IV and associated data length.\n" +"\n" +"For an AF_ALG operation socket."); + +#define _SOCKET_SOCKET_SENDMSG_AFALG_METHODDEF \ + {"sendmsg_afalg", _PyCFunction_CAST(_socket_socket_sendmsg_afalg), METH_FASTCALL|METH_KEYWORDS, _socket_socket_sendmsg_afalg__doc__}, + +static PyObject * +_socket_socket_sendmsg_afalg_impl(PySocketSockObject *self, + PyObject *data_arg, PyObject *opobj, + Py_buffer *iv, PyObject *assoclenobj, + int flags); + +static PyObject * +_socket_socket_sendmsg_afalg(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 5 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(msg), &_Py_ID(op), &_Py_ID(iv), &_Py_ID(assoclen), &_Py_ID(flags), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"msg", "op", "iv", "assoclen", "flags", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "sendmsg_afalg", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[5]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + PyObject *data_arg = NULL; + PyObject *opobj = NULL; + Py_buffer iv = {NULL, NULL}; + PyObject *assoclenobj = NULL; + int flags = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[0]) { + data_arg = args[0]; + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[1]) { + if (!PyLong_Check(args[1])) { + _PyArg_BadArgument("sendmsg_afalg", "argument 'op'", "int", args[1]); + goto exit; + } + opobj = args[1]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[2]) { + if (PyObject_GetBuffer(args[2], &iv, PyBUF_SIMPLE) != 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[3]) { + if (!PyLong_Check(args[3])) { + _PyArg_BadArgument("sendmsg_afalg", "argument 'assoclen'", "int", args[3]); + goto exit; + } + assoclenobj = args[3]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + flags = PyLong_AsInt(args[4]); if (flags == -1 && PyErr_Occurred()) { goto exit; } -skip_optional: - return_value = _socket_socket_sendall_impl((PySocketSockObject *)s, &pbuf, flags); +skip_optional_kwonly: + return_value = _socket_socket_sendmsg_afalg_impl((PySocketSockObject *)self, data_arg, opobj, &iv, assoclenobj, flags); exit: - /* Cleanup for pbuf */ - if (pbuf.obj) { - PyBuffer_Release(&pbuf); + /* Cleanup for iv */ + if (iv.obj) { + PyBuffer_Release(&iv); } return return_value; } -#if defined(CMSG_LEN) +#endif /* defined(HAVE_SOCKADDR_ALG) */ -PyDoc_STRVAR(_socket_socket_sendmsg__doc__, -"sendmsg($self, buffers, ancdata=, flags=0,\n" -" address=, /)\n" +#if defined(HAVE_SHUTDOWN) + +PyDoc_STRVAR(_socket_socket_shutdown__doc__, +"shutdown($self, flag, /)\n" "--\n" "\n" -"Send normal and ancillary data to the socket.\n" +"Shut down one or both halves of the connection.\n" "\n" -"It gathering the non-ancillary data from a series of buffers\n" -"and concatenating it into a single message.\n" -"The buffers argument specifies the non-ancillary\n" -"data as an iterable of bytes-like objects (e.g. bytes objects).\n" -"The ancdata argument specifies the ancillary data (control messages)\n" -"as an iterable of zero or more tuples (cmsg_level, cmsg_type,\n" -"cmsg_data), where cmsg_level and cmsg_type are integers specifying\n" -"the protocol level and protocol-specific type respectively, and\n" -"cmsg_data is a bytes-like object holding the associated data. The\n" -"flags argument defaults to 0 and has the same meaning as for send().\n" -"If address is supplied and not None, it sets a destination address\n" -"for the message. The return value is the number of bytes of\n" -"non-ancillary data sent."); +"Shut down the reading side of the socket (flag == SHUT_RD), the\n" +"writing side of the socket (flag == SHUT_WR), or both ends (flag ==\n" +"SHUT_RDWR)."); -#define _SOCKET_SOCKET_SENDMSG_METHODDEF \ - {"sendmsg", _PyCFunction_CAST(_socket_socket_sendmsg), METH_FASTCALL, _socket_socket_sendmsg__doc__}, +#define _SOCKET_SOCKET_SHUTDOWN_METHODDEF \ + {"shutdown", (PyCFunction)_socket_socket_shutdown, METH_O, _socket_socket_shutdown__doc__}, static PyObject * -_socket_socket_sendmsg_impl(PySocketSockObject *s, PyObject *data_arg, - PyObject *cmsg_arg, int flags, - PyObject *addr_arg); +_socket_socket_shutdown_impl(PySocketSockObject *s, PyObject *arg); static PyObject * -_socket_socket_sendmsg(PyObject *s, PyObject *const *args, Py_ssize_t nargs) +_socket_socket_shutdown(PyObject *s, PyObject *arg) { PyObject *return_value = NULL; - PyObject *data_arg; - PyObject *cmsg_arg = NULL; - int flags = 0; - PyObject *addr_arg = NULL; - if (!_PyArg_CheckPositional("sendmsg", nargs, 1, 4)) { - goto exit; - } - data_arg = args[0]; - if (nargs < 2) { - goto skip_optional; - } - cmsg_arg = args[1]; - if (nargs < 3) { - goto skip_optional; - } - flags = PyLong_AsInt(args[2]); - if (flags == -1 && PyErr_Occurred()) { - goto exit; - } - if (nargs < 4) { - goto skip_optional; + return_value = _socket_socket_shutdown_impl((PySocketSockObject *)s, arg); + + return return_value; +} + +#endif /* defined(HAVE_SHUTDOWN) */ + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(_socket_socket_share__doc__, +"share($self, process_id, /)\n" +"--\n" +"\n" +"Share the socket with another process.\n" +"\n" +"The target process id must be provided and the resulting bytes\n" +"object passed to the target process. There the shared socket can be\n" +"instantiated by calling socket.fromshare()."); + +#define _SOCKET_SOCKET_SHARE_METHODDEF \ + {"share", (PyCFunction)_socket_socket_share, METH_O, _socket_socket_share__doc__}, + +static PyObject * +_socket_socket_share_impl(PySocketSockObject *s, unsigned int processId); + +static PyObject * +_socket_socket_share(PyObject *s, PyObject *arg) +{ + PyObject *return_value = NULL; + unsigned int processId; + + { + Py_ssize_t _bytes = PyLong_AsNativeBytes(arg, &processId, sizeof(unsigned int), + Py_ASNATIVEBYTES_NATIVE_ENDIAN | + Py_ASNATIVEBYTES_ALLOW_INDEX | + Py_ASNATIVEBYTES_UNSIGNED_BUFFER); + if (_bytes < 0) { + goto exit; + } + if ((size_t)_bytes > sizeof(unsigned int)) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "integer value out of range", 1) < 0) + { + goto exit; + } + } } - addr_arg = args[3]; -skip_optional: - return_value = _socket_socket_sendmsg_impl((PySocketSockObject *)s, data_arg, cmsg_arg, flags, addr_arg); + return_value = _socket_socket_share_impl((PySocketSockObject *)s, processId); exit: return return_value; } -#endif /* defined(CMSG_LEN) */ +#endif /* defined(MS_WINDOWS) */ static int sock_initobj_impl(PySocketSockObject *self, int family, int type, int proto, @@ -282,6 +1365,334 @@ sock_initobj(PyObject *self, PyObject *args, PyObject *kwargs) return return_value; } +#if defined(HAVE_GETHOSTNAME) + +PyDoc_STRVAR(_socket_gethostname__doc__, +"gethostname($module, /)\n" +"--\n" +"\n" +"Return the current host name."); + +#define _SOCKET_GETHOSTNAME_METHODDEF \ + {"gethostname", (PyCFunction)_socket_gethostname, METH_NOARGS, _socket_gethostname__doc__}, + +static PyObject * +_socket_gethostname_impl(PyObject *module); + +static PyObject * +_socket_gethostname(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _socket_gethostname_impl(module); +} + +#endif /* defined(HAVE_GETHOSTNAME) */ + +#if defined(HAVE_SETHOSTNAME) + +PyDoc_STRVAR(_socket_sethostname__doc__, +"sethostname($module, name, /)\n" +"--\n" +"\n" +"Set the hostname to name."); + +#define _SOCKET_SETHOSTNAME_METHODDEF \ + {"sethostname", (PyCFunction)_socket_sethostname, METH_O, _socket_sethostname__doc__}, + +#endif /* defined(HAVE_SETHOSTNAME) */ + +#if defined(HAVE_GETADDRINFO) + +PyDoc_STRVAR(_socket_gethostbyname__doc__, +"gethostbyname($module, host, /)\n" +"--\n" +"\n" +"Return the IP address for a host.\n" +"\n" +"The address is a string of the form \'255.255.255.255\'."); + +#define _SOCKET_GETHOSTBYNAME_METHODDEF \ + {"gethostbyname", (PyCFunction)_socket_gethostbyname, METH_O, _socket_gethostbyname__doc__}, + +#endif /* defined(HAVE_GETADDRINFO) */ + +#if (defined(HAVE_GETHOSTBYNAME_R) || defined (HAVE_GETHOSTBYNAME)) + +PyDoc_STRVAR(_socket_gethostbyname_ex__doc__, +"gethostbyname_ex($module, host, /)\n" +"--\n" +"\n" +"Map a host name to its IP number.\n" +"\n" +"Return the true host name, a list of aliases, and a list of IP\n" +"addresses, which are strings of the form \'255.255.255.255\'."); + +#define _SOCKET_GETHOSTBYNAME_EX_METHODDEF \ + {"gethostbyname_ex", (PyCFunction)_socket_gethostbyname_ex, METH_O, _socket_gethostbyname_ex__doc__}, + +#endif /* (defined(HAVE_GETHOSTBYNAME_R) || defined (HAVE_GETHOSTBYNAME)) */ + +#if (defined(HAVE_GETHOSTBYNAME_R) || defined (HAVE_GETHOSTBYADDR)) + +PyDoc_STRVAR(_socket_gethostbyaddr__doc__, +"gethostbyaddr($module, host, /)\n" +"--\n" +"\n" +"Map an IP number or host name to the true host name and addresses.\n" +"\n" +"Return the true host name, a list of aliases, and a list of IP\n" +"addresses. The host argument is a string giving a host name or IP\n" +"number."); + +#define _SOCKET_GETHOSTBYADDR_METHODDEF \ + {"gethostbyaddr", (PyCFunction)_socket_gethostbyaddr, METH_O, _socket_gethostbyaddr__doc__}, + +#endif /* (defined(HAVE_GETHOSTBYNAME_R) || defined (HAVE_GETHOSTBYADDR)) */ + +#if defined(HAVE_GETSERVBYNAME) + +PyDoc_STRVAR(_socket_getservbyname__doc__, +"getservbyname($module, servicename, protocolname=, /)\n" +"--\n" +"\n" +"Return a port number from a service name and protocol name.\n" +"\n" +"The optional protocol name, if given, should be \'tcp\' or \'udp\',\n" +"otherwise any protocol will match."); + +#define _SOCKET_GETSERVBYNAME_METHODDEF \ + {"getservbyname", _PyCFunction_CAST(_socket_getservbyname), METH_FASTCALL, _socket_getservbyname__doc__}, + +static PyObject * +_socket_getservbyname_impl(PyObject *module, const char *name, + const char *proto); + +static PyObject * +_socket_getservbyname(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + const char *name; + const char *proto = NULL; + + if (!_PyArg_CheckPositional("getservbyname", nargs, 1, 2)) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("getservbyname", "argument 1", "str", args[0]); + goto exit; + } + Py_ssize_t name_length; + name = PyUnicode_AsUTF8AndSize(args[0], &name_length); + if (name == NULL) { + goto exit; + } + if (strlen(name) != (size_t)name_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + if (nargs < 2) { + goto skip_optional; + } + if (!PyUnicode_Check(args[1])) { + _PyArg_BadArgument("getservbyname", "argument 2", "str", args[1]); + goto exit; + } + Py_ssize_t proto_length; + proto = PyUnicode_AsUTF8AndSize(args[1], &proto_length); + if (proto == NULL) { + goto exit; + } + if (strlen(proto) != (size_t)proto_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } +skip_optional: + return_value = _socket_getservbyname_impl(module, name, proto); + +exit: + return return_value; +} + +#endif /* defined(HAVE_GETSERVBYNAME) */ + +#if defined(HAVE_GETSERVBYPORT) + +PyDoc_STRVAR(_socket_getservbyport__doc__, +"getservbyport($module, port, protocolname=, /)\n" +"--\n" +"\n" +"Return the service name from a port number and protocol name.\n" +"\n" +"The optional protocol name, if given, should be \'tcp\' or \'udp\',\n" +"otherwise any protocol will match."); + +#define _SOCKET_GETSERVBYPORT_METHODDEF \ + {"getservbyport", _PyCFunction_CAST(_socket_getservbyport), METH_FASTCALL, _socket_getservbyport__doc__}, + +static PyObject * +_socket_getservbyport_impl(PyObject *module, int port, const char *proto); + +static PyObject * +_socket_getservbyport(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int port; + const char *proto = NULL; + + if (!_PyArg_CheckPositional("getservbyport", nargs, 1, 2)) { + goto exit; + } + port = PyLong_AsInt(args[0]); + if (port == -1 && PyErr_Occurred()) { + goto exit; + } + if (nargs < 2) { + goto skip_optional; + } + if (!PyUnicode_Check(args[1])) { + _PyArg_BadArgument("getservbyport", "argument 2", "str", args[1]); + goto exit; + } + Py_ssize_t proto_length; + proto = PyUnicode_AsUTF8AndSize(args[1], &proto_length); + if (proto == NULL) { + goto exit; + } + if (strlen(proto) != (size_t)proto_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } +skip_optional: + return_value = _socket_getservbyport_impl(module, port, proto); + +exit: + return return_value; +} + +#endif /* defined(HAVE_GETSERVBYPORT) */ + +#if defined(HAVE_GETPROTOBYNAME) + +PyDoc_STRVAR(_socket_getprotobyname__doc__, +"getprotobyname($module, name, /)\n" +"--\n" +"\n" +"Return the protocol number for the named protocol."); + +#define _SOCKET_GETPROTOBYNAME_METHODDEF \ + {"getprotobyname", (PyCFunction)_socket_getprotobyname, METH_O, _socket_getprotobyname__doc__}, + +static PyObject * +_socket_getprotobyname_impl(PyObject *module, const char *name); + +static PyObject * +_socket_getprotobyname(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *name; + + if (!PyUnicode_Check(arg)) { + _PyArg_BadArgument("getprotobyname", "argument", "str", arg); + goto exit; + } + Py_ssize_t name_length; + name = PyUnicode_AsUTF8AndSize(arg, &name_length); + if (name == NULL) { + goto exit; + } + if (strlen(name) != (size_t)name_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + return_value = _socket_getprotobyname_impl(module, name); + +exit: + return return_value; +} + +#endif /* defined(HAVE_GETPROTOBYNAME) */ + +PyDoc_STRVAR(_socket_close__doc__, +"close($module, fd, /)\n" +"--\n" +"\n" +"Close a socket fd."); + +#define _SOCKET_CLOSE_METHODDEF \ + {"close", (PyCFunction)_socket_close, METH_O, _socket_close__doc__}, + +#if !defined(NO_DUP) + +PyDoc_STRVAR(_socket_dup__doc__, +"dup($module, fd, /)\n" +"--\n" +"\n" +"Duplicate a socket descriptor.\n" +"\n" +"The new descriptor is non-inheritable."); + +#define _SOCKET_DUP_METHODDEF \ + {"dup", (PyCFunction)_socket_dup, METH_O, _socket_dup__doc__}, + +#endif /* !defined(NO_DUP) */ + +#if defined(HAVE_SOCKETPAIR) + +PyDoc_STRVAR(_socket_socketpair__doc__, +"socketpair($module, family=AF_UNIX, type=SOCK_STREAM, proto=0, /)\n" +"--\n" +"\n" +"Create a pair of connected socket objects.\n" +"\n" +"The sockets are returned by the platform socketpair() function. The\n" +"arguments are the same as for socket()."); + +#define _SOCKET_SOCKETPAIR_METHODDEF \ + {"socketpair", _PyCFunction_CAST(_socket_socketpair), METH_FASTCALL, _socket_socketpair__doc__}, + +static PyObject * +_socket_socketpair_impl(PyObject *module, int family, int type, int proto); + +static PyObject * +_socket_socketpair(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int family = AF_UNIX; + int type = SOCK_STREAM; + int proto = 0; + + if (!_PyArg_CheckPositional("socketpair", nargs, 0, 3)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + family = PyLong_AsInt(args[0]); + if (family == -1 && PyErr_Occurred()) { + goto exit; + } + if (nargs < 2) { + goto skip_optional; + } + type = PyLong_AsInt(args[1]); + if (type == -1 && PyErr_Occurred()) { + goto exit; + } + if (nargs < 3) { + goto skip_optional; + } + proto = PyLong_AsInt(args[2]); + if (proto == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + return_value = _socket_socketpair_impl(module, family, type, proto); + +exit: + return return_value; +} + +#endif /* defined(HAVE_SOCKETPAIR) */ + PyDoc_STRVAR(_socket_ntohs__doc__, "ntohs($module, integer, /)\n" "--\n" @@ -463,6 +1874,301 @@ _socket_inet_ntoa(PyObject *module, PyObject *arg) #endif /* defined(HAVE_INET_NTOA) */ +#if defined(HAVE_INET_PTON) + +PyDoc_STRVAR(_socket_inet_pton__doc__, +"inet_pton($module, af, ip, /)\n" +"--\n" +"\n" +"Convert an IP address from string format to a packed string.\n" +"\n" +"The string is suitable for use with low-level network functions."); + +#define _SOCKET_INET_PTON_METHODDEF \ + {"inet_pton", _PyCFunction_CAST(_socket_inet_pton), METH_FASTCALL, _socket_inet_pton__doc__}, + +static PyObject * +_socket_inet_pton_impl(PyObject *module, int af, const char *ip); + +static PyObject * +_socket_inet_pton(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int af; + const char *ip; + + if (!_PyArg_CheckPositional("inet_pton", nargs, 2, 2)) { + goto exit; + } + af = PyLong_AsInt(args[0]); + if (af == -1 && PyErr_Occurred()) { + goto exit; + } + if (!PyUnicode_Check(args[1])) { + _PyArg_BadArgument("inet_pton", "argument 2", "str", args[1]); + goto exit; + } + Py_ssize_t ip_length; + ip = PyUnicode_AsUTF8AndSize(args[1], &ip_length); + if (ip == NULL) { + goto exit; + } + if (strlen(ip) != (size_t)ip_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + return_value = _socket_inet_pton_impl(module, af, ip); + +exit: + return return_value; +} + +#endif /* defined(HAVE_INET_PTON) */ + +#if defined(HAVE_INET_PTON) + +PyDoc_STRVAR(_socket_inet_ntop__doc__, +"inet_ntop($module, af, packed_ip, /)\n" +"--\n" +"\n" +"Convert a packed IP address of the given family to string format."); + +#define _SOCKET_INET_NTOP_METHODDEF \ + {"inet_ntop", _PyCFunction_CAST(_socket_inet_ntop), METH_FASTCALL, _socket_inet_ntop__doc__}, + +static PyObject * +_socket_inet_ntop_impl(PyObject *module, int af, Py_buffer *packed_ip); + +static PyObject * +_socket_inet_ntop(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int af; + Py_buffer packed_ip = {NULL, NULL}; + + if (!_PyArg_CheckPositional("inet_ntop", nargs, 2, 2)) { + goto exit; + } + af = PyLong_AsInt(args[0]); + if (af == -1 && PyErr_Occurred()) { + goto exit; + } + if (PyObject_GetBuffer(args[1], &packed_ip, PyBUF_SIMPLE) != 0) { + goto exit; + } + return_value = _socket_inet_ntop_impl(module, af, &packed_ip); + +exit: + /* Cleanup for packed_ip */ + if (packed_ip.obj) { + PyBuffer_Release(&packed_ip); + } + + return return_value; +} + +#endif /* defined(HAVE_INET_PTON) */ + +#if defined(HAVE_GETADDRINFO) + +PyDoc_STRVAR(_socket_getaddrinfo__doc__, +"getaddrinfo($module, /, host, port, family=AF_UNSPEC, type=0, proto=0,\n" +" flags=0)\n" +"--\n" +"\n" +"Resolve host and port into a list of 5-tuples.\n" +"\n" +"Each tuple is (family, type, proto, canonname, sockaddr)."); + +#define _SOCKET_GETADDRINFO_METHODDEF \ + {"getaddrinfo", _PyCFunction_CAST(_socket_getaddrinfo), METH_FASTCALL|METH_KEYWORDS, _socket_getaddrinfo__doc__}, + +static PyObject * +_socket_getaddrinfo_impl(PyObject *module, PyObject *hobj, PyObject *pobj, + int family, int socktype, int protocol, int flags); + +static PyObject * +_socket_getaddrinfo(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 6 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(host), &_Py_ID(port), &_Py_ID(family), &_Py_ID(type), &_Py_ID(proto), &_Py_ID(flags), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"host", "port", "family", "type", "proto", "flags", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "getaddrinfo", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[6]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + PyObject *hobj; + PyObject *pobj; + int family = AF_UNSPEC; + int socktype = 0; + int protocol = 0; + int flags = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 2, /*maxpos*/ 6, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + hobj = args[0]; + pobj = args[1]; + if (!noptargs) { + goto skip_optional_pos; + } + if (args[2]) { + family = PyLong_AsInt(args[2]); + if (family == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[3]) { + socktype = PyLong_AsInt(args[3]); + if (socktype == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[4]) { + protocol = PyLong_AsInt(args[4]); + if (protocol == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + flags = PyLong_AsInt(args[5]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional_pos: + return_value = _socket_getaddrinfo_impl(module, hobj, pobj, family, socktype, protocol, flags); + +exit: + return return_value; +} + +#endif /* defined(HAVE_GETADDRINFO) */ + +#if defined(HAVE_GETNAMEINFO) + +PyDoc_STRVAR(_socket_getnameinfo__doc__, +"getnameinfo($module, sockaddr, flags, /)\n" +"--\n" +"\n" +"Get host and port for a sockaddr."); + +#define _SOCKET_GETNAMEINFO_METHODDEF \ + {"getnameinfo", _PyCFunction_CAST(_socket_getnameinfo), METH_FASTCALL, _socket_getnameinfo__doc__}, + +static PyObject * +_socket_getnameinfo_impl(PyObject *module, PyObject *sa, int flags); + +static PyObject * +_socket_getnameinfo(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *sa; + int flags; + + if (!_PyArg_CheckPositional("getnameinfo", nargs, 2, 2)) { + goto exit; + } + sa = args[0]; + flags = PyLong_AsInt(args[1]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _socket_getnameinfo_impl(module, sa, flags); + +exit: + return return_value; +} + +#endif /* defined(HAVE_GETNAMEINFO) */ + +PyDoc_STRVAR(_socket_getdefaulttimeout__doc__, +"getdefaulttimeout($module, /)\n" +"--\n" +"\n" +"Return the default timeout in seconds for new socket objects.\n" +"\n" +"A value of None indicates that new socket objects have no timeout.\n" +"When the socket module is first imported, the default is None."); + +#define _SOCKET_GETDEFAULTTIMEOUT_METHODDEF \ + {"getdefaulttimeout", (PyCFunction)_socket_getdefaulttimeout, METH_NOARGS, _socket_getdefaulttimeout__doc__}, + +static PyObject * +_socket_getdefaulttimeout_impl(PyObject *module); + +static PyObject * +_socket_getdefaulttimeout(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _socket_getdefaulttimeout_impl(module); +} + +PyDoc_STRVAR(_socket_setdefaulttimeout__doc__, +"setdefaulttimeout($module, timeout, /)\n" +"--\n" +"\n" +"Set the default timeout in seconds for new socket objects.\n" +"\n" +"A value of None indicates that new socket objects have no timeout.\n" +"When the socket module is first imported, the default is None."); + +#define _SOCKET_SETDEFAULTTIMEOUT_METHODDEF \ + {"setdefaulttimeout", (PyCFunction)_socket_setdefaulttimeout, METH_O, _socket_setdefaulttimeout__doc__}, + +#if (defined(HAVE_IF_NAMEINDEX) || defined(MS_WINDOWS)) + +PyDoc_STRVAR(_socket_if_nameindex__doc__, +"if_nameindex($module, /)\n" +"--\n" +"\n" +"Return a list of network interface information (index, name) tuples."); + +#define _SOCKET_IF_NAMEINDEX_METHODDEF \ + {"if_nameindex", (PyCFunction)_socket_if_nameindex, METH_NOARGS, _socket_if_nameindex__doc__}, + +static PyObject * +_socket_if_nameindex_impl(PyObject *module); + +static PyObject * +_socket_if_nameindex(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _socket_if_nameindex_impl(module); +} + +#endif /* (defined(HAVE_IF_NAMEINDEX) || defined(MS_WINDOWS)) */ + #if (defined(HAVE_IF_NAMEINDEX) || defined(MS_WINDOWS)) PyDoc_STRVAR(_socket_if_nametoindex__doc__, @@ -528,14 +2234,223 @@ _socket_if_indextoname(PyObject *module, PyObject *arg) #endif /* (defined(HAVE_IF_NAMEINDEX) || defined(MS_WINDOWS)) */ +#if defined(CMSG_LEN) + +PyDoc_STRVAR(_socket_CMSG_LEN__doc__, +"CMSG_LEN($module, length, /)\n" +"--\n" +"\n" +"Return the total length of an ancillary data item with associated data.\n" +"\n" +"The associated data has the given length. This value can often be\n" +"used as the buffer size for recvmsg() to receive a single item of\n" +"ancillary data, but RFC 3542 requires portable applications to use\n" +"CMSG_SPACE() and thus include space for padding, even when the item\n" +"will be the last in the buffer. Raises OverflowError if length is\n" +"outside the permissible range of values."); + +#define _SOCKET_CMSG_LEN_METHODDEF \ + {"CMSG_LEN", (PyCFunction)_socket_CMSG_LEN, METH_O, _socket_CMSG_LEN__doc__}, + +static PyObject * +_socket_CMSG_LEN_impl(PyObject *module, Py_ssize_t length); + +static PyObject * +_socket_CMSG_LEN(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + Py_ssize_t length; + + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(arg); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + length = ival; + } + return_value = _socket_CMSG_LEN_impl(module, length); + +exit: + return return_value; +} + +#endif /* defined(CMSG_LEN) */ + +#if defined(CMSG_LEN) && defined(CMSG_SPACE) + +PyDoc_STRVAR(_socket_CMSG_SPACE__doc__, +"CMSG_SPACE($module, length, /)\n" +"--\n" +"\n" +"Return the buffer size needed to receive an ancillary data item.\n" +"\n" +"The item has associated data of the given length, and the size\n" +"includes any trailing padding. The buffer space needed to receive\n" +"multiple items is the sum of the CMSG_SPACE() values for their\n" +"associated data lengths. Raises OverflowError if length is outside\n" +"the permissible range of values."); + +#define _SOCKET_CMSG_SPACE_METHODDEF \ + {"CMSG_SPACE", (PyCFunction)_socket_CMSG_SPACE, METH_O, _socket_CMSG_SPACE__doc__}, + +static PyObject * +_socket_CMSG_SPACE_impl(PyObject *module, Py_ssize_t length); + +static PyObject * +_socket_CMSG_SPACE(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + Py_ssize_t length; + + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(arg); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + length = ival; + } + return_value = _socket_CMSG_SPACE_impl(module, length); + +exit: + return return_value; +} + +#endif /* defined(CMSG_LEN) && defined(CMSG_SPACE) */ + +#ifndef _SOCKET_SOCKET__ACCEPT_METHODDEF + #define _SOCKET_SOCKET__ACCEPT_METHODDEF +#endif /* !defined(_SOCKET_SOCKET__ACCEPT_METHODDEF) */ + +#ifndef _SOCKET_SOCKET_BIND_METHODDEF + #define _SOCKET_SOCKET_BIND_METHODDEF +#endif /* !defined(_SOCKET_SOCKET_BIND_METHODDEF) */ + +#ifndef _SOCKET_SOCKET_CONNECT_METHODDEF + #define _SOCKET_SOCKET_CONNECT_METHODDEF +#endif /* !defined(_SOCKET_SOCKET_CONNECT_METHODDEF) */ + +#ifndef _SOCKET_SOCKET_CONNECT_EX_METHODDEF + #define _SOCKET_SOCKET_CONNECT_EX_METHODDEF +#endif /* !defined(_SOCKET_SOCKET_CONNECT_EX_METHODDEF) */ + +#ifndef _SOCKET_SOCKET_GETSOCKNAME_METHODDEF + #define _SOCKET_SOCKET_GETSOCKNAME_METHODDEF +#endif /* !defined(_SOCKET_SOCKET_GETSOCKNAME_METHODDEF) */ + +#ifndef _SOCKET_SOCKET_GETPEERNAME_METHODDEF + #define _SOCKET_SOCKET_GETPEERNAME_METHODDEF +#endif /* !defined(_SOCKET_SOCKET_GETPEERNAME_METHODDEF) */ + +#ifndef _SOCKET_SOCKET_LISTEN_METHODDEF + #define _SOCKET_SOCKET_LISTEN_METHODDEF +#endif /* !defined(_SOCKET_SOCKET_LISTEN_METHODDEF) */ + +#ifndef _SOCKET_SOCKET_RECVFROM_METHODDEF + #define _SOCKET_SOCKET_RECVFROM_METHODDEF +#endif /* !defined(_SOCKET_SOCKET_RECVFROM_METHODDEF) */ + +#ifndef _SOCKET_SOCKET_RECVFROM_INTO_METHODDEF + #define _SOCKET_SOCKET_RECVFROM_INTO_METHODDEF +#endif /* !defined(_SOCKET_SOCKET_RECVFROM_INTO_METHODDEF) */ + +#ifndef _SOCKET_SOCKET_RECVMSG_METHODDEF + #define _SOCKET_SOCKET_RECVMSG_METHODDEF +#endif /* !defined(_SOCKET_SOCKET_RECVMSG_METHODDEF) */ + +#ifndef _SOCKET_SOCKET_RECVMSG_INTO_METHODDEF + #define _SOCKET_SOCKET_RECVMSG_INTO_METHODDEF +#endif /* !defined(_SOCKET_SOCKET_RECVMSG_INTO_METHODDEF) */ + #ifndef _SOCKET_SOCKET_SENDMSG_METHODDEF #define _SOCKET_SOCKET_SENDMSG_METHODDEF #endif /* !defined(_SOCKET_SOCKET_SENDMSG_METHODDEF) */ +#ifndef _SOCKET_SOCKET_SENDMSG_AFALG_METHODDEF + #define _SOCKET_SOCKET_SENDMSG_AFALG_METHODDEF +#endif /* !defined(_SOCKET_SOCKET_SENDMSG_AFALG_METHODDEF) */ + +#ifndef _SOCKET_SOCKET_SHUTDOWN_METHODDEF + #define _SOCKET_SOCKET_SHUTDOWN_METHODDEF +#endif /* !defined(_SOCKET_SOCKET_SHUTDOWN_METHODDEF) */ + +#ifndef _SOCKET_SOCKET_SHARE_METHODDEF + #define _SOCKET_SOCKET_SHARE_METHODDEF +#endif /* !defined(_SOCKET_SOCKET_SHARE_METHODDEF) */ + +#ifndef _SOCKET_GETHOSTNAME_METHODDEF + #define _SOCKET_GETHOSTNAME_METHODDEF +#endif /* !defined(_SOCKET_GETHOSTNAME_METHODDEF) */ + +#ifndef _SOCKET_SETHOSTNAME_METHODDEF + #define _SOCKET_SETHOSTNAME_METHODDEF +#endif /* !defined(_SOCKET_SETHOSTNAME_METHODDEF) */ + +#ifndef _SOCKET_GETHOSTBYNAME_METHODDEF + #define _SOCKET_GETHOSTBYNAME_METHODDEF +#endif /* !defined(_SOCKET_GETHOSTBYNAME_METHODDEF) */ + +#ifndef _SOCKET_GETHOSTBYNAME_EX_METHODDEF + #define _SOCKET_GETHOSTBYNAME_EX_METHODDEF +#endif /* !defined(_SOCKET_GETHOSTBYNAME_EX_METHODDEF) */ + +#ifndef _SOCKET_GETHOSTBYADDR_METHODDEF + #define _SOCKET_GETHOSTBYADDR_METHODDEF +#endif /* !defined(_SOCKET_GETHOSTBYADDR_METHODDEF) */ + +#ifndef _SOCKET_GETSERVBYNAME_METHODDEF + #define _SOCKET_GETSERVBYNAME_METHODDEF +#endif /* !defined(_SOCKET_GETSERVBYNAME_METHODDEF) */ + +#ifndef _SOCKET_GETSERVBYPORT_METHODDEF + #define _SOCKET_GETSERVBYPORT_METHODDEF +#endif /* !defined(_SOCKET_GETSERVBYPORT_METHODDEF) */ + +#ifndef _SOCKET_GETPROTOBYNAME_METHODDEF + #define _SOCKET_GETPROTOBYNAME_METHODDEF +#endif /* !defined(_SOCKET_GETPROTOBYNAME_METHODDEF) */ + +#ifndef _SOCKET_DUP_METHODDEF + #define _SOCKET_DUP_METHODDEF +#endif /* !defined(_SOCKET_DUP_METHODDEF) */ + +#ifndef _SOCKET_SOCKETPAIR_METHODDEF + #define _SOCKET_SOCKETPAIR_METHODDEF +#endif /* !defined(_SOCKET_SOCKETPAIR_METHODDEF) */ + #ifndef _SOCKET_INET_NTOA_METHODDEF #define _SOCKET_INET_NTOA_METHODDEF #endif /* !defined(_SOCKET_INET_NTOA_METHODDEF) */ +#ifndef _SOCKET_INET_PTON_METHODDEF + #define _SOCKET_INET_PTON_METHODDEF +#endif /* !defined(_SOCKET_INET_PTON_METHODDEF) */ + +#ifndef _SOCKET_INET_NTOP_METHODDEF + #define _SOCKET_INET_NTOP_METHODDEF +#endif /* !defined(_SOCKET_INET_NTOP_METHODDEF) */ + +#ifndef _SOCKET_GETADDRINFO_METHODDEF + #define _SOCKET_GETADDRINFO_METHODDEF +#endif /* !defined(_SOCKET_GETADDRINFO_METHODDEF) */ + +#ifndef _SOCKET_GETNAMEINFO_METHODDEF + #define _SOCKET_GETNAMEINFO_METHODDEF +#endif /* !defined(_SOCKET_GETNAMEINFO_METHODDEF) */ + +#ifndef _SOCKET_IF_NAMEINDEX_METHODDEF + #define _SOCKET_IF_NAMEINDEX_METHODDEF +#endif /* !defined(_SOCKET_IF_NAMEINDEX_METHODDEF) */ + #ifndef _SOCKET_IF_NAMETOINDEX_METHODDEF #define _SOCKET_IF_NAMETOINDEX_METHODDEF #endif /* !defined(_SOCKET_IF_NAMETOINDEX_METHODDEF) */ @@ -543,4 +2458,12 @@ _socket_if_indextoname(PyObject *module, PyObject *arg) #ifndef _SOCKET_IF_INDEXTONAME_METHODDEF #define _SOCKET_IF_INDEXTONAME_METHODDEF #endif /* !defined(_SOCKET_IF_INDEXTONAME_METHODDEF) */ -/*[clinic end generated code: output=0b1fa78ac6589353 input=a9049054013a1b77]*/ + +#ifndef _SOCKET_CMSG_LEN_METHODDEF + #define _SOCKET_CMSG_LEN_METHODDEF +#endif /* !defined(_SOCKET_CMSG_LEN_METHODDEF) */ + +#ifndef _SOCKET_CMSG_SPACE_METHODDEF + #define _SOCKET_CMSG_SPACE_METHODDEF +#endif /* !defined(_SOCKET_CMSG_SPACE_METHODDEF) */ +/*[clinic end generated code: output=c96ac95c17326e10 input=a9049054013a1b77]*/ diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 73ae1c942daba48..5ae7d832440697c 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -3085,11 +3085,21 @@ sock_accept_impl(PySocketSockObject *s, void *data) /* s._accept() -> (fd, address) */ +/*[clinic input] +_socket.socket._accept + self as s: self(type="PySocketSockObject *") + +Wait for an incoming connection. + +Return a new socket file descriptor representing the connection, and +the address of the client. For IP sockets, the address info is a +pair (hostaddr, port). +[clinic start generated code]*/ + static PyObject * -sock_accept(PyObject *self, PyObject *Py_UNUSED(ignored)) +_socket_socket__accept_impl(PySocketSockObject *s) +/*[clinic end generated code: output=d24eca9a1d4c988e input=07959cdbb2f2a387]*/ { - PySocketSockObject *s = _PySocketSockObject_CAST(self); - sock_addr_t addrbuf; SOCKET_T newfd; socklen_t addrlen; @@ -3155,12 +3165,6 @@ sock_accept(PyObject *self, PyObject *Py_UNUSED(ignored)) return NULL; } -PyDoc_STRVAR(accept_doc, -"_accept() -> (integer, address info)\n\ -\n\ -Wait for an incoming connection. Return a new socket file descriptor\n\ -representing the connection, and the address of the client.\n\ -For IP sockets, the address info is a pair (hostaddr, port)."); #endif // defined(HAVE_ACCEPT) || defined(HAVE_ACCEPT4) @@ -3169,8 +3173,21 @@ For IP sockets, the address info is a pair (hostaddr, port)."); True -- blocking mode; same as settimeout(None) */ +/*[clinic input] +_socket.socket.setblocking + self as s: self(type="PySocketSockObject *") + flag as arg: object + / + +Set the socket to blocking (flag is true) or non-blocking (false). + +setblocking(True) is equivalent to settimeout(None); +setblocking(False) is equivalent to settimeout(0.0). +[clinic start generated code]*/ + static PyObject * -sock_setblocking(PyObject *self, PyObject *arg) +_socket_socket_setblocking_impl(PySocketSockObject *s, PyObject *arg) +/*[clinic end generated code: output=39a348904324f352 input=115fee5787faedac]*/ { long block; @@ -3178,7 +3195,6 @@ sock_setblocking(PyObject *self, PyObject *arg) if (block < 0) return NULL; - PySocketSockObject *s = _PySocketSockObject_CAST(self); s->sock_timeout = _PyTime_FromSeconds(block ? -1 : 0); if (internal_setblocking(s, block) == -1) { return NULL; @@ -3186,21 +3202,22 @@ sock_setblocking(PyObject *self, PyObject *arg) Py_RETURN_NONE; } -PyDoc_STRVAR(setblocking_doc, -"setblocking(flag)\n\ -\n\ -Set the socket to blocking (flag is true) or non-blocking (false).\n\ -setblocking(True) is equivalent to settimeout(None);\n\ -setblocking(False) is equivalent to settimeout(0.0)."); /* s.getblocking() method. Returns True if socket is in blocking mode, False if it is in non-blocking mode. */ +/*[clinic input] +_socket.socket.getblocking + self as s: self(type="PySocketSockObject *") + +Return True if socket is in blocking mode, False if in non-blocking. +[clinic start generated code]*/ + static PyObject * -sock_getblocking(PyObject *self, PyObject *Py_UNUSED(ignored)) +_socket_socket_getblocking_impl(PySocketSockObject *s) +/*[clinic end generated code: output=e760d93dae8b6ef7 input=13dfb70bc40c3cf8]*/ { - PySocketSockObject *s = _PySocketSockObject_CAST(self); if (s->sock_timeout) { Py_RETURN_TRUE; } @@ -3209,11 +3226,6 @@ sock_getblocking(PyObject *self, PyObject *Py_UNUSED(ignored)) } } -PyDoc_STRVAR(getblocking_doc, -"getblocking()\n\ -\n\ -Returns True if socket is in blocking mode, or False if it\n\ -is in non-blocking mode."); static int socket_parse_timeout(PyTime_t *timeout, PyObject *timeout_obj) @@ -3262,15 +3274,29 @@ socket_parse_timeout(PyTime_t *timeout, PyObject *timeout_obj) > 0 -- timeout mode; operations time out after timeout seconds < 0 -- illegal; raises an exception */ +/*[clinic input] +_socket.socket.settimeout + self as s: self(type="PySocketSockObject *") + timeout as arg: object + / + +Set a timeout on socket operations. + +'timeout' can be a float, giving in seconds, or None. Setting a +timeout of None disables the timeout feature and is equivalent to +setblocking(1). Setting a timeout of zero is the same as +setblocking(0). +[clinic start generated code]*/ + static PyObject * -sock_settimeout(PyObject *self, PyObject *arg) +_socket_socket_settimeout_impl(PySocketSockObject *s, PyObject *arg) +/*[clinic end generated code: output=5e57e2e1cba1c234 input=08bc8324b9fdb3f9]*/ { PyTime_t timeout; if (socket_parse_timeout(&timeout, arg) < 0) return NULL; - PySocketSockObject *s = _PySocketSockObject_CAST(self); s->sock_timeout = timeout; int block = timeout < 0; @@ -3301,13 +3327,6 @@ sock_settimeout(PyObject *self, PyObject *arg) Py_RETURN_NONE; } -PyDoc_STRVAR(settimeout_doc, -"settimeout(timeout)\n\ -\n\ -Set a timeout on socket operations. 'timeout' can be a float,\n\ -giving in seconds, or None. Setting a timeout of None disables\n\ -the timeout feature and is equivalent to setblocking(1).\n\ -Setting a timeout of zero is the same as setblocking(0)."); /* s.gettimeout() method. Returns the timeout associated with a socket. */ @@ -3324,10 +3343,20 @@ sock_gettimeout_impl(PyObject *self, void *Py_UNUSED(ignored)) } } -static inline PyObject * -sock_gettimeout_method(PyObject *self, PyObject *Py_UNUSED(ignored)) +/*[clinic input] +_socket.socket.gettimeout + +Return the timeout in seconds (float) of socket operations. + +A timeout of None indicates that timeouts on socket operations are +disabled. +[clinic start generated code]*/ + +static PyObject * +_socket_socket_gettimeout_impl(PySocketSockObject *self) +/*[clinic end generated code: output=cd49b7758a504532 input=47e7c5bf80e26eaa]*/ { - return sock_gettimeout_impl(self, NULL); + return sock_gettimeout_impl((PyObject *)self, NULL); } static inline PyObject * @@ -3336,12 +3365,6 @@ sock_gettimeout_getter(PyObject *self, void *Py_UNUSED(closure)) return sock_gettimeout_impl(self, NULL); } -PyDoc_STRVAR(gettimeout_doc, -"gettimeout() -> timeout\n\ -\n\ -Returns the timeout in seconds (float) associated with socket\n\ -operations. A timeout of None indicates that timeouts on socket\n\ -operations are disabled."); #ifdef HAVE_SETSOCKOPT /* s.setsockopt() method. @@ -3483,22 +3506,30 @@ None, optlen."); With a third integer argument, retrieves a string buffer of that size; use optional built-in module 'struct' to decode the string. */ +/*[clinic input] +_socket.socket.getsockopt + self as s: self(type="PySocketSockObject *") + level: int + option as optname: int + buffersize as buflen: int = 0 + / + +Get a socket option. + +See the Unix manual for level and option. If a nonzero buffersize +argument is given, the return value is a bytes object of that +length; otherwise it is an integer. +[clinic start generated code]*/ + static PyObject * -sock_getsockopt(PyObject *self, PyObject *args) +_socket_socket_getsockopt_impl(PySocketSockObject *s, int level, int optname, + int buflen) +/*[clinic end generated code: output=0b397d1e2237a512 input=1a586fad20b3c3fa]*/ { - PySocketSockObject *s = _PySocketSockObject_CAST(self); - - int level; - int optname; int res; - socklen_t buflen = 0; int flag = 0; socklen_t flagsize; - if (!PyArg_ParseTuple(args, "ii|i:getsockopt", - &level, &optname, &buflen)) - return NULL; - if (buflen == 0) { #ifdef AF_VSOCK if (s->sock_family == AF_VSOCK) { @@ -3539,31 +3570,38 @@ sock_getsockopt(PyObject *self, PyObject *args) if (writer == NULL) { return NULL; } + socklen_t optlen = buflen; res = getsockopt(get_sock_fd(s), level, optname, - PyBytesWriter_GetData(writer), &buflen); + PyBytesWriter_GetData(writer), &optlen); if (res < 0) { PyBytesWriter_Discard(writer); return s->errorhandler(); } - return PyBytesWriter_FinishWithSize(writer, buflen); + return PyBytesWriter_FinishWithSize(writer, optlen); } -PyDoc_STRVAR(getsockopt_doc, -"getsockopt(level, option[, buffersize]) -> value\n\ -\n\ -Get a socket option. See the Unix manual for level and option.\n\ -If a nonzero buffersize argument is given, the return value is a\n\ -string of that length; otherwise it is an integer."); #ifdef HAVE_BIND /* s.bind(sockaddr) method */ +/*[clinic input] +_socket.socket.bind + self as s: self(type="PySocketSockObject *") + address as addro: object + / + +Bind the socket to a local address. + +For IP sockets, the address is a pair (host, port); the host must +refer to the local host. For raw packet sockets the address is a +tuple (ifname, proto [,pkttype [,hatype [,addr]]]). +[clinic start generated code]*/ + static PyObject * -sock_bind(PyObject *self, PyObject *addro) +_socket_socket_bind_impl(PySocketSockObject *s, PyObject *addro) +/*[clinic end generated code: output=b8d74d0184a9f187 input=ee3f536adbaaa1cb]*/ { - PySocketSockObject *s = _PySocketSockObject_CAST(self); - sock_addr_t addrbuf; int addrlen; int res; @@ -3584,12 +3622,6 @@ sock_bind(PyObject *self, PyObject *addro) Py_RETURN_NONE; } -PyDoc_STRVAR(bind_doc, -"bind(address)\n\ -\n\ -Bind the socket to a local address. For IP sockets, the address is a\n\ -pair (host, port); the host must refer to the local host. For raw packet\n\ -sockets the address is a tuple (ifname, proto [,pkttype [,hatype [,addr]]])"); #endif @@ -3633,21 +3665,25 @@ _socket_socket_close_impl(PySocketSockObject *s) Py_RETURN_NONE; } +/*[clinic input] +_socket.socket.detach + self as s: self(type="PySocketSockObject *") + +Close the socket object without closing the file descriptor. + +The object cannot be used after this call, but the file descriptor +can be reused for other purposes. The file descriptor is returned. +[clinic start generated code]*/ + static PyObject * -sock_detach(PyObject *self, PyObject *Py_UNUSED(ignored)) +_socket_socket_detach_impl(PySocketSockObject *s) +/*[clinic end generated code: output=769cc72d7fdddebd input=ee1305f0594b88cc]*/ { - PySocketSockObject *s = _PySocketSockObject_CAST(self); SOCKET_T fd = get_sock_fd(s); set_sock_fd(s, INVALID_SOCKET); return PyLong_FromSocket_t(fd); } -PyDoc_STRVAR(detach_doc, -"detach()\n\ -\n\ -Close the socket object without closing the underlying file descriptor.\n\ -The object cannot be used after this call, but the file descriptor\n\ -can be reused for other purposes. The file descriptor is returned."); #ifdef HAVE_CONNECT static int @@ -3751,11 +3787,21 @@ internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen, /* s.connect(sockaddr) method */ +/*[clinic input] +_socket.socket.connect + self as s: self(type="PySocketSockObject *") + address as addro: object + / + +Connect the socket to a remote address. + +For IP sockets, the address is a pair (host, port). +[clinic start generated code]*/ + static PyObject * -sock_connect(PyObject *self, PyObject *addro) +_socket_socket_connect_impl(PySocketSockObject *s, PyObject *addro) +/*[clinic end generated code: output=d4f73817eb43ed12 input=1b7c601416490538]*/ { - PySocketSockObject *s = _PySocketSockObject_CAST(self); - sock_addr_t addrbuf; int addrlen; int res; @@ -3777,20 +3823,26 @@ sock_connect(PyObject *self, PyObject *addro) Py_RETURN_NONE; } -PyDoc_STRVAR(connect_doc, -"connect(address)\n\ -\n\ -Connect the socket to a remote address. For IP sockets, the address\n\ -is a pair (host, port)."); /* s.connect_ex(sockaddr) method */ +/*[clinic input] +_socket.socket.connect_ex + self as s: self(type="PySocketSockObject *") + address as addro: object + / + +Connect the socket to a remote address. + +This is like connect(address), but returns an error code (the errno +value) instead of raising an exception when an error occurs. +[clinic start generated code]*/ + static PyObject * -sock_connect_ex(PyObject *self, PyObject *addro) +_socket_socket_connect_ex_impl(PySocketSockObject *s, PyObject *addro) +/*[clinic end generated code: output=bc8b7cdf80e419af input=716f3a78a296d7ca]*/ { - PySocketSockObject *s = _PySocketSockObject_CAST(self); - sock_addr_t addrbuf; int addrlen; int res; @@ -3811,37 +3863,45 @@ sock_connect_ex(PyObject *self, PyObject *addro) return PyLong_FromLong((long) res); } -PyDoc_STRVAR(connect_ex_doc, -"connect_ex(address) -> errno\n\ -\n\ -This is like connect(address), but returns an error code (the errno value)\n\ -instead of raising an exception when an error occurs."); #endif // HAVE_CONNECT /* s.fileno() method */ +/*[clinic input] +_socket.socket.fileno + self as s: self(type="PySocketSockObject *") + +Return the integer file descriptor of the socket. +[clinic start generated code]*/ + static PyObject * -sock_fileno(PyObject *self, PyObject *Py_UNUSED(ignored)) +_socket_socket_fileno_impl(PySocketSockObject *s) +/*[clinic end generated code: output=6d422560f508d2c6 input=7f817a2413c3c37c]*/ { - PySocketSockObject *s = _PySocketSockObject_CAST(self); return PyLong_FromSocket_t(get_sock_fd(s)); } -PyDoc_STRVAR(fileno_doc, -"fileno() -> integer\n\ -\n\ -Return the integer file descriptor of the socket."); #ifdef HAVE_GETSOCKNAME /* s.getsockname() method */ +/*[clinic input] +_socket.socket.getsockname + self as s: self(type="PySocketSockObject *") + +Return the address of the local endpoint. + +The format depends on the address family. For IPv4 sockets, the +address info is a pair (hostaddr, port). For IPv6 sockets, the +address info is a 4-tuple (hostaddr, port, flowinfo, scope_id). +[clinic start generated code]*/ + static PyObject * -sock_getsockname(PyObject *self, PyObject *Py_UNUSED(ignored)) +_socket_socket_getsockname_impl(PySocketSockObject *s) +/*[clinic end generated code: output=b4c94874b6bf20ed input=b6628802847b2eef]*/ { - PySocketSockObject *s = _PySocketSockObject_CAST(self); - sock_addr_t addrbuf; int res; socklen_t addrlen; @@ -3858,24 +3918,25 @@ sock_getsockname(PyObject *self, PyObject *Py_UNUSED(ignored)) s->sock_proto); } -PyDoc_STRVAR(getsockname_doc, -"getsockname() -> address info\n\ -\n\ -Return the address of the local endpoint. The format depends on the\n\ -address family. For IPv4 sockets, the address info is a pair\n\ -(hostaddr, port). For IPv6 sockets, the address info is a 4-tuple\n\ -(hostaddr, port, flowinfo, scope_id)."); #endif #ifdef HAVE_GETPEERNAME /* Cray APP doesn't have this :-( */ /* s.getpeername() method */ +/*[clinic input] +_socket.socket.getpeername + self as s: self(type="PySocketSockObject *") + +Return the address of the remote endpoint. + +For IP sockets, the address info is a pair (hostaddr, port). +[clinic start generated code]*/ + static PyObject * -sock_getpeername(PyObject *self, PyObject *Py_UNUSED(ignored)) +_socket_socket_getpeername_impl(PySocketSockObject *s) +/*[clinic end generated code: output=3e20211d74c8f60b input=aa6b96e92c7996be]*/ { - PySocketSockObject *s = _PySocketSockObject_CAST(self); - sock_addr_t addrbuf; int res; socklen_t addrlen; @@ -3892,11 +3953,6 @@ sock_getpeername(PyObject *self, PyObject *Py_UNUSED(ignored)) s->sock_proto); } -PyDoc_STRVAR(getpeername_doc, -"getpeername() -> address info\n\ -\n\ -Return the address of the remote endpoint. For IP sockets, the address\n\ -info is a pair (hostaddr, port)."); #endif /* HAVE_GETPEERNAME */ @@ -3904,18 +3960,26 @@ info is a pair (hostaddr, port)."); #ifdef HAVE_LISTEN /* s.listen(n) method */ +/*[clinic input] +_socket.socket.listen + self as s: self(type="PySocketSockObject *") + backlog: int(c_default="Py_MIN(SOMAXCONN, 128)") = min(SOMAXCONN, 128) + / + +Enable a server to accept connections. + +If backlog is specified, it must be at least 0 (if it is lower, it +is set to 0); it specifies the number of unaccepted connections that +the system will allow before refusing new connections. If not +specified, a default reasonable value is chosen. +[clinic start generated code]*/ + static PyObject * -sock_listen(PyObject *self, PyObject *args) +_socket_socket_listen_impl(PySocketSockObject *s, int backlog) +/*[clinic end generated code: output=245718576af7f07b input=8eb794d108797ad9]*/ { - PySocketSockObject *s = _PySocketSockObject_CAST(self); - /* We try to choose a default backlog high enough to avoid connection drops - * for common workloads, yet not too high to limit resource usage. */ - int backlog = Py_MIN(SOMAXCONN, 128); int res; - if (!PyArg_ParseTuple(args, "|i:listen", &backlog)) - return NULL; - Py_BEGIN_ALLOW_THREADS /* To avoid problems on systems that don't allow a negative backlog * (which doesn't make sense anyway) we force a minimum value of 0. */ @@ -3928,13 +3992,6 @@ sock_listen(PyObject *self, PyObject *args) Py_RETURN_NONE; } -PyDoc_STRVAR(listen_doc, -"listen([backlog])\n\ -\n\ -Enable a server to accept connections. If backlog is specified, it must be\n\ -at least 0 (if it is lower, it is set to 0); it specifies the number of\n\ -unaccepted connections that the system will allow before refusing new\n\ -connections. If not specified, a default reasonable value is chosen."); #endif struct sock_recv { @@ -3995,16 +4052,27 @@ sock_recv_guts(PySocketSockObject *s, char* cbuf, Py_ssize_t len, int flags) /* s.recv(nbytes [,flags]) method */ -static PyObject * -sock_recv(PyObject *self, PyObject *args) -{ - PySocketSockObject *s = _PySocketSockObject_CAST(self); +/*[clinic input] +_socket.socket.recv + self as s: self(type="PySocketSockObject *") + buffersize as recvlen: Py_ssize_t + flags: int = 0 + / - Py_ssize_t recvlen, outlen; - int flags = 0; +Receive up to buffersize bytes from the socket. - if (!PyArg_ParseTuple(args, "n|i:recv", &recvlen, &flags)) - return NULL; +For the optional flags argument, see the Unix manual. When no data +is available, block until at least one byte is available or until +the remote end is closed. When the remote end is closed and all data +is read, return the empty string. +[clinic start generated code]*/ + +static PyObject * +_socket_socket_recv_impl(PySocketSockObject *s, Py_ssize_t recvlen, + int flags) +/*[clinic end generated code: output=412b46af1a68ee75 input=6c8382200e8f85fc]*/ +{ + Py_ssize_t outlen; if (recvlen < 0) { PyErr_SetString(PyExc_ValueError, @@ -4030,37 +4098,34 @@ sock_recv(PyObject *self, PyObject *args) return PyBytesWriter_FinishWithSize(writer, outlen); } -PyDoc_STRVAR(recv_doc, -"recv(buffersize[, flags]) -> data\n\ -\n\ -Receive up to buffersize bytes from the socket. For the optional flags\n\ -argument, see the Unix manual. When no data is available, block until\n\ -at least one byte is available or until the remote end is closed. When\n\ -the remote end is closed and all data is read, return the empty string."); - /* s.recv_into(buffer, [nbytes [,flags]]) method */ -static PyObject* -sock_recv_into(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"buffer", "nbytes", "flags", 0}; - PySocketSockObject *s = _PySocketSockObject_CAST(self); +/*[clinic input] +_socket.socket.recv_into + self as s: self(type="PySocketSockObject *") + buffer as pbuf: Py_buffer(accept={rwbuffer}) + nbytes as recvlen: Py_ssize_t = 0 + flags: int = 0 - int flags = 0; - Py_buffer pbuf; - char *buf; - Py_ssize_t buflen, readlen, recvlen = 0; +Receive up to nbytes bytes from the socket, storing into a buffer. - /* Get the buffer's memory */ - if (!PyArg_ParseTupleAndKeywords(args, kwds, "w*|ni:recv_into", kwlist, - &pbuf, &recvlen, &flags)) - return NULL; - buf = pbuf.buf; - buflen = pbuf.len; +A version of recv() that stores its data into a buffer rather than +creating a new bytes object. If nbytes is not specified (or 0), +receive up to the size available in the given buffer. + +See recv() for documentation about the flags. +[clinic start generated code]*/ + +static PyObject * +_socket_socket_recv_into_impl(PySocketSockObject *s, Py_buffer *pbuf, + Py_ssize_t recvlen, int flags) +/*[clinic end generated code: output=58a1cbe9fadb88d7 input=410e6aff36c416a0]*/ +{ + char *buf = pbuf->buf; + Py_ssize_t buflen = pbuf->len, readlen; if (recvlen < 0) { - PyBuffer_Release(&pbuf); PyErr_SetString(PyExc_ValueError, "negative buffersize in recv_into"); return NULL; @@ -4072,7 +4137,6 @@ sock_recv_into(PyObject *self, PyObject *args, PyObject *kwds) /* Check if the buffer is large enough */ if (buflen < recvlen) { - PyBuffer_Release(&pbuf); PyErr_SetString(PyExc_ValueError, "buffer too small for requested bytes"); return NULL; @@ -4082,24 +4146,14 @@ sock_recv_into(PyObject *self, PyObject *args, PyObject *kwds) readlen = sock_recv_guts(s, buf, recvlen, flags); if (readlen < 0) { /* Return an error. */ - PyBuffer_Release(&pbuf); return NULL; } - PyBuffer_Release(&pbuf); /* Return the number of bytes read. Note that we do not do anything special here in the case that readlen < recvlen. */ return PyLong_FromSsize_t(readlen); } -PyDoc_STRVAR(recv_into_doc, -"recv_into(buffer, [nbytes[, flags]]) -> nbytes_read\n\ -\n\ -A version of recv() that stores its data into a buffer rather than creating\n\ -a new string. Receive up to buffersize bytes from the socket. If buffersize\n\ -is not specified (or 0), receive up to the size available in the given buffer.\n\ -\n\ -See recv() for documentation about the flags."); struct sock_recvfrom { char* cbuf; @@ -4178,17 +4232,26 @@ sock_recvfrom_guts(PySocketSockObject *s, char* cbuf, Py_ssize_t len, int flags, /* s.recvfrom(nbytes [,flags]) method */ +/*[clinic input] +_socket.socket.recvfrom + self as s: self(type="PySocketSockObject *") + buffersize as recvlen: Py_ssize_t + flags: int = 0 + / + +Receive up to buffersize bytes and the sender's address info. + +Like recv(buffersize, flags), but return a (data, address info) +pair. +[clinic start generated code]*/ + static PyObject * -sock_recvfrom(PyObject *self, PyObject *args) +_socket_socket_recvfrom_impl(PySocketSockObject *s, Py_ssize_t recvlen, + int flags) +/*[clinic end generated code: output=52b2ece9ea4251b1 input=d8c8c5dc56c02e86]*/ { - PySocketSockObject *s = _PySocketSockObject_CAST(self); - PyObject *addr = NULL; - int flags = 0; - Py_ssize_t recvlen, outlen; - - if (!PyArg_ParseTuple(args, "n|i:recvfrom", &recvlen, &flags)) - return NULL; + Py_ssize_t outlen; if (recvlen < 0) { PyErr_SetString(PyExc_ValueError, @@ -4220,36 +4283,33 @@ sock_recvfrom(PyObject *self, PyObject *args) return NULL; } -PyDoc_STRVAR(recvfrom_doc, -"recvfrom(buffersize[, flags]) -> (data, address info)\n\ -\n\ -Like recv(buffersize, flags) but also return the sender's address info."); /* s.recvfrom_into(buffer[, nbytes [,flags]]) method */ -static PyObject * -sock_recvfrom_into(PyObject *self, PyObject *args, PyObject* kwds) -{ - static char *kwlist[] = {"buffer", "nbytes", "flags", 0}; - PySocketSockObject *s = _PySocketSockObject_CAST(self); +/*[clinic input] +_socket.socket.recvfrom_into + self as s: self(type="PySocketSockObject *") + buffer as pbuf: Py_buffer(accept={rwbuffer}) + nbytes as recvlen: Py_ssize_t = 0 + flags: int = 0 - int flags = 0; - Py_buffer pbuf; - char *buf; - Py_ssize_t readlen, buflen, recvlen = 0; +Receive up to nbytes bytes and the sender's address info. - PyObject *addr = NULL; +Like recv_into(buffer, nbytes, flags), but return a (nbytes, address +info) pair. +[clinic start generated code]*/ - if (!PyArg_ParseTupleAndKeywords(args, kwds, "w*|ni:recvfrom_into", - kwlist, &pbuf, - &recvlen, &flags)) - return NULL; - buf = pbuf.buf; - buflen = pbuf.len; +static PyObject * +_socket_socket_recvfrom_into_impl(PySocketSockObject *s, Py_buffer *pbuf, + Py_ssize_t recvlen, int flags) +/*[clinic end generated code: output=e60b491a1c9d5bec input=2a15bf437b8b98ba]*/ +{ + char *buf = pbuf->buf; + Py_ssize_t readlen, buflen = pbuf->len; + PyObject *addr = NULL; if (recvlen < 0) { - PyBuffer_Release(&pbuf); PyErr_SetString(PyExc_ValueError, "negative buffersize in recvfrom_into"); return NULL; @@ -4258,7 +4318,6 @@ sock_recvfrom_into(PyObject *self, PyObject *args, PyObject* kwds) /* If nbytes was not specified, use the buffer's length */ recvlen = buflen; } else if (recvlen > buflen) { - PyBuffer_Release(&pbuf); PyErr_SetString(PyExc_ValueError, "nbytes is greater than the length of the buffer"); return NULL; @@ -4266,22 +4325,16 @@ sock_recvfrom_into(PyObject *self, PyObject *args, PyObject* kwds) readlen = sock_recvfrom_guts(s, buf, recvlen, flags, &addr); if (readlen < 0) { - PyBuffer_Release(&pbuf); /* Return an error */ Py_XDECREF(addr); return NULL; } - PyBuffer_Release(&pbuf); /* Return the number of bytes read and the address. Note that we do not do anything special here in the case that readlen < recvlen. */ return Py_BuildValue("nN", readlen, addr); } -PyDoc_STRVAR(recvfrom_into_doc, -"recvfrom_into(buffer[, nbytes[, flags]]) -> (nbytes, address info)\n\ -\n\ -Like recv_into(buffer[, nbytes[, flags]]) but also return the sender's address info."); #endif /* The sendmsg() and recvmsg[_into]() methods require a working @@ -4456,14 +4509,47 @@ makeval_recvmsg(ssize_t received, void *data) /* s.recvmsg(bufsize[, ancbufsize[, flags]]) method */ +/*[clinic input] +_socket.socket.recvmsg + self as s: self(type="PySocketSockObject *") + bufsize: Py_ssize_t + ancbufsize: Py_ssize_t = 0 + flags: int = 0 + / + +Receive normal data and ancillary data from the socket. + +Receive up to bufsize bytes of normal data. The ancbufsize argument +sets the size in bytes of the internal buffer used to receive the +ancillary data; it defaults to 0, meaning that no ancillary data +will be received. Appropriate buffer sizes for ancillary data can +be calculated using CMSG_SPACE() or CMSG_LEN(), and items which do +not fit into the buffer might be truncated or discarded. The flags +argument defaults to 0 and has the same meaning as for recv(). + +The return value is a 4-tuple: (data, ancdata, msg_flags, address). +The data item is a bytes object holding the non-ancillary data +received. The ancdata item is a list of zero or more tuples +(cmsg_level, cmsg_type, cmsg_data) representing the ancillary data +(control messages) received: cmsg_level and cmsg_type are integers +specifying the protocol level and protocol-specific type +respectively, and cmsg_data is a bytes object holding the associated +data. The msg_flags item is the bitwise OR of various flags +indicating conditions on the received message; see your system +documentation for details. If the receiving socket is unconnected, +address is the address of the sending socket, if available; +otherwise, its value is unspecified. + +If recvmsg() raises an exception after the system call returns, it +will first attempt to close any file descriptors received via the +SCM_RIGHTS mechanism. +[clinic start generated code]*/ + static PyObject * -sock_recvmsg(PyObject *self, PyObject *args) +_socket_socket_recvmsg_impl(PySocketSockObject *s, Py_ssize_t bufsize, + Py_ssize_t ancbufsize, int flags) +/*[clinic end generated code: output=1a26c130cf1a898f input=ae53e29436e6c0a3]*/ { - Py_ssize_t bufsize, ancbufsize = 0; - int flags = 0; - if (!PyArg_ParseTuple(args, "n|ni:recvmsg", &bufsize, &ancbufsize, &flags)) - return NULL; - if (bufsize < 0) { PyErr_SetString(PyExc_ValueError, "negative buffer size in recvmsg()"); return NULL; @@ -4481,41 +4567,12 @@ sock_recvmsg(PyObject *self, PyObject *args) writer (&writer); makeval_recvmsg() finish it and set our pointer to NULL. */ PyObject *retval; - PySocketSockObject *s = _PySocketSockObject_CAST(self); retval = sock_recvmsg_guts(s, &iov, 1, flags, ancbufsize, &makeval_recvmsg, &writer); PyBytesWriter_Discard(writer); return retval; } -PyDoc_STRVAR(recvmsg_doc, -"recvmsg(bufsize[, ancbufsize[, flags]]) -> (data, ancdata, msg_flags, address)\n\ -\n\ -Receive normal data (up to bufsize bytes) and ancillary data from the\n\ -socket. The ancbufsize argument sets the size in bytes of the\n\ -internal buffer used to receive the ancillary data; it defaults to 0,\n\ -meaning that no ancillary data will be received. Appropriate buffer\n\ -sizes for ancillary data can be calculated using CMSG_SPACE() or\n\ -CMSG_LEN(), and items which do not fit into the buffer might be\n\ -truncated or discarded. The flags argument defaults to 0 and has the\n\ -same meaning as for recv().\n\ -\n\ -The return value is a 4-tuple: (data, ancdata, msg_flags, address).\n\ -The data item is a bytes object holding the non-ancillary data\n\ -received. The ancdata item is a list of zero or more tuples\n\ -(cmsg_level, cmsg_type, cmsg_data) representing the ancillary data\n\ -(control messages) received: cmsg_level and cmsg_type are integers\n\ -specifying the protocol level and protocol-specific type respectively,\n\ -and cmsg_data is a bytes object holding the associated data. The\n\ -msg_flags item is the bitwise OR of various flags indicating\n\ -conditions on the received message; see your system documentation for\n\ -details. If the receiving socket is unconnected, address is the\n\ -address of the sending socket, if available; otherwise, its value is\n\ -unspecified.\n\ -\n\ -If recvmsg() raises an exception after the system call returns, it\n\ -will first attempt to close any file descriptors received via the\n\ -SCM_RIGHTS mechanism."); static PyObject * @@ -4526,21 +4583,55 @@ makeval_recvmsg_into(ssize_t received, void *data) /* s.recvmsg_into(buffers[, ancbufsize[, flags]]) method */ +/*[clinic input] +_socket.socket.recvmsg_into + self as s: self(type="PySocketSockObject *") + buffers as buffers_arg: object + ancbufsize: Py_ssize_t = 0 + flags: int = 0 + / + +Receive normal and ancillary data, scattering the normal data. + +The buffers argument must be an iterable of objects that export +writable buffers (e.g. bytearray objects); these will be filled +with successive chunks of the non-ancillary data until it has all +been written or there are no more buffers. The ancbufsize argument +sets the size in bytes of the internal buffer used to receive the +ancillary data; it defaults to 0, meaning that no ancillary data +will be received. Appropriate buffer sizes for ancillary data can +be calculated using CMSG_SPACE() or CMSG_LEN(), and items which do +not fit into the buffer might be truncated or discarded. The flags +argument defaults to 0 and has the same meaning as for recv(). + +The return value is a 4-tuple: (nbytes, ancdata, msg_flags, +address). The nbytes item is the total number of bytes of +non-ancillary data written into the buffers. The ancdata item is a +list of zero or more tuples (cmsg_level, cmsg_type, cmsg_data) +representing the ancillary data (control messages) received: +cmsg_level and cmsg_type are integers specifying the protocol level +and protocol-specific type respectively, and cmsg_data is a bytes +object holding the associated data. The msg_flags item is the +bitwise OR of various flags indicating conditions on the received +message; see your system documentation for details. If the +receiving socket is unconnected, address is the address of the +sending socket, if available; otherwise, its value is unspecified. + +If recvmsg_into() raises an exception after the system call returns, +it will first attempt to close any file descriptors received via the +SCM_RIGHTS mechanism. +[clinic start generated code]*/ + static PyObject * -sock_recvmsg_into(PyObject *self, PyObject *args) +_socket_socket_recvmsg_into_impl(PySocketSockObject *s, + PyObject *buffers_arg, + Py_ssize_t ancbufsize, int flags) +/*[clinic end generated code: output=282fd7dd1bdb15f8 input=427536a5043122d2]*/ { - PySocketSockObject *s = _PySocketSockObject_CAST(self); - - Py_ssize_t ancbufsize = 0; - int flags = 0; struct iovec *iovs = NULL; Py_ssize_t i, nitems, nbufs = 0; Py_buffer *bufs = NULL; - PyObject *buffers_arg, *buffers_tuple, *retval = NULL; - - if (!PyArg_ParseTuple(args, "O|ni:recvmsg_into", - &buffers_arg, &ancbufsize, &flags)) - return NULL; + PyObject *buffers_tuple, *retval = NULL; buffers_tuple = PySequence_Tuple(buffers_arg); if (buffers_tuple == NULL) { @@ -4582,38 +4673,6 @@ sock_recvmsg_into(PyObject *self, PyObject *args) return retval; } -PyDoc_STRVAR(recvmsg_into_doc, -"recvmsg_into(buffers[, ancbufsize[, flags]]) -> (nbytes, ancdata, msg_flags, address)\n\ -\n\ -Receive normal data and ancillary data from the socket, scattering the\n\ -non-ancillary data into a series of buffers. The buffers argument\n\ -must be an iterable of objects that export writable buffers\n\ -(e.g. bytearray objects); these will be filled with successive chunks\n\ -of the non-ancillary data until it has all been written or there are\n\ -no more buffers. The ancbufsize argument sets the size in bytes of\n\ -the internal buffer used to receive the ancillary data; it defaults to\n\ -0, meaning that no ancillary data will be received. Appropriate\n\ -buffer sizes for ancillary data can be calculated using CMSG_SPACE()\n\ -or CMSG_LEN(), and items which do not fit into the buffer might be\n\ -truncated or discarded. The flags argument defaults to 0 and has the\n\ -same meaning as for recv().\n\ -\n\ -The return value is a 4-tuple: (nbytes, ancdata, msg_flags, address).\n\ -The nbytes item is the total number of bytes of non-ancillary data\n\ -written into the buffers. The ancdata item is a list of zero or more\n\ -tuples (cmsg_level, cmsg_type, cmsg_data) representing the ancillary\n\ -data (control messages) received: cmsg_level and cmsg_type are\n\ -integers specifying the protocol level and protocol-specific type\n\ -respectively, and cmsg_data is a bytes object holding the associated\n\ -data. The msg_flags item is the bitwise OR of various flags\n\ -indicating conditions on the received message; see your system\n\ -documentation for details. If the receiving socket is unconnected,\n\ -address is the address of the sending socket, if available; otherwise,\n\ -its value is unspecified.\n\ -\n\ -If recvmsg_into() raises an exception after the system call returns,\n\ -it will first attempt to close any file descriptors received via the\n\ -SCM_RIGHTS mechanism."); #endif /* CMSG_LEN */ @@ -5140,27 +5199,37 @@ _socket_socket_sendmsg_impl(PySocketSockObject *s, PyObject *data_arg, #endif /* CMSG_LEN */ #ifdef HAVE_SOCKADDR_ALG -static PyObject* -sock_sendmsg_afalg(PyObject *s, PyObject *args, PyObject *kwds) -{ - PySocketSockObject *self = _PySocketSockObject_CAST(s); +/*[clinic input] +_socket.socket.sendmsg_afalg + self: self(type="PySocketSockObject *") + msg as data_arg: object = NULL + * + op as opobj: object(subclass_of='&PyLong_Type') = NULL + iv: Py_buffer = NULL + assoclen as assoclenobj: object(subclass_of='&PyLong_Type') = NULL + flags: int = 0 + +Set operation mode, IV and associated data length. + +For an AF_ALG operation socket. +[clinic start generated code]*/ +static PyObject * +_socket_socket_sendmsg_afalg_impl(PySocketSockObject *self, + PyObject *data_arg, PyObject *opobj, + Py_buffer *iv, PyObject *assoclenobj, + int flags) +/*[clinic end generated code: output=3fd9856d4d9f7c97 input=3ed371da034a1bb3]*/ +{ PyObject *retval = NULL; Py_ssize_t i, ndatabufs = 0; Py_buffer *databufs = NULL; - PyObject *data_arg = NULL; - Py_buffer iv = {NULL, NULL}; - - PyObject *opobj = NULL; int op = -1; - - PyObject *assoclenobj = NULL; int assoclen = -1; unsigned int *uiptr; - int flags = 0; struct msghdr msg; struct cmsghdr *header = NULL; @@ -5168,7 +5237,6 @@ sock_sendmsg_afalg(PyObject *s, PyObject *args, PyObject *kwds) struct sock_sendmsg ctx; Py_ssize_t controllen; void *controlbuf = NULL; - static char *keywords[] = {"msg", "op", "iv", "assoclen", "flags", 0}; if (self->sock_family != AF_ALG) { PyErr_SetString(PyExc_OSError, @@ -5176,14 +5244,6 @@ sock_sendmsg_afalg(PyObject *s, PyObject *args, PyObject *kwds) return NULL; } - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "|O$O!y*O!i:sendmsg_afalg", keywords, - &data_arg, - &PyLong_Type, &opobj, &iv, - &PyLong_Type, &assoclenobj, &flags)) { - return NULL; - } - memset(&msg, 0, sizeof(msg)); /* op is a required, keyword-only argument >= 0 */ @@ -5210,8 +5270,8 @@ sock_sendmsg_afalg(PyObject *s, PyObject *args, PyObject *kwds) } controllen = CMSG_SPACE(4); - if (iv.buf != NULL) { - controllen += CMSG_SPACE(sizeof(*alg_iv) + iv.len); + if (iv->buf != NULL) { + controllen += CMSG_SPACE(sizeof(*alg_iv) + iv->len); } if (assoclen >= 0) { controllen += CMSG_SPACE(4); @@ -5249,7 +5309,7 @@ sock_sendmsg_afalg(PyObject *s, PyObject *args, PyObject *kwds) *uiptr = (unsigned int)op; /* set initialization vector */ - if (iv.buf != NULL) { + if (iv->buf != NULL) { header = CMSG_NXTHDR(&msg, header); if (header == NULL) { PyErr_SetString(PyExc_RuntimeError, @@ -5258,10 +5318,10 @@ sock_sendmsg_afalg(PyObject *s, PyObject *args, PyObject *kwds) } header->cmsg_level = SOL_ALG; header->cmsg_type = ALG_SET_IV; - header->cmsg_len = CMSG_SPACE(sizeof(*alg_iv) + iv.len); + header->cmsg_len = CMSG_SPACE(sizeof(*alg_iv) + iv->len); alg_iv = (void*)CMSG_DATA(header); - alg_iv->ivlen = iv.len; - memcpy(alg_iv->iv, iv.buf, iv.len); + alg_iv->ivlen = iv->len; + memcpy(alg_iv->iv, iv->buf, iv->len); } /* set length of associated data for AEAD */ @@ -5289,9 +5349,8 @@ sock_sendmsg_afalg(PyObject *s, PyObject *args, PyObject *kwds) finally: PyMem_Free(controlbuf); - if (iv.buf != NULL) { - PyBuffer_Release(&iv); - } + if (iv->buf != NULL) { + } PyMem_Free(msg.msg_iov); for (i = 0; i < ndatabufs; i++) { PyBuffer_Release(&databufs[i]); @@ -5300,21 +5359,28 @@ sock_sendmsg_afalg(PyObject *s, PyObject *args, PyObject *kwds) return retval; } -PyDoc_STRVAR(sendmsg_afalg_doc, -"sendmsg_afalg([msg], *, op[, iv[, assoclen[, flags=MSG_MORE]]])\n\ -\n\ -Set operation mode, IV and length of associated data for an AF_ALG\n\ -operation socket."); #endif #ifdef HAVE_SHUTDOWN /* s.shutdown(how) method */ +/*[clinic input] +_socket.socket.shutdown + self as s: self(type="PySocketSockObject *") + flag as arg: object + / + +Shut down one or both halves of the connection. + +Shut down the reading side of the socket (flag == SHUT_RD), the +writing side of the socket (flag == SHUT_WR), or both ends (flag == +SHUT_RDWR). +[clinic start generated code]*/ + static PyObject * -sock_shutdown(PyObject *self, PyObject *arg) +_socket_socket_shutdown_impl(PySocketSockObject *s, PyObject *arg) +/*[clinic end generated code: output=84264513a6049ca7 input=a90afb227247ce03]*/ { - PySocketSockObject *s = _PySocketSockObject_CAST(self); - int how; int res; @@ -5329,11 +5395,6 @@ sock_shutdown(PyObject *self, PyObject *arg) Py_RETURN_NONE; } -PyDoc_STRVAR(shutdown_doc, -"shutdown(flag)\n\ -\n\ -Shut down the reading side of the socket (flag == SHUT_RD), the writing side\n\ -of the socket (flag == SHUT_WR), or both ends (flag == SHUT_RDWR)."); #endif #if defined(MS_WINDOWS) && defined(SIO_RCVALL) @@ -5395,18 +5456,26 @@ SIO_LOOPBACK_FAST_PATH: 'option' is a boolean value, and is disabled by default" #endif #if defined(MS_WINDOWS) -static PyObject* -sock_share(PyObject *self, PyObject *arg) -{ - PySocketSockObject *s = _PySocketSockObject_CAST(self); +/*[clinic input] +_socket.socket.share + self as s: self(type="PySocketSockObject *") + process_id as processId: unsigned_int(bitwise=True) + / + +Share the socket with another process. +The target process id must be provided and the resulting bytes +object passed to the target process. There the shared socket can be +instantiated by calling socket.fromshare(). +[clinic start generated code]*/ + +static PyObject * +_socket_socket_share_impl(PySocketSockObject *s, unsigned int processId) +/*[clinic end generated code: output=446bfcc5fe3273c6 input=0a9d7536371bfe2d]*/ +{ WSAPROTOCOL_INFOW info; - DWORD processId; int result; - if (!PyArg_ParseTuple(arg, "I", &processId)) - return NULL; - Py_BEGIN_ALLOW_THREADS result = WSADuplicateSocketW(get_sock_fd(s), processId, &info); Py_END_ALLOW_THREADS @@ -5414,13 +5483,6 @@ sock_share(PyObject *self, PyObject *arg) 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 @@ -5429,81 +5491,53 @@ socket.fromshare()."); static PyMethodDef sock_methods[] = { #if defined(HAVE_ACCEPT) || defined(HAVE_ACCEPT4) - {"_accept", sock_accept, METH_NOARGS, accept_doc}, + _SOCKET_SOCKET__ACCEPT_METHODDEF #endif #ifdef HAVE_BIND - {"bind", sock_bind, METH_O, bind_doc}, + _SOCKET_SOCKET_BIND_METHODDEF #endif _SOCKET_SOCKET_CLOSE_METHODDEF #ifdef HAVE_CONNECT - {"connect", sock_connect, METH_O, connect_doc}, - {"connect_ex", sock_connect_ex, METH_O, connect_ex_doc}, + _SOCKET_SOCKET_CONNECT_METHODDEF + _SOCKET_SOCKET_CONNECT_EX_METHODDEF #endif - {"detach", sock_detach, METH_NOARGS, detach_doc}, - {"fileno", sock_fileno, METH_NOARGS, fileno_doc}, + _SOCKET_SOCKET_DETACH_METHODDEF + _SOCKET_SOCKET_FILENO_METHODDEF #ifdef HAVE_GETPEERNAME - {"getpeername", sock_getpeername, METH_NOARGS, getpeername_doc}, + _SOCKET_SOCKET_GETPEERNAME_METHODDEF #endif #ifdef HAVE_GETSOCKNAME - {"getsockname", sock_getsockname, METH_NOARGS, getsockname_doc}, + _SOCKET_SOCKET_GETSOCKNAME_METHODDEF #endif - {"getsockopt", sock_getsockopt, METH_VARARGS, getsockopt_doc}, + _SOCKET_SOCKET_GETSOCKOPT_METHODDEF #if defined(MS_WINDOWS) && defined(SIO_RCVALL) {"ioctl", sock_ioctl, METH_VARARGS, sock_ioctl_doc}, #endif -#if defined(MS_WINDOWS) - {"share", sock_share, METH_VARARGS, sock_share_doc}, -#endif -#ifdef HAVE_LISTEN - {"listen", sock_listen, METH_VARARGS, listen_doc}, -#endif - {"recv", sock_recv, METH_VARARGS, recv_doc}, - { - "recv_into", - _PyCFunction_CAST(sock_recv_into), - METH_VARARGS | METH_KEYWORDS, - recv_into_doc - }, -#ifdef HAVE_RECVFROM - {"recvfrom", sock_recvfrom, METH_VARARGS, recvfrom_doc}, - { - "recvfrom_into", - _PyCFunction_CAST(sock_recvfrom_into), - METH_VARARGS | METH_KEYWORDS, - recvfrom_into_doc - }, -#endif + _SOCKET_SOCKET_SHARE_METHODDEF + _SOCKET_SOCKET_LISTEN_METHODDEF + _SOCKET_SOCKET_RECV_METHODDEF + _SOCKET_SOCKET_RECV_INTO_METHODDEF + _SOCKET_SOCKET_RECVFROM_METHODDEF + _SOCKET_SOCKET_RECVFROM_INTO_METHODDEF _SOCKET_SOCKET_SEND_METHODDEF _SOCKET_SOCKET_SENDALL_METHODDEF #ifdef HAVE_SENDTO {"sendto", sock_sendto, METH_VARARGS, sendto_doc}, #endif - {"setblocking", sock_setblocking, METH_O, setblocking_doc}, - {"getblocking", sock_getblocking, METH_NOARGS, getblocking_doc}, - {"settimeout", sock_settimeout, METH_O, settimeout_doc}, - { - "gettimeout", sock_gettimeout_method, METH_NOARGS, - gettimeout_doc - }, + _SOCKET_SOCKET_SETBLOCKING_METHODDEF + _SOCKET_SOCKET_GETBLOCKING_METHODDEF + _SOCKET_SOCKET_SETTIMEOUT_METHODDEF + _SOCKET_SOCKET_GETTIMEOUT_METHODDEF #ifdef HAVE_SETSOCKOPT {"setsockopt", sock_setsockopt, METH_VARARGS, setsockopt_doc}, #endif #ifdef HAVE_SHUTDOWN - {"shutdown", sock_shutdown, METH_O, shutdown_doc}, + _SOCKET_SOCKET_SHUTDOWN_METHODDEF #endif -#ifdef CMSG_LEN - {"recvmsg", sock_recvmsg, METH_VARARGS, recvmsg_doc}, - {"recvmsg_into", sock_recvmsg_into, METH_VARARGS, recvmsg_into_doc}, + _SOCKET_SOCKET_RECVMSG_METHODDEF + _SOCKET_SOCKET_RECVMSG_INTO_METHODDEF _SOCKET_SOCKET_SENDMSG_METHODDEF -#endif -#ifdef HAVE_SOCKADDR_ALG - { - "sendmsg_afalg", - _PyCFunction_CAST(sock_sendmsg_afalg), - METH_VARARGS | METH_KEYWORDS, - sendmsg_afalg_doc - }, -#endif + _SOCKET_SOCKET_SENDMSG_AFALG_METHODDEF {NULL, NULL, 0, NULL} /* sentinel */ }; @@ -5882,8 +5916,15 @@ static PyType_Spec sock_spec = { /* Python interface to gethostname(). */ /*ARGSUSED*/ +/*[clinic input] +_socket.gethostname + +Return the current host name. +[clinic start generated code]*/ + static PyObject * -socket_gethostname(PyObject *self, PyObject *unused) +_socket_gethostname_impl(PyObject *module) +/*[clinic end generated code: output=1d9b789d69464c01 input=994028f092f41baf]*/ { if (PySys_Audit("socket.gethostname", NULL) < 0) { return NULL; @@ -5939,21 +5980,23 @@ socket_gethostname(PyObject *self, PyObject *unused) #endif } -PyDoc_STRVAR(gethostname_doc, -"gethostname() -> string\n\ -\n\ -Return the current host name."); #endif #ifdef HAVE_SETHOSTNAME -PyDoc_STRVAR(sethostname_doc, -"sethostname(name)\n\n\ -Sets the hostname to name."); + +/*[clinic input] +_socket.sethostname + + name as hnobj: object + / + +Set the hostname to name. +[clinic start generated code]*/ static PyObject * -socket_sethostname(PyObject *self, PyObject *args) +_socket_sethostname(PyObject *module, PyObject *hnobj) +/*[clinic end generated code: output=0b789350cbbc4553 input=89c1a7022cb1082a]*/ { - PyObject *hnobj; Py_buffer buf; int res, flag = 0; @@ -5963,15 +6006,16 @@ socket_sethostname(PyObject *self, PyObject *args) extern int sethostname(const char *, size_t); #endif - if (!PyArg_ParseTuple(args, "S:sethostname", &hnobj)) { - PyErr_Clear(); - if (!PyArg_ParseTuple(args, "O&:sethostname", - PyUnicode_FSConverter, &hnobj)) + if (!PyBytes_Check(hnobj)) { + if (!PyUnicode_FSConverter(hnobj, &hnobj)) { return NULL; + } flag = 1; } if (PySys_Audit("socket.sethostname", "(O)", hnobj) < 0) { + if (flag) + Py_DECREF(hnobj); return NULL; } @@ -5992,19 +6036,32 @@ extern int sethostname(const char *, size_t); /* Python interface to gethostbyname(name). */ /*ARGSUSED*/ +/*[clinic input] +_socket.gethostbyname + + host as hobj: object + / + +Return the IP address for a host. + +The address is a string of the form '255.255.255.255'. +[clinic start generated code]*/ + static PyObject * -socket_gethostbyname(PyObject *self, PyObject *args) +_socket_gethostbyname(PyObject *module, PyObject *hobj) +/*[clinic end generated code: output=19f571343780c48b input=3c0d3b92e44a1795]*/ { - char *name; struct sockaddr_in addrbuf; + char *name; PyObject *ret = NULL; - if (!PyArg_ParseTuple(args, "et:gethostbyname", "idna", &name)) + if (!PyArg_Parse(hobj, "et:gethostbyname", "idna", &name)) { return NULL; - if (PySys_Audit("socket.gethostbyname", "O", args) < 0) { + } + if (PySys_Audit("socket.gethostbyname", "(O)", hobj) < 0) { goto finally; } - socket_state *state = get_module_state(self); + socket_state *state = get_module_state(module); int rc = setipaddr(state, name, (struct sockaddr *)&addrbuf, sizeof(addrbuf), AF_INET); if (rc < 0) { @@ -6015,11 +6072,6 @@ socket_gethostbyname(PyObject *self, PyObject *args) PyMem_Free(name); return ret; } - -PyDoc_STRVAR(gethostbyname_doc, -"gethostbyname(host) -> address\n\ -\n\ -Return the IP address (a string of the form '255.255.255.255') for a host."); #endif @@ -6184,8 +6236,21 @@ gethost_common(socket_state *state, struct hostent *h, struct sockaddr *addr, /* Python interface to gethostbyname_ex(name). */ /*ARGSUSED*/ +/*[clinic input] +_socket.gethostbyname_ex + + host as hobj: object + / + +Map a host name to its IP number. + +Return the true host name, a list of aliases, and a list of IP +addresses, which are strings of the form '255.255.255.255'. +[clinic start generated code]*/ + static PyObject * -socket_gethostbyname_ex(PyObject *self, PyObject *args) +_socket_gethostbyname_ex(PyObject *module, PyObject *hobj) +/*[clinic end generated code: output=a1ea4607d257756e input=1ee9eb485339c58b]*/ { char *name; struct hostent *h; @@ -6206,12 +6271,13 @@ socket_gethostbyname_ex(PyObject *self, PyObject *args) #endif #endif /* HAVE_GETHOSTBYNAME_R */ - if (!PyArg_ParseTuple(args, "et:gethostbyname_ex", "idna", &name)) + if (!PyArg_Parse(hobj, "et:gethostbyname_ex", "idna", &name)) { return NULL; - if (PySys_Audit("socket.gethostbyname", "O", args) < 0) { + } + if (PySys_Audit("socket.gethostbyname", "(O)", hobj) < 0) { goto finally; } - socket_state *state = get_module_state(self); + socket_state *state = get_module_state(module); if (setipaddr(state, name, SAS2SA(&addr), sizeof(addr), AF_INET) < 0) { goto finally; } @@ -6252,23 +6318,32 @@ socket_gethostbyname_ex(PyObject *self, PyObject *args) return ret; } -PyDoc_STRVAR(ghbn_ex_doc, -"gethostbyname_ex(host) -> (name, aliaslist, addresslist)\n\ -\n\ -Return the true host name, a list of aliases, and a list of IP addresses,\n\ -for a host. The host argument is a string giving a host name or IP number."); #endif #if defined(HAVE_GETHOSTBYNAME_R) || defined (HAVE_GETHOSTBYADDR) /* Python interface to gethostbyaddr(IP). */ /*ARGSUSED*/ +/*[clinic input] +_socket.gethostbyaddr + + host as hobj: object + / + +Map an IP number or host name to the true host name and addresses. + +Return the true host name, a list of aliases, and a list of IP +addresses. The host argument is a string giving a host name or IP +number. +[clinic start generated code]*/ + static PyObject * -socket_gethostbyaddr(PyObject *self, PyObject *args) +_socket_gethostbyaddr(PyObject *module, PyObject *hobj) +/*[clinic end generated code: output=4ba6c4d7a3085ab5 input=c602ba97bf0d395b]*/ { + char *ip_num; sock_addr_t addr; struct sockaddr *sa = SAS2SA(&addr); - char *ip_num; struct hostent *h; PyObject *ret = NULL; #ifdef HAVE_GETHOSTBYNAME_R @@ -6292,13 +6367,14 @@ socket_gethostbyaddr(PyObject *self, PyObject *args) int al; int af; - if (!PyArg_ParseTuple(args, "et:gethostbyaddr", "idna", &ip_num)) + if (!PyArg_Parse(hobj, "et:gethostbyaddr", "idna", &ip_num)) { return NULL; - if (PySys_Audit("socket.gethostbyaddr", "O", args) < 0) { + } + if (PySys_Audit("socket.gethostbyaddr", "(O)", hobj) < 0) { goto finally; } af = AF_UNSPEC; - socket_state *state = get_module_state(self); + socket_state *state = get_module_state(module); if (setipaddr(state, ip_num, sa, sizeof(addr), af) < 0) { goto finally; } @@ -6349,15 +6425,8 @@ socket_gethostbyaddr(PyObject *self, PyObject *args) PyMutex_Unlock(&netdb_lock); #endif finally: - PyMem_Free(ip_num); return ret; } - -PyDoc_STRVAR(gethostbyaddr_doc, -"gethostbyaddr(host) -> (name, aliaslist, addresslist)\n\ -\n\ -Return the true host name, a list of aliases, and a list of IP addresses,\n\ -for a host. The host argument is a string giving a host name or IP number."); #endif #ifdef HAVE_GETSERVBYNAME @@ -6366,13 +6435,25 @@ for a host. The host argument is a string giving a host name or IP number."); known or not useful (like the list of aliases). */ /*ARGSUSED*/ +/*[clinic input] +_socket.getservbyname + + servicename as name: str + protocolname as proto: str = NULL + / + +Return a port number from a service name and protocol name. + +The optional protocol name, if given, should be 'tcp' or 'udp', +otherwise any protocol will match. +[clinic start generated code]*/ + static PyObject * -socket_getservbyname(PyObject *self, PyObject *args) +_socket_getservbyname_impl(PyObject *module, const char *name, + const char *proto) +/*[clinic end generated code: output=b0c47287f8ec2b00 input=a8e3ad7ced8c8798]*/ { - const char *name, *proto=NULL; struct servent *sp; - if (!PyArg_ParseTuple(args, "s|s:getservbyname", &name, &proto)) - return NULL; if (PySys_Audit("socket.getservbyname", "ss", name, proto) < 0) { return NULL; @@ -6388,12 +6469,6 @@ socket_getservbyname(PyObject *self, PyObject *args) return PyLong_FromLong((long) ntohs(sp->s_port)); } -PyDoc_STRVAR(getservbyname_doc, -"getservbyname(servicename[, protocolname]) -> integer\n\ -\n\ -Return a port number from a service name and protocol name.\n\ -The optional protocol name, if given, should be 'tcp' or 'udp',\n\ -otherwise any protocol will match."); #endif #ifdef HAVE_GETSERVBYPORT @@ -6402,14 +6477,25 @@ otherwise any protocol will match."); known or not useful (like the list of aliases). */ /*ARGSUSED*/ +/*[clinic input] +_socket.getservbyport + + port: int + protocolname as proto: str = NULL + / + +Return the service name from a port number and protocol name. + +The optional protocol name, if given, should be 'tcp' or 'udp', +otherwise any protocol will match. +[clinic start generated code]*/ + static PyObject * -socket_getservbyport(PyObject *self, PyObject *args) +_socket_getservbyport_impl(PyObject *module, int port, const char *proto) +/*[clinic end generated code: output=42351ab1857aa9e4 input=9a2a3091ea6ff146]*/ { - int port; - const char *proto=NULL; struct servent *sp; - if (!PyArg_ParseTuple(args, "i|s:getservbyport", &port, &proto)) - return NULL; + if (port < 0 || port > 0xffff) { PyErr_SetString( PyExc_OverflowError, @@ -6431,12 +6517,6 @@ socket_getservbyport(PyObject *self, PyObject *args) return PyUnicode_FromString(sp->s_name); } -PyDoc_STRVAR(getservbyport_doc, -"getservbyport(port[, protocolname]) -> string\n\ -\n\ -Return the service name from a port number and protocol name.\n\ -The optional protocol name, if given, should be 'tcp' or 'udp',\n\ -otherwise any protocol will match."); #endif #ifdef HAVE_GETPROTOBYNAME @@ -6445,13 +6525,20 @@ otherwise any protocol will match."); already known or not useful (like the list of aliases). */ /*ARGSUSED*/ +/*[clinic input] +_socket.getprotobyname + + name: str + / + +Return the protocol number for the named protocol. +[clinic start generated code]*/ + static PyObject * -socket_getprotobyname(PyObject *self, PyObject *args) +_socket_getprotobyname_impl(PyObject *module, const char *name) +/*[clinic end generated code: output=30fb71f0c6ffbaea input=d197d3726c828e38]*/ { - const char *name; struct protoent *sp; - if (!PyArg_ParseTuple(args, "s:getprotobyname", &name)) - return NULL; Py_BEGIN_ALLOW_THREADS sp = getprotobyname(name); Py_END_ALLOW_THREADS @@ -6462,14 +6549,20 @@ socket_getprotobyname(PyObject *self, PyObject *args) return PyLong_FromLong((long) sp->p_proto); } -PyDoc_STRVAR(getprotobyname_doc, -"getprotobyname(name) -> integer\n\ -\n\ -Return the protocol number for the named protocol. (Rarely used.)"); #endif +/*[clinic input] +_socket.close + + fd as fdobj: object + / + +Close a socket fd. +[clinic start generated code]*/ + static PyObject * -socket_close(PyObject *self, PyObject *fdobj) +_socket_close(PyObject *module, PyObject *fdobj) +/*[clinic end generated code: output=1d62092e6fc365dc input=3928558b90299147]*/ { SOCKET_T fd; int res; @@ -6488,17 +6581,24 @@ socket_close(PyObject *self, PyObject *fdobj) Py_RETURN_NONE; } -PyDoc_STRVAR(close_doc, -"close(integer) -> None\n\ -\n\ -Close an integer socket file descriptor. This is like os.close(), but for\n\ -sockets; on some platforms os.close() won't work for socket file descriptors."); #ifndef NO_DUP /* dup() function for socket fds */ +/*[clinic input] +_socket.dup + + fd as fdobj: object + / + +Duplicate a socket descriptor. + +The new descriptor is non-inheritable. +[clinic start generated code]*/ + static PyObject * -socket_dup(PyObject *self, PyObject *fdobj) +_socket_dup(PyObject *module, PyObject *fdobj) +/*[clinic end generated code: output=7e9c4485cf5a76c0 input=dfc5de188bf696ef]*/ { SOCKET_T fd, newfd; PyObject *newfdobj; @@ -6542,11 +6642,6 @@ socket_dup(PyObject *self, PyObject *fdobj) return newfdobj; } -PyDoc_STRVAR(dup_doc, -"dup(integer) -> integer\n\ -\n\ -Duplicate an integer socket file descriptor. This is like os.dup(), but for\n\ -sockets; on some platforms os.dup() won't work for socket file descriptors."); #endif @@ -6556,13 +6651,27 @@ sockets; on some platforms os.dup() won't work for socket file descriptors."); defined on the platform; otherwise, the default is AF_INET. */ /*ARGSUSED*/ +/*[clinic input] +_socket.socketpair + + family: int(c_default="AF_UNIX") = AF_UNIX + type: int(c_default="SOCK_STREAM") = SOCK_STREAM + proto: int = 0 + / + +Create a pair of connected socket objects. + +The sockets are returned by the platform socketpair() function. The +arguments are the same as for socket(). +[clinic start generated code]*/ + static PyObject * -socket_socketpair(PyObject *self, PyObject *args) +_socket_socketpair_impl(PyObject *module, int family, int type, int proto) +/*[clinic end generated code: output=c012ae1f558bb0ca input=823902632e78e181]*/ { PySocketSockObject *s0 = NULL, *s1 = NULL; SOCKET_T sv[2]; - int family, type = SOCK_STREAM, proto = 0; - socket_state *state = get_module_state(self); + socket_state *state = get_module_state(module); #ifdef SOCK_CLOEXEC int *atomic_flag_works = &sock_cloexec_works; #else @@ -6570,15 +6679,6 @@ socket_socketpair(PyObject *self, PyObject *args) #endif int ret; -#if defined(AF_UNIX) - family = AF_UNIX; -#else - family = AF_INET; -#endif - if (!PyArg_ParseTuple(args, "|iii:socketpair", - &family, &type, &proto)) - return NULL; - /* Create a pair of socket fds */ Py_BEGIN_ALLOW_THREADS #ifdef SOCK_CLOEXEC @@ -6628,13 +6728,6 @@ socket_socketpair(PyObject *self, PyObject *args) return NULL; } -PyDoc_STRVAR(socketpair_doc, -"socketpair([family[, type [, proto]]]) -> (socket object, socket object)\n\ -\n\ -Create a pair of socket objects from the sockets returned by the platform\n\ -socketpair() function.\n\ -The arguments are the same as for socket() except the default family is\n\ -AF_UNIX if defined on the platform; otherwise, the default is AF_INET."); #endif /* HAVE_SOCKETPAIR */ @@ -6811,27 +6904,29 @@ _socket_inet_ntoa_impl(PyObject *module, Py_buffer *packed_ip) #ifdef HAVE_INET_PTON -PyDoc_STRVAR(inet_pton_doc, -"inet_pton(af, ip) -> packed IP address string\n\ -\n\ -Convert an IP address from string format to a packed string suitable\n\ -for use with low-level network functions."); + +/*[clinic input] +_socket.inet_pton + + af: int + ip: str + / + +Convert an IP address from string format to a packed string. + +The string is suitable for use with low-level network functions. +[clinic start generated code]*/ static PyObject * -socket_inet_pton(PyObject *self, PyObject *args) +_socket_inet_pton_impl(PyObject *module, int af, const char *ip) +/*[clinic end generated code: output=a1488ddddc478dc2 input=044acc246469c125]*/ { - int af; - const char* ip; int retval; #ifdef ENABLE_IPV6 char packed[Py_MAX(sizeof(struct in_addr), sizeof(struct in6_addr))]; #else char packed[sizeof(struct in_addr)]; #endif - if (!PyArg_ParseTuple(args, "is:inet_pton", &af, &ip)) { - return NULL; - } - #if !defined(ENABLE_IPV6) && defined(AF_INET6) if(af == AF_INET6) { PyErr_SetString(PyExc_OSError, @@ -6862,16 +6957,21 @@ socket_inet_pton(PyObject *self, PyObject *args) } } -PyDoc_STRVAR(inet_ntop_doc, -"inet_ntop(af, packed_ip) -> string formatted IP address\n\ -\n\ -Convert a packed IP address of the given family to string format."); + +/*[clinic input] +_socket.inet_ntop + + af: int + packed_ip: Py_buffer + / + +Convert a packed IP address of the given family to string format. +[clinic start generated code]*/ static PyObject * -socket_inet_ntop(PyObject *self, PyObject *args) +_socket_inet_ntop_impl(PyObject *module, int af, Py_buffer *packed_ip) +/*[clinic end generated code: output=eabff3e56456ede0 input=7027f0a0abdf71d1]*/ { - int af; - Py_buffer packed_ip; const char* retval; #ifdef ENABLE_IPV6 char ip[Py_MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)]; @@ -6879,43 +6979,33 @@ socket_inet_ntop(PyObject *self, PyObject *args) char ip[INET_ADDRSTRLEN]; #endif - if (!PyArg_ParseTuple(args, "iy*:inet_ntop", &af, &packed_ip)) { - return NULL; - } - if (af == AF_INET) { - if (packed_ip.len != sizeof(struct in_addr)) { + if (packed_ip->len != sizeof(struct in_addr)) { PyErr_SetString(PyExc_ValueError, "invalid length of packed IP address string"); - PyBuffer_Release(&packed_ip); return NULL; } #ifdef ENABLE_IPV6 } else if (af == AF_INET6) { - if (packed_ip.len != sizeof(struct in6_addr)) { + if (packed_ip->len != sizeof(struct in6_addr)) { PyErr_SetString(PyExc_ValueError, "invalid length of packed IP address string"); - PyBuffer_Release(&packed_ip); return NULL; } #endif } else { PyErr_Format(PyExc_ValueError, "unknown address family %d", af); - PyBuffer_Release(&packed_ip); return NULL; } /* inet_ntop guarantee NUL-termination of resulting string. */ - retval = inet_ntop(af, packed_ip.buf, ip, sizeof(ip)); + retval = inet_ntop(af, packed_ip->buf, ip, sizeof(ip)); if (!retval) { PyErr_SetFromErrno(PyExc_OSError); - PyBuffer_Release(&packed_ip); return NULL; - } else { - PyBuffer_Release(&packed_ip); - return PyUnicode_FromString(retval); } + return PyUnicode_FromString(retval); } #endif /* HAVE_INET_PTON */ @@ -6924,29 +7014,34 @@ socket_inet_ntop(PyObject *self, PyObject *args) /* Python interface to getaddrinfo(host, port). */ /*ARGSUSED*/ +/*[clinic input] +_socket.getaddrinfo + + host as hobj: object + port as pobj: object + family: int(c_default="AF_UNSPEC") = AF_UNSPEC + type as socktype: int = 0 + proto as protocol: int = 0 + flags: int = 0 + +Resolve host and port into a list of 5-tuples. + +Each tuple is (family, type, proto, canonname, sockaddr). +[clinic start generated code]*/ + static PyObject * -socket_getaddrinfo(PyObject *self, PyObject *args, PyObject* kwargs) +_socket_getaddrinfo_impl(PyObject *module, PyObject *hobj, PyObject *pobj, + int family, int socktype, int protocol, int flags) +/*[clinic end generated code: output=a54f59f33f3da184 input=1fd64ac89aee1d18]*/ { - static char* kwnames[] = {"host", "port", "family", "type", "proto", - "flags", 0}; struct addrinfo hints, *res; struct addrinfo *res0 = NULL; - PyObject *hobj = NULL; - PyObject *pobj = (PyObject *)NULL; PyObject *pstr = NULL; const char *hptr, *pptr; - int family, socktype, protocol, flags; int error; PyObject *all = (PyObject *)NULL; PyObject *idna = NULL; - socktype = protocol = flags = 0; - family = AF_UNSPEC; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iiii:getaddrinfo", - kwnames, &hobj, &pobj, &family, &socktype, - &protocol, &flags)) { - return NULL; - } if (hobj == Py_None) { hptr = NULL; } else if (PyUnicode_Check(hobj)) { @@ -7011,7 +7106,7 @@ socket_getaddrinfo(PyObject *self, PyObject *args, PyObject* kwargs) Py_END_ALLOW_THREADS if (error) { res0 = NULL; // gh-100795 - socket_state *state = get_module_state(self); + socket_state *state = get_module_state(module); set_gaierror(state, error); goto err; } @@ -7053,22 +7148,26 @@ socket_getaddrinfo(PyObject *self, PyObject *args, PyObject* kwargs) return (PyObject *)NULL; } -PyDoc_STRVAR(getaddrinfo_doc, -"getaddrinfo(host, port [, family, type, proto, flags])\n\ - -> list of (family, type, proto, canonname, sockaddr)\n\ -\n\ -Resolve host and port into addrinfo struct."); #endif // HAVE_GETADDRINFO #ifdef HAVE_GETNAMEINFO /* Python interface to getnameinfo(sa, flags). */ /*ARGSUSED*/ +/*[clinic input] +_socket.getnameinfo + + sockaddr as sa: object + flags: int + / + +Get host and port for a sockaddr. +[clinic start generated code]*/ + static PyObject * -socket_getnameinfo(PyObject *self, PyObject *args) +_socket_getnameinfo_impl(PyObject *module, PyObject *sa, int flags) +/*[clinic end generated code: output=2e1d7ef2bd94f698 input=dd0444ac9adae4d3]*/ { - PyObject *sa = (PyObject *)NULL; - int flags; const char *hostp; int port; unsigned int flowinfo, scope_id; @@ -7078,9 +7177,7 @@ socket_getnameinfo(PyObject *self, PyObject *args) PyObject *ret = (PyObject *)NULL; PyObject *name; - flags = flowinfo = scope_id = 0; - if (!PyArg_ParseTuple(args, "Oi:getnameinfo", &sa, &flags)) - return NULL; + flowinfo = scope_id = 0; if (!PyTuple_Check(sa)) { PyErr_SetString(PyExc_TypeError, "getnameinfo() argument 1 must be a tuple"); @@ -7111,7 +7208,7 @@ socket_getnameinfo(PyObject *self, PyObject *args) Py_END_ALLOW_THREADS if (error) { res = NULL; // gh-100795 - socket_state *state = get_module_state(self); + socket_state *state = get_module_state(module); set_gaierror(state, error); goto fail; } @@ -7146,7 +7243,7 @@ socket_getnameinfo(PyObject *self, PyObject *args) hbuf, sizeof(hbuf), pbuf, sizeof(pbuf), flags); Py_END_ALLOW_THREADS if (error) { - socket_state *state = get_module_state(self); + socket_state *state = get_module_state(module); set_gaierror(state, error); goto fail; } @@ -7162,18 +7259,24 @@ socket_getnameinfo(PyObject *self, PyObject *args) return ret; } -PyDoc_STRVAR(getnameinfo_doc, -"getnameinfo(sockaddr, flags) --> (host, port)\n\ -\n\ -Get host and port for a sockaddr."); #endif // HAVE_GETNAMEINFO /* Python API to getting and setting the default timeout value. */ +/*[clinic input] +_socket.getdefaulttimeout + +Return the default timeout in seconds for new socket objects. + +A value of None indicates that new socket objects have no timeout. +When the socket module is first imported, the default is None. +[clinic start generated code]*/ + static PyObject * -socket_getdefaulttimeout(PyObject *self, PyObject *Py_UNUSED(ignored)) +_socket_getdefaulttimeout_impl(PyObject *module) +/*[clinic end generated code: output=7b3e1be56948c44c input=c9fb729acf998a58]*/ { - socket_state *state = get_module_state(self); + socket_state *state = get_module_state(module); PyTime_t timeout = _Py_atomic_load_int64_relaxed(&state->defaulttimeout); if (timeout < 0) { Py_RETURN_NONE; @@ -7184,39 +7287,47 @@ socket_getdefaulttimeout(PyObject *self, PyObject *Py_UNUSED(ignored)) } } -PyDoc_STRVAR(getdefaulttimeout_doc, -"getdefaulttimeout() -> timeout\n\ -\n\ -Returns the default timeout in seconds (float) for new socket objects.\n\ -A value of None indicates that new socket objects have no timeout.\n\ -When the socket module is first imported, the default is None."); + +/*[clinic input] +_socket.setdefaulttimeout + + timeout as arg: object + / + +Set the default timeout in seconds for new socket objects. + +A value of None indicates that new socket objects have no timeout. +When the socket module is first imported, the default is None. +[clinic start generated code]*/ static PyObject * -socket_setdefaulttimeout(PyObject *self, PyObject *arg) +_socket_setdefaulttimeout(PyObject *module, PyObject *arg) +/*[clinic end generated code: output=b5d59296163d66bf input=929785d885173684]*/ { PyTime_t timeout; if (socket_parse_timeout(&timeout, arg) < 0) return NULL; - socket_state *state = get_module_state(self); + socket_state *state = get_module_state(module); _Py_atomic_store_int64_relaxed(&state->defaulttimeout, timeout); Py_RETURN_NONE; } -PyDoc_STRVAR(setdefaulttimeout_doc, -"setdefaulttimeout(timeout)\n\ -\n\ -Set the default timeout in seconds (real number) for new socket objects.\n\ -A value of None indicates that new socket objects have no timeout.\n\ -When the socket module is first imported, the default is None."); #if defined(HAVE_IF_NAMEINDEX) || defined(MS_WINDOWS) /* Python API for getting interface indices and names */ +/*[clinic input] +_socket.if_nameindex + +Return a list of network interface information (index, name) tuples. +[clinic start generated code]*/ + static PyObject * -socket_if_nameindex(PyObject *self, PyObject *arg) +_socket_if_nameindex_impl(PyObject *module) +/*[clinic end generated code: output=93c863a6262059c4 input=d6438bb556de2100]*/ { PyObject *list = PyList_New(0); if (list == NULL) { @@ -7296,10 +7407,6 @@ socket_if_nameindex(PyObject *self, PyObject *arg) #endif } -PyDoc_STRVAR(if_nameindex_doc, -"if_nameindex()\n\ -\n\ -Returns a list of network interface information (index, name) tuples."); /*[clinic input] _socket.if_nametoindex @@ -7359,14 +7466,28 @@ _socket_if_indextoname_impl(PyObject *module, NET_IFINDEX index) #ifdef CMSG_LEN /* Python interface to CMSG_LEN(length). */ +/*[clinic input] +_socket.CMSG_LEN + + length: Py_ssize_t + / + +Return the total length of an ancillary data item with associated data. + +The associated data has the given length. This value can often be +used as the buffer size for recvmsg() to receive a single item of +ancillary data, but RFC 3542 requires portable applications to use +CMSG_SPACE() and thus include space for padding, even when the item +will be the last in the buffer. Raises OverflowError if length is +outside the permissible range of values. +[clinic start generated code]*/ + static PyObject * -socket_CMSG_LEN(PyObject *self, PyObject *args) +_socket_CMSG_LEN_impl(PyObject *module, Py_ssize_t length) +/*[clinic end generated code: output=e1dd6bb3a3f4a7ff input=b0787fd8c8d9c7be]*/ { - Py_ssize_t length; size_t result; - if (!PyArg_ParseTuple(args, "n:CMSG_LEN", &length)) - return NULL; if (length < 0 || !get_CMSG_LEN(length, &result)) { PyErr_Format(PyExc_OverflowError, "CMSG_LEN() argument out of range"); return NULL; @@ -7374,29 +7495,32 @@ socket_CMSG_LEN(PyObject *self, PyObject *args) return PyLong_FromSize_t(result); } -PyDoc_STRVAR(CMSG_LEN_doc, -"CMSG_LEN(length) -> control message length\n\ -\n\ -Return the total length, without trailing padding, of an ancillary\n\ -data item with associated data of the given length. This value can\n\ -often be used as the buffer size for recvmsg() to receive a single\n\ -item of ancillary data, but RFC 3542 requires portable applications to\n\ -use CMSG_SPACE() and thus include space for padding, even when the\n\ -item will be the last in the buffer. Raises OverflowError if length\n\ -is outside the permissible range of values."); #ifdef CMSG_SPACE /* Python interface to CMSG_SPACE(length). */ +/*[clinic input] +_socket.CMSG_SPACE + + length: Py_ssize_t + / + +Return the buffer size needed to receive an ancillary data item. + +The item has associated data of the given length, and the size +includes any trailing padding. The buffer space needed to receive +multiple items is the sum of the CMSG_SPACE() values for their +associated data lengths. Raises OverflowError if length is outside +the permissible range of values. +[clinic start generated code]*/ + static PyObject * -socket_CMSG_SPACE(PyObject *self, PyObject *args) +_socket_CMSG_SPACE_impl(PyObject *module, Py_ssize_t length) +/*[clinic end generated code: output=857b925dc29c68c3 input=dedf123dcda72642]*/ { - Py_ssize_t length; size_t result; - if (!PyArg_ParseTuple(args, "n:CMSG_SPACE", &length)) - return NULL; if (length < 0 || !get_CMSG_SPACE(length, &result)) { PyErr_SetString(PyExc_OverflowError, "CMSG_SPACE() argument out of range"); @@ -7405,15 +7529,6 @@ socket_CMSG_SPACE(PyObject *self, PyObject *args) return PyLong_FromSize_t(result); } -PyDoc_STRVAR(CMSG_SPACE_doc, -"CMSG_SPACE(length) -> buffer size\n\ -\n\ -Return the buffer size needed for recvmsg() to receive an ancillary\n\ -data item with associated data of the given length, along with any\n\ -trailing padding. The buffer space needed to receive multiple items\n\ -is the sum of the CMSG_SPACE() values for their associated data\n\ -lengths. Raises OverflowError if length is outside the permissible\n\ -range of values."); #endif /* CMSG_SPACE */ #endif /* CMSG_LEN */ @@ -7421,88 +7536,40 @@ range of values."); /* List of functions exported by this module. */ static PyMethodDef socket_methods[] = { -#ifdef HAVE_GETADDRINFO - {"gethostbyname", socket_gethostbyname, - METH_VARARGS, gethostbyname_doc}, -#endif -#if defined(HAVE_GETHOSTBYNAME_R) || defined (HAVE_GETHOSTBYNAME) - {"gethostbyname_ex", socket_gethostbyname_ex, - METH_VARARGS, ghbn_ex_doc}, -#endif -#if defined(HAVE_GETHOSTBYNAME_R) || defined (HAVE_GETHOSTBYADDR) - {"gethostbyaddr", socket_gethostbyaddr, - METH_VARARGS, gethostbyaddr_doc}, -#endif + _SOCKET_GETHOSTBYNAME_METHODDEF + _SOCKET_GETHOSTBYNAME_EX_METHODDEF + _SOCKET_GETHOSTBYADDR_METHODDEF #ifdef HAVE_GETHOSTNAME - {"gethostname", socket_gethostname, - METH_NOARGS, gethostname_doc}, -#endif -#ifdef HAVE_SETHOSTNAME - {"sethostname", socket_sethostname, - METH_VARARGS, sethostname_doc}, -#endif -#ifdef HAVE_GETSERVBYNAME - {"getservbyname", socket_getservbyname, - METH_VARARGS, getservbyname_doc}, -#endif -#ifdef HAVE_GETSERVBYPORT - {"getservbyport", socket_getservbyport, - METH_VARARGS, getservbyport_doc}, -#endif -#ifdef HAVE_GETPROTOBYNAME - {"getprotobyname", socket_getprotobyname, - METH_VARARGS, getprotobyname_doc}, + _SOCKET_GETHOSTNAME_METHODDEF #endif - {"close", socket_close, - METH_O, close_doc}, + _SOCKET_SETHOSTNAME_METHODDEF + _SOCKET_GETSERVBYNAME_METHODDEF + _SOCKET_GETSERVBYPORT_METHODDEF + _SOCKET_GETPROTOBYNAME_METHODDEF + _SOCKET_CLOSE_METHODDEF #ifndef NO_DUP - {"dup", socket_dup, - METH_O, dup_doc}, -#endif -#ifdef HAVE_SOCKETPAIR - {"socketpair", socket_socketpair, - METH_VARARGS, socketpair_doc}, + _SOCKET_DUP_METHODDEF #endif + _SOCKET_SOCKETPAIR_METHODDEF _SOCKET_NTOHS_METHODDEF _SOCKET_NTOHL_METHODDEF _SOCKET_HTONS_METHODDEF _SOCKET_HTONL_METHODDEF _SOCKET_INET_ATON_METHODDEF -#ifdef HAVE_INET_NTOA _SOCKET_INET_NTOA_METHODDEF -#endif -#ifdef HAVE_INET_PTON - {"inet_pton", socket_inet_pton, - METH_VARARGS, inet_pton_doc}, - {"inet_ntop", socket_inet_ntop, - METH_VARARGS, inet_ntop_doc}, -#endif -#ifdef HAVE_GETADDRINFO - {"getaddrinfo", _PyCFunction_CAST(socket_getaddrinfo), - METH_VARARGS | METH_KEYWORDS, getaddrinfo_doc}, -#endif -#ifdef HAVE_GETNAMEINFO - {"getnameinfo", socket_getnameinfo, - METH_VARARGS, getnameinfo_doc}, -#endif - {"getdefaulttimeout", socket_getdefaulttimeout, - METH_NOARGS, getdefaulttimeout_doc}, - {"setdefaulttimeout", socket_setdefaulttimeout, - METH_O, setdefaulttimeout_doc}, + _SOCKET_INET_PTON_METHODDEF + _SOCKET_INET_NTOP_METHODDEF + _SOCKET_GETADDRINFO_METHODDEF + _SOCKET_GETNAMEINFO_METHODDEF + _SOCKET_GETDEFAULTTIMEOUT_METHODDEF + _SOCKET_SETDEFAULTTIMEOUT_METHODDEF #if defined(HAVE_IF_NAMEINDEX) || defined(MS_WINDOWS) - {"if_nameindex", socket_if_nameindex, - METH_NOARGS, if_nameindex_doc}, + _SOCKET_IF_NAMEINDEX_METHODDEF _SOCKET_IF_NAMETOINDEX_METHODDEF _SOCKET_IF_INDEXTONAME_METHODDEF #endif -#ifdef CMSG_LEN - {"CMSG_LEN", socket_CMSG_LEN, - METH_VARARGS, CMSG_LEN_doc}, -#ifdef CMSG_SPACE - {"CMSG_SPACE", socket_CMSG_SPACE, - METH_VARARGS, CMSG_SPACE_doc}, -#endif -#endif + _SOCKET_CMSG_LEN_METHODDEF + _SOCKET_CMSG_SPACE_METHODDEF {NULL, NULL} /* Sentinel */ }; From 0403d564e91155596ad82391282bb0f70e677901 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 5 Aug 2026 23:02:06 +0300 Subject: [PATCH 2/4] Add test_socket_module_has_signatures() --- Lib/test/test_inspect/test_inspect.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Lib/test/test_inspect/test_inspect.py b/Lib/test/test_inspect/test_inspect.py index 5153e5eb9a4ff8b..b230535608092f0 100644 --- a/Lib/test/test_inspect/test_inspect.py +++ b/Lib/test/test_inspect/test_inspect.py @@ -6312,6 +6312,24 @@ def test_signal_module_has_signatures(self): import signal self._test_module_has_signatures(signal) + def test_socket_module_has_signatures(self): + import socket + # The socket type has no signature, it is created by socket(). + no_signature = {'SocketType'} + # The C default is NULL and None is not accepted + unsupported_signature = {'getservbyname', 'getservbyport'} + # These cannot be converted to Argument Clinic: their behaviour + # depends on the number of the arguments. + methods_no_signature = {'ioctl', 'sendto', 'setsockopt'} + # These have parameters with unrepresentable default values. + methods_unsupported_signature = {'listen', 'sendmsg', 'sendmsg_afalg'} + # Not all methods are available on all platforms. + defined = vars(socket.SocketType).keys() + self._test_module_has_signatures(socket, + no_signature, unsupported_signature, + {'SocketType': methods_no_signature & defined}, + {'SocketType': methods_unsupported_signature & defined}) + def test_stat_module_has_signatures(self): import stat self._test_module_has_signatures(stat) From f519333a8b1672dff36ec80e17f90e87f596f269 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Thu, 6 Aug 2026 08:56:42 +0300 Subject: [PATCH 3/4] Regenerate the global objects for the new keywords --- .../pycore_global_objects_fini_generated.h | 6 +++++ Include/internal/pycore_global_strings.h | 6 +++++ .../internal/pycore_runtime_init_generated.h | 6 +++++ .../internal/pycore_unicodeobject_generated.h | 24 +++++++++++++++++++ 4 files changed, 42 insertions(+) diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h index 6df1c01f151f68e..c982f76431c52d1 100644 --- a/Include/internal/pycore_global_objects_fini_generated.h +++ b/Include/internal/pycore_global_objects_fini_generated.h @@ -1596,6 +1596,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(argv)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(as_integer_ratio)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(asend)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(assoclen)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(ast)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(athrow)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(attr)); @@ -1811,6 +1812,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(headers)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(hi)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(hook)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(host)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(hour)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(hours)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(id)); @@ -1859,6 +1861,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(iter)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(iterable)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(iterations)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(iv)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(join)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(jump)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(keepends)); @@ -1937,6 +1940,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(namespace_separator)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(namespaces)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(native)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(nbytes)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(ndigits)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(nested)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(new_file_name)); @@ -1961,6 +1965,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(onceregistry)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(only_active_thread)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(only_keys)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(op)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(oparg)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(opcode)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(opcodes)); @@ -1995,6 +2000,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(pidfd)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(pointer_bits)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(policy)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(port)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(pos)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(pos1)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(pos2)); diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index 873344fbdcb67b0..c430d0fb99bc41d 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -319,6 +319,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(argv) STRUCT_FOR_ID(as_integer_ratio) STRUCT_FOR_ID(asend) + STRUCT_FOR_ID(assoclen) STRUCT_FOR_ID(ast) STRUCT_FOR_ID(athrow) STRUCT_FOR_ID(attr) @@ -534,6 +535,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(headers) STRUCT_FOR_ID(hi) STRUCT_FOR_ID(hook) + STRUCT_FOR_ID(host) STRUCT_FOR_ID(hour) STRUCT_FOR_ID(hours) STRUCT_FOR_ID(id) @@ -582,6 +584,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(iter) STRUCT_FOR_ID(iterable) STRUCT_FOR_ID(iterations) + STRUCT_FOR_ID(iv) STRUCT_FOR_ID(join) STRUCT_FOR_ID(jump) STRUCT_FOR_ID(keepends) @@ -660,6 +663,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(namespace_separator) STRUCT_FOR_ID(namespaces) STRUCT_FOR_ID(native) + STRUCT_FOR_ID(nbytes) STRUCT_FOR_ID(ndigits) STRUCT_FOR_ID(nested) STRUCT_FOR_ID(new_file_name) @@ -684,6 +688,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(onceregistry) STRUCT_FOR_ID(only_active_thread) STRUCT_FOR_ID(only_keys) + STRUCT_FOR_ID(op) STRUCT_FOR_ID(oparg) STRUCT_FOR_ID(opcode) STRUCT_FOR_ID(opcodes) @@ -718,6 +723,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(pidfd) STRUCT_FOR_ID(pointer_bits) STRUCT_FOR_ID(policy) + STRUCT_FOR_ID(port) STRUCT_FOR_ID(pos) STRUCT_FOR_ID(pos1) STRUCT_FOR_ID(pos2) diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index 378f27ca17b5079..5a194478f562314 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -1594,6 +1594,7 @@ extern "C" { INIT_ID(argv), \ INIT_ID(as_integer_ratio), \ INIT_ID(asend), \ + INIT_ID(assoclen), \ INIT_ID(ast), \ INIT_ID(athrow), \ INIT_ID(attr), \ @@ -1809,6 +1810,7 @@ extern "C" { INIT_ID(headers), \ INIT_ID(hi), \ INIT_ID(hook), \ + INIT_ID(host), \ INIT_ID(hour), \ INIT_ID(hours), \ INIT_ID(id), \ @@ -1857,6 +1859,7 @@ extern "C" { INIT_ID(iter), \ INIT_ID(iterable), \ INIT_ID(iterations), \ + INIT_ID(iv), \ INIT_ID(join), \ INIT_ID(jump), \ INIT_ID(keepends), \ @@ -1935,6 +1938,7 @@ extern "C" { INIT_ID(namespace_separator), \ INIT_ID(namespaces), \ INIT_ID(native), \ + INIT_ID(nbytes), \ INIT_ID(ndigits), \ INIT_ID(nested), \ INIT_ID(new_file_name), \ @@ -1959,6 +1963,7 @@ extern "C" { INIT_ID(onceregistry), \ INIT_ID(only_active_thread), \ INIT_ID(only_keys), \ + INIT_ID(op), \ INIT_ID(oparg), \ INIT_ID(opcode), \ INIT_ID(opcodes), \ @@ -1993,6 +1998,7 @@ extern "C" { INIT_ID(pidfd), \ INIT_ID(pointer_bits), \ INIT_ID(policy), \ + INIT_ID(port), \ INIT_ID(pos), \ INIT_ID(pos1), \ INIT_ID(pos2), \ diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h index daf6840aa47f328..25529c5ca713a95 100644 --- a/Include/internal/pycore_unicodeobject_generated.h +++ b/Include/internal/pycore_unicodeobject_generated.h @@ -1056,6 +1056,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(assoclen); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(ast); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -1916,6 +1920,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(host); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(hour); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -2108,6 +2116,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(iv); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(join); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -2420,6 +2432,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(nbytes); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(ndigits); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -2516,6 +2532,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(op); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(oparg); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -2652,6 +2672,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(port); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(pos); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); From cbf38e74ea431f0c0cc02e9f1ac71601f37baaad Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Thu, 6 Aug 2026 10:04:10 +0300 Subject: [PATCH 4/4] Not all socket functions are available on all platforms --- Lib/test/test_inspect/test_inspect.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_inspect/test_inspect.py b/Lib/test/test_inspect/test_inspect.py index b230535608092f0..83b1ef37185e859 100644 --- a/Lib/test/test_inspect/test_inspect.py +++ b/Lib/test/test_inspect/test_inspect.py @@ -6318,12 +6318,13 @@ def test_socket_module_has_signatures(self): no_signature = {'SocketType'} # The C default is NULL and None is not accepted unsupported_signature = {'getservbyname', 'getservbyport'} + # Not all functions and methods are available on all platforms. + unsupported_signature &= vars(socket).keys() # These cannot be converted to Argument Clinic: their behaviour # depends on the number of the arguments. methods_no_signature = {'ioctl', 'sendto', 'setsockopt'} # These have parameters with unrepresentable default values. methods_unsupported_signature = {'listen', 'sendmsg', 'sendmsg_afalg'} - # Not all methods are available on all platforms. defined = vars(socket.SocketType).keys() self._test_module_has_signatures(socket, no_signature, unsupported_signature,