diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/supplemental/http/http_api.h | 17 | ||||
| -rw-r--r-- | src/supplemental/http/http_conn.c | 36 | ||||
| -rw-r--r-- | src/supplemental/http/http_msg.c | 46 | ||||
| -rw-r--r-- | src/supplemental/http/http_public.c | 12 | ||||
| -rw-r--r-- | src/supplemental/http/http_server.c | 230 | ||||
| -rw-r--r-- | src/supplemental/http/http_server_test.c | 12 | ||||
| -rw-r--r-- | src/supplemental/websocket/websocket.c | 78 |
7 files changed, 197 insertions, 234 deletions
diff --git a/src/supplemental/http/http_api.h b/src/supplemental/http/http_api.h index a6dfa6ca..1630198d 100644 --- a/src/supplemental/http/http_api.h +++ b/src/supplemental/http/http_api.h @@ -114,12 +114,13 @@ extern int nni_http_conn_getopt( extern int nni_http_req_alloc(nni_http_req **, const nng_url *); extern int nni_http_res_alloc(nni_http_res **); extern int nni_http_res_alloc_error(nni_http_res **, uint16_t); +extern int nni_http_res_set_error(nni_http_res *, uint16_t); extern void nni_http_req_free(nni_http_req *); extern void nni_http_res_free(nni_http_res *); extern void nni_http_write_req(nni_http_conn *, nni_http_req *, nni_aio *); -extern void nni_http_write_res(nni_http_conn *, nni_http_res *, nni_aio *); -extern void nni_http_read_req(nni_http_conn *, nni_http_req *, nni_aio *); extern void nni_http_read_res(nni_http_conn *, nni_http_res *, nni_aio *); +extern void nni_http_read_req(nni_http_conn *, nni_aio *); +extern void nni_http_write_res(nni_http_conn *, nni_aio *); extern const char *nni_http_req_get_header(const nni_http_req *, const char *); extern const char *nni_http_res_get_header(const nni_http_res *, const char *); @@ -258,15 +259,8 @@ extern int nni_http_hijack(nni_http_conn *); // Note that methods which modify a handler cannot be called while the handler // is registered with the server, and that a handler can only be registered // once per server. -// -// The callback function will receive the following arguments (via -// nng_aio_get_input(): nni_http_request *, nni_http_handler *, and -// nni_http_conn_t *. The first is a request object, for convenience. -// The second is the handler, from which the callback can obtain any other -// data it has set. The final is the http context, from which its possible -// to hijack the session. extern int nni_http_handler_init( - nni_http_handler **, const char *, void (*)(nni_aio *)); + nni_http_handler **, const char *, nng_http_handler_func); // nni_http_handler_init_file creates a handler with a function to serve // up a file named in the last argument. @@ -395,4 +389,7 @@ extern void nni_http_transact( // upper layer scheme. extern const char *nni_http_stream_scheme(const char *); +// Private method used for the server. +extern bool nni_http_conn_res_sent(nni_http_conn *conn); + #endif // NNG_SUPPLEMENTAL_HTTP_HTTP_API_H diff --git a/src/supplemental/http/http_conn.c b/src/supplemental/http/http_conn.c index 912f2cc9..9ed882f1 100644 --- a/src/supplemental/http/http_conn.c +++ b/src/supplemental/http/http_conn.c @@ -63,6 +63,8 @@ struct nng_http_conn { size_t rd_bufsz; bool rd_buffered; + bool res_sent; + enum write_flavor wr_flavor; }; @@ -509,10 +511,13 @@ http_wr_submit(nni_http_conn *conn, nni_aio *aio, enum write_flavor flavor) } void -nni_http_read_req(nni_http_conn *conn, nni_http_req *req, nni_aio *aio) +nni_http_read_req(nni_http_conn *conn, nni_aio *aio) { - nni_aio_set_prov_data(aio, req); + nni_aio_set_prov_data(aio, &conn->req); + // clear the sent flag (used for the server) + conn->res_sent = false; + nni_http_req_reset(&conn->req); nni_mtx_lock(&conn->mtx); http_rd_submit(conn, aio, HTTP_RD_REQ); nni_mtx_unlock(&conn->mtx); @@ -590,16 +595,18 @@ nni_http_write_req(nni_http_conn *conn, nni_http_req *req, nni_aio *aio) } void -nni_http_write_res(nni_http_conn *conn, nni_http_res *res, nni_aio *aio) +nni_http_write_res(nni_http_conn *conn, nni_aio *aio) { - int rv; - void *buf; - size_t bufsz; - void *data; - size_t size; - nni_iov iov[2]; - int nio; - + int rv; + void *buf; + size_t bufsz; + void *data; + size_t size; + nni_iov iov[2]; + int nio; + nng_http_res *res = nng_http_conn_res(conn); + + conn->res_sent = true; if ((rv = nni_http_res_get_buf(res, &buf, &bufsz)) != 0) { nni_aio_finish_error(aio, rv); return; @@ -713,3 +720,10 @@ nni_http_conn_init(nni_http_conn **connp, nng_stream *stream) } return (rv); } + +// private to the HTTP framework, used on the server +bool +nni_http_conn_res_sent(nni_http_conn *conn) +{ + return (conn->res_sent); +} diff --git a/src/supplemental/http/http_msg.c b/src/supplemental/http/http_msg.c index 08c594ac..6b12496c 100644 --- a/src/supplemental/http/http_msg.c +++ b/src/supplemental/http/http_msg.c @@ -263,8 +263,10 @@ static int http_entity_alloc_data(nni_http_entity *entity, size_t size) { void *newdata; - if ((newdata = nni_zalloc(size)) == NULL) { - return (NNG_ENOMEM); + if (size != 0) { + if ((newdata = nni_zalloc(size)) == NULL) { + return (NNG_ENOMEM); + } } http_entity_set_data(entity, newdata, size); entity->own = true; @@ -1057,25 +1059,37 @@ nni_http_alloc_html_error(char **html, uint16_t code, const char *details) } int -nni_http_res_alloc_error(nni_http_res **resp, uint16_t err) +nni_http_res_set_error(nni_http_res *res, uint16_t err) { - char *html = NULL; - nni_http_res *res = NULL; - int rv; - - if (((rv = nni_http_res_alloc(&res)) != 0) || - ((rv = nni_http_alloc_html_error(&html, err, NULL)) != 0) || + int rv; + char *html = NULL; + if (((rv = nni_http_alloc_html_error(&html, err, NULL)) != 0) || ((rv = nni_http_res_set_header( res, "Content-Type", "text/html; charset=UTF-8")) != 0) || ((rv = nni_http_res_copy_data(res, html, strlen(html))) != 0)) { nni_strfree(html); - nni_http_res_free(res); - } else { - nni_strfree(html); - res->code = err; - res->iserr = true; - *resp = res; + return (rv); } + nni_strfree(html); + res->code = err; + res->iserr = true; + return (0); +} - return (rv); +int +nni_http_res_alloc_error(nni_http_res **resp, uint16_t err) +{ + nni_http_res *res; + int rv; + + if ((rv = nni_http_res_alloc(&res)) != 0) { + return (rv); + } + rv = nni_http_res_set_error(res, err); + if (rv != 0) { + nni_http_res_free(res); + return (rv); + } + *resp = res; + return (0); } diff --git a/src/supplemental/http/http_public.c b/src/supplemental/http/http_public.c index 8a81404e..dd35151a 100644 --- a/src/supplemental/http/http_public.c +++ b/src/supplemental/http/http_public.c @@ -482,25 +482,23 @@ nng_http_conn_write_req(nng_http_conn *conn, nng_http_req *req, nng_aio *aio) } void -nng_http_conn_write_res(nng_http_conn *conn, nng_http_res *res, nng_aio *aio) +nng_http_conn_write_res(nng_http_conn *conn, nng_aio *aio) { #ifdef NNG_SUPP_HTTP - nni_http_write_res(conn, res, aio); + nni_http_write_res(conn, aio); #else NNI_ARG_UNUSED(conn); - NNI_ARG_UNUSED(res); nni_aio_finish_error(aio, NNG_ENOTSUP); #endif } void -nng_http_conn_read_req(nng_http_conn *conn, nng_http_req *req, nng_aio *aio) +nng_http_conn_read_req(nng_http_conn *conn, nng_aio *aio) { #ifdef NNG_SUPP_HTTP - nni_http_read_req(conn, req, aio); + nni_http_read_req(conn, aio); #else NNI_ARG_UNUSED(conn); - NNI_ARG_UNUSED(req); nni_aio_finish_error(aio, NNG_ENOTSUP); #endif } @@ -519,7 +517,7 @@ nng_http_conn_read_res(nng_http_conn *conn, nng_http_res *res, nng_aio *aio) int nng_http_handler_alloc( - nng_http_handler **hp, const char *uri, void (*cb)(nng_aio *)) + nng_http_handler **hp, const char *uri, nng_http_handler_func cb) { #ifdef NNG_SUPP_HTTP return (nni_http_handler_init(hp, uri, cb)); diff --git a/src/supplemental/http/http_server.c b/src/supplemental/http/http_server.c index c6c453c9..87285417 100644 --- a/src/supplemental/http/http_server.c +++ b/src/supplemental/http/http_server.c @@ -1,5 +1,5 @@ // -// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech> +// Copyright 2025 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2018 Capitar IT Group BV <info@capitar.com> // Copyright 2018 QXSoftware <lh563566994@126.com> // Copyright 2019 Devolutions <info@devolutions.net> @@ -20,35 +20,35 @@ #include "core/nng_impl.h" #include "http_api.h" +#include "nng/supplemental/http/http.h" #ifndef NNG_HTTP_MAX_URI #define NNG_HTTP_MAX_URI 1024 #endif struct nng_http_handler { - nni_list_node node; - char uri[NNG_HTTP_MAX_URI]; - char method[32]; - char host[256]; // RFC 1035 - nng_sockaddr host_addr; - bool host_ip; - bool tree; - bool tree_exclusive; - nni_atomic_int ref; - nni_atomic_bool busy; - size_t maxbody; - bool getbody; - void *data; - nni_cb dtor; - void (*cb)(nni_aio *); + nni_list_node node; + char uri[NNG_HTTP_MAX_URI]; + char method[32]; + char host[256]; // RFC 1035 + nng_sockaddr host_addr; + bool host_ip; + bool tree; + bool tree_exclusive; + nni_atomic_int ref; + nni_atomic_bool busy; + size_t maxbody; + bool getbody; + void *data; + nni_cb dtor; + nng_http_handler_func cb; + void *arg; }; typedef struct http_sconn { nni_list_node node; nni_http_conn *conn; nni_http_server *server; - nni_http_req *req; - nni_http_res *res; nni_http_handler *handler; // set if we deferred to read body nni_http_handler *release; // set if we dispatched handler bool close; @@ -103,7 +103,7 @@ static nni_reap_list http_server_reap_list = { int nni_http_handler_init( - nni_http_handler **hp, const char *uri, void (*cb)(nni_aio *)) + nni_http_handler **hp, const char *uri, nng_http_handler_func cb) { nni_http_handler *h; @@ -255,8 +255,6 @@ http_sc_reap(void *arg) if (sc->conn != NULL) { nni_http_conn_fini(sc->conn); } - nni_http_req_free(sc->req); - nni_http_res_free(sc->res); nni_aio_fini(&sc->rxaio); nni_aio_fini(&sc->txaio); nni_aio_fini(&sc->txdataio); @@ -307,17 +305,13 @@ http_sconn_txdatdone(void *arg) return; } - nni_http_res_free(sc->res); - sc->res = NULL; - if (sc->close) { http_sconn_close(sc); return; } sc->handler = NULL; - nni_http_req_reset(sc->req); - nni_http_read_req(sc->conn, sc->req, &sc->rxaio); + nni_http_read_req(sc->conn, &sc->rxaio); } static void @@ -336,11 +330,8 @@ http_sconn_txdone(void *arg) return; } - nni_http_res_free(sc->res); - sc->res = NULL; sc->handler = NULL; - nni_http_req_reset(sc->req); - nni_http_read_req(sc->conn, sc->req, &sc->rxaio); + nni_http_read_req(sc->conn, &sc->rxaio); } static char @@ -425,26 +416,20 @@ http_sconn_error(http_sconn *sc, uint16_t err) { nni_http_res *res; - if (nni_http_res_alloc(&res) != 0) { - http_sconn_close(sc); - return; - } + res = nng_http_conn_res(sc->conn); nni_http_res_set_status(res, err); if (nni_http_server_res_error(sc->server, res) != 0) { - nni_http_res_free(res); http_sconn_close(sc); return; } if (sc->close) { if (nni_http_res_set_header(res, "Connection", "close") != 0) { - nni_http_res_free(res); http_sconn_close(sc); return; } } - sc->res = res; - nni_http_write_res(sc->conn, res, &sc->txaio); + nni_http_write_res(sc->conn, &sc->txaio); } int @@ -459,7 +444,6 @@ nni_http_hijack(nni_http_conn *conn) nni_mtx_lock(&s->mtx); sc->conn = NULL; - sc->req = NULL; nni_mtx_unlock(&s->mtx); } return (0); @@ -531,7 +515,7 @@ http_sconn_rxdone(void *arg) nni_http_handler *h = NULL; nni_http_handler *head = NULL; const char *val; - nni_http_req *req = sc->req; + nni_http_req *req = nng_http_conn_req(sc->conn); char *uri; size_t urisz; char *path; @@ -693,9 +677,6 @@ http_sconn_rxdone(void *arg) finish: sc->release = h; sc->handler = NULL; - nni_aio_set_input(&sc->cbaio, 0, sc->req); - nni_aio_set_input(&sc->cbaio, 1, h); - nni_aio_set_input(&sc->cbaio, 2, sc->conn); // Set a reference -- this because the callback may be running // asynchronously even after it gets removed from the server. @@ -704,7 +685,11 @@ finish: nni_aio_reset(&sc->cbaio); nni_mtx_unlock(&s->mtx); - h->cb(&sc->cbaio); + + // make sure the response is freshly initialized + nni_http_res_reset(nni_http_conn_res(sc->conn)); + + h->cb(sc->conn, h->data, &sc->cbaio); } static void @@ -730,8 +715,6 @@ http_sconn_cbdone(void *arg) return; } - res = nni_aio_get_output(aio, 0); - // If it's an upgrader, and they didn't give us back a response, // it means that they took over, and we should just discard // this session, without closing the underlying channel. @@ -741,7 +724,8 @@ http_sconn_cbdone(void *arg) http_sconn_close(sc); return; } - if (res != NULL) { + res = nni_http_conn_res(sc->conn); + if (!nni_http_conn_res_sent(sc->conn)) { const char *val; val = nni_http_res_get_header(res, "Connection"); if ((val != NULL) && (strstr(val, "close") != NULL)) { @@ -750,8 +734,9 @@ http_sconn_cbdone(void *arg) if (sc->close) { nni_http_res_set_header(res, "Connection", "close"); } - sc->res = res; - if (strcmp(nni_http_req_get_method(sc->req), "HEAD") == 0) { + if (strcmp( + nni_http_req_get_method(nng_http_conn_req(sc->conn)), + "HEAD") == 0) { void *data; size_t size; // prune off the data, but preserve the content-length @@ -763,15 +748,14 @@ http_sconn_cbdone(void *arg) } else if (nni_http_res_is_error(res)) { (void) nni_http_server_res_error(s, res); } - nni_http_write_res(sc->conn, res, &sc->txaio); + nni_http_write_res(sc->conn, &sc->txaio); } else if (sc->close) { http_sconn_close(sc); } else { // Presumably client already sent a response. // Wait for another request. sc->handler = NULL; - nni_http_req_reset(sc->req); - nni_http_read_req(sc->conn, sc->req, &sc->rxaio); + nni_http_read_req(sc->conn, &sc->rxaio); } } @@ -791,8 +775,7 @@ http_sconn_init(http_sconn **scp, nng_stream *stream) nni_aio_init(&sc->txdataio, http_sconn_txdatdone, sc); nni_aio_init(&sc->cbaio, http_sconn_cbdone, sc); - if (((rv = nni_http_req_alloc(&sc->req, NULL)) != 0) || - ((rv = nni_http_conn_init(&sc->conn, stream)) != 0)) { + if ((rv = nni_http_conn_init(&sc->conn, stream)) != 0) { // Can't even accept the incoming request. Hard close. http_sconn_close(sc); return (rv); @@ -839,7 +822,7 @@ http_server_acccb(void *arg) nni_list_append(&s->conns, sc); sc->handler = NULL; - nni_http_read_req(sc->conn, sc->req, &sc->rxaio); + nni_http_read_req(sc->conn, &sc->rxaio); nng_stream_listener_accept(s->listener, aio); nni_mtx_unlock(&s->mtx); } @@ -1333,20 +1316,20 @@ http_lookup_type(const char *path) } typedef struct http_file { + char *base; char *path; char *ctype; } http_file; static void -http_handle_file(nni_aio *aio) +http_handle_file(nni_http_conn *conn, void *arg, nni_aio *aio) { - nni_http_handler *h = nni_aio_get_input(aio, 1); - nni_http_res *res = NULL; - void *data; - size_t size; - int rv; - http_file *hf = nni_http_handler_get_data(h); - const char *ctype; + nni_http_res *res = nng_http_conn_res(conn); + void *data; + size_t size; + int rv; + http_file *hf = arg; + const char *ctype; if ((ctype = hf->ctype) == NULL) { ctype = "application/octet-stream"; @@ -1373,7 +1356,7 @@ http_handle_file(nni_aio *aio) status = NNG_HTTP_STATUS_INTERNAL_SERVER_ERROR; break; } - if ((rv = nni_http_res_alloc_error(&res, status)) != 0) { + if ((rv = nni_http_res_set_error(res, status)) != 0) { nni_aio_finish_error(aio, rv); return; } @@ -1381,11 +1364,9 @@ http_handle_file(nni_aio *aio) nni_aio_finish(aio, 0, 0); return; } - if (((rv = nni_http_res_alloc(&res)) != 0) || - ((rv = nni_http_res_set_header(res, "Content-Type", ctype)) != + if (((rv = nni_http_res_set_header(res, "Content-Type", ctype)) != 0) || ((rv = nni_http_res_copy_data(res, data, size)) != 0)) { - nni_http_res_free(res); nni_free(data, size); nni_aio_finish_error(aio, rv); return; @@ -1405,6 +1386,7 @@ http_file_free(void *arg) if ((hf = arg) != NULL) { nni_strfree(hf->path); nni_strfree(hf->ctype); + nni_strfree(hf->base); NNI_FREE_STRUCT(hf); } } @@ -1457,23 +1439,22 @@ nni_http_handler_init_file( } static void -http_handle_dir(nni_aio *aio) +http_handle_dir(nng_http_conn *conn, void *arg, nng_aio *aio) { - nni_http_req *req = nni_aio_get_input(aio, 0); - nni_http_handler *h = nni_aio_get_input(aio, 1); - nni_http_res *res = NULL; - void *data; - size_t size; - int rv; - http_file *hf = nni_http_handler_get_data(h); - const char *path = hf->path; - const char *base = nni_http_handler_get_uri(h); // base uri - const char *uri = nni_http_req_get_uri(req); - const char *ctype; - char *dst; - size_t len; - size_t pnsz; - char *pn; + nni_http_req *req = nni_http_conn_req(conn); + nni_http_res *res = nni_http_conn_res(conn); + void *data; + size_t size; + int rv; + http_file *hf = arg; + const char *path = hf->path; + const char *base = hf->base; + const char *uri = nni_http_req_get_uri(req); + const char *ctype; + char *dst; + size_t len; + size_t pnsz; + char *pn; len = strlen(base); if (base[1] != '\0' && // Allows "/" as base @@ -1563,7 +1544,7 @@ http_handle_dir(nni_aio *aio) status = NNG_HTTP_STATUS_INTERNAL_SERVER_ERROR; break; } - if ((rv = nni_http_res_alloc_error(&res, status)) != 0) { + if ((rv = nni_http_res_set_error(res, status)) != 0) { nni_aio_finish_error(aio, rv); return; } @@ -1572,11 +1553,9 @@ http_handle_dir(nni_aio *aio) return; } - if (((rv = nni_http_res_alloc(&res)) != 0) || - ((rv = nni_http_res_set_header(res, "Content-Type", ctype)) != + if (((rv = nni_http_res_set_header(res, "Content-Type", ctype)) != 0) || ((rv = nni_http_res_copy_data(res, data, size)) != 0)) { - nni_http_res_free(res); nni_free(data, size); nni_aio_finish_error(aio, rv); return; @@ -1600,8 +1579,9 @@ nni_http_handler_init_directory( if ((hf = NNI_ALLOC_STRUCT(hf)) == NULL) { return (NNG_ENOMEM); } - if ((hf->path = nni_strdup(path)) == NULL) { - NNI_FREE_STRUCT(hf); + if (((hf->path = nni_strdup(path)) == NULL) || + ((hf->base = nni_strdup(uri)) == NULL)) { + http_file_free(hf); return (NNG_ENOMEM); } @@ -1621,29 +1601,25 @@ nni_http_handler_init_directory( typedef struct http_redirect { uint16_t code; char *where; + char *from; } http_redirect; static void -http_handle_redirect(nni_aio *aio) +http_handle_redirect(nng_http_conn *conn, void *data, nng_aio *aio) { - nni_http_res *r = NULL; - char *html = NULL; - char *msg = NULL; - char *loc = NULL; - http_redirect *hr; - nni_http_handler *h; - int rv; - nni_http_req *req; - const char *base; - const char *uri; - - req = nni_aio_get_input(aio, 0); - h = nni_aio_get_input(aio, 1); - base = nni_http_handler_get_uri(h); // base uri + nni_http_res *res = nng_http_conn_res(conn); + nni_http_req *req = nng_http_conn_req(conn); + char *html = NULL; + char *msg = NULL; + char *loc = NULL; + http_redirect *hr = data; + int rv; + const char *base; + const char *uri; + + base = hr->from; // base uri uri = nni_http_req_get_uri(req); - hr = nni_http_handler_get_data(h); - // If we are doing a full tree, then include the entire suffix. if (strncmp(uri, base, strlen(base)) == 0) { rv = nni_asprintf(&loc, "%s%s", hr->where, uri + strlen(base)); @@ -1664,31 +1640,31 @@ http_handle_redirect(nni_aio *aio) // because it is probably going to another server. This also // keeps us from having to consume the entity body, we can just // discard it. - if ((rv != 0) || ((rv = nni_http_res_alloc(&r)) != 0) || + if ((rv != 0) || ((rv = nni_http_alloc_html_error(&html, hr->code, msg)) != 0) || - ((rv = nni_http_res_set_header(r, "Connection", "close")) != 0) || + ((rv = nni_http_res_set_header(res, "Connection", "close")) != + 0) || ((rv = nni_http_res_set_header( - r, "Content-Type", "text/html; charset=UTF-8")) != 0) || - ((rv = nni_http_res_set_header(r, "Location", loc)) != 0) || - ((rv = nni_http_res_copy_data(r, html, strlen(html))) != 0)) { + res, "Content-Type", "text/html; charset=UTF-8")) != 0) || + ((rv = nni_http_res_set_header(res, "Location", loc)) != 0) || + ((rv = nni_http_res_copy_data(res, html, strlen(html))) != 0)) { if (loc != hr->where) { nni_strfree(loc); } nni_strfree(msg); nni_strfree(html); - nni_http_res_free(r); nni_aio_finish_error(aio, rv); return; } - nni_http_res_set_status(r, hr->code); + nni_http_res_set_status(res, hr->code); if (loc != hr->where) { nni_strfree(loc); } nni_strfree(msg); nni_strfree(html); - nni_aio_set_output(aio, 0, r); + nni_aio_set_output(aio, 0, res); nni_aio_finish(aio, 0, 0); } @@ -1699,6 +1675,7 @@ http_redirect_free(void *arg) if ((hr = arg) != NULL) { nni_strfree(hr->where); + nni_strfree(hr->from); NNI_FREE_STRUCT(hr); } } @@ -1714,8 +1691,9 @@ nni_http_handler_init_redirect(nni_http_handler **hpp, const char *uri, if ((hr = NNI_ALLOC_STRUCT(hr)) == NULL) { return (NNG_ENOMEM); } - if ((hr->where = nni_strdup(where)) == NULL) { - NNI_FREE_STRUCT(hr); + if (((hr->where = nni_strdup(where)) == NULL) || + ((hr->from = nni_strdup(uri)) == NULL)) { + http_redirect_free(hr); return (NNG_ENOMEM); } if (status == 0) { @@ -1747,25 +1725,21 @@ typedef struct http_static { } http_static; static void -http_handle_static(nni_aio *aio) +http_handle_static(nng_http_conn *conn, void *data, nni_aio *aio) { - http_static *hs; - const char *ctype; - nni_http_handler *h; - nni_http_res *r = NULL; - int rv; - - h = nni_aio_get_input(aio, 1); - hs = nni_http_handler_get_data(h); + http_static *hs = data; + const char *ctype; + nni_http_res *r = NULL; + int rv; if ((ctype = hs->ctype) == NULL) { ctype = "application/octet-stream"; } - if (((rv = nni_http_res_alloc(&r)) != 0) || - ((rv = nni_http_res_set_header(r, "Content-Type", ctype)) != 0) || + r = nng_http_conn_res(conn); + nng_http_res_reset(r); + if (((rv = nni_http_res_set_header(r, "Content-Type", ctype)) != 0) || ((rv = nni_http_res_set_data(r, hs->data, hs->size)) != 0)) { - nni_http_res_free(r); nni_aio_finish_error(aio, rv); return; } diff --git a/src/supplemental/http/http_server_test.c b/src/supplemental/http/http_server_test.c index 37c45f14..91411499 100644 --- a/src/supplemental/http/http_server_test.c +++ b/src/supplemental/http/http_server_test.c @@ -10,6 +10,7 @@ // // Basic HTTP server tests. +#include "core/defs.h" #include <nng/nng.h> #include <nng/supplemental/http/http.h> @@ -141,21 +142,20 @@ fail: } static void -httpecho(nng_aio *aio) +httpecho(nng_http_conn *conn, void *arg, nng_aio *aio) { - nng_http_req *req = nng_aio_get_input(aio, 0); - nng_http_res *res; + nng_http_req *req = nng_http_conn_req(conn); + nng_http_res *res = nng_http_conn_res(conn); int rv; void *body; size_t len; + NNI_ARG_UNUSED(arg); nng_http_req_get_data(req, &body, &len); - if (((rv = nng_http_res_alloc(&res)) != 0) || - ((rv = nng_http_res_copy_data(res, body, len)) != 0) || + if (((rv = nng_http_res_copy_data(res, body, len)) != 0) || ((rv = nng_http_res_set_header( res, "Content-type", "text/plain")) != 0)) { - nng_http_res_free(res); nng_aio_finish(aio, rv); return; } diff --git a/src/supplemental/websocket/websocket.c b/src/supplemental/websocket/websocket.c index 84d3fd72..70323b0c 100644 --- a/src/supplemental/websocket/websocket.c +++ b/src/supplemental/websocket/websocket.c @@ -1,5 +1,5 @@ // -// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech> +// Copyright 2025 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2018 Capitar IT Group BV <info@capitar.com> // Copyright 2019 Devolutions <info@devolutions.net> // @@ -1243,12 +1243,6 @@ ws_fini(void *arg) if (ws->http) { nni_http_conn_fini(ws->http); } - if (ws->req) { - nni_http_req_free(ws->req); - } - if (ws->res) { - nni_http_res_free(ws->res); - } nni_strfree(ws->reqhdrs); nni_strfree(ws->reshdrs); @@ -1332,9 +1326,7 @@ ws_http_cb_dialer(nni_ws *ws, nni_aio *aio) // If we have no response structure, then this was completion // of sending the request. Prepare an empty response, and read it. if (ws->res == NULL) { - if ((rv = nni_http_res_alloc(&ws->res)) != 0) { - goto err; - } + ws->res = nni_http_conn_res(ws->http); nni_http_read_res(ws->http, ws->res, &ws->httpaio); nni_mtx_unlock(&d->mtx); return; @@ -1514,25 +1506,19 @@ ws_listener_free(void *arg) } static void -ws_handler(nni_aio *aio) +ws_handler(nng_http_conn *conn, void *arg, nng_aio *aio) { - nni_ws_listener *l; - nni_ws *ws; - nni_http_conn *conn; - nni_http_req *req; - nni_http_res *res; - nni_http_handler *h; - const char *ptr; - const char *proto; - uint16_t status; - int rv; - char key[29]; - ws_header *hdr; - - req = nni_aio_get_input(aio, 0); - h = nni_aio_get_input(aio, 1); - conn = nni_aio_get_input(aio, 2); - l = nni_http_handler_get_data(h); + nni_ws_listener *l = arg; + ; + nni_http_req *req = nng_http_conn_req(conn); + nni_http_res *res = nng_http_conn_res(conn); + nni_ws *ws; + const char *ptr; + const char *proto; + uint16_t status; + int rv; + char key[29]; + ws_header *hdr; nni_mtx_lock(&l->mtx); if (l->closed) { @@ -1595,24 +1581,16 @@ ws_handler(nni_aio *aio) goto err; } - if ((rv = nni_http_res_alloc(&res)) != 0) { - // Give a chance to reply to client. - status = NNG_HTTP_STATUS_INTERNAL_SERVER_ERROR; - goto err; - } - nni_http_res_set_status(res, NNG_HTTP_STATUS_SWITCHING); if ((SETH("Connection", "Upgrade") != 0) || (SETH("Upgrade", "websocket") != 0) || (SETH("Sec-WebSocket-Accept", key) != 0)) { status = NNG_HTTP_STATUS_INTERNAL_SERVER_ERROR; - nni_http_res_free(res); goto err; } if ((proto != NULL) && (SETH("Sec-WebSocket-Protocol", proto) != 0)) { status = NNG_HTTP_STATUS_INTERNAL_SERVER_ERROR; - nni_http_res_free(res); goto err; } @@ -1621,7 +1599,6 @@ ws_handler(nni_aio *aio) NNI_LIST_FOREACH (&l->headers, hdr) { if (SETH(hdr->name, hdr->value) != 0) { status = NNG_HTTP_STATUS_INTERNAL_SERVER_ERROR; - nni_http_res_free(res); goto err; } } @@ -1633,7 +1610,6 @@ ws_handler(nni_aio *aio) if (l->hookfn != NULL) { rv = l->hookfn(l->hookarg, req, res); if (rv != 0) { - nni_http_res_free(res); nni_aio_finish_error(aio, rv); nni_mtx_unlock(&l->mtx); return; @@ -1649,7 +1625,6 @@ ws_handler(nni_aio *aio) // the hook can also give back various other // headers, but it would be bad for it to alter // the websocket mandated headers.) - nni_http_req_free(req); nni_aio_set_output(aio, 0, res); nni_aio_finish(aio, 0, 0); nni_mtx_unlock(&l->mtx); @@ -1663,8 +1638,6 @@ ws_handler(nni_aio *aio) // We are good to go, provided we can get the websocket struct, // and send the reply. if ((rv = ws_init(&ws)) != 0) { - nni_http_req_free(req); - nni_http_res_free(res); status = NNG_HTTP_STATUS_INTERNAL_SERVER_ERROR; goto err; } @@ -1681,7 +1654,7 @@ ws_handler(nni_aio *aio) ws->listener = l; nni_list_append(&l->reply, ws); - nni_http_write_res(conn, res, &ws->httpaio); + nni_http_write_res(conn, &ws->httpaio); (void) nni_http_hijack(conn); nni_aio_set_output(aio, 0, NULL); nni_aio_finish(aio, 0, 0); @@ -1689,7 +1662,7 @@ ws_handler(nni_aio *aio) return; err: - if ((rv = nni_http_res_alloc_error(&res, status)) != 0) { + if ((rv = nni_http_res_set_error(res, status)) != 0) { nni_aio_finish_error(aio, rv); } else { nni_aio_set_output(aio, 0, res); @@ -2174,7 +2147,6 @@ ws_conn_cb(void *arg) nni_ws_dialer *d; nni_ws *ws; nni_aio *uaio; - nni_http_conn *http; nni_http_req *req = NULL; int rv; uint8_t raw[16]; @@ -2206,13 +2178,12 @@ ws_conn_cb(void *arg) return; } + ws->http = nni_aio_get_output(&ws->connaio, 0); nni_mtx_lock(&ws->mtx); uaio = ws->useraio; - http = nni_aio_get_output(&ws->connaio, 0); nni_aio_set_output(&ws->connaio, 0, NULL); if (uaio == NULL) { // This request was canceled for some reason. - nni_http_conn_fini(http); nni_mtx_unlock(&ws->mtx); ws_reap(ws); return; @@ -2224,8 +2195,10 @@ ws_conn_cb(void *arg) nni_base64_encode(raw, 16, wskey, 24); wskey[24] = '\0'; + req = nni_http_conn_req(ws->http); + #define SETH(h, v) nni_http_req_set_header(req, h, v) - if ((rv != 0) || ((rv = nni_http_req_alloc(&req, d->url)) != 0) || + if ((rv != 0) || ((rv = nni_http_req_set_url(req, d->url)) != 0) || ((rv = SETH("Upgrade", "websocket")) != 0) || ((rv = SETH("Connection", "Upgrade")) != 0) || ((rv = SETH("Sec-WebSocket-Key", wskey)) != 0) || @@ -2245,22 +2218,15 @@ ws_conn_cb(void *arg) } #undef SETH - ws->http = http; - ws->req = req; + ws->req = req; - nni_http_write_req(http, req, &ws->httpaio); + nni_http_write_req(ws->http, req, &ws->httpaio); nni_mtx_unlock(&ws->mtx); return; err: nni_aio_finish_error(uaio, rv); nni_mtx_unlock(&ws->mtx); - if (http != NULL) { - nni_http_conn_fini(http); - } - if (req != NULL) { - nni_http_req_free(req); - } ws_reap(ws); } |
