aboutsummaryrefslogtreecommitdiff
path: root/src/supplemental/websocket/websocket.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/supplemental/websocket/websocket.c')
-rw-r--r--src/supplemental/websocket/websocket.c229
1 files changed, 208 insertions, 21 deletions
diff --git a/src/supplemental/websocket/websocket.c b/src/supplemental/websocket/websocket.c
index df4a0834..44117f7b 100644
--- a/src/supplemental/websocket/websocket.c
+++ b/src/supplemental/websocket/websocket.c
@@ -28,7 +28,7 @@ typedef int (*nni_ws_listen_hook)(void *, nng_http_req *, nng_http_res *);
// We have chosen to be a bit more stringent in the size of the frames that
// we send, while we more generously allow larger incoming frames. These
// may be tuned by options.
-#define WS_DEF_RECVMAX (1U << 20) // 1MB Message limit (message mode only)
+#define WS_DEF_RECVMAX (1U << 20) // 1MB Message limit (message mode only)
#define WS_DEF_MAXRXFRAME (1U << 20) // 1MB Frame size (recv)
#define WS_DEF_MAXTXFRAME (1U << 16) // 64KB Frame size (send)
@@ -54,6 +54,8 @@ struct nni_ws {
bool wclose;
bool isstream;
bool inmsg;
+ bool send_text;
+ bool recv_text;
nni_mtx mtx;
nni_list sendq;
nni_list recvq;
@@ -92,6 +94,8 @@ struct nni_ws_listener {
bool started;
bool closed;
bool isstream;
+ bool send_text;
+ bool recv_text;
nni_http_handler * handler;
nni_ws_listen_hook hookfn;
void * hookarg;
@@ -119,6 +123,8 @@ struct nni_ws_dialer {
nni_list wspend; // ws structures still negotiating
bool closed;
bool isstream;
+ bool send_text;
+ bool recv_text;
nni_list headers; // request headers
size_t maxframe;
size_t fragsize;
@@ -455,7 +461,7 @@ ws_frame_prep_tx(nni_ws *ws, ws_frame *frame)
return (NNG_ENOMEM);
}
frame->asize = frame->len;
- frame->buf = frame->adata;
+ frame->buf = frame->adata;
}
buf = frame->buf;
@@ -474,7 +480,11 @@ ws_frame_prep_tx(nni_ws *ws, ws_frame *frame)
if (nni_aio_count(aio) == 0) {
// This is the first frame.
- frame->op = WS_BINARY;
+ if (ws->send_text) {
+ frame->op = WS_TEXT;
+ } else {
+ frame->op = WS_BINARY;
+ }
} else {
frame->op = WS_CONT;
}
@@ -944,6 +954,12 @@ ws_read_frame_cb(nni_ws *ws, ws_frame *frame)
ws->rxframe = NULL;
nni_list_append(&ws->rxq, frame);
break;
+ case WS_TEXT:
+ if (!ws->recv_text) {
+ // No support for text mode at present.
+ ws_close(ws, WS_CLOSE_UNSUPP_FORMAT);
+ }
+ // FALLTHROUGH
case WS_BINARY:
if (ws->inmsg) {
ws_close(ws, WS_CLOSE_PROTOCOL_ERR);
@@ -955,10 +971,6 @@ ws_read_frame_cb(nni_ws *ws, ws_frame *frame)
ws->rxframe = NULL;
nni_list_append(&ws->rxq, frame);
break;
- case WS_TEXT:
- // No support for text mode at present.
- ws_close(ws, WS_CLOSE_UNSUPP_FORMAT);
- return;
case WS_PING:
if (frame->len > 125) {
@@ -1120,7 +1132,7 @@ ws_read_cb(void *arg)
return;
}
frame->asize = frame->len;
- frame->buf = frame->adata;
+ frame->buf = frame->adata;
}
iov.iov_buf = frame->buf;
@@ -1624,14 +1636,16 @@ ws_handler(nni_aio *aio)
status = NNG_HTTP_STATUS_INTERNAL_SERVER_ERROR;
goto err;
}
- ws->http = conn;
- ws->req = req;
- ws->res = res;
- ws->server = true;
- ws->maxframe = l->maxframe;
- ws->fragsize = l->fragsize;
- ws->recvmax = l->recvmax;
- ws->isstream = l->isstream;
+ ws->http = conn;
+ ws->req = req;
+ ws->res = res;
+ ws->server = true;
+ ws->maxframe = l->maxframe;
+ ws->fragsize = l->fragsize;
+ ws->recvmax = l->recvmax;
+ ws->isstream = l->isstream;
+ ws->recv_text = l->recv_text;
+ ws->send_text = l->send_text;
nni_list_append(&l->reply, ws);
nni_aio_set_data(ws->httpaio, 0, l);
@@ -1907,6 +1921,58 @@ ws_listener_set_msgmode(void *arg, const void *buf, size_t sz, nni_type t)
}
static int
+ws_listener_set_recv_text(void *arg, const void *buf, size_t sz, nni_type t)
+{
+ nni_ws_listener *l = arg;
+ int rv;
+ bool b;
+
+ if ((rv = nni_copyin_bool(&b, buf, sz, t)) == 0) {
+ nni_mtx_lock(&l->mtx);
+ l->recv_text = b;
+ nni_mtx_unlock(&l->mtx);
+ }
+ return (rv);
+}
+
+static int
+ws_listener_set_send_text(void *arg, const void *buf, size_t sz, nni_type t)
+{
+ nni_ws_listener *l = arg;
+ int rv;
+ bool b;
+
+ if ((rv = nni_copyin_bool(&b, buf, sz, t)) == 0) {
+ nni_mtx_lock(&l->mtx);
+ l->send_text = b;
+ nni_mtx_unlock(&l->mtx);
+ }
+ return (rv);
+}
+
+static int
+ws_listener_get_recv_text(void *arg, void *buf, size_t *szp, nni_type t)
+{
+ nni_ws_listener *l = arg;
+ int rv;
+ nni_mtx_lock(&l->mtx);
+ rv = nni_copyout_bool(l->recv_text, buf, szp, t);
+ nni_mtx_unlock(&l->mtx);
+ return (rv);
+}
+
+static int
+ws_listener_get_send_text(void *arg, void *buf, size_t *szp, nni_type t)
+{
+ nni_ws_listener *l = arg;
+ int rv;
+ nni_mtx_lock(&l->mtx);
+ rv = nni_copyout_bool(l->send_text, buf, szp, t);
+ nni_mtx_unlock(&l->mtx);
+ return (rv);
+}
+
+static int
ws_listener_get_url(void *arg, void *buf, size_t *szp, nni_type t)
{
nni_ws_listener *l = arg;
@@ -1953,6 +2019,16 @@ static const nni_option ws_listener_options[] = {
.o_get = ws_listener_get_url,
},
{
+ .o_name = NNG_OPT_WS_RECV_TEXT,
+ .o_set = ws_listener_set_recv_text,
+ .o_get = ws_listener_get_recv_text,
+ },
+ {
+ .o_name = NNG_OPT_WS_SEND_TEXT,
+ .o_set = ws_listener_set_send_text,
+ .o_get = ws_listener_get_send_text,
+ },
+ {
.o_name = NULL,
},
};
@@ -2245,11 +2321,13 @@ ws_dialer_dial(void *arg, nni_aio *aio)
ws_reap(ws);
return;
}
- ws->dialer = d;
- ws->useraio = aio;
- ws->server = false;
- ws->maxframe = d->maxframe;
- ws->isstream = d->isstream;
+ ws->dialer = d;
+ ws->useraio = aio;
+ ws->server = false;
+ ws->maxframe = d->maxframe;
+ ws->isstream = d->isstream;
+ ws->recv_text = d->recv_text;
+ ws->send_text = d->send_text;
nni_list_append(&d->wspend, ws);
nni_http_client_connect(d->client, ws->connaio);
nni_mtx_unlock(&d->mtx);
@@ -2271,6 +2349,36 @@ ws_dialer_set_msgmode(void *arg, const void *buf, size_t sz, nni_type t)
}
static int
+ws_dialer_set_recv_text(void *arg, const void *buf, size_t sz, nni_type t)
+{
+ nni_ws_dialer *d = arg;
+ int rv;
+ bool b;
+
+ if ((rv = nni_copyin_bool(&b, buf, sz, t)) == 0) {
+ nni_mtx_lock(&d->mtx);
+ d->recv_text = b;
+ nni_mtx_unlock(&d->mtx);
+ }
+ return (rv);
+}
+
+static int
+ws_dialer_set_send_text(void *arg, const void *buf, size_t sz, nni_type t)
+{
+ nni_ws_dialer *d = arg;
+ int rv;
+ bool b;
+
+ if ((rv = nni_copyin_bool(&b, buf, sz, t)) == 0) {
+ nni_mtx_lock(&d->mtx);
+ d->send_text = b;
+ nni_mtx_unlock(&d->mtx);
+ }
+ return (rv);
+}
+
+static int
ws_dialer_set_size(
nni_ws_dialer *d, size_t *valp, const void *buf, size_t sz, nni_type t)
{
@@ -2388,6 +2496,28 @@ ws_dialer_get_proto(void *arg, void *buf, size_t *szp, nni_type t)
return (rv);
}
+static int
+ws_dialer_get_recv_text(void *arg, void *buf, size_t *szp, nni_type t)
+{
+ nni_ws_dialer *d = arg;
+ int rv;
+ nni_mtx_lock(&d->mtx);
+ rv = nni_copyout_bool(d->recv_text, buf, szp, t);
+ nni_mtx_unlock(&d->mtx);
+ return (rv);
+}
+
+static int
+ws_dialer_get_send_text(void *arg, void *buf, size_t *szp, nni_type t)
+{
+ nni_ws_dialer *d = arg;
+ int rv;
+ nni_mtx_lock(&d->mtx);
+ rv = nni_copyout_bool(d->send_text, buf, szp, t);
+ nni_mtx_unlock(&d->mtx);
+ return (rv);
+}
+
static const nni_option ws_dialer_options[] = {
{
.o_name = NNI_OPT_WS_MSGMODE,
@@ -2419,6 +2549,17 @@ static const nni_option ws_dialer_options[] = {
.o_get = ws_dialer_get_proto,
},
{
+ .o_name = NNG_OPT_WS_RECV_TEXT,
+ .o_set = ws_dialer_set_recv_text,
+ .o_get = ws_dialer_get_recv_text,
+ },
+ {
+ .o_name = NNG_OPT_WS_SEND_TEXT,
+ .o_set = ws_dialer_set_send_text,
+ .o_get = ws_dialer_get_send_text,
+ },
+
+ {
.o_name = NULL,
},
};
@@ -2649,6 +2790,30 @@ ws_get_request_uri(void *arg, void *buf, size_t *szp, nni_type t)
return (nni_copyout_str(nni_http_req_get_uri(ws->req), buf, szp, t));
}
+static int
+ws_get_recv_text(void *arg, void *buf, size_t *szp, nni_type t)
+{
+ nni_ws *ws = arg;
+ bool b;
+ nni_mtx_lock(&ws->mtx);
+ b = ws->recv_text;
+ nni_mtx_unlock(&ws->mtx);
+
+ return (nni_copyout_bool(b, buf, szp, t));
+}
+
+static int
+ws_get_send_text(void *arg, void *buf, size_t *szp, nni_type t)
+{
+ nni_ws *ws = arg;
+ bool b;
+ nni_mtx_lock(&ws->mtx);
+ b = ws->send_text;
+ nni_mtx_unlock(&ws->mtx);
+
+ return (nni_copyout_bool(b, buf, szp, t));
+}
+
static const nni_option ws_options[] = {
{
.o_name = NNG_OPT_WS_REQUEST_HEADERS,
@@ -2663,6 +2828,14 @@ static const nni_option ws_options[] = {
.o_get = ws_get_request_uri,
},
{
+ .o_name = NNG_OPT_WS_RECV_TEXT,
+ .o_get = ws_get_recv_text,
+ },
+ {
+ .o_name = NNG_OPT_WS_SEND_TEXT,
+ .o_get = ws_get_send_text,
+ },
+ {
.o_name = NULL,
},
};
@@ -2753,6 +2926,12 @@ ws_check_size(const void *buf, size_t sz, nni_type t)
return (nni_copyin_size(NULL, buf, sz, 0, NNI_MAXSZ, t));
}
+static int
+ws_check_bool(const void *buf, size_t sz, nni_type t)
+{
+ return (nni_copyin_size(NULL, buf, sz, 0, NNI_MAXSZ, t));
+}
+
static const nni_chkoption ws_chkopts[] = {
{
.o_name = NNG_OPT_WS_SENDMAXFRAME,
@@ -2779,6 +2958,14 @@ static const nni_chkoption ws_chkopts[] = {
.o_check = ws_check_string,
},
{
+ .o_name = NNG_OPT_WS_RECV_TEXT,
+ .o_check = ws_check_bool,
+ },
+ {
+ .o_name = NNG_OPT_WS_SEND_TEXT,
+ .o_check = ws_check_bool,
+ },
+ {
.o_name = NULL,
},
};