mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'bugfix/error_logging_in_https_server' into 'master'
fix(esp_https_server): Add error logs in https server Closes IDFGH-10815 See merge request espressif/esp-idf!27970
This commit is contained in:
commit
f460cc731f
@ -926,6 +926,8 @@ int esp_mbedtls_server_session_create(esp_tls_cfg_server_t *cfg, int sockfd, esp
|
||||
if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE) {
|
||||
ESP_LOGE(TAG, "mbedtls_ssl_handshake returned -0x%04X", -ret);
|
||||
mbedtls_print_error_msg(ret);
|
||||
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
|
||||
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED);
|
||||
tls->conn_state = ESP_TLS_FAIL;
|
||||
return ret;
|
||||
}
|
||||
|
@ -3,5 +3,5 @@ set(inc "include")
|
||||
|
||||
idf_component_register(SRCS ${src}
|
||||
INCLUDE_DIRS ${inc}
|
||||
REQUIRES esp_http_server esp-tls
|
||||
REQUIRES esp_http_server esp-tls esp_event
|
||||
PRIV_REQUIRES lwip)
|
||||
|
@ -12,10 +12,24 @@
|
||||
#include "esp_http_server.h"
|
||||
#include "esp_tls.h"
|
||||
|
||||
#include "esp_event.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
ESP_EVENT_DECLARE_BASE(ESP_HTTPS_SERVER_EVENT);
|
||||
|
||||
typedef enum {
|
||||
HTTPS_SERVER_EVENT_ERROR = 0, /*!< This event occurs when there are any errors during execution */
|
||||
HTTPS_SERVER_EVENT_START, /*!< This event occurs when HTTPS Server is started */
|
||||
HTTPS_SERVER_EVENT_ON_CONNECTED, /*!< Once the HTTPS Server has been connected to the client */
|
||||
HTTPS_SERVER_EVENT_ON_DATA, /*!< Occurs when receiving data from the client */
|
||||
HTTPS_SERVER_EVENT_SENT_DATA, /*!< Occurs when an ESP HTTPS server sends data to the client */
|
||||
HTTPS_SERVER_EVENT_DISCONNECTED, /*!< The connection has been disconnected */
|
||||
HTTPS_SERVER_EVENT_STOP, /*!< This event occurs when HTTPS Server is stopped */
|
||||
} esp_https_server_event_id_t;
|
||||
|
||||
typedef enum {
|
||||
HTTPD_SSL_TRANSPORT_SECURE, // SSL Enabled
|
||||
HTTPD_SSL_TRANSPORT_INSECURE // SSL disabled
|
||||
@ -39,6 +53,8 @@ typedef struct esp_https_server_user_cb_arg {
|
||||
esp_tls_t *tls; /*!< ESP-TLS connection handle */
|
||||
} esp_https_server_user_cb_arg_t;
|
||||
|
||||
typedef esp_tls_last_error_t esp_https_server_last_error_t;
|
||||
|
||||
/**
|
||||
* @brief Callback function prototype
|
||||
* Can be used to get connection or client information (SSL context)
|
||||
|
@ -23,6 +23,16 @@ typedef struct httpd_ssl_transport_ctx {
|
||||
httpd_ssl_ctx_t *global_ctx;
|
||||
} httpd_ssl_transport_ctx_t;
|
||||
|
||||
ESP_EVENT_DEFINE_BASE(ESP_HTTPS_SERVER_EVENT);
|
||||
|
||||
static void http_dispatch_event_to_event_loop(int32_t event_id, const void* event_data, size_t event_data_size)
|
||||
{
|
||||
esp_err_t err = esp_event_post(ESP_HTTPS_SERVER_EVENT, event_id, event_data, event_data_size, portMAX_DELAY);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to post http_client event: %"PRId32", error: %s", event_id, esp_err_to_name(err));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SSL socket close handler
|
||||
*
|
||||
@ -46,6 +56,7 @@ static void httpd_ssl_close(void *ctx)
|
||||
esp_tls_server_session_delete(tls);
|
||||
free(ctx);
|
||||
ESP_LOGD(TAG, "Secure socket closed");
|
||||
http_dispatch_event_to_event_loop(HTTPS_SERVER_EVENT_DISCONNECTED, NULL, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -61,7 +72,16 @@ static int httpd_ssl_pending(httpd_handle_t server, int sockfd)
|
||||
assert(transport_ctx != NULL);
|
||||
esp_tls_t *tls = transport_ctx->tls;
|
||||
assert(tls != NULL);
|
||||
return esp_tls_get_bytes_avail(tls);
|
||||
int ret = esp_tls_get_bytes_avail(tls);
|
||||
if (ret < 0) {
|
||||
esp_tls_error_handle_t error_handle;
|
||||
if (esp_tls_get_error_handle(tls, &error_handle) == ESP_OK) {
|
||||
esp_https_server_last_error_t last_error = {0};
|
||||
last_error.last_error = esp_tls_get_and_clear_last_error(error_handle, &last_error.esp_tls_error_code, &last_error.esp_tls_flags);
|
||||
http_dispatch_event_to_event_loop(HTTPS_SERVER_EVENT_ERROR, &last_error, sizeof(last_error));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -80,7 +100,18 @@ static int httpd_ssl_recv(httpd_handle_t server, int sockfd, char *buf, size_t b
|
||||
assert(transport_ctx != NULL);
|
||||
esp_tls_t *tls = transport_ctx->tls;
|
||||
assert(tls != NULL);
|
||||
return esp_tls_conn_read(tls, buf, buf_len);
|
||||
int ret = esp_tls_conn_read(tls, buf, buf_len);
|
||||
if (ret < 0) {
|
||||
esp_tls_error_handle_t error_handle;
|
||||
if (esp_tls_get_error_handle(tls, &error_handle) == ESP_OK) {
|
||||
esp_https_server_last_error_t last_error = {0};
|
||||
last_error.last_error = esp_tls_get_and_clear_last_error(error_handle, &last_error.esp_tls_error_code, &last_error.esp_tls_flags);
|
||||
http_dispatch_event_to_event_loop(HTTPS_SERVER_EVENT_ERROR, &last_error, sizeof(last_error));
|
||||
}
|
||||
} else {
|
||||
http_dispatch_event_to_event_loop(HTTPS_SERVER_EVENT_ON_DATA, &ret, sizeof(int));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -99,7 +130,18 @@ static int httpd_ssl_send(httpd_handle_t server, int sockfd, const char *buf, si
|
||||
assert(transport_ctx != NULL);
|
||||
esp_tls_t *tls = transport_ctx->tls;
|
||||
assert(tls != NULL);
|
||||
return esp_tls_conn_write(tls, buf, buf_len);
|
||||
int ret = esp_tls_conn_write(tls, buf, buf_len);
|
||||
if (ret < 0) {
|
||||
esp_tls_error_handle_t error_handle;
|
||||
if (esp_tls_get_error_handle(tls, &error_handle) == ESP_OK) {
|
||||
esp_https_server_last_error_t last_error = {0};
|
||||
last_error.last_error = esp_tls_get_and_clear_last_error(error_handle, &last_error.esp_tls_error_code, &last_error.esp_tls_flags);
|
||||
http_dispatch_event_to_event_loop(HTTPS_SERVER_EVENT_ERROR, &last_error, sizeof(last_error));
|
||||
}
|
||||
} else {
|
||||
http_dispatch_event_to_event_loop(HTTPS_SERVER_EVENT_SENT_DATA, NULL, 0);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -120,12 +162,15 @@ static esp_err_t httpd_ssl_open(httpd_handle_t server, int sockfd)
|
||||
|
||||
esp_tls_t *tls = esp_tls_init();
|
||||
if (!tls) {
|
||||
esp_https_server_last_error_t last_error = {0};
|
||||
last_error.last_error = ESP_ERR_NO_MEM;
|
||||
http_dispatch_event_to_event_loop(HTTPS_SERVER_EVENT_ERROR, &last_error, sizeof(last_error));
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
ESP_LOGI(TAG, "performing session handshake");
|
||||
int ret = esp_tls_server_session_create(global_ctx->tls_cfg, sockfd, tls);
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(TAG, "esp_tls_create_server_session failed");
|
||||
ESP_LOGE(TAG, "esp_tls_create_server_session failed, 0x%04x", -ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -134,6 +179,9 @@ static esp_err_t httpd_ssl_open(httpd_handle_t server, int sockfd)
|
||||
// NOTE: allocated memory will be freed by httpd_ssl_close
|
||||
httpd_ssl_transport_ctx_t *transport_ctx = (httpd_ssl_transport_ctx_t *)calloc(1, sizeof(httpd_ssl_transport_ctx_t));
|
||||
if (!transport_ctx) {
|
||||
esp_https_server_last_error_t last_error = {0};
|
||||
last_error.last_error = ESP_ERR_NO_MEM;
|
||||
http_dispatch_event_to_event_loop(HTTPS_SERVER_EVENT_ERROR, &last_error, sizeof(last_error));
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
transport_ctx->tls = tls;
|
||||
@ -160,10 +208,18 @@ static esp_err_t httpd_ssl_open(httpd_handle_t server, int sockfd)
|
||||
user_cb_data.tls = tls;
|
||||
(global_ctx->user_cb)((void *)&user_cb_data);
|
||||
}
|
||||
|
||||
http_dispatch_event_to_event_loop(HTTPS_SERVER_EVENT_ON_CONNECTED, NULL, 0);
|
||||
return ESP_OK;
|
||||
fail:
|
||||
esp_tls_server_session_delete(tls);
|
||||
{
|
||||
esp_tls_error_handle_t error_handle;
|
||||
if (esp_tls_get_error_handle(tls, &error_handle) == ESP_OK) {
|
||||
esp_https_server_last_error_t last_error = {0};
|
||||
last_error.last_error = esp_tls_get_and_clear_last_error(error_handle, &last_error.esp_tls_error_code, &last_error.esp_tls_flags);
|
||||
http_dispatch_event_to_event_loop(HTTPS_SERVER_EVENT_ERROR, &last_error, sizeof(last_error));
|
||||
}
|
||||
esp_tls_server_session_delete(tls);
|
||||
}
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
@ -192,35 +248,35 @@ static void free_secure_context(void *ctx)
|
||||
free(ssl_ctx);
|
||||
}
|
||||
|
||||
static httpd_ssl_ctx_t *create_secure_context(const struct httpd_ssl_config *config)
|
||||
static esp_err_t create_secure_context(const struct httpd_ssl_config *config, httpd_ssl_ctx_t **ssl_ctx)
|
||||
{
|
||||
httpd_ssl_ctx_t *ssl_ctx = calloc(1, sizeof(httpd_ssl_ctx_t));
|
||||
if (!ssl_ctx) {
|
||||
return NULL;
|
||||
if (!ssl_ctx || !*ssl_ctx) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
esp_err_t ret = ESP_OK;
|
||||
esp_tls_cfg_server_t *cfg = (esp_tls_cfg_server_t *)calloc(1, sizeof(esp_tls_cfg_server_t));
|
||||
if (!cfg) {
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (config->session_tickets) {
|
||||
if ( esp_tls_cfg_server_session_tickets_init(cfg) != ESP_OK ) {
|
||||
ESP_LOGE(TAG, "Failed to init session ticket support");
|
||||
ret = esp_tls_cfg_server_session_tickets_init(cfg);
|
||||
if ( ret != ESP_OK ) {
|
||||
ESP_LOGE(TAG, "Failed to init session ticket support. error: %s", esp_err_to_name(ret));
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
cfg->userdata = config->ssl_userdata;
|
||||
|
||||
|
||||
cfg->alpn_protos = config->alpn_protos;
|
||||
|
||||
#if defined(CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK)
|
||||
cfg->cert_select_cb = config->cert_select_cb;
|
||||
#endif
|
||||
|
||||
ssl_ctx->tls_cfg = cfg;
|
||||
ssl_ctx->user_cb = config->user_cb;
|
||||
(*ssl_ctx)->tls_cfg = cfg;
|
||||
(*ssl_ctx)->user_cb = config->user_cb;
|
||||
|
||||
/* cacert = CA which signs client cert, or client cert itself */
|
||||
if (config->cacert_pem != NULL && config->cacert_len > 0) {
|
||||
@ -231,6 +287,7 @@ static httpd_ssl_ctx_t *create_secure_context(const struct httpd_ssl_config *con
|
||||
cfg->cacert_bytes = config->cacert_len;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Could not allocate memory for client certificate authority");
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
@ -244,6 +301,7 @@ static httpd_ssl_ctx_t *create_secure_context(const struct httpd_ssl_config *con
|
||||
cfg->servercert_bytes = config->servercert_len;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Could not allocate memory for server certificate");
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
goto exit;
|
||||
}
|
||||
} else {
|
||||
@ -251,6 +309,7 @@ static httpd_ssl_ctx_t *create_secure_context(const struct httpd_ssl_config *con
|
||||
if (config->cert_select_cb == NULL) {
|
||||
#endif
|
||||
ESP_LOGE(TAG, "No Server certificate supplied");
|
||||
ret = ESP_ERR_INVALID_ARG;
|
||||
goto exit;
|
||||
#if defined(CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK)
|
||||
} else {
|
||||
@ -264,8 +323,8 @@ static httpd_ssl_ctx_t *create_secure_context(const struct httpd_ssl_config *con
|
||||
if (!cfg->use_secure_element) {
|
||||
if (config->use_ecdsa_peripheral) {
|
||||
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
|
||||
ssl_ctx->tls_cfg->use_ecdsa_peripheral = config->use_ecdsa_peripheral;
|
||||
ssl_ctx->tls_cfg->ecdsa_key_efuse_blk = config->ecdsa_key_efuse_blk;
|
||||
(*ssl_ctx)->tls_cfg->use_ecdsa_peripheral = config->use_ecdsa_peripheral;
|
||||
(*ssl_ctx)->tls_cfg->ecdsa_key_efuse_blk = config->ecdsa_key_efuse_blk;
|
||||
#else
|
||||
ESP_LOGE(TAG, "Please enable the support for signing using ECDSA peripheral in menuconfig.");
|
||||
goto exit;
|
||||
@ -278,24 +337,27 @@ static httpd_ssl_ctx_t *create_secure_context(const struct httpd_ssl_config *con
|
||||
cfg->serverkey_bytes = config->prvtkey_len;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Could not allocate memory for server key");
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
goto exit;
|
||||
}
|
||||
} else {
|
||||
#if defined(CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK)
|
||||
if (config->cert_select_cb == NULL) {
|
||||
ESP_LOGE(TAG, "No Server key supplied and no certificate selection hook is present");
|
||||
ret = ESP_ERR_INVALID_ARG;
|
||||
goto exit;
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Server key not supplied, make sure to supply it in the certificate selection hook");
|
||||
}
|
||||
#else
|
||||
ESP_LOGE(TAG, "No Server key supplied");
|
||||
ret = ESP_ERR_INVALID_ARG;
|
||||
goto exit;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return ssl_ctx;
|
||||
return ret;
|
||||
|
||||
exit:
|
||||
if (cfg) {
|
||||
@ -303,8 +365,8 @@ exit:
|
||||
free((void *) cfg->cacert_buf);
|
||||
}
|
||||
free(cfg);
|
||||
free(ssl_ctx);
|
||||
return NULL;
|
||||
free(*ssl_ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Start the server */
|
||||
@ -315,11 +377,16 @@ esp_err_t httpd_ssl_start(httpd_handle_t *pHandle, struct httpd_ssl_config *conf
|
||||
|
||||
ESP_LOGI(TAG, "Starting server");
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
if (HTTPD_SSL_TRANSPORT_SECURE == config->transport_mode) {
|
||||
|
||||
httpd_ssl_ctx_t *ssl_ctx = create_secure_context(config);
|
||||
httpd_ssl_ctx_t *ssl_ctx = calloc(1, sizeof(httpd_ssl_ctx_t));
|
||||
if (!ssl_ctx) {
|
||||
return -1;
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
ret = create_secure_context(config, &ssl_ctx);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "SSL context ready");
|
||||
@ -342,17 +409,22 @@ esp_err_t httpd_ssl_start(httpd_handle_t *pHandle, struct httpd_ssl_config *conf
|
||||
|
||||
httpd_handle_t handle = NULL;
|
||||
|
||||
esp_err_t ret = httpd_start(&handle, &config->httpd);
|
||||
ret = httpd_start(&handle, &config->httpd);
|
||||
if (ret != ESP_OK) return ret;
|
||||
|
||||
*pHandle = handle;
|
||||
|
||||
ESP_LOGI(TAG, "Server listening on port %d", config->httpd.server_port);
|
||||
http_dispatch_event_to_event_loop(HTTPS_SERVER_EVENT_START, NULL, 0);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/** Stop the server */
|
||||
esp_err_t httpd_ssl_stop(httpd_handle_t handle)
|
||||
{
|
||||
return httpd_stop(handle);
|
||||
esp_err_t ret = httpd_stop(handle);
|
||||
if (ret == ESP_OK) {
|
||||
http_dispatch_event_to_event_loop(HTTPS_SERVER_EVENT_STOP, NULL, 0);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -46,6 +46,23 @@ Performance
|
||||
|
||||
The initial session setup can take about two seconds, or more with slower clock speed or more verbose logging. Subsequent requests through the open secure socket are much faster (down to under 100 ms).
|
||||
|
||||
Event Handling
|
||||
--------------
|
||||
|
||||
ESP HTTPS Server has various events for which a handler can be triggered by :doc:`the Event Loop library <../system/esp_event>` when the particular event occurs. The handler has to be registered using :cpp:func:`esp_event_handler_register`. This helps in event handling for ESP HTTPS Server.
|
||||
|
||||
:cpp:enum:`esp_https_server_event_id_t` has all the events which can happen for ESP HTTPS server.
|
||||
|
||||
Expected data type for different ESP HTTP server events in event loop:
|
||||
|
||||
- HTTPS_SERVER_EVENT_ERROR : ``esp_https_server_last_error_t``
|
||||
- HTTPS_SERVER_EVENT_START : ``NULL``
|
||||
- HTTPS_SERVER_EVENT_ON_CONNECTED : ``NULL``
|
||||
- HTTPS_SERVER_EVENT_ON_DATA : ``int``
|
||||
- HTTPS_SERVER_EVENT_SENT_DATA : ``NULL``
|
||||
- HTTPS_SERVER_EVENT_DISCONNECTED : ``NULL``
|
||||
- HTTPS_SERVER_EVENT_STOP : ``NULL``
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
|
@ -27,6 +27,18 @@
|
||||
|
||||
static const char *TAG = "example";
|
||||
|
||||
/* Event handler for catching system events */
|
||||
static void event_handler(void* arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void* event_data)
|
||||
{
|
||||
if (event_base == ESP_HTTPS_SERVER_EVENT) {
|
||||
if (event_id == HTTPS_SERVER_EVENT_ERROR) {
|
||||
esp_https_server_last_error_t *last_error = (esp_tls_last_error_t *) event_data;
|
||||
ESP_LOGE(TAG, "Error event triggered: last_error = %s, last_tls_err = %d, tls_flag = %d", esp_err_to_name(last_error->last_error), last_error->esp_tls_error_code, last_error->esp_tls_flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* An HTTP GET handler */
|
||||
static esp_err_t root_get_handler(httpd_req_t *req)
|
||||
{
|
||||
@ -210,6 +222,7 @@ void app_main(void)
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &connect_handler, &server));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_DISCONNECTED, &disconnect_handler, &server));
|
||||
#endif // CONFIG_EXAMPLE_CONNECT_ETHERNET
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(ESP_HTTPS_SERVER_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
|
||||
|
||||
/* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
|
||||
* Read "Establishing Wi-Fi or Ethernet Connection" section in
|
||||
|
Loading…
Reference in New Issue
Block a user