diff options
Diffstat (limited to 'src/supplemental/http/server.c')
| -rw-r--r-- | src/supplemental/http/server.c | 146 |
1 files changed, 106 insertions, 40 deletions
diff --git a/src/supplemental/http/server.c b/src/supplemental/http/server.c index 01f1230d..700ec536 100644 --- a/src/supplemental/http/server.c +++ b/src/supplemental/http/server.c @@ -69,6 +69,7 @@ struct nni_http_server { nng_tls_config * tls; nni_aio * accaio; nni_plat_tcp_ep *tep; + nni_url * url; }; static nni_list http_servers; @@ -78,13 +79,15 @@ static void http_handler_fini(http_handler *); static void http_sconn_reap(void *arg) { - http_sconn *sc = arg; + http_sconn * sc = arg; + nni_http_server *s = sc->server; NNI_ASSERT(!sc->finished); sc->finished = true; nni_aio_stop(sc->rxaio); nni_aio_stop(sc->txaio); nni_aio_stop(sc->txdataio); nni_aio_stop(sc->cbaio); + if (sc->http != NULL) { nni_http_fini(sc->http); } @@ -98,6 +101,17 @@ http_sconn_reap(void *arg) nni_aio_fini(sc->txaio); nni_aio_fini(sc->txdataio); nni_aio_fini(sc->cbaio); + + // Now it is safe to release our reference on the server. + nni_mtx_lock(&s->mtx); + if (nni_list_node_active(&sc->node)) { + nni_list_remove(&s->conns, sc); + if (nni_list_empty(&s->conns)) { + nni_cv_wake(&s->cv); + } + } + nni_mtx_unlock(&s->mtx); + NNI_FREE_STRUCT(sc); } @@ -120,13 +134,6 @@ http_sconn_close_locked(http_sconn *sc) NNI_ASSERT(!sc->finished); sc->closed = true; - // Close the underlying transport. - if (nni_list_node_active(&sc->node)) { - nni_list_remove(&s->conns, sc); - if (nni_list_empty(&s->conns)) { - nni_cv_wake(&s->cv); - } - } nni_aio_cancel(sc->rxaio, NNG_ECLOSED); nni_aio_cancel(sc->txaio, NNG_ECLOSED); nni_aio_cancel(sc->txdataio, NNG_ECLOSED); @@ -144,10 +151,6 @@ http_sconn_close(http_sconn *sc) nni_http_server *s; s = sc->server; - if (sc->closed) { - return; - } - nni_mtx_lock(&s->mtx); http_sconn_close_locked(sc); nni_mtx_unlock(&s->mtx); @@ -631,6 +634,9 @@ http_server_fini(nni_http_server *s) http_handler_fini(h); } nni_mtx_unlock(&s->mtx); + if (s->url != NULL) { + nni_url_free(s->url); + } #ifdef NNG_SUPP_TLS if (s->tls != NULL) { nni_tls_config_fini(s->tls); @@ -655,14 +661,34 @@ nni_http_server_fini(nni_http_server *s) } static int -http_server_init(nni_http_server **serverp, nng_sockaddr *sa) +http_server_init(nni_http_server **serverp, nni_url *url) { nni_http_server *s; int rv; + const char * host; + const char * port; + nni_aio * aio; + + host = url->u_hostname; + if (strlen(host) == 0) { + host = NULL; + } + port = url->u_port; + if ((strcmp(url->u_scheme, "http") != 0) && +#ifdef NNG_SUPP_TLS + (strcmp(url->u_scheme, "https") != 0) && + (strcmp(url->u_scheme, "wss") != 0) && +#endif + (strcmp(url->u_scheme, "ws") != 0)) { + nni_url_free(url); + return (NNG_EADDRINVAL); + } if ((s = NNI_ALLOC_STRUCT(s)) == NULL) { + nni_url_free(url); return (NNG_ENOMEM); } + s->url = url; nni_mtx_init(&s->mtx); nni_cv_init(&s->cv, &s->mtx); NNI_LIST_INIT(&s->handlers, http_handler, node); @@ -671,49 +697,71 @@ http_server_init(nni_http_server **serverp, nng_sockaddr *sa) http_server_fini(s); return (rv); } - s->addr = *sa; - *serverp = s; +#ifdef NNG_SUPP_TLS + if ((strcmp(url->u_scheme, "https") == 0) || + (strcmp(url->u_scheme, "wss") == 0)) { + rv = nni_tls_config_init(&s->tls, NNG_TLS_MODE_SERVER); + if (rv != 0) { + http_server_fini(s); + return (rv); + } + } +#endif + + // Do the DNS lookup *now*. This means that this is synchronous, + // but it should be fast, since it should either resolve as a number, + // or resolve locally, without having to hit up DNS. + if ((rv = nni_aio_init(&aio, NULL, NULL)) != 0) { + http_server_fini(s); + return (rv); + } + aio->a_addr = &s->addr; + host = (strlen(url->u_hostname) != 0) ? url->u_hostname : NULL; + port = (strlen(url->u_port) != 0) ? url->u_port : NULL; + nni_plat_tcp_resolv(host, port, NNG_AF_UNSPEC, true, aio); + nni_aio_wait(aio); + rv = nni_aio_result(aio); + nni_aio_fini(aio); + if (rv != 0) { + http_server_fini(s); + return (rv); + } + s->refcnt = 1; + *serverp = s; return (0); } int -nni_http_server_init(nni_http_server **serverp, nng_sockaddr *sa) +nni_http_server_init(nni_http_server **serverp, const char *urlstr) { int rv; nni_http_server *s; + nni_url * url; + + if ((rv = nni_url_parse(&url, urlstr)) != 0) { + return (rv); + } nni_initialize(&http_server_initializer); nni_mtx_lock(&http_servers_lk); NNI_LIST_FOREACH (&http_servers, s) { - switch (sa->s_un.s_family) { - case NNG_AF_INET: - if (memcmp(&s->addr.s_un.s_in, &sa->s_un.s_in, - sizeof(sa->s_un.s_in)) == 0) { - *serverp = s; - s->refcnt++; - nni_mtx_unlock(&http_servers_lk); - return (0); - } - break; - case NNG_AF_INET6: - if (memcmp(&s->addr.s_un.s_in6, &sa->s_un.s_in6, - sizeof(sa->s_un.s_in6)) == 0) { - *serverp = s; - s->refcnt++; - nni_mtx_unlock(&http_servers_lk); - return (0); - } - break; + if ((strcmp(url->u_port, s->url->u_port) == 0) && + (strcmp(url->u_hostname, s->url->u_hostname) == 0)) { + nni_url_free(url); + *serverp = s; + s->refcnt++; + nni_mtx_unlock(&http_servers_lk); + return (0); } } // We didn't find a server, try to make a new one. - if ((rv = http_server_init(&s, sa)) == 0) { - s->addr = *sa; - s->refcnt = 1; + if ((rv = http_server_init(&s, url)) == 0) { nni_list_append(&http_servers, s); *serverp = s; + } else { + nni_url_free(url); } nni_mtx_unlock(&http_servers_lk); @@ -724,7 +772,6 @@ static int http_server_start(nni_http_server *s) { int rv; - rv = nni_plat_tcp_ep_init(&s->tep, &s->addr, NULL, NNI_EP_MODE_LISTEN); if (rv != 0) { return (rv); @@ -1116,10 +1163,10 @@ nni_http_server_add_static(nni_http_server *s, const char *host, return (0); } -#ifdef NNG_SUPP_TLS int nni_http_server_set_tls(nni_http_server *s, nng_tls_config *tcfg) { +#ifdef NNG_SUPP_TLS nng_tls_config *old; nni_mtx_lock(&s->mtx); if (s->starts) { @@ -1136,8 +1183,27 @@ nni_http_server_set_tls(nni_http_server *s, nng_tls_config *tcfg) nni_tls_config_fini(old); } return (0); +#else + return (NNG_ENOTSUP); +#endif } + +int +nni_http_server_get_tls(nni_http_server *s, nng_tls_config **tp) +{ +#ifdef NNG_SUPP_TLS + nni_mtx_lock(&s->mtx); + if (s->tls == NULL) { + nni_mtx_unlock(&s->mtx); + return (NNG_EINVAL); + } + *tp = s->tls; + nni_mtx_unlock(&s->mtx); + return (0); +#else + return (NNG_ENOTSUP); #endif +} static int http_server_sys_init(void) |
