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.c105
1 files changed, 101 insertions, 4 deletions
diff --git a/src/supplemental/websocket/websocket.c b/src/supplemental/websocket/websocket.c
index dfcac3e7..53e4af8c 100644
--- a/src/supplemental/websocket/websocket.c
+++ b/src/supplemental/websocket/websocket.c
@@ -23,10 +23,16 @@
typedef struct ws_frame ws_frame;
typedef struct ws_msg ws_msg;
+typedef struct ws_header {
+ nni_list_node node;
+ char * name;
+ char * value;
+} ws_header;
+
struct nni_ws {
- int mode; // NNI_EP_MODE_DIAL or NNI_EP_MODE_LISTEN
nni_list_node node;
nni_reap_item reap;
+ int mode; // NNI_EP_MODE_DIAL or NNI_EP_MODE_LISTEN
bool closed;
bool ready;
bool wclose;
@@ -42,6 +48,8 @@ struct nni_ws {
nni_http * http;
nni_http_req *req;
nni_http_res *res;
+ char * reqhdrs;
+ char * reshdrs;
size_t maxframe;
size_t fragsize;
};
@@ -64,6 +72,7 @@ struct nni_ws_listener {
nni_http_handler handler;
nni_ws_listen_hook hookfn;
void * hookarg;
+ nni_list headers; // response headers
};
// The dialer tracks user aios in two lists. The first list is for aios
@@ -91,6 +100,7 @@ struct nni_ws_dialer {
bool started;
bool closed;
nng_sockaddr sa;
+ nni_list headers; // request headers
};
typedef enum ws_type {
@@ -724,7 +734,6 @@ ws_start_read(nni_ws *ws)
nni_aio_finish_error(wm->aio, NNG_ENOMEM);
}
ws_msg_fini(wm);
- // XXX: NOW WHAT?
return;
}
@@ -1028,6 +1037,28 @@ nni_ws_request(nni_ws *ws)
return (ws->req);
}
+const char *
+nni_ws_request_headers(nni_ws *ws)
+{
+ nni_mtx_lock(&ws->mtx);
+ if (ws->reqhdrs == NULL) {
+ ws->reqhdrs = nni_http_req_headers(ws->req);
+ }
+ nni_mtx_unlock(&ws->mtx);
+ return (ws->reqhdrs);
+}
+
+const char *
+nni_ws_response_headers(nni_ws *ws)
+{
+ nni_mtx_lock(&ws->mtx);
+ if (ws->reshdrs == NULL) {
+ ws->reshdrs = nni_http_res_headers(ws->res);
+ }
+ nni_mtx_unlock(&ws->mtx);
+ return (ws->reshdrs);
+}
+
static void
ws_fini(void *arg)
{
@@ -1075,6 +1106,8 @@ ws_fini(void *arg)
nni_http_res_fini(ws->res);
}
+ nni_strfree(ws->reqhdrs);
+ nni_strfree(ws->reshdrs);
nni_http_fini(ws->http);
nni_aio_fini(ws->rxaio);
nni_aio_fini(ws->txaio);
@@ -1261,12 +1294,20 @@ ws_init(nni_ws **wsp, nni_http *http, nni_http_req *req, nni_http_res *res)
void
nni_ws_listener_fini(nni_ws_listener *l)
{
+ ws_header *hdr;
+
nni_mtx_fini(&l->mtx);
nni_strfree(l->url);
nni_strfree(l->proto);
nni_strfree(l->host);
nni_strfree(l->serv);
nni_strfree(l->path);
+ while ((hdr = nni_list_first(&l->headers)) != NULL) {
+ nni_list_remove(&l->headers, hdr);
+ nni_strfree(hdr->name);
+ nni_strfree(hdr->value);
+ NNI_FREE_STRUCT(hdr);
+ }
NNI_FREE_STRUCT(l);
}
@@ -1718,6 +1759,7 @@ ws_conn_cb(void *arg)
uint8_t raw[16];
char wskey[25];
nni_ws * ws;
+ ws_header * hdr;
nni_mtx_lock(&d->mtx);
uaio = nni_list_first(&d->conaios);
@@ -1776,6 +1818,13 @@ ws_conn_cb(void *arg)
((rv = SETH("Sec-WebSocket-Protocol", d->proto)) != 0)) {
goto err;
}
+
+ NNI_LIST_FOREACH (&d->headers, hdr) {
+ if ((rv = SETH(hdr->name, hdr->value)) != 0) {
+ goto err;
+ }
+ }
+
#undef SETH
if ((rv = ws_init(&ws, http, req, NULL)) != 0) {
@@ -1807,6 +1856,8 @@ err:
void
nni_ws_dialer_fini(nni_ws_dialer *d)
{
+ ws_header *hdr;
+
nni_aio_fini(d->conaio);
nni_strfree(d->proto);
nni_strfree(d->addr);
@@ -1815,6 +1866,12 @@ nni_ws_dialer_fini(nni_ws_dialer *d)
nni_strfree(d->serv);
nni_strfree(d->path);
nni_strfree(d->qinfo);
+ while ((hdr = nni_list_first(&d->headers)) != NULL) {
+ nni_list_remove(&d->headers, hdr);
+ nni_strfree(hdr->name);
+ nni_strfree(hdr->value);
+ NNI_FREE_STRUCT(hdr);
+ }
if (d->client) {
nni_http_client_fini(d->client);
}
@@ -1832,6 +1889,7 @@ nni_ws_dialer_init(nni_ws_dialer **dp, const char *url)
if ((d = NNI_ALLOC_STRUCT(d)) == NULL) {
return (NNG_ENOMEM);
}
+ NNI_LIST_INIT(&d->headers, ws_header, node);
nni_mtx_init(&d->mtx);
nni_aio_list_init(&d->conaios);
nni_aio_list_init(&d->httpaios);
@@ -1877,7 +1935,6 @@ nni_ws_dialer_init(nni_ws_dialer **dp, const char *url)
void
nni_ws_dialer_close(nni_ws_dialer *d)
{
- // XXX: what to do here?
nni_mtx_lock(&d->mtx);
if (d->closed) {
nni_mtx_unlock(&d->mtx);
@@ -1944,7 +2001,47 @@ nni_ws_dialer_dial(nni_ws_dialer *d, nni_aio *aio)
nni_mtx_unlock(&d->mtx);
}
-extern int nni_ws_dialer_header(nni_ws_dialer *, const char *, const char *);
+static int
+ws_set_header(nni_list *l, const char *n, const char *v)
+{
+ ws_header *hdr;
+ char * nv;
+
+ if ((nv = nni_strdup(v)) == NULL) {
+ return (NNG_ENOMEM);
+ }
+
+ NNI_LIST_FOREACH (l, hdr) {
+ if (strcasecmp(hdr->name, n) == 0) {
+ nni_strfree(hdr->value);
+ hdr->value = nv;
+ return (0);
+ }
+ }
+
+ if ((hdr = NNI_ALLOC_STRUCT(hdr)) == NULL) {
+ nni_strfree(nv);
+ return (NNG_ENOMEM);
+ }
+ if ((hdr->name = strdup(n)) == NULL) {
+ nni_strfree(nv);
+ NNI_FREE_STRUCT(hdr);
+ return (NNG_ENOMEM);
+ }
+ hdr->value = nv;
+ nni_list_append(l, hdr);
+ return (0);
+}
+
+int
+nni_ws_dialer_header(nni_ws_dialer *d, const char *n, const char *v)
+{
+ int rv;
+ nni_mtx_lock(&d->mtx);
+ rv = ws_set_header(&d->headers, n, v);
+ nni_mtx_unlock(&d->mtx);
+ return (rv);
+}
// Dialer does not get a hook chance, as it can examine the request
// and reply after dial is done; this is not a 3-way handshake, so