--- py3k_2/Modules/socketmodule.c 2009-07-23 17:07:55.474581000 +0200
+++ py3k/Modules/socketmodule.c 2009-07-24 10:17:33.540000250 +0200
@@ -2388,6 +2388,7 @@
return n;
}
+
/* s.recvfrom(nbytes [,flags]) method */
static PyObject *
@@ -2440,6 +2441,156 @@
Like recv(buffersize, flags) but also return the sender's address info.");
+/* s.recvmsg(datalen, controllen, flags) method */
+
+static PyObject *
+sock_recvmsg(PySocketSockObject *s, PyObject *args)
+{
+ PyObject *dbuf, *cbuf, *alist, *tmp;
+ ssize_t n = -1;
+ int status, timeout;
+ int rdlen, rclen, flags = 0;
+ struct msghdr mhdr;
+ struct cmsghdr *chdr;
+ struct iovec iov[1];
+
+ if (!PyArg_ParseTuple(args, "ii|i:recvmsg", &rdlen, &rclen, &flags))
+ return NULL;
+
+ if (rdlen < 0 || rclen < 0)
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "negative buffersize in recvmsg");
+ return NULL;
+ }
+
+ /* allocate buffers */
+ dbuf = PyBytes_FromStringAndSize((char *) 0, rdlen);
+ if (dbuf == NULL)
+ {
+ return NULL;
+ }
+
+ cbuf = PyBytes_FromStringAndSize((char *) 0, rclen);
+ if (cbuf == NULL)
+ {
+ Py_DECREF(dbuf);
+ return NULL;
+ }
+
+ alist = PyList_New(0);
+ if (alist == NULL)
+ {
+ Py_DECREF(dbuf);
+ Py_DECREF(cbuf);
+ return NULL;
+ }
+
+ /* set up the msghdr struct */
+ memset(&mhdr, 0, sizeof(struct msghdr));
+
+ /* iov -- we use only one buffer, and don't use scatter-gather
+ possible TODO */
+ iov[0].iov_base = PyBytes_AS_STRING(dbuf);
+ iov[0].iov_len = rdlen;
+
+ /* msghdr */
+ mhdr.msg_name = NULL; /* TODO make use of this */
+ mhdr.msg_namelen = 0;
+ mhdr.msg_iov = iov;
+ mhdr.msg_iovlen = 1;
+ mhdr.msg_control = PyBytes_AS_STRING(cbuf);
+ mhdr.msg_controllen = rclen;
+ mhdr.msg_flags = 0;
+
+ /* call recvmsg() */
+ if (!IS_SELECTABLE(s)) {
+ select_error();
+ return -1;
+ }
+
+ Py_BEGIN_ALLOW_THREADS
+ timeout = internal_select(s, 0);
+ if (!timeout)
+ n = recvmsg(s->sock_fd, &mhdr, flags);
+ Py_END_ALLOW_THREADS
+
+ if (timeout == 1)
+ {
+ PyErr_SetString(socket_timeout, "timed out");
+ goto err;
+ }
+
+ if (n < 0)
+ {
+ s->errorhandler();
+ goto err;
+ }
+
+ for (chdr = CMSG_FIRSTHDR(&mhdr); chdr != NULL;
+ chdr = CMSG_NXTHDR(&mhdr, chdr))
+ {
+ tmp = Py_BuildValue("(iiy#)", chdr->cmsg_level,
+ chdr->cmsg_type, (char *)CMSG_DATA(chdr),
+ /* TODO XXX ugly hack, to compute
+ CMSG_DATA's size. Any better ways to
+ do this? */
+ (int)chdr->cmsg_len -
+ ((int)CMSG_DATA(chdr) -
+ (int)chdr));
+ if (tmp == NULL)
+ goto err;
+
+ status = PyList_Append(alist, tmp);
+ Py_DECREF(tmp);
+
+ if (status == -1)
+ goto err;
+ }
+
+ /* if we received less than we anticipated, resize the buffer */
+ if (n != rdlen)
+ {
+ if (_PyBytes_Resize(&dbuf, n) == -1)
+ {
+ Py_DECREF(cbuf);
+ Py_DECREF(alist);
+ return NULL;
+ }
+ }
+
+ /* assemble the final return value, watch out for offsets! */
+ tmp = PyTuple_New(3);
+ if (tmp == NULL)
+ goto err;
+
+ PyTuple_SetItem(tmp, 0, dbuf);
+ PyTuple_SetItem(tmp, 1, alist);
+ PyTuple_SetItem(tmp, 2, Py_BuildValue("i", mhdr.msg_flags));
+
+ /* dbuf and alist are now in tmp, remove reference to
+ cbuf and return */
+ Py_DECREF(cbuf);
+
+ return tmp;
+
+err:
+ Py_DECREF(dbuf);
+ Py_DECREF(cbuf);
+ Py_DECREF(alist);
+ return NULL;
+}
+
+PyDoc_STRVAR(recvmsg_doc,
+"recvmsg(datalen, controllen, flags) method -> (bytes(), [(msglevel, \
+msgtype, msgdata) ... ], flags)\n\
+\n\
+Returns a tuple with three elements, 0: data bytes, 1: list of tuples \
+with three elements\n\
+containing msg_level, msg_type, msg_data, 2: msg_flags\n\
+Currently it's incapable of using multiple buffers and addresses.");
+
+
/* s.recvfrom_into(buffer[, nbytes [,flags]]) method */
static PyObject *
@@ -2655,6 +2806,146 @@
For IP sockets, the address is a pair (hostaddr, port).");
+/* s.sendmsg(data, [(msglevel, msgtype, msgdata), ...], flags) method */
+
+static PyObject *
+sock_sendmsg(PySocketSockObject *s, PyObject *args)
+{
+ Py_buffer dbuf;
+ PyObject *cbuf;
+ PyObject *tmp;
+ Py_buffer tmpdata;
+ PyObject *control;
+ size_t cbuflen = 0;
+ size_t controllen;
+ int tmplev, tmptype;
+ int timeout, flags = 0;
+ int i, n = -1;
+ struct msghdr mhdr;
+ struct cmsghdr *chdr;
+ struct iovec iov[1];
+
+ if (!PyArg_ParseTuple(args, "y*O!I|:sendmsg", &dbuf, &PyList_Type,
+ &control, &flags)) {
+ return NULL;
+ }
+
+ controllen = PyList_Size(control);
+
+ /* set up the msghdr struct
+ count the bytes to allocate for msg_control */
+ for (i=0; i