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:
committed by
Harshit Malpani
parent
1d25057a24
commit
3824eba04d
@@ -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) */
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user