aboutsummaryrefslogtreecommitdiff
path: root/src/transport/ws/websocket.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/transport/ws/websocket.c')
-rw-r--r--src/transport/ws/websocket.c757
1 files changed, 479 insertions, 278 deletions
diff --git a/src/transport/ws/websocket.c b/src/transport/ws/websocket.c
index 19cc347c..2fa0fd67 100644
--- a/src/transport/ws/websocket.c
+++ b/src/transport/ws/websocket.c
@@ -21,8 +21,9 @@
#include "websocket.h"
-typedef struct ws_ep ws_ep;
-typedef struct ws_pipe ws_pipe;
+typedef struct ws_dialer ws_dialer;
+typedef struct ws_listener ws_listener;
+typedef struct ws_pipe ws_pipe;
typedef struct ws_hdr {
nni_list_node node;
@@ -30,26 +31,35 @@ typedef struct ws_hdr {
char * value;
} ws_hdr;
-struct ws_ep {
- int mode; // NNI_EP_MODE_DIAL or NNI_EP_MODE_LISTEN
+struct ws_dialer {
+ uint16_t lproto; // local protocol
+ uint16_t rproto; // remote protocol
+ size_t rcvmax;
+ char * prname;
+ nni_list aios;
+ nni_mtx mtx;
+ nni_aio * connaio;
+ nni_ws_dialer *dialer;
+ nni_list headers; // req headers
+ bool started;
+};
+
+struct ws_listener {
uint16_t lproto; // local protocol
uint16_t rproto; // remote protocol
size_t rcvmax;
- char * protoname;
+ char * prname;
nni_list aios;
nni_mtx mtx;
- nni_aio * connaio;
nni_aio * accaio;
nni_ws_listener *listener;
- nni_ws_dialer * dialer;
- nni_list headers; // to send, res or req
+ nni_list headers; // res headers
bool started;
};
struct ws_pipe {
- int mode; // NNI_EP_MODE_DIAL or NNI_EP_MODE_LISTEN
nni_mtx mtx;
- size_t rcvmax; // inherited from EP
+ size_t rcvmax;
bool closed;
uint16_t rproto;
uint16_t lproto;
@@ -220,7 +230,7 @@ ws_pipe_close(void *arg)
}
static int
-ws_pipe_init(ws_pipe **pipep, ws_ep *ep, void *ws)
+ws_pipe_init(ws_pipe **pipep, void *ws)
{
ws_pipe *p;
int rv;
@@ -236,12 +246,7 @@ ws_pipe_init(ws_pipe **pipep, ws_ep *ep, void *ws)
ws_pipe_fini(p);
return (rv);
}
-
- p->mode = ep->mode;
- p->rcvmax = ep->rcvmax;
- p->rproto = ep->rproto;
- p->lproto = ep->lproto;
- p->ws = ws;
+ p->ws = ws;
*pipep = p;
return (0);
@@ -261,14 +266,14 @@ ws_pipe_peer(void *arg)
static int
ws_hook(void *arg, nni_http_req *req, nni_http_res *res)
{
- ws_ep * ep = arg;
- ws_hdr *h;
+ ws_listener *l = arg;
+ ws_hdr * h;
NNI_ARG_UNUSED(req);
// Eventually we'll want user customizable hooks.
// For now we just set the headers we want.
- NNI_LIST_FOREACH (&ep->headers, h) {
+ NNI_LIST_FOREACH (&l->headers, h) {
int rv;
rv = nng_http_res_set_header(res, h->name, h->value);
if (rv != 0) {
@@ -279,38 +284,38 @@ ws_hook(void *arg, nni_http_req *req, nni_http_res *res)
}
static int
-ws_ep_bind(void *arg)
+ws_listener_bind(void *arg)
{
- ws_ep *ep = arg;
- int rv;
+ ws_listener *l = arg;
+ int rv;
- nni_ws_listener_set_maxframe(ep->listener, ep->rcvmax);
- nni_ws_listener_hook(ep->listener, ws_hook, ep);
+ nni_ws_listener_set_maxframe(l->listener, l->rcvmax);
+ nni_ws_listener_hook(l->listener, ws_hook, l);
- if ((rv = nni_ws_listener_listen(ep->listener)) == 0) {
- ep->started = true;
+ if ((rv = nni_ws_listener_listen(l->listener)) == 0) {
+ l->started = true;
}
return (rv);
}
static void
-ws_ep_cancel(nni_aio *aio, int rv)
+ws_listener_cancel(nni_aio *aio, int rv)
{
- ws_ep *ep = nni_aio_get_prov_data(aio);
+ ws_listener *l = nni_aio_get_prov_data(aio);
- nni_mtx_lock(&ep->mtx);
+ nni_mtx_lock(&l->mtx);
if (nni_aio_list_active(aio)) {
nni_aio_list_remove(aio);
nni_aio_finish_error(aio, rv);
}
- nni_mtx_unlock(&ep->mtx);
+ nni_mtx_unlock(&l->mtx);
}
static void
-ws_ep_accept(void *arg, nni_aio *aio)
+ws_listener_accept(void *arg, nni_aio *aio)
{
- ws_ep *ep = arg;
- int rv;
+ ws_listener *l = arg;
+ int rv;
// We already bound, so we just need to look for an available
// pipe (created by the handler), and match it.
@@ -318,33 +323,46 @@ ws_ep_accept(void *arg, nni_aio *aio)
if (nni_aio_begin(aio) != 0) {
return;
}
- nni_mtx_lock(&ep->mtx);
- if ((rv = nni_aio_schedule(aio, ws_ep_cancel, ep)) != 0) {
- nni_mtx_unlock(&ep->mtx);
+ nni_mtx_lock(&l->mtx);
+ if ((rv = nni_aio_schedule(aio, ws_listener_cancel, l)) != 0) {
+ nni_mtx_unlock(&l->mtx);
nni_aio_finish_error(aio, rv);
return;
}
- nni_list_append(&ep->aios, aio);
- if (aio == nni_list_first(&ep->aios)) {
- nni_ws_listener_accept(ep->listener, ep->accaio);
+ nni_list_append(&l->aios, aio);
+ if (aio == nni_list_first(&l->aios)) {
+ nni_ws_listener_accept(l->listener, l->accaio);
+ }
+ nni_mtx_unlock(&l->mtx);
+}
+
+static void
+ws_dialer_cancel(nni_aio *aio, int rv)
+{
+ ws_dialer *d = nni_aio_get_prov_data(aio);
+
+ nni_mtx_lock(&d->mtx);
+ if (nni_aio_list_active(aio)) {
+ nni_aio_list_remove(aio);
+ nni_aio_finish_error(aio, rv);
}
- nni_mtx_unlock(&ep->mtx);
+ nni_mtx_unlock(&d->mtx);
}
static void
-ws_ep_connect(void *arg, nni_aio *aio)
+ws_dialer_connect(void *arg, nni_aio *aio)
{
- ws_ep *ep = arg;
- int rv;
+ ws_dialer *d = arg;
+ int rv;
if (nni_aio_begin(aio) != 0) {
return;
}
- if (!ep->started) {
+ if (!d->started) {
ws_hdr *h;
- NNI_LIST_FOREACH (&ep->headers, h) {
- int rv = nni_ws_dialer_header(
- ep->dialer, h->name, h->value);
+ NNI_LIST_FOREACH (&d->headers, h) {
+ int rv =
+ nni_ws_dialer_header(d->dialer, h->name, h->value);
if (rv != 0) {
nni_aio_finish_error(aio, rv);
return;
@@ -352,22 +370,22 @@ ws_ep_connect(void *arg, nni_aio *aio)
}
}
- nni_mtx_lock(&ep->mtx);
- if ((rv = nni_aio_schedule(aio, ws_ep_cancel, ep)) != 0) {
- nni_mtx_unlock(&ep->mtx);
+ nni_mtx_lock(&d->mtx);
+ if ((rv = nni_aio_schedule(aio, ws_dialer_cancel, d)) != 0) {
+ nni_mtx_unlock(&d->mtx);
nni_aio_finish_error(aio, rv);
return;
}
- NNI_ASSERT(nni_list_empty(&ep->aios));
- ep->started = true;
- nni_list_append(&ep->aios, aio);
- nni_ws_dialer_set_maxframe(ep->dialer, ep->rcvmax);
- nni_ws_dialer_dial(ep->dialer, ep->connaio);
- nni_mtx_unlock(&ep->mtx);
+ NNI_ASSERT(nni_list_empty(&d->aios));
+ d->started = true;
+ nni_list_append(&d->aios, aio);
+ nni_ws_dialer_set_maxframe(d->dialer, d->rcvmax);
+ nni_ws_dialer_dial(d->dialer, d->connaio);
+ nni_mtx_unlock(&d->mtx);
}
static int
-ws_ep_chk_string(const void *v, size_t sz, nni_opt_type t)
+ws_check_string(const void *v, size_t sz, nni_opt_type t)
{
if ((t != NNI_TYPE_OPAQUE) && (t != NNI_TYPE_STRING)) {
return (NNG_EBADTYPE);
@@ -379,40 +397,59 @@ ws_ep_chk_string(const void *v, size_t sz, nni_opt_type t)
}
static int
-ws_ep_set_recvmaxsz(void *arg, const void *v, size_t sz, nni_opt_type t)
+ws_dialer_set_recvmaxsz(void *arg, const void *v, size_t sz, nni_opt_type t)
{
- ws_ep *ep = arg;
- size_t val;
- int rv;
+ ws_dialer *d = arg;
+ size_t val;
+ int rv;
if ((rv = nni_copyin_size(&val, v, sz, 0, NNI_MAXSZ, t)) == 0) {
- nni_mtx_lock(&ep->mtx);
- ep->rcvmax = val;
- nni_mtx_unlock(&ep->mtx);
- if (ep->mode == NNI_EP_MODE_DIAL) {
- nni_ws_dialer_set_maxframe(ep->dialer, val);
- } else {
- nni_ws_listener_set_maxframe(ep->listener, val);
- }
+ nni_mtx_lock(&d->mtx);
+ d->rcvmax = val;
+ nni_mtx_unlock(&d->mtx);
+ nni_ws_dialer_set_maxframe(d->dialer, val);
}
return (rv);
}
static int
-ws_ep_chk_recvmaxsz(const void *v, size_t sz, nni_opt_type t)
+ws_dialer_get_recvmaxsz(void *arg, void *v, size_t *szp, nni_opt_type t)
{
- return (nni_copyin_size(NULL, v, sz, 0, NNI_MAXSZ, t));
+ ws_dialer *d = arg;
+ return (nni_copyout_size(d->rcvmax, v, szp, t));
+}
+
+static int
+ws_listener_set_recvmaxsz(void *arg, const void *v, size_t sz, nni_opt_type t)
+{
+ ws_listener *l = arg;
+ size_t val;
+ int rv;
+
+ if ((rv = nni_copyin_size(&val, v, sz, 0, NNI_MAXSZ, t)) == 0) {
+ nni_mtx_lock(&l->mtx);
+ l->rcvmax = val;
+ nni_mtx_unlock(&l->mtx);
+ nni_ws_listener_set_maxframe(l->listener, val);
+ }
+ return (rv);
+}
+
+static int
+ws_listener_get_recvmaxsz(void *arg, void *v, size_t *szp, nni_opt_type t)
+{
+ ws_listener *l = arg;
+ return (nni_copyout_size(l->rcvmax, v, szp, t));
}
static int
-ws_ep_get_recvmaxsz(void *arg, void *v, size_t *szp, nni_opt_type t)
+ws_check_recvmaxsz(const void *v, size_t sz, nni_opt_type t)
{
- ws_ep *ep = arg;
- return (nni_copyout_size(ep->rcvmax, v, szp, t));
+ return (nni_copyin_size(NULL, v, sz, 0, NNI_MAXSZ, t));
}
static int
-ws_ep_set_headers(ws_ep *ep, const char *v)
+ws_set_headers(nni_list *headers, const char *v)
{
char * dupstr;
size_t duplen;
@@ -423,10 +460,6 @@ ws_ep_set_headers(ws_ep *ep, const char *v)
ws_hdr * h;
int rv;
- if (ep->started) {
- return (NNG_EBUSY);
- }
-
NNI_LIST_INIT(&l, ws_hdr, node);
if ((dupstr = nni_strdup(v)) == NULL) {
return (NNG_ENOMEM);
@@ -471,15 +504,15 @@ ws_ep_set_headers(ws_ep *ep, const char *v)
name = nl;
}
- while ((h = nni_list_first(&ep->headers)) != NULL) {
- nni_list_remove(&ep->headers, h);
+ while ((h = nni_list_first(headers)) != NULL) {
+ nni_list_remove(headers, h);
nni_strfree(h->name);
nni_strfree(h->value);
NNI_FREE_STRUCT(h);
}
while ((h = nni_list_first(&l)) != NULL) {
nni_list_remove(&l, h);
- nni_list_append(&ep->headers, h);
+ nni_list_append(headers, h);
}
rv = 0;
@@ -495,33 +528,32 @@ done:
}
static int
-ws_ep_set_reqhdrs(void *arg, const void *v, size_t sz, nni_opt_type t)
+ws_dialer_set_reqhdrs(void *arg, const void *v, size_t sz, nni_opt_type t)
{
- ws_ep *ep = arg;
- int rv;
+ ws_dialer *d = arg;
+ int rv;
- if ((rv = ws_ep_chk_string(v, sz, t)) == 0) {
- if (ep->mode == NNI_EP_MODE_LISTEN) {
- rv = NNG_EREADONLY;
- } else {
- rv = ws_ep_set_headers(ep, v);
- }
+ if (d->started) {
+ return (NNG_EBUSY);
+ }
+
+ if ((rv = ws_check_string(v, sz, t)) == 0) {
+ rv = ws_set_headers(&d->headers, v);
}
return (rv);
}
static int
-ws_ep_set_reshdrs(void *arg, const void *v, size_t sz, nni_opt_type t)
+ws_listener_set_reshdrs(void *arg, const void *v, size_t sz, nni_opt_type t)
{
- ws_ep *ep = arg;
- int rv;
+ ws_listener *l = arg;
+ int rv;
- if ((rv = ws_ep_chk_string(v, sz, t)) == 0) {
- if (ep->mode == NNI_EP_MODE_DIAL) {
- rv = NNG_EREADONLY;
- } else {
- rv = ws_ep_set_headers(ep, v);
- }
+ if (l->started) {
+ return (NNG_EBUSY);
+ }
+ if ((rv = ws_check_string(v, sz, t)) == 0) {
+ rv = ws_set_headers(&l->headers, v);
}
return (rv);
}
@@ -628,25 +660,39 @@ static nni_tran_pipe_ops ws_pipe_ops = {
.p_options = ws_pipe_options,
};
-static nni_tran_option ws_ep_options[] = {
+static nni_tran_option ws_dialer_options[] = {
{
.o_name = NNG_OPT_RECVMAXSZ,
.o_type = NNI_TYPE_SIZE,
- .o_get = ws_ep_get_recvmaxsz,
- .o_set = ws_ep_set_recvmaxsz,
- .o_chk = ws_ep_chk_recvmaxsz,
+ .o_get = ws_dialer_get_recvmaxsz,
+ .o_set = ws_dialer_set_recvmaxsz,
+ .o_chk = ws_check_recvmaxsz,
},
{
.o_name = NNG_OPT_WS_REQUEST_HEADERS,
.o_type = NNI_TYPE_STRING,
- .o_set = ws_ep_set_reqhdrs,
- .o_chk = ws_ep_chk_string,
+ .o_set = ws_dialer_set_reqhdrs,
+ .o_chk = ws_check_string,
+ },
+ // terminate list
+ {
+ .o_name = NULL,
+ },
+};
+
+static nni_tran_option ws_listener_options[] = {
+ {
+ .o_name = NNG_OPT_RECVMAXSZ,
+ .o_type = NNI_TYPE_SIZE,
+ .o_get = ws_listener_get_recvmaxsz,
+ .o_set = ws_listener_set_recvmaxsz,
+ .o_chk = ws_check_recvmaxsz,
},
{
.o_name = NNG_OPT_WS_RESPONSE_HEADERS,
.o_type = NNI_TYPE_STRING,
- .o_set = ws_ep_set_reshdrs,
- .o_chk = ws_ep_chk_string,
+ .o_set = ws_listener_set_reshdrs,
+ .o_chk = ws_check_string,
},
// terminate list
{
@@ -655,93 +701,117 @@ static nni_tran_option ws_ep_options[] = {
};
static void
-ws_ep_fini(void *arg)
+ws_dialer_fini(void *arg)
{
- ws_ep * ep = arg;
- ws_hdr *hdr;
+ ws_dialer *d = arg;
+ ws_hdr * hdr;
- nni_aio_stop(ep->accaio);
- nni_aio_stop(ep->connaio);
- if (ep->listener != NULL) {
- nni_ws_listener_fini(ep->listener);
+ nni_aio_stop(d->connaio);
+ if (d->dialer != NULL) {
+ nni_ws_dialer_fini(d->dialer);
}
- if (ep->dialer != NULL) {
- nni_ws_dialer_fini(ep->dialer);
- }
- nni_aio_fini(ep->accaio);
- nni_aio_fini(ep->connaio);
- while ((hdr = nni_list_first(&ep->headers)) != NULL) {
- nni_list_remove(&ep->headers, hdr);
+ nni_aio_fini(d->connaio);
+ 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);
}
- nni_strfree(ep->protoname);
- nni_mtx_fini(&ep->mtx);
- NNI_FREE_STRUCT(ep);
+ nni_strfree(d->prname);
+ nni_mtx_fini(&d->mtx);
+ NNI_FREE_STRUCT(d);
}
static void
-ws_ep_conn_cb(void *arg)
+ws_listener_fini(void *arg)
{
- ws_ep * ep = arg;
- ws_pipe *p;
- nni_aio *caio = ep->connaio;
- nni_aio *uaio;
- int rv;
- nni_ws * ws = NULL;
+ ws_listener *l = arg;
+ ws_hdr * hdr;
+
+ nni_aio_stop(l->accaio);
+ if (l->listener != NULL) {
+ nni_ws_listener_fini(l->listener);
+ }
+ nni_aio_fini(l->accaio);
+ 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_strfree(l->prname);
+ nni_mtx_fini(&l->mtx);
+ NNI_FREE_STRUCT(l);
+}
- nni_mtx_lock(&ep->mtx);
+static void
+ws_connect_cb(void *arg)
+{
+ ws_dialer *d = arg;
+ ws_pipe * p;
+ nni_aio * caio = d->connaio;
+ nni_aio * uaio;
+ int rv;
+ nni_ws * ws = NULL;
+
+ nni_mtx_lock(&d->mtx);
if (nni_aio_result(caio) == 0) {
ws = nni_aio_get_output(caio, 0);
}
- if ((uaio = nni_list_first(&ep->aios)) == NULL) {
+ if ((uaio = nni_list_first(&d->aios)) == NULL) {
// The client stopped caring about this!
if (ws != NULL) {
nni_ws_fini(ws);
}
- nni_mtx_unlock(&ep->mtx);
+ nni_mtx_unlock(&d->mtx);
return;
}
nni_aio_list_remove(uaio);
- NNI_ASSERT(nni_list_empty(&ep->aios));
+ NNI_ASSERT(nni_list_empty(&d->aios));
if ((rv = nni_aio_result(caio)) != 0) {
nni_aio_finish_error(uaio, rv);
- } else if ((rv = ws_pipe_init(&p, ep, ws)) != 0) {
+ } else if ((rv = ws_pipe_init(&p, ws)) != 0) {
nni_ws_fini(ws);
nni_aio_finish_error(uaio, rv);
} else {
+ p->rcvmax = d->rcvmax;
+ p->rproto = d->rproto;
+ p->lproto = d->lproto;
+
nni_aio_set_output(uaio, 0, p);
nni_aio_finish(uaio, 0, 0);
}
- nni_mtx_unlock(&ep->mtx);
+ nni_mtx_unlock(&d->mtx);
}
static void
-ws_ep_close(void *arg)
+ws_dialer_close(void *arg)
{
- ws_ep *ep = arg;
+ ws_dialer *d = arg;
- nni_aio_close(ep->accaio);
- nni_aio_close(ep->connaio);
+ nni_aio_close(d->connaio);
+ nni_ws_dialer_close(d->dialer);
+}
- if (ep->mode == NNI_EP_MODE_LISTEN) {
- nni_ws_listener_close(ep->listener);
- } else {
- nni_ws_dialer_close(ep->dialer);
- }
+static void
+ws_listener_close(void *arg)
+{
+ ws_listener *l = arg;
+
+ nni_aio_close(l->accaio);
+ nni_ws_listener_close(l->listener);
}
static void
-ws_ep_acc_cb(void *arg)
+ws_accept_cb(void *arg)
{
- ws_ep * ep = arg;
- nni_aio *aaio = ep->accaio;
- nni_aio *uaio;
- int rv;
+ ws_listener *l = arg;
+ nni_aio * aaio = l->accaio;
+ nni_aio * uaio;
+ int rv;
- nni_mtx_lock(&ep->mtx);
- uaio = nni_list_first(&ep->aios);
+ nni_mtx_lock(&l->mtx);
+ uaio = nni_list_first(&l->aios);
if ((rv = nni_aio_result(aaio)) != 0) {
if (uaio != NULL) {
nni_aio_list_remove(uaio);
@@ -753,72 +823,86 @@ ws_ep_acc_cb(void *arg)
ws_pipe *p;
// Make a pipe
nni_aio_list_remove(uaio);
- if ((rv = ws_pipe_init(&p, ep, ws)) != 0) {
+ if ((rv = ws_pipe_init(&p, ws)) != 0) {
nni_ws_close(ws);
nni_aio_finish_error(uaio, rv);
} else {
+ p->rcvmax = l->rcvmax;
+ p->rproto = l->rproto;
+ p->lproto = l->lproto;
+
nni_aio_set_output(uaio, 0, p);
nni_aio_finish(uaio, 0, 0);
}
}
}
- if (!nni_list_empty(&ep->aios)) {
- nni_ws_listener_accept(ep->listener, aaio);
+ if (!nni_list_empty(&l->aios)) {
+ nni_ws_listener_accept(l->listener, aaio);
}
- nni_mtx_unlock(&ep->mtx);
+ nni_mtx_unlock(&l->mtx);
}
static int
-ws_ep_init(void **epp, nni_url *url, nni_sock *sock, int mode)
+ws_dialer_init(void **dp, nni_url *url, nni_sock *s)
{
- ws_ep * ep;
- const char *pname;
+ ws_dialer * d;
+ const char *n;
int rv;
- if ((ep = NNI_ALLOC_STRUCT(ep)) == NULL) {
+ if ((d = NNI_ALLOC_STRUCT(d)) == NULL) {
return (NNG_ENOMEM);
}
- nni_mtx_init(&ep->mtx);
- NNI_LIST_INIT(&ep->headers, ws_hdr, node);
+ nni_mtx_init(&d->mtx);
+ NNI_LIST_INIT(&d->headers, ws_hdr, node);
- // List of pipes (server only).
- nni_aio_list_init(&ep->aios);
+ nni_aio_list_init(&d->aios);
- ep->mode = mode;
- ep->lproto = nni_sock_proto_id(sock);
- ep->rproto = nni_sock_peer_id(sock);
+ d->lproto = nni_sock_proto_id(s);
+ d->rproto = nni_sock_peer_id(s);
+ n = nni_sock_peer_name(s);
- if (mode == NNI_EP_MODE_DIAL) {
- pname = nni_sock_peer_name(sock);
- rv = nni_ws_dialer_init(&ep->dialer, url);
- } else {
- pname = nni_sock_proto_name(sock);
- rv = nni_ws_listener_init(&ep->listener, url);
- }
-
- if ((rv != 0) ||
- ((rv = nni_aio_init(&ep->connaio, ws_ep_conn_cb, ep)) != 0) ||
- ((rv = nni_aio_init(&ep->accaio, ws_ep_acc_cb, ep)) != 0) ||
- ((rv = nni_asprintf(&ep->protoname, "%s.sp.nanomsg.org", pname)) !=
- 0)) {
- ws_ep_fini(ep);
+ if (((rv = nni_ws_dialer_init(&d->dialer, url)) != 0) ||
+ ((rv = nni_aio_init(&d->connaio, ws_connect_cb, d)) != 0) ||
+ ((rv = nni_asprintf(&d->prname, "%s.sp.nanomsg.org", n)) != 0) ||
+ ((rv = nni_ws_dialer_proto(d->dialer, d->prname)) != 0)) {
+ ws_dialer_fini(d);
return (rv);
}
- if (mode == NNI_EP_MODE_DIAL) {
- rv = nni_ws_dialer_proto(ep->dialer, ep->protoname);
- } else {
- rv = nni_ws_listener_proto(ep->listener, ep->protoname);
+ *dp = d;
+ return (0);
+}
+
+static int
+ws_listener_init(void **lp, nni_url *url, nni_sock *sock)
+{
+ ws_listener *l;
+ const char * n;
+ int rv;
+
+ if ((l = NNI_ALLOC_STRUCT(l)) == NULL) {
+ return (NNG_ENOMEM);
}
+ nni_mtx_init(&l->mtx);
+ NNI_LIST_INIT(&l->headers, ws_hdr, node);
+
+ nni_aio_list_init(&l->aios);
+
+ l->lproto = nni_sock_proto_id(sock);
+ l->rproto = nni_sock_peer_id(sock);
+ n = nni_sock_proto_name(sock);
- if (rv != 0) {
- ws_ep_fini(ep);
+ if (((rv = nni_ws_listener_init(&l->listener, url)) != 0) ||
+ ((rv = nni_aio_init(&l->accaio, ws_accept_cb, l)) != 0) ||
+ ((rv = nni_asprintf(&l->prname, "%s.sp.nanomsg.org", n)) != 0) ||
+ ((rv = nni_ws_listener_proto(l->listener, l->prname)) != 0)) {
+ ws_listener_fini(l);
return (rv);
}
-
- *epp = ep;
+ *lp = l;
return (0);
}
+
static int
ws_tran_init(void)
{
@@ -830,23 +914,31 @@ ws_tran_fini(void)
{
}
-static nni_tran_ep_ops ws_ep_ops = {
- .ep_init = ws_ep_init,
- .ep_fini = ws_ep_fini,
- .ep_connect = ws_ep_connect,
- .ep_bind = ws_ep_bind,
- .ep_accept = ws_ep_accept,
- .ep_close = ws_ep_close,
- .ep_options = ws_ep_options,
+static nni_tran_dialer_ops ws_dialer_ops = {
+ .d_init = ws_dialer_init,
+ .d_fini = ws_dialer_fini,
+ .d_connect = ws_dialer_connect,
+ .d_close = ws_dialer_close,
+ .d_options = ws_dialer_options,
+};
+
+static nni_tran_listener_ops ws_listener_ops = {
+ .l_init = ws_listener_init,
+ .l_fini = ws_listener_fini,
+ .l_bind = ws_listener_bind,
+ .l_accept = ws_listener_accept,
+ .l_close = ws_listener_close,
+ .l_options = ws_listener_options,
};
static nni_tran ws_tran = {
- .tran_version = NNI_TRANSPORT_VERSION,
- .tran_scheme = "ws",
- .tran_ep = &ws_ep_ops,
- .tran_pipe = &ws_pipe_ops,
- .tran_init = ws_tran_init,
- .tran_fini = ws_tran_fini,
+ .tran_version = NNI_TRANSPORT_VERSION,
+ .tran_scheme = "ws",
+ .tran_dialer = &ws_dialer_ops,
+ .tran_listener = &ws_listener_ops,
+ .tran_pipe = &ws_pipe_ops,
+ .tran_init = ws_tran_init,
+ .tran_fini = ws_tran_fini,
};
int
@@ -858,25 +950,27 @@ nng_ws_register(void)
#ifdef NNG_TRANSPORT_WSS
static int
-wss_get_tls(ws_ep *ep, nng_tls_config **tlsp)
+wss_dialer_get_tlsconfig(void *arg, void *v, size_t *szp, nni_opt_type t)
{
- switch (ep->mode) {
- case NNI_EP_MODE_DIAL:
- return (nni_ws_dialer_get_tls(ep->dialer, tlsp));
- case NNI_EP_MODE_LISTEN:
- return (nni_ws_listener_get_tls(ep->listener, tlsp));
+ ws_dialer * d = arg;
+ nng_tls_config *tls;
+ int rv;
+
+ if (((rv = nni_ws_dialer_get_tls(d->dialer, &tls)) != 0) ||
+ ((rv = nni_copyout_ptr(tls, v, szp, t)) != 0)) {
+ return (rv);
}
- return (NNG_EINVAL);
+ return (0);
}
static int
-wss_ep_get_tlsconfig(void *arg, void *v, size_t *szp, nni_opt_type t)
+wss_listener_get_tlsconfig(void *arg, void *v, size_t *szp, nni_opt_type t)
{
- ws_ep * ep = arg;
+ ws_listener * l = arg;
nng_tls_config *tls;
int rv;
- if (((rv = wss_get_tls(ep, &tls)) != 0) ||
+ if (((rv = nni_ws_listener_get_tls(l->listener, &tls)) != 0) ||
((rv = nni_copyout_ptr(tls, v, szp, t)) != 0)) {
return (rv);
}
@@ -884,7 +978,7 @@ wss_ep_get_tlsconfig(void *arg, void *v, size_t *szp, nni_opt_type t)
}
static int
-wss_ep_chk_tlsconfig(const void *v, size_t sz, nni_opt_type t)
+wss_check_tlsconfig(const void *v, size_t sz, nni_opt_type t)
{
void *p;
int rv;
@@ -895,9 +989,9 @@ wss_ep_chk_tlsconfig(const void *v, size_t sz, nni_opt_type t)
}
static int
-wss_ep_set_tlsconfig(void *arg, const void *v, size_t sz, nni_opt_type t)
+wss_dialer_set_tlsconfig(void *arg, const void *v, size_t sz, nni_opt_type t)
{
- ws_ep * ep = arg;
+ ws_dialer * d = arg;
nng_tls_config *cfg;
int rv;
@@ -905,56 +999,114 @@ wss_ep_set_tlsconfig(void *arg, const void *v, size_t sz, nni_opt_type t)
return (rv);
}
if (cfg == NULL) {
- // NULL is clearly invalid.
return (NNG_EINVAL);
}
- if (ep->mode == NNI_EP_MODE_LISTEN) {
- rv = nni_ws_listener_set_tls(ep->listener, cfg);
- } else {
- rv = nni_ws_dialer_set_tls(ep->dialer, cfg);
+ return (nni_ws_dialer_set_tls(d->dialer, cfg));
+}
+
+static int
+wss_listener_set_tlsconfig(void *arg, const void *v, size_t sz, nni_opt_type t)
+{
+ ws_listener * l = arg;
+ nng_tls_config *cfg;
+ int rv;
+
+ if ((rv = nni_copyin_ptr((void **) &cfg, v, sz, t)) != 0) {
+ return (rv);
}
- return (rv);
+ if (cfg == NULL) {
+ return (NNG_EINVAL);
+ }
+ return (nni_ws_listener_set_tls(l->listener, cfg));
}
static int
-wss_ep_set_cert_key_file(void *arg, const void *v, size_t sz, nni_opt_type t)
+wss_dialer_set_cert_key_file(
+ void *arg, const void *v, size_t sz, nni_opt_type t)
{
- ws_ep * ep = arg;
+ ws_dialer * d = arg;
int rv;
nng_tls_config *tls;
- if (((rv = ws_ep_chk_string(v, sz, t)) != 0) ||
- ((rv = wss_get_tls(ep, &tls)) != 0)) {
+ if (((rv = ws_check_string(v, sz, t)) != 0) ||
+ ((rv = nni_ws_dialer_get_tls(d->dialer, &tls)) != 0)) {
return (rv);
}
return (nng_tls_config_cert_key_file(tls, v, NULL));
}
static int
-wss_ep_set_ca_file(void *arg, const void *v, size_t sz, nni_opt_type t)
+wss_listener_set_cert_key_file(
+ void *arg, const void *v, size_t sz, nni_opt_type t)
{
- ws_ep * ep = arg;
+ ws_listener * l = arg;
int rv;
nng_tls_config *tls;
- if (((rv = ws_ep_chk_string(v, sz, t)) != 0) ||
- ((rv = wss_get_tls(ep, &tls)) != 0)) {
+ if (((rv = ws_check_string(v, sz, t)) != 0) ||
+ ((rv = nni_ws_listener_get_tls(l->listener, &tls)) != 0)) {
+ return (rv);
+ }
+ return (nng_tls_config_cert_key_file(tls, v, NULL));
+}
+
+static int
+wss_dialer_set_ca_file(void *arg, const void *v, size_t sz, nni_opt_type t)
+{
+ ws_dialer * d = arg;
+ int rv;
+ nng_tls_config *tls;
+
+ if (((rv = ws_check_string(v, sz, t)) != 0) ||
+ ((rv = nni_ws_dialer_get_tls(d->dialer, &tls)) != 0)) {
return (rv);
}
return (nng_tls_config_ca_file(tls, v));
}
static int
-wss_ep_chk_auth_mode(const void *v, size_t sz, nni_opt_type t)
+wss_listener_set_ca_file(void *arg, const void *v, size_t sz, nni_opt_type t)
+{
+ ws_listener * l = arg;
+ int rv;
+ nng_tls_config *tls;
+
+ if (((rv = ws_check_string(v, sz, t)) != 0) ||
+ ((rv = nni_ws_listener_get_tls(l->listener, &tls)) != 0)) {
+ return (rv);
+ }
+ return (nng_tls_config_ca_file(tls, v));
+}
+
+static int
+wss_check_auth_mode(const void *v, size_t sz, nni_opt_type t)
{
return (nni_copyin_int(NULL, v, sz, NNG_TLS_AUTH_MODE_NONE,
NNG_TLS_AUTH_MODE_REQUIRED, t));
}
static int
-wss_ep_set_auth_mode(void *arg, const void *v, size_t sz, nni_opt_type t)
+wss_dialer_set_auth_mode(void *arg, const void *v, size_t sz, nni_opt_type t)
+{
+ ws_dialer * d = arg;
+ int rv;
+ nng_tls_config *tls;
+ int mode;
+
+ rv = nni_copyin_int(&mode, v, sz, NNG_TLS_AUTH_MODE_NONE,
+ NNG_TLS_AUTH_MODE_REQUIRED, t);
+
+ if ((rv != 0) ||
+ ((rv = nni_ws_dialer_get_tls(d->dialer, &tls)) != 0)) {
+ return (rv);
+ }
+ return (nng_tls_config_auth_mode(tls, mode));
+}
+
+static int
+wss_listener_set_auth_mode(void *arg, const void *v, size_t sz, nni_opt_type t)
{
- ws_ep * ep = arg;
+ ws_listener * l = arg;
int rv;
nng_tls_config *tls;
int mode;
@@ -962,77 +1114,73 @@ wss_ep_set_auth_mode(void *arg, const void *v, size_t sz, nni_opt_type t)
rv = nni_copyin_int(&mode, v, sz, NNG_TLS_AUTH_MODE_NONE,
NNG_TLS_AUTH_MODE_REQUIRED, t);
- if ((rv != 0) || ((rv = wss_get_tls(ep, &tls)) != 0)) {
+ if ((rv != 0) ||
+ ((rv = nni_ws_listener_get_tls(l->listener, &tls)) != 0)) {
return (rv);
}
return (nng_tls_config_auth_mode(tls, mode));
}
static int
-wss_ep_set_tls_server_name(void *arg, const void *v, size_t sz, nni_opt_type t)
+wss_dialer_set_tls_server_name(
+ void *arg, const void *v, size_t sz, nni_opt_type t)
{
- ws_ep * ep = arg;
+ ws_dialer * d = arg;
int rv;
nng_tls_config *tls;
- if (((rv = ws_ep_chk_string(v, sz, t)) != 0) ||
- ((rv = wss_get_tls(ep, &tls)) != 0)) {
+ if (((rv = ws_check_string(v, sz, t)) != 0) ||
+ ((rv = nni_ws_dialer_get_tls(d->dialer, &tls)) != 0)) {
return (rv);
}
return (nng_tls_config_server_name(tls, v));
}
-static nni_tran_option wss_ep_options[] = {
+static nni_tran_option wss_dialer_options[] = {
{
.o_name = NNG_OPT_RECVMAXSZ,
.o_type = NNI_TYPE_SIZE,
- .o_get = ws_ep_get_recvmaxsz,
- .o_set = ws_ep_set_recvmaxsz,
- .o_chk = ws_ep_chk_recvmaxsz,
+ .o_get = ws_dialer_get_recvmaxsz,
+ .o_set = ws_dialer_set_recvmaxsz,
+ .o_chk = ws_check_recvmaxsz,
},
{
.o_name = NNG_OPT_WS_REQUEST_HEADERS,
.o_type = NNI_TYPE_STRING,
- .o_set = ws_ep_set_reqhdrs,
- .o_chk = ws_ep_chk_string,
- },
- {
- .o_name = NNG_OPT_WS_RESPONSE_HEADERS,
- .o_type = NNI_TYPE_STRING,
- .o_set = ws_ep_set_reshdrs,
- .o_chk = ws_ep_chk_string,
+ .o_set = ws_dialer_set_reqhdrs,
+ .o_chk = ws_check_string,
},
{
.o_name = NNG_OPT_TLS_CONFIG,
.o_type = NNI_TYPE_POINTER,
- .o_get = wss_ep_get_tlsconfig,
- .o_set = wss_ep_set_tlsconfig,
- .o_chk = wss_ep_chk_tlsconfig,
+ .o_get = wss_dialer_get_tlsconfig,
+ .o_set = wss_dialer_set_tlsconfig,
+ .o_chk = wss_check_tlsconfig,
},
{
.o_name = NNG_OPT_TLS_CERT_KEY_FILE,
.o_type = NNI_TYPE_STRING,
- .o_set = wss_ep_set_cert_key_file,
- .o_chk = ws_ep_chk_string,
+ .o_set = wss_dialer_set_cert_key_file,
+ .o_chk = ws_check_string,
},
{
.o_name = NNG_OPT_TLS_CA_FILE,
.o_type = NNI_TYPE_STRING,
- .o_set = wss_ep_set_ca_file,
- .o_chk = ws_ep_chk_string,
+ .o_set = wss_dialer_set_ca_file,
+ .o_chk = ws_check_string,
},
{
.o_name = NNG_OPT_TLS_AUTH_MODE,
.o_type = NNI_TYPE_INT32,
- .o_set = wss_ep_set_auth_mode,
- .o_chk = wss_ep_chk_auth_mode,
+ .o_set = wss_dialer_set_auth_mode,
+ .o_chk = wss_check_auth_mode,
},
{
.o_name = NNG_OPT_TLS_SERVER_NAME,
.o_type = NNI_TYPE_STRING,
- .o_set = wss_ep_set_tls_server_name,
- .o_chk = ws_ep_chk_string,
+ .o_set = wss_dialer_set_tls_server_name,
+ .o_chk = ws_check_string,
},
// terminate list
{
@@ -1040,23 +1188,76 @@ static nni_tran_option wss_ep_options[] = {
},
};
-static nni_tran_ep_ops wss_ep_ops = {
- .ep_init = ws_ep_init,
- .ep_fini = ws_ep_fini,
- .ep_connect = ws_ep_connect,
- .ep_bind = ws_ep_bind,
- .ep_accept = ws_ep_accept,
- .ep_close = ws_ep_close,
- .ep_options = wss_ep_options,
+static nni_tran_option wss_listener_options[] = {
+ {
+ .o_name = NNG_OPT_RECVMAXSZ,
+ .o_type = NNI_TYPE_SIZE,
+ .o_get = ws_listener_get_recvmaxsz,
+ .o_set = ws_listener_set_recvmaxsz,
+ .o_chk = ws_check_recvmaxsz,
+ },
+ {
+ .o_name = NNG_OPT_WS_RESPONSE_HEADERS,
+ .o_type = NNI_TYPE_STRING,
+ .o_set = ws_listener_set_reshdrs,
+ .o_chk = ws_check_string,
+ },
+ {
+ .o_name = NNG_OPT_TLS_CONFIG,
+ .o_type = NNI_TYPE_POINTER,
+ .o_get = wss_listener_get_tlsconfig,
+ .o_set = wss_listener_set_tlsconfig,
+ .o_chk = wss_check_tlsconfig,
+ },
+ {
+ .o_name = NNG_OPT_TLS_CERT_KEY_FILE,
+ .o_type = NNI_TYPE_STRING,
+ .o_set = wss_listener_set_cert_key_file,
+ .o_chk = ws_check_string,
+ },
+ {
+ .o_name = NNG_OPT_TLS_CA_FILE,
+ .o_type = NNI_TYPE_STRING,
+ .o_set = wss_listener_set_ca_file,
+ .o_chk = ws_check_string,
+ },
+ {
+ .o_name = NNG_OPT_TLS_AUTH_MODE,
+ .o_type = NNI_TYPE_INT32,
+ .o_set = wss_listener_set_auth_mode,
+ .o_chk = wss_check_auth_mode,
+ },
+ // terminate list
+ {
+ .o_name = NULL,
+ },
+};
+
+static nni_tran_dialer_ops wss_dialer_ops = {
+ .d_init = ws_dialer_init,
+ .d_fini = ws_dialer_fini,
+ .d_connect = ws_dialer_connect,
+ .d_close = ws_dialer_close,
+ .d_options = wss_dialer_options,
+};
+
+static nni_tran_listener_ops wss_listener_ops = {
+ .l_init = ws_listener_init,
+ .l_fini = ws_listener_fini,
+ .l_bind = ws_listener_bind,
+ .l_accept = ws_listener_accept,
+ .l_close = ws_listener_close,
+ .l_options = wss_listener_options,
};
static nni_tran wss_tran = {
- .tran_version = NNI_TRANSPORT_VERSION,
- .tran_scheme = "wss",
- .tran_ep = &wss_ep_ops,
- .tran_pipe = &ws_pipe_ops,
- .tran_init = ws_tran_init,
- .tran_fini = ws_tran_fini,
+ .tran_version = NNI_TRANSPORT_VERSION,
+ .tran_scheme = "wss",
+ .tran_dialer = &wss_dialer_ops,
+ .tran_listener = &wss_listener_ops,
+ .tran_pipe = &ws_pipe_ops,
+ .tran_init = ws_tran_init,
+ .tran_fini = ws_tran_fini,
};
int