aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compat/nanomsg/nn.c33
-rw-r--r--src/core/url.c6
-rw-r--r--src/supplemental/http/http_server.c35
-rw-r--r--src/supplemental/websocket/websocket.c46
-rw-r--r--src/supplemental/websocket/websocket.h6
-rw-r--r--src/transport/ws/websocket.c8
6 files changed, 103 insertions, 31 deletions
diff --git a/src/compat/nanomsg/nn.c b/src/compat/nanomsg/nn.c
index 564e60d8..bc27832e 100644
--- a/src/compat/nanomsg/nn.c
+++ b/src/compat/nanomsg/nn.c
@@ -749,6 +749,33 @@ nn_setignore(nng_socket s, const void *valp, size_t sz)
}
static int
+nn_getwsmsgtype(nng_socket s, void *valp, size_t *szp)
+{
+ int val = NN_WS_MSG_TYPE_BINARY;
+ NNI_ARG_UNUSED(s);
+ memcpy(valp, &val, *szp < sizeof(val) ? *szp : sizeof(val));
+ *szp = sizeof(val);
+ return (0);
+}
+
+static int
+nn_setwsmsgtype(nng_socket s, const void *valp, size_t sz)
+{
+ int val;
+ NNI_ARG_UNUSED(s);
+ if (sz != sizeof(val)) {
+ nn_seterror(NNG_EINVAL);
+ return (-1);
+ }
+ memcpy(&val, valp, sizeof(val));
+ if (val != NN_WS_MSG_TYPE_BINARY) {
+ nn_seterror(NNG_EINVAL);
+ return (-1);
+ }
+ return (0);
+}
+
+static int
nn_settcpnodelay(nng_socket s, const void *valp, size_t sz)
{
bool val;
@@ -1039,6 +1066,12 @@ static const struct {
.nnopt = NN_TCP_NODELAY,
.get = nn_gettcpnodelay,
.set = nn_settcpnodelay,
+ },
+ {
+ .nnlevel = NN_WS,
+ .nnopt = NN_WS_MSG_TYPE,
+ .get = nn_getwsmsgtype,
+ .set = nn_setwsmsgtype,
}
// XXX: IPV4ONLY, SNDPRIO, RCVPRIO
};
diff --git a/src/core/url.c b/src/core/url.c
index 93f1298e..7d45f82d 100644
--- a/src/core/url.c
+++ b/src/core/url.c
@@ -421,6 +421,12 @@ nni_url_parse(nni_url **urlp, const char *raw)
s++; // skip over ']', only used with IPv6 addresses
}
if (s[0] == ':') {
+ // If a colon was present, but no port value present, then
+ // that is an error.
+ if (s[1] == '\0') {
+ rv = NNG_EINVAL;
+ goto error;
+ }
url->u_port = nni_strdup(s + 1);
} else {
url->u_port = nni_strdup(nni_url_default_port(url->u_scheme));
diff --git a/src/supplemental/http/http_server.c b/src/supplemental/http/http_server.c
index c7738aee..5c6d1dcc 100644
--- a/src/supplemental/http/http_server.c
+++ b/src/supplemental/http/http_server.c
@@ -30,7 +30,7 @@ static nni_initializer http_server_initializer = {
struct nng_http_handler {
nni_list_node node;
- char * path;
+ char * uri;
char * method;
char * host;
bool tree;
@@ -75,14 +75,18 @@ struct nng_http_server {
int
nni_http_handler_init(
- nni_http_handler **hp, const char *path, void (*cb)(nni_aio *))
+ nni_http_handler **hp, const char *uri, void (*cb)(nni_aio *))
{
nni_http_handler *h;
if ((h = NNI_ALLOC_STRUCT(h)) == NULL) {
return (NNG_ENOMEM);
}
- if (((h->path = nni_strdup(path)) == NULL) ||
+ // Default for HTTP is /.
+ if ((uri == NULL) || (strlen(uri) == 0)) {
+ uri = "/";
+ }
+ if (((h->uri = nni_strdup(uri)) == NULL) ||
((h->method = nni_strdup("GET")) == NULL)) {
nni_http_handler_fini(h);
return (NNG_ENOMEM);
@@ -108,7 +112,7 @@ nni_http_handler_fini(nni_http_handler *h)
h->dtor(h->data);
}
nni_strfree(h->host);
- nni_strfree(h->path);
+ nni_strfree(h->uri);
nni_strfree(h->method);
NNI_FREE_STRUCT(h);
}
@@ -133,7 +137,7 @@ nni_http_handler_get_data(nni_http_handler *h)
const char *
nni_http_handler_get_uri(nni_http_handler *h)
{
- return (h->path);
+ return (h->uri);
}
int
@@ -383,8 +387,7 @@ http_uri_canonify(char *path)
}
*dst = '\0';
- // XXX: this is where we should also remove /./ and /../ references.
- return (path);
+ return ((strlen(path) != 0) ? path : "/");
}
static void
@@ -527,8 +530,8 @@ http_sconn_rxdone(void *arg)
}
}
- len = strlen(h->path);
- if (strncmp(path, h->path, len) != 0) {
+ len = strlen(h->uri);
+ if (strncmp(path, h->uri, len) != 0) {
continue;
}
switch (path[len]) {
@@ -957,11 +960,11 @@ nni_http_server_add_handler(nni_http_server *s, nni_http_handler *h)
// Must have a legal method (and not one that is HEAD), path,
// and handler. (The reason HEAD is verboten is that we supply
// it automatically as part of GET support.)
- if (((len = strlen(h->path)) == 0) || (h->path[0] != '/') ||
+ if (((len = strlen(h->uri)) == 0) || (h->uri[0] != '/') ||
(h->cb == NULL)) {
return (NNG_EINVAL);
}
- while ((len > 0) && (h->path[len - 1] == '/')) {
+ while ((len > 0) && (h->uri[len - 1] == '/')) {
len--; // ignore trailing '/' (this collapses them)
}
@@ -992,22 +995,22 @@ nni_http_server_add_handler(nni_http_server *s, nni_http_handler *h)
continue;
}
- len2 = strlen(h2->path);
+ len2 = strlen(h2->uri);
- while ((len2 > 0) && (h2->path[len2 - 1] == '/')) {
+ while ((len2 > 0) && (h2->uri[len2 - 1] == '/')) {
len2--; // ignore trailing '/'
}
- if (strncmp(h->path, h2->path, len > len2 ? len2 : len) != 0) {
+ if (strncmp(h->uri, h2->uri, len > len2 ? len2 : len) != 0) {
continue; // prefixes don't match.
}
if (len2 > len) {
- if ((h2->path[len] == '/') && (h->tree)) {
+ if ((h2->uri[len] == '/') && (h->tree)) {
nni_mtx_unlock(&s->mtx);
return (NNG_EADDRINUSE);
}
} else if (len > len2) {
- if ((h->path[len2] == '/') && (h2->tree)) {
+ if ((h->uri[len2] == '/') && (h2->tree)) {
nni_mtx_unlock(&s->mtx);
return (NNG_EADDRINUSE);
}
diff --git a/src/supplemental/websocket/websocket.c b/src/supplemental/websocket/websocket.c
index 6d4d3c13..18491190 100644
--- a/src/supplemental/websocket/websocket.c
+++ b/src/supplemental/websocket/websocket.c
@@ -75,6 +75,7 @@ struct nni_ws_listener {
nni_ws_listen_hook hookfn;
void * hookarg;
nni_list headers; // response headers
+ size_t maxframe;
};
// The dialer tracks user aios in two lists. The first list is for aios
@@ -94,6 +95,7 @@ struct nni_ws_dialer {
bool closed;
nng_sockaddr sa;
nni_list headers; // request headers
+ size_t maxframe;
};
typedef enum ws_type {
@@ -945,7 +947,7 @@ ws_read_cb(void *arg)
break;
}
- if (frame->len > ws->maxframe) {
+ if ((frame->len > ws->maxframe) && (ws->maxframe > 0)) {
ws_close(ws, WS_CLOSE_TOO_BIG);
nni_mtx_unlock(&ws->mtx);
return;
@@ -1380,7 +1382,6 @@ ws_init(nni_ws **wsp)
nni_aio_set_timeout(ws->httpaio, 2000);
ws->fragsize = 1 << 20; // we won't send a frame larger than this
- ws->maxframe = (1 << 20) * 10; // default limit on incoming frame size
*wsp = ws;
return (0);
}
@@ -1557,12 +1558,13 @@ ws_handler(nni_aio *aio)
status = NNG_HTTP_STATUS_INTERNAL_SERVER_ERROR;
goto err;
}
- ws->http = conn;
- ws->req = req;
- ws->res = res;
- ws->mode = NNI_EP_MODE_LISTEN;
+ ws->http = conn;
+ ws->req = req;
+ ws->res = res;
+ ws->mode = NNI_EP_MODE_LISTEN;
+ ws->maxframe = l->maxframe;
- // XXX: Inherit fragmentation and message size limits!
+ // XXX: Inherit fragmentation? (Frag is limited for now).
nni_list_append(&l->reply, ws);
nni_aio_set_data(ws->httpaio, 0, l);
@@ -1621,7 +1623,8 @@ nni_ws_listener_init(nni_ws_listener **wslp, nni_url *url)
return (rv);
}
- *wslp = l;
+ l->maxframe = 0;
+ *wslp = l;
return (0);
}
@@ -1785,6 +1788,14 @@ nni_ws_listener_get_tls(nni_ws_listener *l, nng_tls_config **tlsp)
}
void
+nni_ws_listener_set_maxframe(nni_ws_listener *l, size_t maxframe)
+{
+ nni_mtx_lock(&l->mtx);
+ l->maxframe = maxframe;
+ nni_mtx_unlock(&l->mtx);
+}
+
+void
ws_conn_cb(void *arg)
{
nni_ws_dialer *d;
@@ -1920,8 +1931,8 @@ nni_ws_dialer_init(nni_ws_dialer **dp, nni_url *url)
nni_ws_dialer_fini(d);
return (rv);
}
-
- *dp = d;
+ d->maxframe = 0;
+ *dp = d;
return (0);
}
@@ -2021,9 +2032,10 @@ nni_ws_dialer_dial(nni_ws_dialer *d, nni_aio *aio)
ws_fini(ws);
return;
}
- ws->dialer = d;
- ws->useraio = aio;
- ws->mode = NNI_EP_MODE_DIAL;
+ ws->dialer = d;
+ ws->useraio = aio;
+ ws->mode = NNI_EP_MODE_DIAL;
+ ws->maxframe = d->maxframe;
nni_list_append(&d->wspend, ws);
nni_http_client_connect(d->client, ws->connaio);
nni_mtx_unlock(&d->mtx);
@@ -2071,6 +2083,14 @@ nni_ws_dialer_header(nni_ws_dialer *d, const char *n, const char *v)
return (rv);
}
+void
+nni_ws_dialer_set_maxframe(nni_ws_dialer *d, size_t maxframe)
+{
+ nni_mtx_lock(&d->mtx);
+ d->maxframe = maxframe;
+ nni_mtx_unlock(&d->mtx);
+}
+
// 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
// the dialer does not confirm the server's response at the HTTP
diff --git a/src/supplemental/websocket/websocket.h b/src/supplemental/websocket/websocket.h
index 546f41a9..9936b10f 100644
--- a/src/supplemental/websocket/websocket.h
+++ b/src/supplemental/websocket/websocket.h
@@ -33,14 +33,16 @@ extern int nni_ws_listener_listen(nni_ws_listener *);
extern void nni_ws_listener_accept(nni_ws_listener *, nng_aio *);
extern void nni_ws_listener_hook(
nni_ws_listener *, nni_ws_listen_hook, void *);
-extern int nni_ws_listener_set_tls(nni_ws_listener *, nng_tls_config *);
-extern int nni_ws_listener_get_tls(nni_ws_listener *, nng_tls_config **s);
+extern int nni_ws_listener_set_tls(nni_ws_listener *, nng_tls_config *);
+extern int nni_ws_listener_get_tls(nni_ws_listener *, nng_tls_config **s);
+extern void nni_ws_listener_set_maxframe(nni_ws_listener *, size_t);
extern int nni_ws_dialer_init(nni_ws_dialer **, nni_url *);
extern void nni_ws_dialer_fini(nni_ws_dialer *);
extern void nni_ws_dialer_close(nni_ws_dialer *);
extern int nni_ws_dialer_proto(nni_ws_dialer *, const char *);
extern int nni_ws_dialer_header(nni_ws_dialer *, const char *, const char *);
+extern void nni_ws_dialer_set_maxframe(nni_ws_dialer *, size_t);
extern void nni_ws_dialer_dial(nni_ws_dialer *, nng_aio *);
extern int nni_ws_dialer_set_tls(nni_ws_dialer *, nng_tls_config *);
extern int nni_ws_dialer_get_tls(nni_ws_dialer *, nng_tls_config **);
diff --git a/src/transport/ws/websocket.c b/src/transport/ws/websocket.c
index 36deddac..97175d49 100644
--- a/src/transport/ws/websocket.c
+++ b/src/transport/ws/websocket.c
@@ -284,7 +284,9 @@ ws_ep_bind(void *arg)
ws_ep *ep = arg;
int rv;
+ nni_ws_listener_set_maxframe(ep->listener, ep->rcvmax);
nni_ws_listener_hook(ep->listener, ws_hook, ep);
+
if ((rv = nni_ws_listener_listen(ep->listener)) == 0) {
ep->started = true;
}
@@ -359,6 +361,7 @@ ws_ep_connect(void *arg, nni_aio *aio)
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);
}
@@ -373,6 +376,11 @@ ws_ep_setopt_recvmaxsz(void *arg, const void *v, size_t sz, int typ)
rv = nni_copyin_size(&val, v, sz, 0, NNI_MAXSZ, typ);
if ((rv == 0) && (ep != NULL)) {
ep->rcvmax = val;
+ if (ep->mode == NNI_EP_MODE_DIAL) {
+ nni_ws_dialer_set_maxframe(ep->dialer, ep->rcvmax);
+ } else {
+ nni_ws_listener_set_maxframe(ep->listener, ep->rcvmax);
+ }
}
return (rv);
}