kore

a fork of the worlds most advanced web framework
Log | Files | Refs | README | LICENSE

commit 01c1a8f8f84a91b17babf4f064014314cf60bb90
parent 2057f4db58321785340ebdb2637cb0b11c8b1f73
Author: Erik Karlsson <erik.karlsson@tutus.se>
Date:   Thu, 28 Feb 2019 14:45:56 +0100

support AF_UNIX in recvfrom()/sendto() python sockets

Diffstat:
Minclude/kore/python_methods.h | 5++++-
Msrc/python.c | 111+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
2 files changed, 87 insertions(+), 29 deletions(-)

diff --git a/include/kore/python_methods.h b/include/kore/python_methods.h @@ -208,7 +208,10 @@ struct pysocket_data { int state; size_t length; struct kore_buf buffer; - struct sockaddr_in sendaddr; + union { + struct sockaddr_in ipv4; + struct sockaddr_un sun; + } sendaddr; struct pysocket *socket; struct kore_timer *timer; }; diff --git a/src/python.c b/src/python.c @@ -1672,21 +1672,27 @@ pysocket_sendto(struct pysocket *sock, PyObject *args) { Py_buffer buf; struct pysocket_op *op; - const char *ip; PyObject *ret; int port; + const char *ip, *sockaddr; - if (sock->family != AF_INET) { - PyErr_SetString(PyExc_RuntimeError, - "sendto only supported on AF_INET sockets"); - return (NULL); - } - - if (!PyArg_ParseTuple(args, "siy*", &ip, &port, &buf)) - return (NULL); + switch (sock->family) { + case AF_INET: + if (!PyArg_ParseTuple(args, "siy*", &ip, &port, &buf)) + return (NULL); - if (port <= 0 || port >= USHRT_MAX) { - PyErr_SetString(PyExc_RuntimeError, "invalid port"); + if (port <= 0 || port >= USHRT_MAX) { + PyErr_SetString(PyExc_RuntimeError, "invalid port"); + return (NULL); + } + break; + + case AF_UNIX: + if (!PyArg_ParseTuple(args, "sy*", &sockaddr, &buf)) + return (NULL); + break; + default: + PyErr_SetString(PyExc_RuntimeError, "unsupported family"); return (NULL); } @@ -1694,9 +1700,23 @@ pysocket_sendto(struct pysocket *sock, PyObject *args) op = (struct pysocket_op *)ret; - op->data.sendaddr.sin_family = AF_INET; - op->data.sendaddr.sin_port = htons(port); - op->data.sendaddr.sin_addr.s_addr = inet_addr(ip); + switch (sock->family) { + case AF_INET: + op->data.sendaddr.ipv4.sin_family = AF_INET; + op->data.sendaddr.ipv4.sin_port = htons(port); + op->data.sendaddr.ipv4.sin_addr.s_addr = inet_addr(ip); + break; + case AF_UNIX: + op->data.sendaddr.sun.sun_family = AF_UNIX; + size_t maxwrite = sizeof(op->data.sendaddr.sun.sun_path); + if(kore_strlcpy(op->data.sendaddr.sun.sun_path, sockaddr, + maxwrite) >= maxwrite) + fatal("pysocket_sendto: failed to write path"); + break; + default: + PyErr_SetString(PyExc_RuntimeError, "unsupported family"); + return (NULL); + } return (ret); } @@ -1733,12 +1753,6 @@ pysocket_recvfrom(struct pysocket *sock, PyObject *args) { Py_ssize_t len; - if (sock->family != AF_INET) { - PyErr_SetString(PyExc_RuntimeError, - "recvfrom only supported on AF_INET sockets"); - return (NULL); - } - if (!PyArg_ParseTuple(args, "n", &len)) return (NULL); @@ -2056,6 +2070,7 @@ pysocket_async_recv(struct pysocket_op *op) ssize_t ret; u_int16_t port; socklen_t socklen; + struct sockaddr *sendaddr; const char *ptr, *ip; PyObject *bytes, *result, *tuple; @@ -2068,10 +2083,23 @@ pysocket_async_recv(struct pysocket_op *op) ret = read(op->data.fd, op->data.buffer.data, op->data.buffer.length); } else { - socklen = sizeof(op->data.sendaddr); + switch(op->data.socket->family) { + case AF_INET: + socklen = sizeof(op->data.sendaddr.ipv4); + sendaddr = (struct sockaddr *)&op->data.sendaddr.ipv4; + break; + case AF_UNIX: + socklen = sizeof(op->data.sendaddr.sun); + sendaddr = (struct sockaddr *)&op->data.sendaddr.sun; + break; + default: + PyErr_SetString(PyExc_RuntimeError, "Unsupported family"); + return (NULL); + } + ret = recvfrom(op->data.fd, op->data.buffer.data, op->data.buffer.length, 0, - (struct sockaddr *)&op->data.sendaddr, + sendaddr, &socklen); } @@ -2104,11 +2132,23 @@ pysocket_async_recv(struct pysocket_op *op) return (NULL); } - port = ntohs(op->data.sendaddr.sin_port); - ip = inet_ntoa(op->data.sendaddr.sin_addr); + switch(op->data.socket->family) { + case AF_INET: + port = ntohs(op->data.sendaddr.ipv4.sin_port); + ip = inet_ntoa(op->data.sendaddr.ipv4.sin_addr); - if ((tuple = Py_BuildValue("(sHN)", ip, port, bytes)) == NULL) + if ((tuple = Py_BuildValue("(sHN)", ip, port, bytes)) == NULL) + return (NULL); + break; + case AF_UNIX: + if ((tuple = Py_BuildValue("(sN)", + op->data.sendaddr.sun.sun_path, bytes)) == NULL) + return (NULL); + break; + default: + PyErr_SetString(PyExc_RuntimeError, "Unsupported family"); return (NULL); + } result = PyObject_CallFunctionObjArgs(PyExc_StopIteration, tuple, NULL); if (result == NULL) { @@ -2125,7 +2165,9 @@ pysocket_async_recv(struct pysocket_op *op) static PyObject * pysocket_async_send(struct pysocket_op *op) { - ssize_t ret; + ssize_t ret; + const struct sockaddr *sendaddr; + socklen_t socklen; if (!(op->data.evt.flags & KORE_EVENT_WRITE)) { Py_RETURN_NONE; @@ -2137,11 +2179,24 @@ pysocket_async_send(struct pysocket_op *op) op->data.buffer.data + op->data.buffer.offset, op->data.buffer.length - op->data.buffer.offset); } else { + switch(op->data.socket->family) { + case AF_INET: + socklen = sizeof(op->data.sendaddr.ipv4); + sendaddr = (struct sockaddr *)&op->data.sendaddr.ipv4; + break; + case AF_UNIX: + socklen = sizeof(op->data.sendaddr.sun); + sendaddr = (struct sockaddr *)&op->data.sendaddr.sun; + break; + default: + PyErr_SetString(PyExc_RuntimeError, "unsupported family"); + return (NULL); + } + ret = sendto(op->data.fd, op->data.buffer.data + op->data.buffer.offset, op->data.buffer.length - op->data.buffer.offset, - 0, (const struct sockaddr *)&op->data.sendaddr, - sizeof(op->data.sendaddr)); + 0, sendaddr, socklen); } if (ret == -1) {