mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-30 10:47:19 +02:00
fix(esp_http_server): prevent concurrent access to socket used in async http requests
This commit is contained in:
committed by
David Cermak
parent
9f4b1bd471
commit
8b559ce614
@ -55,7 +55,7 @@ static esp_err_t httpd_accept_conn(struct httpd_data *hd, int listen_fd)
|
|||||||
if (!httpd_is_sess_available(hd)) {
|
if (!httpd_is_sess_available(hd)) {
|
||||||
/* Queue asynchronous closure of the least recently used session */
|
/* Queue asynchronous closure of the least recently used session */
|
||||||
return httpd_sess_close_lru(hd);
|
return httpd_sess_close_lru(hd);
|
||||||
/* Returning from this allowes the main server thread to process
|
/* Returning from this allows the main server thread to process
|
||||||
* the queued asynchronous control message for closing LRU session.
|
* the queued asynchronous control message for closing LRU session.
|
||||||
* Since connection request hasn't been addressed yet using accept()
|
* Since connection request hasn't been addressed yet using accept()
|
||||||
* therefore httpd_accept_conn() will be called again, but this time
|
* therefore httpd_accept_conn() will be called again, but this time
|
||||||
@ -254,6 +254,11 @@ static int httpd_process_session(struct sock_db *session, void *context)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// session is busy in an async task, do not process here.
|
||||||
|
if (session->for_async_req) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
process_session_context_t *ctx = (process_session_context_t *)context;
|
process_session_context_t *ctx = (process_session_context_t *)context;
|
||||||
int fd = session->fd;
|
int fd = session->fd;
|
||||||
|
|
||||||
|
@ -72,6 +72,7 @@ static int enum_function(struct sock_db *session, void *context)
|
|||||||
case HTTPD_TASK_INIT:
|
case HTTPD_TASK_INIT:
|
||||||
session->fd = -1;
|
session->fd = -1;
|
||||||
session->ctx = NULL;
|
session->ctx = NULL;
|
||||||
|
session->for_async_req = false;
|
||||||
break;
|
break;
|
||||||
// Get active session
|
// Get active session
|
||||||
case HTTPD_TASK_GET_ACTIVE:
|
case HTTPD_TASK_GET_ACTIVE:
|
||||||
@ -87,7 +88,7 @@ static int enum_function(struct sock_db *session, void *context)
|
|||||||
break;
|
break;
|
||||||
// Set descriptor
|
// Set descriptor
|
||||||
case HTTPD_TASK_SET_DESCRIPTOR:
|
case HTTPD_TASK_SET_DESCRIPTOR:
|
||||||
if (session->fd != -1) {
|
if (session->fd != -1 && !session->for_async_req) {
|
||||||
FD_SET(session->fd, ctx->fdset);
|
FD_SET(session->fd, ctx->fdset);
|
||||||
if (session->fd > ctx->max_fd) {
|
if (session->fd > ctx->max_fd) {
|
||||||
ctx->max_fd = session->fd;
|
ctx->max_fd = session->fd;
|
||||||
|
@ -627,9 +627,11 @@ esp_err_t httpd_req_async_handler_begin(httpd_req_t *r, httpd_req_t **out)
|
|||||||
}
|
}
|
||||||
memcpy(async_aux->resp_hdrs, r_aux->resp_hdrs, hd->config.max_resp_headers * sizeof(struct resp_hdr));
|
memcpy(async_aux->resp_hdrs, r_aux->resp_hdrs, hd->config.max_resp_headers * sizeof(struct resp_hdr));
|
||||||
|
|
||||||
|
// Prevent the main thread from reading the rest of the request after the handler returns.
|
||||||
|
r_aux->remaining_len = 0;
|
||||||
|
|
||||||
// mark socket as "in use"
|
// mark socket as "in use"
|
||||||
struct httpd_req_aux *ra = r->aux;
|
r_aux->sd->for_async_req = true;
|
||||||
ra->sd->for_async_req = true;
|
|
||||||
|
|
||||||
*out = async;
|
*out = async;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user