From bf7dd7ac6301b34368e08e2e754eb879fe40b677 Mon Sep 17 00:00:00 2001 From: Dmitry Frank <mail@dmitryfrank.com> Date: Wed, 15 Mar 2017 17:20:04 +0000 Subject: [PATCH] Add separate userdata for each http endpoint hdlr PUBLISHED_FROM=29a204c2c7f35724b6f1e8435edb94869da2362c --- .../mg_register_http_endpoint.md | 3 +- examples/big_upload/big_upload.c | 2 +- mongoose.c | 132 +++++++++++------- mongoose.h | 3 +- 4 files changed, 86 insertions(+), 54 deletions(-) diff --git a/docs/c-api/http_server.h/mg_register_http_endpoint.md b/docs/c-api/http_server.h/mg_register_http_endpoint.md index 99418caa5..394bbb51e 100644 --- a/docs/c-api/http_server.h/mg_register_http_endpoint.md +++ b/docs/c-api/http_server.h/mg_register_http_endpoint.md @@ -4,7 +4,8 @@ decl_name: "mg_register_http_endpoint" symbol_kind: "func" signature: | void mg_register_http_endpoint(struct mg_connection *nc, const char *uri_path, - mg_event_handler_t handler); + MG_CB(mg_event_handler_t handler, + void *user_data); --- Registers a callback for a specified http endpoint diff --git a/examples/big_upload/big_upload.c b/examples/big_upload/big_upload.c index 8bd3cc5a5..682a0c318 100644 --- a/examples/big_upload/big_upload.c +++ b/examples/big_upload/big_upload.c @@ -98,7 +98,7 @@ int main(void) { mg_mgr_init(&mgr, NULL); nc = mg_bind(&mgr, s_http_port, ev_handler); - mg_register_http_endpoint(nc, "/upload", handle_upload); + mg_register_http_endpoint(nc, "/upload", handle_upload MG_UD_ARG(NULL)); // Set up HTTP server parameters mg_set_protocol_http_websocket(nc); diff --git a/mongoose.c b/mongoose.c index a694cd510..a24c89f22 100644 --- a/mongoose.c +++ b/mongoose.c @@ -62,7 +62,8 @@ MG_INTERNAL struct mg_connection *mg_do_connect(struct mg_connection *nc, MG_INTERNAL int mg_parse_address(const char *str, union socket_address *sa, int *proto, char *host, size_t host_len); MG_INTERNAL void mg_call(struct mg_connection *nc, - mg_event_handler_t ev_handler, int ev, void *ev_data); + mg_event_handler_t ev_handler, void *user_data, int ev, + void *ev_data); void mg_forward(struct mg_connection *from, struct mg_connection *to); MG_INTERNAL void mg_add_conn(struct mg_mgr *mgr, struct mg_connection *c); MG_INTERNAL void mg_remove_conn(struct mg_connection *c); @@ -2021,7 +2022,8 @@ MG_INTERNAL void mg_remove_conn(struct mg_connection *conn) { } MG_INTERNAL void mg_call(struct mg_connection *nc, - mg_event_handler_t ev_handler, int ev, void *ev_data) { + mg_event_handler_t ev_handler, void *user_data, int ev, + void *ev_data) { if (ev_handler == NULL) { /* * If protocol handler is specified, call it. Otherwise, call user-specified @@ -2051,7 +2053,7 @@ MG_INTERNAL void mg_call(struct mg_connection *nc, if (ev_handler != NULL) { unsigned long flags_before = nc->flags; size_t recv_mbuf_before = nc->recv_mbuf.len, recved; - ev_handler(nc, ev, ev_data MG_UD_ARG(nc->user_data)); + ev_handler(nc, ev, ev_data MG_UD_ARG(user_data)); recved = (recv_mbuf_before - nc->recv_mbuf.len); /* Prevent user handler from fiddling with system flags. */ if (ev_handler == nc->handler && nc->flags != flags_before) { @@ -2067,12 +2069,15 @@ MG_INTERNAL void mg_call(struct mg_connection *nc, ev_handler == nc->handler ? "user" : "proto", nc->flags, (int) nc->recv_mbuf.len, (int) nc->send_mbuf.len)); } +#if !MG_ENABLE_CALLBACK_USERDATA + (void) user_data; +#endif } void mg_if_timer(struct mg_connection *c, double now) { if (c->ev_timer_time > 0 && now >= c->ev_timer_time) { double old_value = c->ev_timer_time; - mg_call(c, NULL, MG_EV_TIMER, &now); + mg_call(c, NULL, c->user_data, MG_EV_TIMER, &now); /* * To prevent timer firing all the time, reset the timer after delivery. * However, in case user sets it to new value, do not reset. @@ -2085,7 +2090,7 @@ void mg_if_timer(struct mg_connection *c, double now) { void mg_if_poll(struct mg_connection *nc, time_t now) { if (!(nc->flags & MG_F_SSL) || (nc->flags & MG_F_SSL_HANDSHAKE_DONE)) { - mg_call(nc, NULL, MG_EV_POLL, &now); + mg_call(nc, NULL, nc->user_data, MG_EV_POLL, &now); } } @@ -2108,7 +2113,7 @@ void mg_close_conn(struct mg_connection *conn) { DBG(("%p %lu %d", conn, conn->flags, conn->sock)); mg_remove_conn(conn); conn->iface->vtable->destroy_conn(conn); - mg_call(conn, NULL, MG_EV_CLOSE, NULL); + mg_call(conn, NULL, conn->user_data, MG_EV_CLOSE, NULL); mg_destroy_conn(conn, 0 /* destroy_if */); } @@ -2452,7 +2457,7 @@ void mg_if_accept_tcp_cb(struct mg_connection *nc, union socket_address *sa, size_t sa_len) { (void) sa_len; nc->sa = *sa; - mg_call(nc, NULL, MG_EV_ACCEPT, &nc->sa); + mg_call(nc, NULL, nc->user_data, MG_EV_ACCEPT, &nc->sa); } void mg_send(struct mg_connection *nc, const void *buf, int len) { @@ -2473,7 +2478,7 @@ void mg_if_sent_cb(struct mg_connection *nc, int num_sent) { if (num_sent < 0) { nc->flags |= MG_F_CLOSE_IMMEDIATELY; } - mg_call(nc, NULL, MG_EV_SEND, &num_sent); + mg_call(nc, NULL, nc->user_data, MG_EV_SEND, &num_sent); } MG_INTERNAL void mg_recv_common(struct mg_connection *nc, void *buf, int len, @@ -2502,7 +2507,7 @@ MG_INTERNAL void mg_recv_common(struct mg_connection *nc, void *buf, int len, mbuf_append(&nc->recv_mbuf, buf, len); MG_FREE(buf); } - mg_call(nc, NULL, MG_EV_RECV, &len); + mg_call(nc, NULL, nc->user_data, MG_EV_RECV, &len); } void mg_if_recv_tcp_cb(struct mg_connection *nc, void *buf, int len, int own) { @@ -2550,7 +2555,7 @@ void mg_if_recv_udp_cb(struct mg_connection *nc, void *buf, int len, */ nc->flags |= MG_F_SEND_AND_CLOSE; mg_add_conn(lc->mgr, nc); - mg_call(nc, NULL, MG_EV_ACCEPT, &nc->sa); + mg_call(nc, NULL, nc->user_data, MG_EV_ACCEPT, &nc->sa); } else { DBG(("OOM")); /* No return here, we still need to drop on the floor */ @@ -2594,7 +2599,7 @@ void mg_if_connect_cb(struct mg_connection *nc, int err) { if (err != 0) { nc->flags |= MG_F_CLOSE_IMMEDIATELY; } - mg_call(nc, NULL, MG_EV_CONNECT, &err); + mg_call(nc, NULL, nc->user_data, MG_EV_CONNECT, &err); } #if MG_ENABLE_ASYNC_RESOLVER @@ -2632,14 +2637,14 @@ static void resolve_cb(struct mg_dns_message *msg, void *data, if (e == MG_RESOLVE_TIMEOUT) { double now = mg_time(); - mg_call(nc, NULL, MG_EV_TIMER, &now); + mg_call(nc, NULL, nc->user_data, MG_EV_TIMER, &now); } /* * If we get there was no MG_DNS_A_RECORD in the answer */ - mg_call(nc, NULL, MG_EV_CONNECT, &failure); - mg_call(nc, NULL, MG_EV_CLOSE, NULL); + mg_call(nc, NULL, nc->user_data, MG_EV_CONNECT, &failure); + mg_call(nc, NULL, nc->user_data, MG_EV_CLOSE, NULL); mg_destroy_conn(nc, 1 /* destroy_if */); } #endif @@ -5021,6 +5026,9 @@ struct mg_http_endpoint { const char *name; size_t name_len; mg_event_handler_t handler; +#if MG_ENABLE_CALLBACK_USERDATA + void *user_data; +#endif }; enum mg_http_multipart_stream_state { @@ -5502,7 +5510,7 @@ MG_INTERNAL size_t mg_handle_chunked(struct mg_connection *nc, /* Send MG_EV_HTTP_CHUNK event */ nc->flags &= ~MG_F_DELETE_CHUNK; - mg_call(nc, nc->handler, MG_EV_HTTP_CHUNK, hm); + mg_call(nc, nc->handler, nc->user_data, MG_EV_HTTP_CHUNK, hm); /* Delete processed data if user set MG_F_DELETE_CHUNK flag */ if (nc->flags & MG_F_DELETE_CHUNK) { @@ -5523,10 +5531,10 @@ MG_INTERNAL size_t mg_handle_chunked(struct mg_connection *nc, return body_len; } -static mg_event_handler_t mg_http_get_endpoint_handler( - struct mg_connection *nc, struct mg_str *uri_path) { +struct mg_http_endpoint *mg_http_get_endpoint_handler(struct mg_connection *nc, + struct mg_str *uri_path) { struct mg_http_proto_data *pd; - mg_event_handler_t ret = NULL; + struct mg_http_endpoint *ret = NULL; int matched, matched_max = 0; struct mg_http_endpoint *ep; @@ -5542,7 +5550,7 @@ static mg_event_handler_t mg_http_get_endpoint_handler( if ((matched = mg_match_prefix_n(name_s, *uri_path)) != -1) { if (matched > matched_max) { /* Looking for the longest suitable handler */ - ret = ep->handler; + ret = ep; matched_max = matched; } } @@ -5556,15 +5564,20 @@ static mg_event_handler_t mg_http_get_endpoint_handler( static void mg_http_call_endpoint_handler(struct mg_connection *nc, int ev, struct http_message *hm) { struct mg_http_proto_data *pd = mg_http_get_proto_data(nc); + void *user_data = nc->user_data; - if (pd->endpoint_handler == NULL || ev == MG_EV_HTTP_REQUEST) { - pd->endpoint_handler = - ev == MG_EV_HTTP_REQUEST - ? mg_http_get_endpoint_handler(nc->listener, &hm->uri) - : NULL; + if (ev == MG_EV_HTTP_REQUEST) { + struct mg_http_endpoint *ep = + mg_http_get_endpoint_handler(nc->listener, &hm->uri); + if (ep != NULL) { + pd->endpoint_handler = ep->handler; +#if MG_ENABLE_CALLBACK_USERDATA + user_data = ep->user_data; +#endif + } } - mg_call(nc, pd->endpoint_handler ? pd->endpoint_handler : nc->handler, ev, - hm); + mg_call(nc, pd->endpoint_handler ? pd->endpoint_handler : nc->handler, + user_data, ev, hm); } #if MG_ENABLE_HTTP_STREAMING_MULTIPART @@ -5627,11 +5640,11 @@ void mg_http_handler(struct mg_connection *nc, int ev, mp.var_name = pd->mp_stream.var_name; mp.file_name = pd->mp_stream.file_name; mg_call(nc, (pd->endpoint_handler ? pd->endpoint_handler : nc->handler), - MG_EV_HTTP_PART_END, &mp); + nc->user_data, MG_EV_HTTP_PART_END, &mp); mp.var_name = NULL; mp.file_name = NULL; mg_call(nc, (pd->endpoint_handler ? pd->endpoint_handler : nc->handler), - MG_EV_HTTP_MULTIPART_REQUEST_END, &mp); + nc->user_data, MG_EV_HTTP_MULTIPART_REQUEST_END, &mp); } else #endif if (io->len > 0 && mg_parse_http(io->buf, io->len, hm, is_req) > 0) { @@ -5652,7 +5665,7 @@ void mg_http_handler(struct mg_connection *nc, int ev, } #endif - mg_call(nc, nc->handler, ev, ev_data); + mg_call(nc, nc->handler, nc->user_data, ev, ev_data); if (ev == MG_EV_RECV) { struct mg_str *s; @@ -5697,11 +5710,12 @@ void mg_http_handler(struct mg_connection *nc, int ev, mbuf_remove(io, req_len); nc->proto_handler = mg_ws_handler; nc->flags |= MG_F_IS_WEBSOCKET; - mg_call(nc, nc->handler, MG_EV_WEBSOCKET_HANDSHAKE_DONE, NULL); + mg_call(nc, nc->handler, nc->user_data, MG_EV_WEBSOCKET_HANDSHAKE_DONE, + NULL); mg_ws_handler(nc, MG_EV_RECV, ev_data MG_UD_ARG(user_data)); } else if (nc->listener != NULL && (vec = mg_get_http_header(hm, "Sec-WebSocket-Key")) != NULL) { - mg_event_handler_t handler; + struct mg_http_endpoint *ep; /* This is a websocket request. Switch protocol handlers. */ mbuf_remove(io, req_len); @@ -5713,18 +5727,23 @@ void mg_http_handler(struct mg_connection *nc, int ev, * deliver subsequent websocket events to this handler after the * protocol switch. */ - handler = mg_http_get_endpoint_handler(nc->listener, &hm->uri); - if (handler != NULL) { - nc->handler = handler; + ep = mg_http_get_endpoint_handler(nc->listener, &hm->uri); + if (ep != NULL) { + nc->handler = ep->handler; +#if MG_ENABLE_CALLBACK_USERDATA + nc->user_data = ep->user_data; +#endif } /* Send handshake */ - mg_call(nc, nc->handler, MG_EV_WEBSOCKET_HANDSHAKE_REQUEST, hm); + mg_call(nc, nc->handler, nc->user_data, MG_EV_WEBSOCKET_HANDSHAKE_REQUEST, + hm); if (!(nc->flags & (MG_F_CLOSE_IMMEDIATELY | MG_F_SEND_AND_CLOSE))) { if (nc->send_mbuf.len == 0) { mg_ws_handshake(nc, vec); } - mg_call(nc, nc->handler, MG_EV_WEBSOCKET_HANDSHAKE_DONE, NULL); + mg_call(nc, nc->handler, nc->user_data, MG_EV_WEBSOCKET_HANDSHAKE_DONE, + NULL); mg_ws_handler(nc, MG_EV_RECV, ev_data MG_UD_ARG(user_data)); } } @@ -5805,6 +5824,7 @@ static void mg_http_multipart_begin(struct mg_connection *nc, struct mg_http_proto_data *pd = mg_http_get_proto_data(nc); struct mg_str *ct; struct mbuf *io = &nc->recv_mbuf; + void *user_data = nc->user_data; char boundary[100]; int boundary_len; @@ -5841,17 +5861,23 @@ static void mg_http_multipart_begin(struct mg_connection *nc, */ nc->flags |= MG_F_CLOSE_IMMEDIATELY; } else { + struct mg_http_endpoint *ep = NULL; pd->mp_stream.state = MPS_BEGIN; pd->mp_stream.boundary = strdup(boundary); pd->mp_stream.boundary_len = strlen(boundary); pd->mp_stream.var_name = pd->mp_stream.file_name = NULL; + pd->endpoint_handler = nc->handler; - pd->endpoint_handler = mg_http_get_endpoint_handler(nc->listener, &hm->uri); - if (pd->endpoint_handler == NULL) { - pd->endpoint_handler = nc->handler; + ep = mg_http_get_endpoint_handler(nc->listener, &hm->uri); + if (ep != NULL) { + pd->endpoint_handler = ep->handler; +#if MG_ENABLE_CALLBACK_USERDATA + user_data = ep->user_data; +#endif } - mg_call(nc, pd->endpoint_handler, MG_EV_HTTP_MULTIPART_REQUEST, hm); + mg_call(nc, pd->endpoint_handler, user_data, MG_EV_HTTP_MULTIPART_REQUEST, + hm); mbuf_remove(io, req_len); } @@ -5872,7 +5898,7 @@ static void mg_http_multipart_call_handler(struct mg_connection *c, int ev, mp.user_data = pd->mp_stream.user_data; mp.data.p = data; mp.data.len = data_len; - mg_call(c, pd->endpoint_handler, ev, &mp); + mg_call(c, pd->endpoint_handler, c->user_data, ev, &mp); pd->mp_stream.user_data = mp.user_data; } @@ -7834,7 +7860,8 @@ size_t mg_parse_multipart(const char *buf, size_t buf_len, char *var_name, } void mg_register_http_endpoint(struct mg_connection *nc, const char *uri_path, - mg_event_handler_t handler) { + MG_CB(mg_event_handler_t handler, + void *user_data)) { struct mg_http_proto_data *pd = NULL; struct mg_http_endpoint *new_ep = NULL; @@ -7846,6 +7873,9 @@ void mg_register_http_endpoint(struct mg_connection *nc, const char *uri_path, new_ep->name = strdup(uri_path); new_ep->name_len = strlen(new_ep->name); new_ep->handler = handler; +#if MG_ENABLE_CALLBACK_USERDATA + new_ep->user_data = user_data; +#endif new_ep->next = pd->endpoints; pd->endpoints = new_ep; } @@ -8480,9 +8510,9 @@ static void mg_send_ssi_file(struct mg_connection *nc, struct http_message *hm, cctx.req = hm; cctx.file = mg_mk_str(path); cctx.arg = mg_mk_str(p + d_call.len + 1); - mg_call(nc, NULL, MG_EV_SSI_CALL, + mg_call(nc, NULL, nc->user_data, MG_EV_SSI_CALL, (void *) cctx.arg.p); /* NUL added above */ - mg_call(nc, NULL, MG_EV_SSI_CALL_CTX, &cctx); + mg_call(nc, NULL, nc->user_data, MG_EV_SSI_CALL_CTX, &cctx); #if MG_ENABLE_HTTP_SSI_EXEC } else if (strncmp(p, d_exec.p, d_exec.len) == 0) { do_ssi_exec(nc, p + d_exec.len + 1); @@ -8846,9 +8876,9 @@ static int mg_is_ws_first_fragment(unsigned char flags) { static void mg_handle_incoming_websocket_frame(struct mg_connection *nc, struct websocket_message *wsm) { if (wsm->flags & 0x8) { - mg_call(nc, nc->handler, MG_EV_WEBSOCKET_CONTROL_FRAME, wsm); + mg_call(nc, nc->handler, nc->user_data, MG_EV_WEBSOCKET_CONTROL_FRAME, wsm); } else { - mg_call(nc, nc->handler, MG_EV_WEBSOCKET_FRAME, wsm); + mg_call(nc, nc->handler, nc->user_data, MG_EV_WEBSOCKET_FRAME, wsm); } } @@ -9071,7 +9101,7 @@ void mg_printf_websocket_frame(struct mg_connection *nc, int op, MG_INTERNAL void mg_ws_handler(struct mg_connection *nc, int ev, void *ev_data MG_UD_ARG(void *user_data)) { - mg_call(nc, nc->handler, ev, ev_data); + mg_call(nc, nc->handler, nc->user_data, ev, ev_data); switch (ev) { case MG_EV_RECV: @@ -12057,7 +12087,7 @@ static void mg_sntp_util_ev_handler(struct mg_connection *c, int ev, switch (ev) { case MG_EV_CONNECT: if (*(int *) ev_data != 0) { - mg_call(c, sd->hander, MG_SNTP_FAILED, NULL); + mg_call(c, sd->hander, c->user_data, MG_SNTP_FAILED, NULL); break; } /* fallthrough */ @@ -12067,16 +12097,16 @@ static void mg_sntp_util_ev_handler(struct mg_connection *c, int ev, mg_set_timer(c, mg_time() + 10); sd->count++; } else { - mg_call(c, sd->hander, MG_SNTP_FAILED, NULL); + mg_call(c, sd->hander, c->user_data, MG_SNTP_FAILED, NULL); c->flags |= MG_F_CLOSE_IMMEDIATELY; } break; case MG_SNTP_MALFORMED_REPLY: - mg_call(c, sd->hander, MG_SNTP_FAILED, NULL); + mg_call(c, sd->hander, c->user_data, MG_SNTP_FAILED, NULL); c->flags |= MG_F_CLOSE_IMMEDIATELY; break; case MG_SNTP_REPLY: - mg_call(c, sd->hander, MG_SNTP_REPLY, ev_data); + mg_call(c, sd->hander, c->user_data, MG_SNTP_REPLY, ev_data); c->flags |= MG_F_CLOSE_IMMEDIATELY; break; case MG_EV_CLOSE: diff --git a/mongoose.h b/mongoose.h index 6f697185f..bc8c8c21e 100644 --- a/mongoose.h +++ b/mongoose.h @@ -4792,7 +4792,8 @@ void mg_file_upload_handler(struct mg_connection *nc, int ev, void *ev_data, * ``` */ void mg_register_http_endpoint(struct mg_connection *nc, const char *uri_path, - mg_event_handler_t handler); + MG_CB(mg_event_handler_t handler, + void *user_data)); /* * Authenticates a HTTP request against an opened password file. -- GitLab