Commit 31c20ab3 authored by Alexander Alashkin's avatar Alexander Alashkin Committed by Marko Mikulicic

Replace m-part&endpoints mbufs with plain structs

PUBLISHED_FROM=b30cf26077b7c6374f0d588e5ef5ba504f979bb3
parent 69215cf9
...@@ -4204,6 +4204,19 @@ struct mg_http_proto_data_chuncked { ...@@ -4204,6 +4204,19 @@ struct mg_http_proto_data_chuncked {
int64_t body_len; /* How many bytes of chunked body was reassembled. */ int64_t body_len; /* How many bytes of chunked body was reassembled. */
}; };
struct mg_http_endpoint {
struct mg_http_endpoint *next;
const char *name;
size_t name_len;
mg_event_handler_t handler;
};
struct mg_http_multipart_stream {
const char *boundary;
const char *var_name;
const char *file_name;
};
struct mg_http_proto_data { struct mg_http_proto_data {
#ifndef MG_DISABLE_FILESYSTEM #ifndef MG_DISABLE_FILESYSTEM
struct mg_http_proto_data_file file; struct mg_http_proto_data_file file;
...@@ -4212,10 +4225,10 @@ struct mg_http_proto_data { ...@@ -4212,10 +4225,10 @@ struct mg_http_proto_data {
struct mg_http_proto_data_cgi cgi; struct mg_http_proto_data_cgi cgi;
#endif #endif
#ifdef MG_ENABLE_HTTP_STREAMING_MULTIPART #ifdef MG_ENABLE_HTTP_STREAMING_MULTIPART
struct mbuf strm_state; /* Used by multi-part streaming */ struct mg_http_multipart_stream mp_stream;
#endif #endif
struct mg_http_proto_data_chuncked chunk; struct mg_http_proto_data_chuncked chunk;
struct mbuf endpoints; /* Used by mg_register_http_endpoint */ struct mg_http_endpoint *endpoints;
mg_event_handler_t endpoint_handler; mg_event_handler_t endpoint_handler;
}; };
...@@ -4231,6 +4244,18 @@ static struct mg_http_proto_data *mg_http_get_proto_data( ...@@ -4231,6 +4244,18 @@ static struct mg_http_proto_data *mg_http_get_proto_data(
return (struct mg_http_proto_data *) c->proto_data; return (struct mg_http_proto_data *) c->proto_data;
} }
#ifdef MG_ENABLE_HTTP_STREAMING_MULTIPART
static void mg_http_free_proto_data_mp_stream(
struct mg_http_multipart_stream *mp) {
free((void *) mp->boundary);
mp->boundary = NULL;
free((void *) mp->var_name);
mp->var_name = NULL;
free((void *) mp->file_name);
mp->file_name = NULL;
}
#endif
#ifndef MG_DISABLE_FILESYSTEM #ifndef MG_DISABLE_FILESYSTEM
static void mg_http_free_proto_data_file(struct mg_http_proto_data_file *d) { static void mg_http_free_proto_data_file(struct mg_http_proto_data_file *d) {
if (d != NULL) { if (d != NULL) {
...@@ -4251,6 +4276,19 @@ static void mg_http_free_proto_data_cgi(struct mg_http_proto_data_cgi *d) { ...@@ -4251,6 +4276,19 @@ static void mg_http_free_proto_data_cgi(struct mg_http_proto_data_cgi *d) {
} }
#endif #endif
static void mg_http_free_proto_data_endpoints(struct mg_http_endpoint **ep) {
struct mg_http_endpoint *current = *ep;
while (current != NULL) {
struct mg_http_endpoint *tmp = current->next;
free((void *) current->name);
free(current);
current = tmp;
}
ep = NULL;
}
static void mg_http_conn_destructor(void *proto_data) { static void mg_http_conn_destructor(void *proto_data) {
struct mg_http_proto_data *pd = (struct mg_http_proto_data *) proto_data; struct mg_http_proto_data *pd = (struct mg_http_proto_data *) proto_data;
#ifndef MG_DISABLE_FILESYSTEM #ifndef MG_DISABLE_FILESYSTEM
...@@ -4260,9 +4298,9 @@ static void mg_http_conn_destructor(void *proto_data) { ...@@ -4260,9 +4298,9 @@ static void mg_http_conn_destructor(void *proto_data) {
mg_http_free_proto_data_cgi(&pd->cgi); mg_http_free_proto_data_cgi(&pd->cgi);
#endif #endif
#ifdef MG_ENABLE_HTTP_STREAMING_MULTIPART #ifdef MG_ENABLE_HTTP_STREAMING_MULTIPART
mbuf_free(&pd->strm_state); mg_http_free_proto_data_mp_stream(&pd->mp_stream);
#endif #endif
mbuf_free(&pd->endpoints); mg_http_free_proto_data_endpoints(&pd->endpoints);
free(proto_data); free(proto_data);
} }
...@@ -4948,9 +4986,9 @@ MG_INTERNAL size_t mg_handle_chunked(struct mg_connection *nc, ...@@ -4948,9 +4986,9 @@ MG_INTERNAL size_t mg_handle_chunked(struct mg_connection *nc,
static mg_event_handler_t mg_http_get_endpoint_handler( static mg_event_handler_t mg_http_get_endpoint_handler(
struct mg_connection *nc, struct mg_str *uri_path) { struct mg_connection *nc, struct mg_str *uri_path) {
struct mg_http_proto_data *pd; struct mg_http_proto_data *pd;
size_t pos = 0;
mg_event_handler_t ret = NULL; mg_event_handler_t ret = NULL;
int matched, matched_max = 0; int matched, matched_max = 0;
struct mg_http_endpoint *ep;
if (nc == NULL) { if (nc == NULL) {
return NULL; return NULL;
...@@ -4958,81 +4996,23 @@ static mg_event_handler_t mg_http_get_endpoint_handler( ...@@ -4958,81 +4996,23 @@ static mg_event_handler_t mg_http_get_endpoint_handler(
pd = mg_http_get_proto_data(nc); pd = mg_http_get_proto_data(nc);
while (pos < pd->endpoints.len) { ep = pd->endpoints;
size_t name_len; while (ep != NULL) {
memcpy(&name_len, pd->endpoints.buf + pos, sizeof(name_len)); if ((matched = mg_match_prefix_n(ep->name, ep->name_len, uri_path->p,
if ((matched = mg_match_prefix_n(pd->endpoints.buf + pos + sizeof(size_t), uri_path->len)) != -1) {
name_len, uri_path->p, uri_path->len)) !=
-1) {
if (matched > matched_max) { if (matched > matched_max) {
/* Looking for the longest suitable handler */ /* Looking for the longest suitable handler */
memcpy(&ret, ret = ep->handler;
pd->endpoints.buf + pos + sizeof(name_len) + (name_len + 1),
sizeof(ret));
matched_max = matched; matched_max = matched;
} }
} }
pos += sizeof(name_len) + (name_len + 1) + sizeof(ret); ep = ep->next;
} }
return ret; return ret;
} }
#ifdef MG_ENABLE_HTTP_STREAMING_MULTIPART
struct mg_http_stream_info {
struct mg_str endpoint;
struct mg_str boundary;
struct mg_str var_name;
struct mg_str file_name;
};
/*
* Save/restore state into buf is convinient due to lack of
* protocol/connection parameters in mongoose
* once mongoose will have way to store connection/protocol
* related data these function can be replaced with usual structs
* TODO(alashkin): replace once those way will be implemented
*/
static void mg_http_parse_stream_info(struct mbuf *buf,
struct mg_http_stream_info *si) {
const char *ptr = buf->buf;
memcpy(&si->endpoint.len, ptr, sizeof(si->endpoint.len));
ptr += sizeof(si->endpoint.len);
si->endpoint.p = ptr;
ptr += si->endpoint.len;
memcpy(&si->boundary.len, ptr, sizeof(si->boundary.len));
ptr += sizeof(si->boundary.len);
si->boundary.p = ptr;
ptr += si->boundary.len + 1; /* Explicitly zero-terminated */
memcpy(&si->var_name.len, ptr, sizeof(si->var_name.len));
ptr += sizeof(si->var_name.len);
si->var_name.p = ptr;
ptr += si->var_name.len + 1;
memcpy(&si->file_name.len, ptr, sizeof(si->file_name.len));
ptr += sizeof(si->file_name.len);
si->file_name.p = ptr;
ptr += si->file_name.len + 1;
}
static void mg_http_store_stream_info(struct mbuf *buf,
struct mg_http_stream_info *si) {
char zero = 0;
mbuf_remove(buf, buf->len);
mbuf_append(buf, &si->endpoint.len, sizeof(si->endpoint.len));
mbuf_append(buf, si->endpoint.p, si->endpoint.len);
mbuf_append(buf, &si->boundary.len, sizeof(si->boundary.len));
mbuf_append(buf, si->boundary.p, si->boundary.len);
mbuf_append(buf, &zero, 1); /* Make boundary zero terminated */
mbuf_append(buf, &si->var_name.len, sizeof(si->var_name.len));
mbuf_append(buf, si->var_name.p, si->var_name.len);
mbuf_append(buf, &zero, 1);
mbuf_append(buf, &si->file_name.len, sizeof(si->file_name.len));
mbuf_append(buf, si->file_name.p, si->file_name.len);
mbuf_append(buf, &zero, 1);
}
#endif /* MG_ENABLE_HTTP_STREAMING_MULTIPART */
static void mg_http_call_endpoint_handler(struct mg_connection *nc, int ev, static void mg_http_call_endpoint_handler(struct mg_connection *nc, int ev,
struct http_message *hm) { struct http_message *hm) {
struct mg_http_proto_data *pd = mg_http_get_proto_data(nc); struct mg_http_proto_data *pd = mg_http_get_proto_data(nc);
...@@ -5087,23 +5067,17 @@ void mg_http_handler(struct mg_connection *nc, int ev, void *ev_data) { ...@@ -5087,23 +5067,17 @@ void mg_http_handler(struct mg_connection *nc, int ev, void *ev_data) {
#endif #endif
if (ev == MG_EV_CLOSE) { if (ev == MG_EV_CLOSE) {
#ifdef MG_ENABLE_HTTP_STREAMING_MULTIPART #ifdef MG_ENABLE_HTTP_STREAMING_MULTIPART
if (pd->strm_state.len != 0) { if (pd->mp_stream.boundary != NULL) {
/* /*
* Multipart message is in progress, but we get close * Multipart message is in progress, but we get close
* MG_EV_HTTP_PART_END with error flag * MG_EV_HTTP_PART_END with error flag
*/ */
struct mg_http_stream_info si;
struct mg_http_multipart_part mp; struct mg_http_multipart_part mp;
mg_event_handler_t handler;
memset(&mp, 0, sizeof(mp));
mg_http_parse_stream_info(&pd->strm_state, &si);
handler = mg_http_get_endpoint_handler(nc->listener, &si.endpoint);
mp.status = -1; mp.status = -1;
mp.var_name = si.var_name.p; mp.var_name = pd->mp_stream.var_name;
mp.file_name = si.file_name.p; mp.file_name = pd->mp_stream.file_name;
mg_call(nc, (handler ? handler : nc->handler), MG_EV_HTTP_PART_END, &mp); mg_call(nc, (pd->endpoint_handler ? pd->endpoint_handler : nc->handler),
MG_EV_HTTP_PART_END, &mp);
} else } else
#endif #endif
if (io->len > 0 && mg_parse_http(io->buf, io->len, hm, is_req) > 0) { if (io->len > 0 && mg_parse_http(io->buf, io->len, hm, is_req) > 0) {
...@@ -5130,7 +5104,7 @@ void mg_http_handler(struct mg_connection *nc, int ev, void *ev_data) { ...@@ -5130,7 +5104,7 @@ void mg_http_handler(struct mg_connection *nc, int ev, void *ev_data) {
struct mg_str *s; struct mg_str *s;
#ifdef MG_ENABLE_HTTP_STREAMING_MULTIPART #ifdef MG_ENABLE_HTTP_STREAMING_MULTIPART
if (pd->strm_state.len != 0) { if (pd->mp_stream.boundary != NULL) {
mg_http_multipart_continue(nc, io, ev, ev_data); mg_http_multipart_continue(nc, io, ev, ev_data);
return; return;
} }
...@@ -5250,8 +5224,6 @@ static void mg_http_multipart_begin(struct mg_connection *nc, ...@@ -5250,8 +5224,6 @@ static void mg_http_multipart_begin(struct mg_connection *nc,
const char multipart[] = "multipart"; const char multipart[] = "multipart";
char boundary[100]; char boundary[100];
int boundary_len; int boundary_len;
struct mg_http_stream_info si;
mg_event_handler_t handler;
if (nc->listener == NULL) { if (nc->listener == NULL) {
/* No streaming for replies now */ /* No streaming for replies now */
...@@ -5285,24 +5257,22 @@ static void mg_http_multipart_begin(struct mg_connection *nc, ...@@ -5285,24 +5257,22 @@ static void mg_http_multipart_begin(struct mg_connection *nc,
/* If we reach this place - that is multipart request */ /* If we reach this place - that is multipart request */
if (pd->strm_state.len != 0) { if (pd->mp_stream.boundary != NULL) {
/* /*
* Another streaming request was in progress, * Another streaming request was in progress,
* looks like protocol error * looks like protocol error
*/ */
nc->flags |= MG_F_CLOSE_IMMEDIATELY; nc->flags |= MG_F_CLOSE_IMMEDIATELY;
mbuf_free(&pd->strm_state);
} else { } else {
si.endpoint = hm->uri; pd->mp_stream.boundary = strdup(boundary);
si.boundary.p = boundary; pd->mp_stream.var_name = pd->mp_stream.file_name = NULL;
si.boundary.len = boundary_len;
si.var_name.p = si.file_name.p = NULL;
si.var_name.len = si.file_name.len = 0;
mg_http_store_stream_info(&pd->strm_state, &si); pd->endpoint_handler = mg_http_get_endpoint_handler(nc->listener, &hm->uri);
handler = mg_http_get_endpoint_handler(nc->listener, &si.endpoint); if (pd->endpoint_handler == NULL) {
mg_call(nc, handler ? handler : nc->handler, MG_EV_HTTP_MULTIPART_REQUEST, pd->endpoint_handler = nc->handler;
hm); }
mg_call(nc, pd->endpoint_handler, MG_EV_HTTP_MULTIPART_REQUEST, hm);
mbuf_remove(io, req_len); mbuf_remove(io, req_len);
} }
...@@ -5313,32 +5283,27 @@ exit_mp: ...@@ -5313,32 +5283,27 @@ exit_mp:
static void mg_http_multipart_continue(struct mg_connection *nc, static void mg_http_multipart_continue(struct mg_connection *nc,
struct mbuf *io, int ev, void *ev_data) { struct mbuf *io, int ev, void *ev_data) {
/* Continue to stream multipart */ /* Continue to stream multipart */
struct mg_http_stream_info si;
mg_event_handler_t handler;
struct mg_http_multipart_part mp; struct mg_http_multipart_part mp;
const char *boundary; const char *boundary;
int req_len; int req_len;
struct mg_http_proto_data *pd = mg_http_get_proto_data(nc); struct mg_http_proto_data *pd = mg_http_get_proto_data(nc);
mg_http_parse_stream_info(&pd->strm_state, &si); mp.var_name = pd->mp_stream.var_name;
handler = mg_http_get_endpoint_handler(nc->listener, &si.endpoint); mp.file_name = pd->mp_stream.file_name;
memset(&mp, 0, sizeof(mp)); boundary = c_strnstr(io->buf, pd->mp_stream.boundary, io->len);
mp.var_name = si.var_name.p;
mp.file_name = si.file_name.p;
boundary = c_strnstr(io->buf, si.boundary.p, io->len);
if (boundary == NULL) { if (boundary == NULL) {
mp.data.p = io->buf; mp.data.p = io->buf;
mp.data.len = io->len; mp.data.len = io->len;
mg_call(nc, handler ? handler : nc->handler, MG_EV_HTTP_PART_DATA, &mp); mg_call(nc, pd->endpoint_handler, MG_EV_HTTP_PART_DATA, &mp);
mbuf_remove(io, io->len); mbuf_remove(io, io->len);
} else { } else {
int has_prefix = 0, has_suffix = 0; int has_prefix = 0, has_suffix = 0,
boundary_len = strlen(pd->mp_stream.boundary);
if (boundary - 2 >= io->buf) { if (boundary - 2 >= io->buf) {
has_prefix = (strncmp(boundary - 2, "--", 2) == 0); has_prefix = (strncmp(boundary - 2, "--", 2) == 0);
} }
if (boundary + si.boundary.len <= io->buf + io->len) { if (boundary + boundary_len <= io->buf + io->len) {
has_suffix = (strncmp(boundary + si.boundary.len, "--", 2) == 0); has_suffix = (strncmp(boundary + boundary_len, "--", 2) == 0);
} }
if (has_prefix && !has_suffix) { if (has_prefix && !has_suffix) {
/* No suffix - not last boundary */ /* No suffix - not last boundary */
...@@ -5350,9 +5315,9 @@ static void mg_http_multipart_continue(struct mg_connection *nc, ...@@ -5350,9 +5315,9 @@ static void mg_http_multipart_continue(struct mg_connection *nc,
if (num_left > 2) { /* \r\n */ if (num_left > 2) { /* \r\n */
mp.data.p = io->buf; mp.data.p = io->buf;
mp.data.len = num_left - 2; mp.data.len = num_left - 2;
mg_call(nc, handler ? handler : nc->handler, MG_EV_HTTP_PART_DATA, &mp); mg_call(nc, pd->endpoint_handler, MG_EV_HTTP_PART_DATA, &mp);
mp.data.len = 0; mp.data.len = 0;
mg_call(nc, handler ? handler : nc->handler, MG_EV_HTTP_PART_END, &mp); mg_call(nc, pd->endpoint_handler, MG_EV_HTTP_PART_END, &mp);
mbuf_remove(io, num_left); mbuf_remove(io, num_left);
} }
...@@ -5362,18 +5327,16 @@ static void mg_http_multipart_continue(struct mg_connection *nc, ...@@ -5362,18 +5327,16 @@ static void mg_http_multipart_continue(struct mg_connection *nc,
mp.file_name = filename; mp.file_name = filename;
if ((req_len = mg_http_get_request_len(io->buf, io->len)) > 0) { if ((req_len = mg_http_get_request_len(io->buf, io->len)) > 0) {
const char *tmp; const char *tmp;
mg_call(nc, handler ? handler : nc->handler, MG_EV_HTTP_PART_BEGIN, mg_call(nc, pd->endpoint_handler, MG_EV_HTTP_PART_BEGIN, &mp);
&mp); free((void *) pd->mp_stream.var_name);
si.var_name.p = mp.var_name; pd->mp_stream.var_name = strdup(mp.var_name);
si.var_name.len = strlen(mp.var_name); free((void *) pd->mp_stream.file_name);
si.file_name.p = mp.file_name; pd->mp_stream.file_name = strdup(mp.file_name);
si.file_name.len = strlen(mp.file_name);
mg_http_store_stream_info(&pd->strm_state, &si);
mbuf_remove(io, req_len); mbuf_remove(io, req_len);
mp.data.p = io->buf; mp.data.p = io->buf;
tmp = c_strnstr(io->buf, si.boundary.p, io->len); tmp = c_strnstr(io->buf, pd->mp_stream.boundary, io->len);
if (tmp == NULL) { if (tmp == NULL) {
mp.data.len = io->len; mp.data.len = io->len;
} else { } else {
...@@ -5382,12 +5345,10 @@ static void mg_http_multipart_continue(struct mg_connection *nc, ...@@ -5382,12 +5345,10 @@ static void mg_http_multipart_continue(struct mg_connection *nc,
if (mp.data.len != 0) { if (mp.data.len != 0) {
size_t data_len = mp.data.len; size_t data_len = mp.data.len;
mg_call(nc, handler ? handler : nc->handler, MG_EV_HTTP_PART_DATA, mg_call(nc, pd->endpoint_handler, MG_EV_HTTP_PART_DATA, &mp);
&mp);
if (data_len != io->len) { if (data_len != io->len) {
mp.data.len = 0; mp.data.len = 0;
mg_call(nc, handler ? handler : nc->handler, MG_EV_HTTP_PART_END, mg_call(nc, pd->endpoint_handler, MG_EV_HTTP_PART_END, &mp);
&mp);
} }
mbuf_remove(io, data_len); mbuf_remove(io, data_len);
} }
...@@ -5401,14 +5362,14 @@ static void mg_http_multipart_continue(struct mg_connection *nc, ...@@ -5401,14 +5362,14 @@ static void mg_http_multipart_continue(struct mg_connection *nc,
mp.data.p = io->buf; mp.data.p = io->buf;
mp.data.len = boundary - io->buf - 4; mp.data.len = boundary - io->buf - 4;
if (mp.data.len != 0) { if (mp.data.len != 0) {
mg_call(nc, handler ? handler : nc->handler, MG_EV_HTTP_PART_DATA, &mp); mg_call(nc, pd->endpoint_handler, MG_EV_HTTP_PART_DATA, &mp);
} }
mg_call(nc, handler ? handler : nc->handler, MG_EV_HTTP_PART_END, &mp); mg_call(nc, pd->endpoint_handler, MG_EV_HTTP_PART_END, &mp);
/* Skip epilogue (if any) */ /* Skip epilogue (if any) */
mbuf_remove(io, io->len); mbuf_remove(io, io->len);
mbuf_free(&pd->strm_state); mg_http_free_proto_data_mp_stream(&pd->mp_stream);
} else { } else {
/* Malformed request */ /* Malformed request */
nc->flags |= MG_F_CLOSE_IMMEDIATELY; nc->flags |= MG_F_CLOSE_IMMEDIATELY;
...@@ -7610,10 +7571,13 @@ size_t mg_parse_multipart(const char *buf, size_t buf_len, char *var_name, ...@@ -7610,10 +7571,13 @@ 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, void mg_register_http_endpoint(struct mg_connection *nc, const char *uri_path,
mg_event_handler_t handler) { mg_event_handler_t handler) {
struct mg_http_proto_data *pd = mg_http_get_proto_data(nc); struct mg_http_proto_data *pd = mg_http_get_proto_data(nc);
size_t len = strlen(uri_path); struct mg_http_endpoint *new_ep =
mbuf_append(&pd->endpoints, &len, sizeof(len)); (struct mg_http_endpoint *) calloc(1, sizeof(*new_ep));
mbuf_append(&pd->endpoints, uri_path, len + 1); new_ep->name = strdup(uri_path);
mbuf_append(&pd->endpoints, &handler, sizeof(handler)); new_ep->name_len = strlen(new_ep->name);
new_ep->handler = handler;
new_ep->next = pd->endpoints;
pd->endpoints = new_ep;
} }
#endif /* MG_DISABLE_HTTP */ #endif /* MG_DISABLE_HTTP */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment