mirror of https://git.kore.io/kore.git
Support recvfrom()/sendto() on kore python sockets.
This commit is contained in:
parent
7aa17df4a1
commit
b07cc0237c
|
@ -164,14 +164,18 @@ static PyObject *pysocket_send(struct pysocket *, PyObject *);
|
||||||
static PyObject *pysocket_recv(struct pysocket *, PyObject *);
|
static PyObject *pysocket_recv(struct pysocket *, PyObject *);
|
||||||
static PyObject *pysocket_close(struct pysocket *, PyObject *);
|
static PyObject *pysocket_close(struct pysocket *, PyObject *);
|
||||||
static PyObject *pysocket_accept(struct pysocket *, PyObject *);
|
static PyObject *pysocket_accept(struct pysocket *, PyObject *);
|
||||||
|
static PyObject *pysocket_sendto(struct pysocket *, PyObject *);
|
||||||
static PyObject *pysocket_connect(struct pysocket *, PyObject *);
|
static PyObject *pysocket_connect(struct pysocket *, PyObject *);
|
||||||
|
static PyObject *pysocket_recvfrom(struct pysocket *, PyObject *);
|
||||||
|
|
||||||
static PyMethodDef pysocket_methods[] = {
|
static PyMethodDef pysocket_methods[] = {
|
||||||
METHOD("recv", pysocket_recv, METH_VARARGS),
|
METHOD("recv", pysocket_recv, METH_VARARGS),
|
||||||
METHOD("send", pysocket_send, METH_VARARGS),
|
METHOD("send", pysocket_send, METH_VARARGS),
|
||||||
METHOD("close", pysocket_close, METH_NOARGS),
|
METHOD("close", pysocket_close, METH_NOARGS),
|
||||||
METHOD("accept", pysocket_accept, METH_NOARGS),
|
METHOD("accept", pysocket_accept, METH_NOARGS),
|
||||||
|
METHOD("sendto", pysocket_sendto, METH_VARARGS),
|
||||||
METHOD("connect", pysocket_connect, METH_VARARGS),
|
METHOD("connect", pysocket_connect, METH_VARARGS),
|
||||||
|
METHOD("recvfrom", pysocket_recvfrom, METH_VARARGS),
|
||||||
METHOD(NULL, NULL, -1),
|
METHOD(NULL, NULL, -1),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -191,6 +195,8 @@ static PyTypeObject pysocket_type = {
|
||||||
#define PYSOCKET_TYPE_CONNECT 2
|
#define PYSOCKET_TYPE_CONNECT 2
|
||||||
#define PYSOCKET_TYPE_RECV 3
|
#define PYSOCKET_TYPE_RECV 3
|
||||||
#define PYSOCKET_TYPE_SEND 4
|
#define PYSOCKET_TYPE_SEND 4
|
||||||
|
#define PYSOCKET_TYPE_RECVFROM 5
|
||||||
|
#define PYSOCKET_TYPE_SENDTO 6
|
||||||
|
|
||||||
struct pysocket_data {
|
struct pysocket_data {
|
||||||
struct kore_event evt;
|
struct kore_event evt;
|
||||||
|
@ -202,6 +208,7 @@ struct pysocket_data {
|
||||||
int state;
|
int state;
|
||||||
size_t length;
|
size_t length;
|
||||||
struct kore_buf buffer;
|
struct kore_buf buffer;
|
||||||
|
struct sockaddr_in sendaddr;
|
||||||
struct pysocket *socket;
|
struct pysocket *socket;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
115
src/python.c
115
src/python.c
|
@ -1617,6 +1617,40 @@ pysocket_send(struct pysocket *sock, PyObject *args)
|
||||||
return (pysocket_op_create(sock, PYSOCKET_TYPE_SEND, buf.buf, buf.len));
|
return (pysocket_op_create(sock, PYSOCKET_TYPE_SEND, buf.buf, buf.len));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
pysocket_sendto(struct pysocket *sock, PyObject *args)
|
||||||
|
{
|
||||||
|
Py_buffer buf;
|
||||||
|
struct pysocket_op *op;
|
||||||
|
const char *ip;
|
||||||
|
PyObject *ret;
|
||||||
|
int port;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (port <= 0 || port >= USHRT_MAX) {
|
||||||
|
PyErr_SetString(PyExc_RuntimeError, "invalid port");
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = pysocket_op_create(sock, PYSOCKET_TYPE_SENDTO, buf.buf, buf.len);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
pysocket_recv(struct pysocket *sock, PyObject *args)
|
pysocket_recv(struct pysocket *sock, PyObject *args)
|
||||||
{
|
{
|
||||||
|
@ -1628,6 +1662,23 @@ pysocket_recv(struct pysocket *sock, PyObject *args)
|
||||||
return (pysocket_op_create(sock, PYSOCKET_TYPE_RECV, NULL, len));
|
return (pysocket_op_create(sock, PYSOCKET_TYPE_RECV, NULL, len));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
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);
|
||||||
|
|
||||||
|
return (pysocket_op_create(sock, PYSOCKET_TYPE_RECVFROM, NULL, len));
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
pysocket_accept(struct pysocket *sock, PyObject *args)
|
pysocket_accept(struct pysocket *sock, PyObject *args)
|
||||||
{
|
{
|
||||||
|
@ -1708,9 +1759,11 @@ pysocket_op_dealloc(struct pysocket_op *op)
|
||||||
switch (op->data.type) {
|
switch (op->data.type) {
|
||||||
case PYSOCKET_TYPE_RECV:
|
case PYSOCKET_TYPE_RECV:
|
||||||
case PYSOCKET_TYPE_ACCEPT:
|
case PYSOCKET_TYPE_ACCEPT:
|
||||||
|
case PYSOCKET_TYPE_RECVFROM:
|
||||||
kore_platform_disable_read(op->data.fd);
|
kore_platform_disable_read(op->data.fd);
|
||||||
break;
|
break;
|
||||||
case PYSOCKET_TYPE_SEND:
|
case PYSOCKET_TYPE_SEND:
|
||||||
|
case PYSOCKET_TYPE_SENDTO:
|
||||||
case PYSOCKET_TYPE_CONNECT:
|
case PYSOCKET_TYPE_CONNECT:
|
||||||
kore_platform_disable_write(op->data.fd);
|
kore_platform_disable_write(op->data.fd);
|
||||||
break;
|
break;
|
||||||
|
@ -1720,6 +1773,7 @@ pysocket_op_dealloc(struct pysocket_op *op)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (op->data.type == PYSOCKET_TYPE_RECV ||
|
if (op->data.type == PYSOCKET_TYPE_RECV ||
|
||||||
|
op->data.type == PYSOCKET_TYPE_RECVFROM ||
|
||||||
op->data.type == PYSOCKET_TYPE_SEND)
|
op->data.type == PYSOCKET_TYPE_SEND)
|
||||||
kore_buf_cleanup(&op->data.buffer);
|
kore_buf_cleanup(&op->data.buffer);
|
||||||
|
|
||||||
|
@ -1768,11 +1822,13 @@ pysocket_op_create(struct pysocket *sock, int type, const void *ptr, size_t len)
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case PYSOCKET_TYPE_RECV:
|
case PYSOCKET_TYPE_RECV:
|
||||||
|
case PYSOCKET_TYPE_RECVFROM:
|
||||||
op->data.evt.flags |= KORE_EVENT_READ;
|
op->data.evt.flags |= KORE_EVENT_READ;
|
||||||
kore_buf_init(&op->data.buffer, len);
|
kore_buf_init(&op->data.buffer, len);
|
||||||
kore_platform_schedule_read(op->data.fd, &op->data);
|
kore_platform_schedule_read(op->data.fd, &op->data);
|
||||||
break;
|
break;
|
||||||
case PYSOCKET_TYPE_SEND:
|
case PYSOCKET_TYPE_SEND:
|
||||||
|
case PYSOCKET_TYPE_SENDTO:
|
||||||
op->data.evt.flags |= KORE_EVENT_WRITE;
|
op->data.evt.flags |= KORE_EVENT_WRITE;
|
||||||
kore_buf_init(&op->data.buffer, len);
|
kore_buf_init(&op->data.buffer, len);
|
||||||
kore_buf_append(&op->data.buffer, ptr, len);
|
kore_buf_append(&op->data.buffer, ptr, len);
|
||||||
|
@ -1832,9 +1888,11 @@ pysocket_op_iternext(struct pysocket_op *op)
|
||||||
ret = pysocket_async_accept(op);
|
ret = pysocket_async_accept(op);
|
||||||
break;
|
break;
|
||||||
case PYSOCKET_TYPE_RECV:
|
case PYSOCKET_TYPE_RECV:
|
||||||
|
case PYSOCKET_TYPE_RECVFROM:
|
||||||
ret = pysocket_async_recv(op);
|
ret = pysocket_async_recv(op);
|
||||||
break;
|
break;
|
||||||
case PYSOCKET_TYPE_SEND:
|
case PYSOCKET_TYPE_SEND:
|
||||||
|
case PYSOCKET_TYPE_SENDTO:
|
||||||
ret = pysocket_async_send(op);
|
ret = pysocket_async_send(op);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1907,16 +1965,27 @@ static PyObject *
|
||||||
pysocket_async_recv(struct pysocket_op *op)
|
pysocket_async_recv(struct pysocket_op *op)
|
||||||
{
|
{
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
const char *ptr;
|
u_int16_t port;
|
||||||
PyObject *bytes;
|
socklen_t socklen;
|
||||||
|
const char *ptr, *ip;
|
||||||
|
PyObject *bytes, *result, *tuple;
|
||||||
|
|
||||||
if (!(op->data.evt.flags & KORE_EVENT_READ)) {
|
if (!(op->data.evt.flags & KORE_EVENT_READ)) {
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
ret = read(op->data.fd, op->data.buffer.data,
|
if (op->data.type == PYSOCKET_TYPE_RECV) {
|
||||||
op->data.buffer.length);
|
ret = read(op->data.fd, op->data.buffer.data,
|
||||||
|
op->data.buffer.length);
|
||||||
|
} else {
|
||||||
|
socklen = sizeof(op->data.sendaddr);
|
||||||
|
ret = recvfrom(op->data.fd, op->data.buffer.data,
|
||||||
|
op->data.buffer.length, 0,
|
||||||
|
(struct sockaddr *)&op->data.sendaddr,
|
||||||
|
&socklen);
|
||||||
|
}
|
||||||
|
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
|
@ -1931,19 +2000,36 @@ pysocket_async_recv(struct pysocket_op *op)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret == 0) {
|
if (op->data.type == PYSOCKET_TYPE_RECV && ret == 0) {
|
||||||
PyErr_SetNone(PyExc_StopIteration);
|
PyErr_SetNone(PyExc_StopIteration);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr = (const char *)op->data.buffer.data;
|
ptr = (const char *)op->data.buffer.data;
|
||||||
|
if ((bytes = PyBytes_FromStringAndSize(ptr, ret)) == NULL)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
bytes = PyBytes_FromStringAndSize(ptr, ret);
|
if (op->data.type == PYSOCKET_TYPE_RECV) {
|
||||||
if (bytes != NULL) {
|
|
||||||
PyErr_SetObject(PyExc_StopIteration, bytes);
|
PyErr_SetObject(PyExc_StopIteration, bytes);
|
||||||
Py_DECREF(bytes);
|
Py_DECREF(bytes);
|
||||||
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
port = ntohs(op->data.sendaddr.sin_port);
|
||||||
|
ip = inet_ntoa(op->data.sendaddr.sin_addr);
|
||||||
|
|
||||||
|
if ((tuple = Py_BuildValue("(sHN)", ip, port, bytes)) == NULL)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
result = PyObject_CallFunctionObjArgs(PyExc_StopIteration, tuple, NULL);
|
||||||
|
if (result == NULL) {
|
||||||
|
Py_DECREF(tuple);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyErr_SetObject(PyExc_StopIteration, result);
|
||||||
|
Py_DECREF(result);
|
||||||
|
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1957,9 +2043,18 @@ pysocket_async_send(struct pysocket_op *op)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
ret = write(op->data.fd,
|
if (op->data.type == PYSOCKET_TYPE_SEND) {
|
||||||
op->data.buffer.data + op->data.buffer.offset,
|
ret = write(op->data.fd,
|
||||||
op->data.buffer.length - op->data.buffer.offset);
|
op->data.buffer.data + op->data.buffer.offset,
|
||||||
|
op->data.buffer.length - op->data.buffer.offset);
|
||||||
|
} else {
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
|
|
Loading…
Reference in New Issue