feat(httpd): add support for asynchronous request handling

This commit adds support for handling multiple requests simultaneously by introducing two new functions: `httpd_req_async_handler_begin()` and `httpd_req_async_handler_complete()`. These functions allow creating an asynchronous copy of a request that can be used on a separate thread and marking the asynchronous request as completed, respectively.

Additionally, a new flag `for_async_req` has been added to the `httpd_sess_t` struct to indicate if a socket is being used for an asynchronous request and should not be purged from the LRU cache.

An example have been added to demonstrate the usage of these new functions.

Closes https://github.com/espressif/esp-idf/issues/10594

Signed-off-by: Harshit Malpani <harshit.malpani@espressif.com>
This commit is contained in:
Chip Weinberger
2023-04-13 17:05:10 -07:00
committed by Harshit Malpani
parent 1d25057a24
commit 3824eba04d
11 changed files with 523 additions and 4 deletions
@@ -72,6 +72,7 @@ struct sock_db {
bool lru_socket; /*!< Flag indicating LRU socket */
char pending_data[PARSER_BLOCK_SIZE]; /*!< Buffer for pending data to be received */
size_t pending_len; /*!< Length of pending data to be received */
bool for_async_req; /*!< If true, the socket will not be LRU purged */
#ifdef CONFIG_HTTPD_WS_SUPPORT
bool ws_handshake_done; /*!< True if it has done WebSocket handshake (if this socket is a valid WS) */
bool ws_close; /*!< Set to true to close the socket later (when WS Close frame received) */
+7 -4
View File
@@ -107,10 +107,13 @@ static int enum_function(struct sock_db *session, void *context)
if (session->fd == -1) {
return 0;
}
// Check/update lowest lru
if (session->lru_counter < ctx->lru_counter) {
ctx->lru_counter = session->lru_counter;
ctx->session = session;
// Only close sockets that are not in use
if (session->for_async_req == false) {
// Check/update lowest lru
if (session->lru_counter < ctx->lru_counter) {
ctx->lru_counter = session->lru_counter;
ctx->session = session;
}
}
break;
case HTTPD_TASK_CLOSE:
@@ -554,6 +554,51 @@ int httpd_req_recv(httpd_req_t *r, char *buf, size_t buf_len)
return ret;
}
esp_err_t httpd_req_async_handler_begin(httpd_req_t *r, httpd_req_t **out)
{
if (r == NULL || out == NULL) {
return ESP_ERR_INVALID_ARG;
}
// alloc async req
httpd_req_t *async = malloc(sizeof(httpd_req_t));
if (async == NULL) {
return ESP_ERR_NO_MEM;
}
memcpy(async, r, sizeof(httpd_req_t));
// alloc async aux
async->aux = malloc(sizeof(struct httpd_req_aux));
if (async->aux == NULL) {
free(async);
return ESP_ERR_NO_MEM;
}
memcpy(async->aux, r->aux, sizeof(struct httpd_req_aux));
// mark socket as "in use"
struct httpd_req_aux *ra = r->aux;
ra->sd->for_async_req = true;
*out = async;
return ESP_OK;
}
esp_err_t httpd_req_async_handler_complete(httpd_req_t *r)
{
if (r == NULL) {
return ESP_ERR_INVALID_ARG;
}
struct httpd_req_aux *ra = r->aux;
ra->sd->for_async_req = false;
free(r->aux);
free(r);
return ESP_OK;
}
int httpd_req_to_sockfd(httpd_req_t *r)
{
if (r == NULL) {