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:
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) {