Add Bounded Ordinary HTTPS Idle Cleanup
This commit is contained in:
+49
-1
@@ -4,14 +4,62 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include "esp_idf_version.h"
|
||||
#include "esp_httpd_priv.h"
|
||||
#include "secure_random.h"
|
||||
|
||||
#if ESP_IDF_VERSION != ESP_IDF_VERSION_VAL(5, 5, 0)
|
||||
#error "Reaudit HTTPD header storage and pre-handler upgrade behavior for this IDF"
|
||||
#error "Reaudit HTTPD headers, upgrade, request completion and idle cleanup for this IDF"
|
||||
#endif
|
||||
|
||||
/* IDF 5.5.0 httpd_sess_process increments lru_counter only AFTER successful
|
||||
* req_new + req_delete (handler, response, leftover-body purge and cleanup).
|
||||
* Work callbacks run between sessions, never inside synchronous parse/TLS/send.
|
||||
* This counter is an observation marker, NOT permission to enable LRU purge. */
|
||||
void web_httpd_idle_sweep(httpd_handle_t server,
|
||||
web_httpd_idle_row_t rows[WEB_HTTPD_IDLE_SOCKETS], int64_t now)
|
||||
{
|
||||
struct httpd_data *hd = server;
|
||||
if (!hd || !rows || hd->config.max_open_sockets > WEB_HTTPD_IDLE_SOCKETS ||
|
||||
httpd_os_thread_handle() != hd->hd_td.handle || hd->hd_req_aux.sd) return;
|
||||
for (unsigned i = 0; i < hd->config.max_open_sockets; ++i) {
|
||||
struct sock_db *sd = &hd->hd_sd[i];
|
||||
web_httpd_idle_row_t *row = &rows[i];
|
||||
/* Actual SDK classification, not delayed diagnostic route metadata. */
|
||||
if (sd->fd < 0 || sd->for_async_req || sd->ws_handshake_done || sd->ws_close) {
|
||||
memset(row, 0, sizeof(*row));
|
||||
continue;
|
||||
}
|
||||
if (!row->observed || row->fd != sd->fd || row->completed != sd->lru_counter) {
|
||||
*row = (web_httpd_idle_row_t){.fd = sd->fd, .completed = sd->lru_counter,
|
||||
.idle_since_us = now, .observed = true};
|
||||
continue;
|
||||
}
|
||||
if (row->shutdown_sent) continue;
|
||||
/* Control work precedes data processing in httpd_main. Do not expire a
|
||||
* connection whose next request is buffered in HTTPD, TLS or TCP. Zero
|
||||
* timeout select does not consume bytes or change TLS receive ownership.
|
||||
* Errors are conservative too; normal HTTPD owns error cleanup. */
|
||||
fd_set ready;
|
||||
FD_ZERO(&ready);
|
||||
if (sd->fd >= FD_SETSIZE) { row->idle_since_us = now; continue; }
|
||||
FD_SET(sd->fd, &ready);
|
||||
struct timeval timeout = {0};
|
||||
if (sd->pending_len || (sd->pending_fn && sd->pending_fn(hd, sd->fd) != 0) ||
|
||||
select(sd->fd + 1, &ready, NULL, NULL, &timeout) != 0) {
|
||||
row->idle_since_us = now;
|
||||
continue;
|
||||
}
|
||||
if (now - row->idle_since_us < WEB_HTTPD_IDLE_TIMEOUT_US) continue;
|
||||
/* Still the current fd on its owner; no queued sock_db pointer can later
|
||||
* target a replacement. HTTPD performs normal TLS/session destruction
|
||||
* on the next read. A failed shutdown retries on the next probe. */
|
||||
if (shutdown(sd->fd, SHUT_RDWR) == 0) row->shutdown_sent = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool web_httpd_headers_valid(httpd_req_t *request)
|
||||
{
|
||||
if (!request || !request->aux) return false;
|
||||
|
||||
Reference in New Issue
Block a user