Commit 05c687e2 authored by Deomid Ryabkov's avatar Deomid Ryabkov Committed by Cesanta Bot

Fix handling of keepalive HTTP requests/responses

Clean the HTTP connection state when ia request/response has been fully
buffered and handler invoked.

Fixes https://github.com/cesanta/mongoose/issues/971

CL: mg: Fix handling of keepalive HTTP requests/responses

PUBLISHED_FROM=70c854aa306aacb9161f6ee48841f38dc0312e6b
parent 492b8f69
......@@ -6616,6 +6616,7 @@ void mg_http_handler(struct mg_connection *nc, int ev,
}
} else {
/* We did receive all HTTP body. */
int request_done = 1;
int trigger_ev = nc->listener ? MG_EV_HTTP_REQUEST : MG_EV_HTTP_REPLY;
char addr[32];
mg_sock_addr_to_str(&nc->sa, addr, sizeof(addr),
......@@ -6627,11 +6628,31 @@ void mg_http_handler(struct mg_connection *nc, int ev,
mg_http_call_endpoint_handler(nc, trigger_ev, hm);
mbuf_remove(io, hm->message.len);
pd->rcvd -= hm->message.len;
#if MG_ENABLE_FILESYSTEM
/* We don't have a generic mechanism of communicating that we are done
* responding to a request (should probably add one). But if we are
* serving
* a file, we are definitely not done. */
if (pd->file.fp != NULL) request_done = 0;
#endif
#if MG_ENABLE_HTTP_CGI
/* If this is a CGI request, we are not done either. */
if (pd->cgi.cgi_nc != NULL) request_done = 0;
#endif
if (request_done) {
/* This request is done but we may receive another on this connection.
*/
mg_http_conn_destructor(pd);
nc->proto_data = NULL;
if (io->len > 0) {
/* We already have data for the next one, restart parsing. */
pd = mg_http_get_proto_data(nc);
pd->rcvd = io->len;
goto again;
}
}
}
}
}
static size_t mg_get_line_len(const char *buf, size_t buf_len) {
......
......@@ -869,6 +869,7 @@ void mg_http_handler(struct mg_connection *nc, int ev,
}
} else {
/* We did receive all HTTP body. */
int request_done = 1;
int trigger_ev = nc->listener ? MG_EV_HTTP_REQUEST : MG_EV_HTTP_REPLY;
char addr[32];
mg_sock_addr_to_str(&nc->sa, addr, sizeof(addr),
......@@ -880,11 +881,31 @@ void mg_http_handler(struct mg_connection *nc, int ev,
mg_http_call_endpoint_handler(nc, trigger_ev, hm);
mbuf_remove(io, hm->message.len);
pd->rcvd -= hm->message.len;
#if MG_ENABLE_FILESYSTEM
/* We don't have a generic mechanism of communicating that we are done
* responding to a request (should probably add one). But if we are
* serving
* a file, we are definitely not done. */
if (pd->file.fp != NULL) request_done = 0;
#endif
#if MG_ENABLE_HTTP_CGI
/* If this is a CGI request, we are not done either. */
if (pd->cgi.cgi_nc != NULL) request_done = 0;
#endif
if (request_done) {
/* This request is done but we may receive another on this connection.
*/
mg_http_conn_destructor(pd);
nc->proto_data = NULL;
if (io->len > 0) {
/* We already have data for the next one, restart parsing. */
pd = mg_http_get_proto_data(nc);
pd->rcvd = io->len;
goto again;
}
}
}
}
}
static size_t mg_get_line_len(const char *buf, size_t buf_len) {
......
......@@ -2069,7 +2069,7 @@ static const char *test_http(void) {
nc->user_data = mime2;
/* Run event loop. Use more cycles to let file download complete. */
poll_until(&mgr, 5, c_str_ne, status, (void *) "");
poll_until(&mgr, 15, c_str_ne, status, (void *) "");
mg_mgr_free(&mgr);
/* Check that test buffer has been filled by the callback properly. */
......
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