Skip to content

Commit f460cc7

Browse files
committed
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
2 parents 07980db + d52955e commit f460cc7

File tree

6 files changed

+147
-27
lines changed

6 files changed

+147
-27
lines changed

components/esp-tls/esp_tls_mbedtls.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -926,6 +926,8 @@ int esp_mbedtls_server_session_create(esp_tls_cfg_server_t *cfg, int sockfd, esp
926926
if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE) {
927927
ESP_LOGE(TAG, "mbedtls_ssl_handshake returned -0x%04X", -ret);
928928
mbedtls_print_error_msg(ret);
929+
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
930+
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED);
929931
tls->conn_state = ESP_TLS_FAIL;
930932
return ret;
931933
}

components/esp_https_server/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ set(inc "include")
33

44
idf_component_register(SRCS ${src}
55
INCLUDE_DIRS ${inc}
6-
REQUIRES esp_http_server esp-tls
6+
REQUIRES esp_http_server esp-tls esp_event
77
PRIV_REQUIRES lwip)

components/esp_https_server/include/esp_https_server.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,24 @@
1212
#include "esp_http_server.h"
1313
#include "esp_tls.h"
1414

15+
#include "esp_event.h"
16+
1517
#ifdef __cplusplus
1618
extern "C" {
1719
#endif
1820

21+
ESP_EVENT_DECLARE_BASE(ESP_HTTPS_SERVER_EVENT);
22+
23+
typedef enum {
24+
HTTPS_SERVER_EVENT_ERROR = 0, /*!< This event occurs when there are any errors during execution */
25+
HTTPS_SERVER_EVENT_START, /*!< This event occurs when HTTPS Server is started */
26+
HTTPS_SERVER_EVENT_ON_CONNECTED, /*!< Once the HTTPS Server has been connected to the client */
27+
HTTPS_SERVER_EVENT_ON_DATA, /*!< Occurs when receiving data from the client */
28+
HTTPS_SERVER_EVENT_SENT_DATA, /*!< Occurs when an ESP HTTPS server sends data to the client */
29+
HTTPS_SERVER_EVENT_DISCONNECTED, /*!< The connection has been disconnected */
30+
HTTPS_SERVER_EVENT_STOP, /*!< This event occurs when HTTPS Server is stopped */
31+
} esp_https_server_event_id_t;
32+
1933
typedef enum {
2034
HTTPD_SSL_TRANSPORT_SECURE, // SSL Enabled
2135
HTTPD_SSL_TRANSPORT_INSECURE // SSL disabled
@@ -39,6 +53,8 @@ typedef struct esp_https_server_user_cb_arg {
3953
esp_tls_t *tls; /*!< ESP-TLS connection handle */
4054
} esp_https_server_user_cb_arg_t;
4155

56+
typedef esp_tls_last_error_t esp_https_server_last_error_t;
57+
4258
/**
4359
* @brief Callback function prototype
4460
* Can be used to get connection or client information (SSL context)

components/esp_https_server/src/https_server.c

Lines changed: 98 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@ typedef struct httpd_ssl_transport_ctx {
2323
httpd_ssl_ctx_t *global_ctx;
2424
} httpd_ssl_transport_ctx_t;
2525

26+
ESP_EVENT_DEFINE_BASE(ESP_HTTPS_SERVER_EVENT);
27+
28+
static void http_dispatch_event_to_event_loop(int32_t event_id, const void* event_data, size_t event_data_size)
29+
{
30+
esp_err_t err = esp_event_post(ESP_HTTPS_SERVER_EVENT, event_id, event_data, event_data_size, portMAX_DELAY);
31+
if (err != ESP_OK) {
32+
ESP_LOGE(TAG, "Failed to post http_client event: %"PRId32", error: %s", event_id, esp_err_to_name(err));
33+
}
34+
}
35+
2636
/**
2737
* SSL socket close handler
2838
*
@@ -46,6 +56,7 @@ static void httpd_ssl_close(void *ctx)
4656
esp_tls_server_session_delete(tls);
4757
free(ctx);
4858
ESP_LOGD(TAG, "Secure socket closed");
59+
http_dispatch_event_to_event_loop(HTTPS_SERVER_EVENT_DISCONNECTED, NULL, 0);
4960
}
5061

5162
/**
@@ -61,7 +72,16 @@ static int httpd_ssl_pending(httpd_handle_t server, int sockfd)
6172
assert(transport_ctx != NULL);
6273
esp_tls_t *tls = transport_ctx->tls;
6374
assert(tls != NULL);
64-
return esp_tls_get_bytes_avail(tls);
75+
int ret = esp_tls_get_bytes_avail(tls);
76+
if (ret < 0) {
77+
esp_tls_error_handle_t error_handle;
78+
if (esp_tls_get_error_handle(tls, &error_handle) == ESP_OK) {
79+
esp_https_server_last_error_t last_error = {0};
80+
last_error.last_error = esp_tls_get_and_clear_last_error(error_handle, &last_error.esp_tls_error_code, &last_error.esp_tls_flags);
81+
http_dispatch_event_to_event_loop(HTTPS_SERVER_EVENT_ERROR, &last_error, sizeof(last_error));
82+
}
83+
}
84+
return ret;
6585
}
6686

6787
/**
@@ -80,7 +100,18 @@ static int httpd_ssl_recv(httpd_handle_t server, int sockfd, char *buf, size_t b
80100
assert(transport_ctx != NULL);
81101
esp_tls_t *tls = transport_ctx->tls;
82102
assert(tls != NULL);
83-
return esp_tls_conn_read(tls, buf, buf_len);
103+
int ret = esp_tls_conn_read(tls, buf, buf_len);
104+
if (ret < 0) {
105+
esp_tls_error_handle_t error_handle;
106+
if (esp_tls_get_error_handle(tls, &error_handle) == ESP_OK) {
107+
esp_https_server_last_error_t last_error = {0};
108+
last_error.last_error = esp_tls_get_and_clear_last_error(error_handle, &last_error.esp_tls_error_code, &last_error.esp_tls_flags);
109+
http_dispatch_event_to_event_loop(HTTPS_SERVER_EVENT_ERROR, &last_error, sizeof(last_error));
110+
}
111+
} else {
112+
http_dispatch_event_to_event_loop(HTTPS_SERVER_EVENT_ON_DATA, &ret, sizeof(int));
113+
}
114+
return ret;
84115
}
85116

86117
/**
@@ -99,7 +130,18 @@ static int httpd_ssl_send(httpd_handle_t server, int sockfd, const char *buf, si
99130
assert(transport_ctx != NULL);
100131
esp_tls_t *tls = transport_ctx->tls;
101132
assert(tls != NULL);
102-
return esp_tls_conn_write(tls, buf, buf_len);
133+
int ret = esp_tls_conn_write(tls, buf, buf_len);
134+
if (ret < 0) {
135+
esp_tls_error_handle_t error_handle;
136+
if (esp_tls_get_error_handle(tls, &error_handle) == ESP_OK) {
137+
esp_https_server_last_error_t last_error = {0};
138+
last_error.last_error = esp_tls_get_and_clear_last_error(error_handle, &last_error.esp_tls_error_code, &last_error.esp_tls_flags);
139+
http_dispatch_event_to_event_loop(HTTPS_SERVER_EVENT_ERROR, &last_error, sizeof(last_error));
140+
}
141+
} else {
142+
http_dispatch_event_to_event_loop(HTTPS_SERVER_EVENT_SENT_DATA, NULL, 0);
143+
}
144+
return ret;
103145
}
104146

105147
/**
@@ -120,12 +162,15 @@ static esp_err_t httpd_ssl_open(httpd_handle_t server, int sockfd)
120162

121163
esp_tls_t *tls = esp_tls_init();
122164
if (!tls) {
165+
esp_https_server_last_error_t last_error = {0};
166+
last_error.last_error = ESP_ERR_NO_MEM;
167+
http_dispatch_event_to_event_loop(HTTPS_SERVER_EVENT_ERROR, &last_error, sizeof(last_error));
123168
return ESP_ERR_NO_MEM;
124169
}
125170
ESP_LOGI(TAG, "performing session handshake");
126171
int ret = esp_tls_server_session_create(global_ctx->tls_cfg, sockfd, tls);
127172
if (ret != 0) {
128-
ESP_LOGE(TAG, "esp_tls_create_server_session failed");
173+
ESP_LOGE(TAG, "esp_tls_create_server_session failed, 0x%04x", -ret);
129174
goto fail;
130175
}
131176

@@ -134,6 +179,9 @@ static esp_err_t httpd_ssl_open(httpd_handle_t server, int sockfd)
134179
// NOTE: allocated memory will be freed by httpd_ssl_close
135180
httpd_ssl_transport_ctx_t *transport_ctx = (httpd_ssl_transport_ctx_t *)calloc(1, sizeof(httpd_ssl_transport_ctx_t));
136181
if (!transport_ctx) {
182+
esp_https_server_last_error_t last_error = {0};
183+
last_error.last_error = ESP_ERR_NO_MEM;
184+
http_dispatch_event_to_event_loop(HTTPS_SERVER_EVENT_ERROR, &last_error, sizeof(last_error));
137185
return ESP_ERR_NO_MEM;
138186
}
139187
transport_ctx->tls = tls;
@@ -160,10 +208,18 @@ static esp_err_t httpd_ssl_open(httpd_handle_t server, int sockfd)
160208
user_cb_data.tls = tls;
161209
(global_ctx->user_cb)((void *)&user_cb_data);
162210
}
163-
211+
http_dispatch_event_to_event_loop(HTTPS_SERVER_EVENT_ON_CONNECTED, NULL, 0);
164212
return ESP_OK;
165213
fail:
166-
esp_tls_server_session_delete(tls);
214+
{
215+
esp_tls_error_handle_t error_handle;
216+
if (esp_tls_get_error_handle(tls, &error_handle) == ESP_OK) {
217+
esp_https_server_last_error_t last_error = {0};
218+
last_error.last_error = esp_tls_get_and_clear_last_error(error_handle, &last_error.esp_tls_error_code, &last_error.esp_tls_flags);
219+
http_dispatch_event_to_event_loop(HTTPS_SERVER_EVENT_ERROR, &last_error, sizeof(last_error));
220+
}
221+
esp_tls_server_session_delete(tls);
222+
}
167223
return ESP_FAIL;
168224
}
169225

@@ -192,35 +248,35 @@ static void free_secure_context(void *ctx)
192248
free(ssl_ctx);
193249
}
194250

195-
static httpd_ssl_ctx_t *create_secure_context(const struct httpd_ssl_config *config)
251+
static esp_err_t create_secure_context(const struct httpd_ssl_config *config, httpd_ssl_ctx_t **ssl_ctx)
196252
{
197-
httpd_ssl_ctx_t *ssl_ctx = calloc(1, sizeof(httpd_ssl_ctx_t));
198-
if (!ssl_ctx) {
199-
return NULL;
253+
if (!ssl_ctx || !*ssl_ctx) {
254+
return ESP_ERR_INVALID_ARG;
200255
}
256+
esp_err_t ret = ESP_OK;
201257
esp_tls_cfg_server_t *cfg = (esp_tls_cfg_server_t *)calloc(1, sizeof(esp_tls_cfg_server_t));
202258
if (!cfg) {
259+
ret = ESP_ERR_NO_MEM;
203260
goto exit;
204261
}
205262

206263
if (config->session_tickets) {
207-
if ( esp_tls_cfg_server_session_tickets_init(cfg) != ESP_OK ) {
208-
ESP_LOGE(TAG, "Failed to init session ticket support");
264+
ret = esp_tls_cfg_server_session_tickets_init(cfg);
265+
if ( ret != ESP_OK ) {
266+
ESP_LOGE(TAG, "Failed to init session ticket support. error: %s", esp_err_to_name(ret));
209267
goto exit;
210268
}
211269
}
212270

213271
cfg->userdata = config->ssl_userdata;
214-
215-
216272
cfg->alpn_protos = config->alpn_protos;
217273

218274
#if defined(CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK)
219275
cfg->cert_select_cb = config->cert_select_cb;
220276
#endif
221277

222-
ssl_ctx->tls_cfg = cfg;
223-
ssl_ctx->user_cb = config->user_cb;
278+
(*ssl_ctx)->tls_cfg = cfg;
279+
(*ssl_ctx)->user_cb = config->user_cb;
224280

225281
/* cacert = CA which signs client cert, or client cert itself */
226282
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
231287
cfg->cacert_bytes = config->cacert_len;
232288
} else {
233289
ESP_LOGE(TAG, "Could not allocate memory for client certificate authority");
290+
ret = ESP_ERR_NO_MEM;
234291
goto exit;
235292
}
236293
}
@@ -244,13 +301,15 @@ static httpd_ssl_ctx_t *create_secure_context(const struct httpd_ssl_config *con
244301
cfg->servercert_bytes = config->servercert_len;
245302
} else {
246303
ESP_LOGE(TAG, "Could not allocate memory for server certificate");
304+
ret = ESP_ERR_NO_MEM;
247305
goto exit;
248306
}
249307
} else {
250308
#if defined(CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK)
251309
if (config->cert_select_cb == NULL) {
252310
#endif
253311
ESP_LOGE(TAG, "No Server certificate supplied");
312+
ret = ESP_ERR_INVALID_ARG;
254313
goto exit;
255314
#if defined(CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK)
256315
} else {
@@ -264,8 +323,8 @@ static httpd_ssl_ctx_t *create_secure_context(const struct httpd_ssl_config *con
264323
if (!cfg->use_secure_element) {
265324
if (config->use_ecdsa_peripheral) {
266325
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
267-
ssl_ctx->tls_cfg->use_ecdsa_peripheral = config->use_ecdsa_peripheral;
268-
ssl_ctx->tls_cfg->ecdsa_key_efuse_blk = config->ecdsa_key_efuse_blk;
326+
(*ssl_ctx)->tls_cfg->use_ecdsa_peripheral = config->use_ecdsa_peripheral;
327+
(*ssl_ctx)->tls_cfg->ecdsa_key_efuse_blk = config->ecdsa_key_efuse_blk;
269328
#else
270329
ESP_LOGE(TAG, "Please enable the support for signing using ECDSA peripheral in menuconfig.");
271330
goto exit;
@@ -278,33 +337,36 @@ static httpd_ssl_ctx_t *create_secure_context(const struct httpd_ssl_config *con
278337
cfg->serverkey_bytes = config->prvtkey_len;
279338
} else {
280339
ESP_LOGE(TAG, "Could not allocate memory for server key");
340+
ret = ESP_ERR_NO_MEM;
281341
goto exit;
282342
}
283343
} else {
284344
#if defined(CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK)
285345
if (config->cert_select_cb == NULL) {
286346
ESP_LOGE(TAG, "No Server key supplied and no certificate selection hook is present");
347+
ret = ESP_ERR_INVALID_ARG;
287348
goto exit;
288349
} else {
289350
ESP_LOGW(TAG, "Server key not supplied, make sure to supply it in the certificate selection hook");
290351
}
291352
#else
292353
ESP_LOGE(TAG, "No Server key supplied");
354+
ret = ESP_ERR_INVALID_ARG;
293355
goto exit;
294356
#endif
295357
}
296358
}
297359

298-
return ssl_ctx;
360+
return ret;
299361

300362
exit:
301363
if (cfg) {
302364
free((void *) cfg->servercert_buf);
303365
free((void *) cfg->cacert_buf);
304366
}
305367
free(cfg);
306-
free(ssl_ctx);
307-
return NULL;
368+
free(*ssl_ctx);
369+
return ret;
308370
}
309371

310372
/** Start the server */
@@ -315,11 +377,16 @@ esp_err_t httpd_ssl_start(httpd_handle_t *pHandle, struct httpd_ssl_config *conf
315377

316378
ESP_LOGI(TAG, "Starting server");
317379

380+
esp_err_t ret = ESP_OK;
318381
if (HTTPD_SSL_TRANSPORT_SECURE == config->transport_mode) {
319-
320-
httpd_ssl_ctx_t *ssl_ctx = create_secure_context(config);
382+
httpd_ssl_ctx_t *ssl_ctx = calloc(1, sizeof(httpd_ssl_ctx_t));
321383
if (!ssl_ctx) {
322-
return -1;
384+
return ESP_ERR_NO_MEM;
385+
}
386+
387+
ret = create_secure_context(config, &ssl_ctx);
388+
if (ret != ESP_OK) {
389+
return ret;
323390
}
324391

325392
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
342409

343410
httpd_handle_t handle = NULL;
344411

345-
esp_err_t ret = httpd_start(&handle, &config->httpd);
412+
ret = httpd_start(&handle, &config->httpd);
346413
if (ret != ESP_OK) return ret;
347414

348415
*pHandle = handle;
349416

350417
ESP_LOGI(TAG, "Server listening on port %d", config->httpd.server_port);
418+
http_dispatch_event_to_event_loop(HTTPS_SERVER_EVENT_START, NULL, 0);
351419
return ESP_OK;
352420
}
353421

354422
/** Stop the server */
355423
esp_err_t httpd_ssl_stop(httpd_handle_t handle)
356424
{
357-
return httpd_stop(handle);
425+
esp_err_t ret = httpd_stop(handle);
426+
if (ret == ESP_OK) {
427+
http_dispatch_event_to_event_loop(HTTPS_SERVER_EVENT_STOP, NULL, 0);
428+
}
429+
return ret;
358430
}

docs/en/api-reference/protocols/esp_https_server.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,23 @@ Performance
4646

4747
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).
4848

49+
Event Handling
50+
--------------
51+
52+
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.
53+
54+
:cpp:enum:`esp_https_server_event_id_t` has all the events which can happen for ESP HTTPS server.
55+
56+
Expected data type for different ESP HTTP server events in event loop:
57+
58+
- HTTPS_SERVER_EVENT_ERROR : ``esp_https_server_last_error_t``
59+
- HTTPS_SERVER_EVENT_START : ``NULL``
60+
- HTTPS_SERVER_EVENT_ON_CONNECTED : ``NULL``
61+
- HTTPS_SERVER_EVENT_ON_DATA : ``int``
62+
- HTTPS_SERVER_EVENT_SENT_DATA : ``NULL``
63+
- HTTPS_SERVER_EVENT_DISCONNECTED : ``NULL``
64+
- HTTPS_SERVER_EVENT_STOP : ``NULL``
65+
4966
API Reference
5067
-------------
5168

examples/protocols/https_server/simple/main/main.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,18 @@
2727

2828
static const char *TAG = "example";
2929

30+
/* Event handler for catching system events */
31+
static void event_handler(void* arg, esp_event_base_t event_base,
32+
int32_t event_id, void* event_data)
33+
{
34+
if (event_base == ESP_HTTPS_SERVER_EVENT) {
35+
if (event_id == HTTPS_SERVER_EVENT_ERROR) {
36+
esp_https_server_last_error_t *last_error = (esp_tls_last_error_t *) event_data;
37+
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);
38+
}
39+
}
40+
}
41+
3042
/* An HTTP GET handler */
3143
static esp_err_t root_get_handler(httpd_req_t *req)
3244
{
@@ -210,6 +222,7 @@ void app_main(void)
210222
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &connect_handler, &server));
211223
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_DISCONNECTED, &disconnect_handler, &server));
212224
#endif // CONFIG_EXAMPLE_CONNECT_ETHERNET
225+
ESP_ERROR_CHECK(esp_event_handler_register(ESP_HTTPS_SERVER_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
213226

214227
/* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
215228
* Read "Establishing Wi-Fi or Ethernet Connection" section in

0 commit comments

Comments
 (0)