diff --git a/core/websockets.c b/core/websockets.c index f4f629ec..bdb8ad12 100644 --- a/core/websockets.c +++ b/core/websockets.c @@ -80,6 +80,19 @@ static int uwsgi_websocket_send_do(struct wsgi_request *wsgi_req, char *msg, siz return uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos); } +static int uwsgi_websocket_send_from_sharedarea_do(struct wsgi_request *wsgi_req, int id, uint64_t pos, uint64_t len, uint8_t opcode) { + struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos); + if (!sa) return -1; + if (!len) len = ((sa->max_pos+1)-pos); + uwsgi_rlock(sa->lock); + sa->hits++; + struct uwsgi_buffer *ub = uwsgi_websocket_message(wsgi_req, sa->area, len, opcode); + uwsgi_rwunlock(sa->lock); + if (!ub) return -1; + + return uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos); +} + int uwsgi_websocket_send(struct wsgi_request *wsgi_req, char *msg, size_t len) { if (wsgi_req->websocket_closed) { return -1; @@ -91,6 +104,17 @@ int uwsgi_websocket_send(struct wsgi_request *wsgi_req, char *msg, size_t len) { return ret; } +int uwsgi_websocket_send_from_sharedarea(struct wsgi_request *wsgi_req, int id, uint64_t pos, uint64_t len) { + if (wsgi_req->websocket_closed) { + return -1; + } + ssize_t ret = uwsgi_websocket_send_from_sharedarea_do(wsgi_req, id, pos, len, 0x81); + if (ret < 0) { + wsgi_req->websocket_closed = 1; + } + return ret; +} + int uwsgi_websocket_send_binary(struct wsgi_request *wsgi_req, char *msg, size_t len) { if (wsgi_req->websocket_closed) { return -1; @@ -102,6 +126,17 @@ int uwsgi_websocket_send_binary(struct wsgi_request *wsgi_req, char *msg, size_t return ret; } +int uwsgi_websocket_send_binary_from_sharedarea(struct wsgi_request *wsgi_req, int id, uint64_t pos, uint64_t len) { + if (wsgi_req->websocket_closed) { + return -1; + } + ssize_t ret = uwsgi_websocket_send_from_sharedarea_do(wsgi_req, id, pos, len, 0x82); + if (ret < 0) { + wsgi_req->websocket_closed = 1; + } + return ret; +} + static void uwsgi_websocket_parse_header(struct wsgi_request *wsgi_req) { uint8_t byte1 = wsgi_req->websocket_buf->buf[0]; uint8_t byte2 = wsgi_req->websocket_buf->buf[1]; diff --git a/plugins/psgi/uwsgi_plmodule.c b/plugins/psgi/uwsgi_plmodule.c index aaebe3ab..37d83f0a 100644 --- a/plugins/psgi/uwsgi_plmodule.c +++ b/plugins/psgi/uwsgi_plmodule.c @@ -498,6 +498,28 @@ XS(XS_websocket_send) { XSRETURN_UNDEF; } +XS(XS_websocket_send_from_sharedarea) { + dXSARGS; + + psgi_check_args(2); + int id = SvIV(ST(0)); + uint64_t pos = SvIV(ST(1)); + uint64_t len = 0; + + if (items > 2) { + len = SvIV(ST(2)); + } + + struct wsgi_request *wsgi_req = current_wsgi_req(); + + if (uwsgi_websocket_send_from_sharedarea(wsgi_req, id, pos, len)) { + croak("unable to send websocket message from sharedarea"); + } + + XSRETURN_UNDEF; +} + + XS(XS_websocket_send_binary) { dXSARGS; @@ -517,6 +539,28 @@ XS(XS_websocket_send_binary) { XSRETURN_UNDEF; } +XS(XS_websocket_send_binary_from_sharedarea) { + dXSARGS; + + psgi_check_args(2); + int id = SvIV(ST(0)); + uint64_t pos = SvIV(ST(1)); + uint64_t len = 0; + + if (items > 2) { + len = SvIV(ST(2)); + } + + struct wsgi_request *wsgi_req = current_wsgi_req(); + + if (uwsgi_websocket_send_binary_from_sharedarea(wsgi_req, id, pos, len)) { + croak("unable to send websocket binary message from sharedarea"); + } + + XSRETURN_UNDEF; +} + + XS(XS_websocket_recv) { dXSARGS; @@ -726,7 +770,7 @@ XS(XS_sharedarea_read) { croak("unable to read from sharedarea %d", id); XSRETURN_UNDEF; } - len = sa->max_pos+1; + len = (sa->max_pos+1)-pos; } char *buf = uwsgi_malloc(len); @@ -858,7 +902,9 @@ void init_perl_embedded_module() { psgi_xs(websocket_recv); psgi_xs(websocket_recv_nb); psgi_xs(websocket_send); + psgi_xs(websocket_send_from_sharedarea); psgi_xs(websocket_send_binary); + psgi_xs(websocket_send_binary_from_sharedarea); psgi_xs(postfork); psgi_xs(atexit); diff --git a/plugins/python/uwsgi_pymodule.c b/plugins/python/uwsgi_pymodule.c index 862e10e3..aa819d84 100644 --- a/plugins/python/uwsgi_pymodule.c +++ b/plugins/python/uwsgi_pymodule.c @@ -1589,7 +1589,7 @@ PyObject *py_uwsgi_sharedarea_read(PyObject * self, PyObject * args) { if (!sa) { return PyErr_Format(PyExc_ValueError, "error calling uwsgi_sharedarea_read()"); } - len = sa->max_pos+1; + len = (sa->max_pos+1)-pos; } PyObject *ret = PyString_FromStringAndSize(NULL, len); diff --git a/uwsgi.h b/uwsgi.h index bdfcce86..3366efd1 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -4588,6 +4588,8 @@ int uwsgi_sharedarea_dec64(int, uint64_t, int64_t); int uwsgi_sharedarea_wait(int, int, int); struct uwsgi_sharedarea *uwsgi_sharedarea_get_by_id(int, uint64_t); +int uwsgi_websocket_send_from_sharedarea(struct wsgi_request *, int, uint64_t, uint64_t); +int uwsgi_websocket_send_binary_from_sharedarea(struct wsgi_request *, int, uint64_t, uint64_t); void uwsgi_setup(int, char **, char **); int uwsgi_run(void);