kore

Kore is a web application platform for writing scalable, concurrent web based processes in C or Python.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

commit ffbabed7d6cf8488e9000fee703d7ab70fa6a8ed
parent 4a56424842d71403a8119006dc653b0a859b0c0e
Author: Joris Vink <joris@coders.se>
Date:   Mon, 13 Mar 2017 13:30:57 +0100

Move websocket_send() to pyconnection.

While here convert all instances of y* for incoming binary data to y#
since we won't be changing it at all and avoids some unneeded copying.

Diffstat:
includes/python_methods.h | 4++--
src/python.c | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
2 files changed, 71 insertions(+), 32 deletions(-)

diff --git a/includes/python_methods.h b/includes/python_methods.h @@ -22,7 +22,6 @@ static PyObject *python_kore_listen(PyObject *, PyObject *); static PyObject *python_kore_pgsql_register(PyObject *, PyObject *); #endif -static PyObject *python_websocket_send(PyObject *, PyObject *); static PyObject *python_websocket_broadcast(PyObject *, PyObject *); #define METHOD(n, c, a) { n, (PyCFunction)c, a, NULL } @@ -34,7 +33,6 @@ static struct PyMethodDef pykore_methods[] = { METHOD("log", python_kore_log, METH_VARARGS), METHOD("fatal", python_kore_fatal, METH_VARARGS), METHOD("listen", python_kore_listen, METH_VARARGS), - METHOD("websocket_send", python_websocket_send, METH_VARARGS), METHOD("websocket_broadcast", python_websocket_broadcast, METH_VARARGS), #if defined(KORE_USE_PGSQL) METHOD("register_database", python_kore_pgsql_register, METH_VARARGS), @@ -52,9 +50,11 @@ struct pyconnection { }; static PyObject *pyconnection_disconnect(struct pyconnection *, PyObject *); +static PyObject *pyconnection_websocket_send(struct pyconnection *, PyObject *); static PyMethodDef pyconnection_methods[] = { METHOD("disconnect", pyconnection_disconnect, METH_NOARGS), + METHOD("websocket_send", pyconnection_websocket_send, METH_VARARGS), METHOD(NULL, NULL, -1), }; diff --git a/src/python.c b/src/python.c @@ -728,16 +728,22 @@ pyhttp_file_alloc(struct http_file *file) static PyObject * pyhttp_response(struct pyhttp_request *pyreq, PyObject *args) { - Py_buffer body; - int status; + const char *body; + int status, len; - if (!PyArg_ParseTuple(args, "iy*", &status, &body)) { + len = -1; + + if (!PyArg_ParseTuple(args, "iy#", &status, &body, &len)) { PyErr_SetString(PyExc_TypeError, "invalid parameters"); return (NULL); } - http_response(pyreq->req, status, body.buf, body.len); - PyBuffer_Release(&body); + if (len < 0) { + PyErr_SetString(PyExc_TypeError, "invalid length"); + return (NULL); + } + + http_response(pyreq->req, status, body, len); Py_RETURN_TRUE; } @@ -965,24 +971,77 @@ pyhttp_websocket_handshake(struct pyhttp_request *pyreq, PyObject *args) } static PyObject * +pyconnection_websocket_send(struct pyconnection *pyc, PyObject *args) +{ + const char *data; + int op, len; + + if (pyc->c->proto != CONN_PROTO_WEBSOCKET) { + PyErr_SetString(PyExc_TypeError, "not a websocket connection"); + return (NULL); + } + + len = -1; + + if (!PyArg_ParseTuple(args, "iy#", &op, &data, &len)) { + PyErr_SetString(PyExc_TypeError, "invalid parameters"); + return (NULL); + } + + if (len < 0) { + PyErr_SetString(PyExc_TypeError, "invalid length"); + return (NULL); + } + + switch (op) { + case WEBSOCKET_OP_TEXT: + case WEBSOCKET_OP_BINARY: + break; + default: + PyErr_SetString(PyExc_TypeError, "invalid op parameter"); + return (NULL); + } + + kore_websocket_send(pyc->c, op, data, len); + + Py_RETURN_TRUE; +} + +static PyObject * python_websocket_broadcast(PyObject *self, PyObject *args) { struct connection *c; struct pyconnection *pyc; - Py_buffer data; + const char *data; PyObject *pysrc; - int op, broadcast; + int op, broadcast, len; + + len = -1; - if (!PyArg_ParseTuple(args, "Oiy*i", &pysrc, &op, &data, &broadcast)) { + if (!PyArg_ParseTuple(args, "Oiy#i", &pysrc, &op, &data, &len, + &broadcast)) { PyErr_SetString(PyExc_TypeError, "invalid parameters"); return (NULL); } + if (len < 0) { + PyErr_SetString(PyExc_TypeError, "invalid length"); + return (NULL); + } + + switch (op) { + case WEBSOCKET_OP_TEXT: + case WEBSOCKET_OP_BINARY: + break; + default: + PyErr_SetString(PyExc_TypeError, "invalid op parameter"); + return (NULL); + } + if (pysrc == Py_None) { c = NULL; } else { if (!PyObject_TypeCheck(pysrc, &pyconnection_type)) { - PyBuffer_Release(&data); PyErr_SetString(PyExc_TypeError, "invalid parameters"); return (NULL); } @@ -990,27 +1049,7 @@ python_websocket_broadcast(PyObject *self, PyObject *args) c = pyc->c; } - kore_websocket_broadcast(c, op, data.buf, data.len, broadcast); - PyBuffer_Release(&data); - - Py_RETURN_TRUE; -} - -static PyObject * -python_websocket_send(PyObject *self, PyObject *args) -{ - int op; - struct pyconnection *pyc; - Py_buffer data; - - if (!PyArg_ParseTuple(args, "O!iy*", - &pyconnection_type, &pyc, &op, &data)) { - PyErr_SetString(PyExc_TypeError, "invalid parameters"); - return (NULL); - } - - kore_websocket_send(pyc->c, op, data.buf, data.len); - PyBuffer_Release(&data); + kore_websocket_broadcast(c, op, data, len, broadcast); Py_RETURN_TRUE; }