From 9c6bec203de071f3b87bf57a4afb5cfd2a55c09a Mon Sep 17 00:00:00 2001 From: Anurag Kar Date: Fri, 17 May 2019 17:01:29 +0530 Subject: [PATCH] HTTP Server : Close new session immediately if open_fn fails open_fn() was introduced in the context of HTTPS server, as a configurable callback function that is called by the HTTP server, on every newly created socket. It is responsible of allocating resources for per session transport security. Earlier, if open_fn were to fail, the newly created socket would be closed by the server but the corresponding entry, for the now invalid socket, will remain in the internal socket database until that invalid socket is detected due to error when calling select(). Because of this delayed closing of sockets, the HTTPS server would quickly face shortage of available sessions when a lot of SSL handshake errors are happening (this typically occurs when a browser finds that the server certificate is self signed). This changes in this MR fix this issue by clearing up the socket from internal database, right after open_fn fails. Closes https://github.com/espressif/esp-idf/issues/3479 --- components/esp_http_server/include/esp_http_server.h | 6 +++++- components/esp_http_server/src/httpd_sess.c | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/components/esp_http_server/include/esp_http_server.h b/components/esp_http_server/include/esp_http_server.h index 9bf05a766..f5a524dba 100644 --- a/components/esp_http_server/include/esp_http_server.h +++ b/components/esp_http_server/include/esp_http_server.h @@ -100,7 +100,9 @@ typedef void (*httpd_free_ctx_fn_t)(void *ctx); * * @param[in] hd server instance * @param[in] sockfd session socket file descriptor - * @return status + * @return + * - ESP_OK : On success + * - Any value other than ESP_OK will signal the server to close the socket immediately */ typedef esp_err_t (*httpd_open_func_t)(httpd_handle_t hd, int sockfd); @@ -201,6 +203,8 @@ typedef struct httpd_config { * * If a context needs to be maintained between these functions, store it in the session using * httpd_sess_set_transport_ctx() and retrieve it later with httpd_sess_get_transport_ctx() + * + * Returning a value other than ESP_OK will immediately close the new socket. */ httpd_open_func_t open_fn; diff --git a/components/esp_http_server/src/httpd_sess.c b/components/esp_http_server/src/httpd_sess.c index 640f37d27..c56c22efa 100644 --- a/components/esp_http_server/src/httpd_sess.c +++ b/components/esp_http_server/src/httpd_sess.c @@ -77,7 +77,11 @@ esp_err_t httpd_sess_new(struct httpd_data *hd, int newfd) /* Call user-defined session opening function */ if (hd->config.open_fn) { esp_err_t ret = hd->config.open_fn(hd, hd->hd_sd[i].fd); - if (ret != ESP_OK) return ret; + if (ret != ESP_OK) { + httpd_sess_delete(hd, hd->hd_sd[i].fd); + ESP_LOGD(TAG, LOG_FMT("open_fn failed for fd = %d"), newfd); + return ret; + } } return ESP_OK; }