From ce519ee783958bf202b877d0f9352bf5b86a8b16 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Wed, 8 Apr 2020 20:04:33 +0200 Subject: [PATCH] tcp_transport: Extend transport error storage for socket error Everytime we report error and log errno, we also capture the actual errno to an internal storage so that user application can retrieve its value. --- components/esp-tls/CMakeLists.txt | 2 +- components/esp-tls/component.mk | 2 +- components/esp-tls/esp_tls.c | 18 ++--- components/esp-tls/esp_tls.h | 30 +++++++ components/esp-tls/esp_tls_error_capture.c | 81 +++++++++++++++++++ components/esp-tls/esp_tls_mbedtls.c | 42 +++++----- components/esp-tls/esp_tls_wolfssl.c | 26 +++--- .../esp_tls_error_capture_internal.h | 57 ++++++------- .../tcp_transport/include/esp_transport.h | 17 +++- .../private_include/esp_transport_internal.h | 13 ++- components/tcp_transport/transport.c | 42 ++++++++-- components/tcp_transport/transport_ssl.c | 2 + components/tcp_transport/transport_tcp.c | 5 ++ 13 files changed, 251 insertions(+), 86 deletions(-) create mode 100644 components/esp-tls/esp_tls_error_capture.c diff --git a/components/esp-tls/CMakeLists.txt b/components/esp-tls/CMakeLists.txt index a8ae11e097..36569cfd51 100644 --- a/components/esp-tls/CMakeLists.txt +++ b/components/esp-tls/CMakeLists.txt @@ -1,4 +1,4 @@ -set(srcs esp_tls.c esp-tls-crypto/esp_tls_crypto.c) +set(srcs esp_tls.c esp-tls-crypto/esp_tls_crypto.c esp_tls_error_capture.c) if(CONFIG_ESP_TLS_USING_MBEDTLS) list(APPEND srcs "esp_tls_mbedtls.c") diff --git a/components/esp-tls/component.mk b/components/esp-tls/component.mk index 59eb4a63a7..6520d7db81 100644 --- a/components/esp-tls/component.mk +++ b/components/esp-tls/component.mk @@ -1,6 +1,6 @@ COMPONENT_SRCDIRS := . esp-tls-crypto -COMPONENT_OBJS := esp_tls.o esp-tls-crypto/esp_tls_crypto.o +COMPONENT_OBJS := esp_tls.o esp-tls-crypto/esp_tls_crypto.o esp_tls_error_capture.o COMPONENT_ADD_INCLUDEDIRS := . esp-tls-crypto private_include diff --git a/components/esp-tls/esp_tls.c b/components/esp-tls/esp_tls.c index d28a06c872..e6e444bb35 100644 --- a/components/esp-tls/esp_tls.c +++ b/components/esp-tls/esp_tls.c @@ -108,7 +108,7 @@ int esp_tls_conn_destroy(esp_tls_t *tls) if (tls->sockfd >= 0) { ret = close(tls->sockfd); } - free(tls->error_handle); + esp_tls_internal_event_tracker_destroy(tls->error_handle); free(tls); return ret; } @@ -121,7 +121,7 @@ esp_tls_t *esp_tls_init(void) if (!tls) { return NULL; } - tls->error_handle = calloc(1, sizeof(esp_tls_last_error_t)); + tls->error_handle = esp_tls_internal_event_tracker_create(); if (!tls->error_handle) { free(tls); return NULL; @@ -172,7 +172,7 @@ static esp_err_t esp_tcp_connect(const char *host, int hostlen, int port, int *s int fd = socket(addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol); if (fd < 0) { ESP_LOGE(TAG, "Failed to create socket (family %d socktype %d protocol %d)", addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_SYSTEM, errno); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_SYSTEM, errno); ret = ESP_ERR_ESP_TLS_CANNOT_CREATE_SOCKET; goto err_freeaddr; } @@ -214,7 +214,7 @@ static esp_err_t esp_tcp_connect(const char *host, int hostlen, int port, int *s if (ret < 0 && !(errno == EINPROGRESS && cfg && cfg->non_block)) { ESP_LOGE(TAG, "Failed to connnect to host (errno %d)", errno); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_SYSTEM, errno); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_SYSTEM, errno); ret = ESP_ERR_ESP_TLS_FAILED_CONNECT_TO_HOST; goto err_freesocket; } @@ -249,7 +249,7 @@ static int esp_tls_low_level_conn(const char *hostname, int hostlen, int port, c tls->is_tls = true; } if ((esp_ret = esp_tcp_connect(hostname, hostlen, port, &tls->sockfd, tls, cfg)) != ESP_OK) { - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, esp_ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, esp_ret); return -1; } if (!cfg) { @@ -284,8 +284,8 @@ static int esp_tls_low_level_conn(const char *hostname, int hostlen, int port, c /* pending error check */ if (getsockopt(tls->sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { ESP_LOGD(TAG, "Non blocking connect failed"); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_SYSTEM, errno); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_SYSTEM, errno); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED); tls->conn_state = ESP_TLS_FAIL; return -1; } @@ -295,7 +295,7 @@ static int esp_tls_low_level_conn(const char *hostname, int hostlen, int port, c esp_ret = create_ssl_handle(hostname, hostlen, cfg, tls); if (esp_ret != ESP_OK) { ESP_LOGE(TAG, "create_ssl_handle failed"); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, esp_ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, esp_ret); tls->conn_state = ESP_TLS_FAIL; return -1; } @@ -367,7 +367,7 @@ int esp_tls_conn_new_sync(const char *hostname, int hostlen, int port, const esp uint32_t expired = xTaskGetTickCount() - start; if (expired >= timeout_ticks) { ESP_LOGW(TAG, "Failed to open new connection in specified timeout"); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT); return 0; } } diff --git a/components/esp-tls/esp_tls.h b/components/esp-tls/esp_tls.h index 752c18e11d..1e4dbdc78e 100644 --- a/components/esp-tls/esp_tls.h +++ b/components/esp-tls/esp_tls.h @@ -74,6 +74,22 @@ extern "C" { #define ESP_TLS_ERR_SSL_WANT_WRITE WOLFSSL_ERROR_WANT_WRITE #define ESP_TLS_ERR_SSL_TIMEOUT WOLFSSL_CBIO_ERR_TIMEOUT #endif /*CONFIG_ESP_TLS_USING_WOLFSSL */ + +/** +* Definition of different types/sources of error codes reported +* from different components +*/ +typedef enum { + ESP_TLS_ERR_TYPE_UNKNOWN = 0, + ESP_TLS_ERR_TYPE_SYSTEM, /*!< System error -- errno */ + ESP_TLS_ERR_TYPE_MBEDTLS, /*!< Error code from mbedTLS library */ + ESP_TLS_ERR_TYPE_MBEDTLS_CERT_FLAGS, /*!< Certificate flags defined in mbedTLS */ + ESP_TLS_ERR_TYPE_ESP, /*!< ESP-IDF error type -- esp_err_t */ + ESP_TLS_ERR_TYPE_WOLFSSL, /*!< Error code from wolfSSL library */ + ESP_TLS_ERR_TYPE_WOLFSSL_CERT_FLAGS, /*!< Certificate flags defined in wolfSSL */ + ESP_TLS_ERR_TYPE_MAX, /*!< Last err type -- invalid entry */ +} esp_tls_error_type_t; + typedef struct esp_tls_last_error* esp_tls_error_handle_t; /** @@ -574,6 +590,20 @@ void esp_tls_free_global_ca_store(void); */ esp_err_t esp_tls_get_and_clear_last_error(esp_tls_error_handle_t h, int *esp_tls_code, int *esp_tls_flags); +/** + * @brief Returns the last error captured in esp_tls of a specific type + * The error information is cleared internally upon return + * + * @param[in] h esp-tls error handle. + * @param[in] err_type specific error type + * @param[out] error_code last error code returned from mbedtls api (set to zero if none) + * This pointer could be NULL if caller does not care about esp_tls_code + * @return + * - ESP_ERR_INVALID_STATE if invalid parameters + * - ESP_OK if a valid error returned and was cleared + */ +esp_err_t esp_tls_get_and_clear_error_type(esp_tls_error_handle_t h, esp_tls_error_type_t err_type, int *error_code); + #if CONFIG_ESP_TLS_USING_MBEDTLS /** * @brief Get the pointer to the global CA store currently being used. diff --git a/components/esp-tls/esp_tls_error_capture.c b/components/esp-tls/esp_tls_error_capture.c new file mode 100644 index 0000000000..365a5eb62a --- /dev/null +++ b/components/esp-tls/esp_tls_error_capture.c @@ -0,0 +1,81 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "esp_tls.h" +#include "esp_tls_error_capture_internal.h" + +typedef struct esp_tls_error_storage { + struct esp_tls_last_error parent; /*!< standard esp-tls last error container */ + int sock_errno; /*!< last socket error captured in esp-tls */ +} esp_tls_error_storage_t; + +void esp_tls_internal_event_tracker_capture(esp_tls_error_handle_t h, uint32_t type, int code) +{ + if (h) { + esp_tls_error_storage_t * storage = __containerof(h, esp_tls_error_storage_t, parent); + + if (type == ESP_TLS_ERR_TYPE_ESP) { + storage->parent.last_error = code; + } else if (type == ESP_TLS_ERR_TYPE_MBEDTLS || + type == ESP_TLS_ERR_TYPE_WOLFSSL) { + storage->parent.esp_tls_error_code = code; + } else if (type == ESP_TLS_ERR_TYPE_MBEDTLS_CERT_FLAGS || + type == ESP_TLS_ERR_TYPE_WOLFSSL_CERT_FLAGS) { + storage->parent.esp_tls_flags = code; + } else if (type == ESP_TLS_ERR_TYPE_SYSTEM) { + storage->sock_errno = code; + } + } +} + +esp_tls_error_handle_t esp_tls_internal_event_tracker_create(void) +{ + // Allocating internal error storage which extends the parent type + // `esp_tls_last_error` defined at interface level + struct esp_tls_error_storage* storage = + calloc(1, sizeof(struct esp_tls_error_storage)); + return &storage->parent; +} + +void esp_tls_internal_event_tracker_destroy(esp_tls_error_handle_t h) +{ + esp_tls_error_storage_t * storage = __containerof(h, esp_tls_error_storage_t, parent); + free(storage); +} + +esp_err_t esp_tls_get_and_clear_error_type(esp_tls_error_handle_t h, esp_tls_error_type_t type, int *code) +{ + if (h && type < ESP_TLS_ERR_TYPE_MAX && code) { + esp_tls_error_storage_t * storage = __containerof(h, esp_tls_error_storage_t, parent); + if (type == ESP_TLS_ERR_TYPE_ESP) { + *code = storage->parent.last_error; + storage->parent.last_error = 0; + } else if (type == ESP_TLS_ERR_TYPE_MBEDTLS || + type == ESP_TLS_ERR_TYPE_WOLFSSL) { + *code = storage->parent.esp_tls_error_code; + storage->parent.esp_tls_error_code = 0; + } else if (type == ESP_TLS_ERR_TYPE_MBEDTLS_CERT_FLAGS || + type == ESP_TLS_ERR_TYPE_WOLFSSL_CERT_FLAGS) { + *code = storage->parent.esp_tls_flags; + storage->parent.esp_tls_flags = 0; + } else if (type == ESP_TLS_ERR_TYPE_SYSTEM) { + *code = storage->sock_errno; + storage->sock_errno = 0; + } else { + return ESP_ERR_INVALID_ARG; + } + return ESP_OK; + } + return ESP_ERR_INVALID_ARG; +} diff --git a/components/esp-tls/esp_tls_mbedtls.c b/components/esp-tls/esp_tls_mbedtls.c index f88a5aa10d..088d2a82ab 100644 --- a/components/esp-tls/esp_tls_mbedtls.c +++ b/components/esp-tls/esp_tls_mbedtls.c @@ -100,7 +100,7 @@ esp_err_t esp_create_mbedtls_handle(const char *hostname, size_t hostlen, const if ((ret = mbedtls_ctr_drbg_seed(&tls->ctr_drbg, mbedtls_entropy_func, &tls->entropy, NULL, 0)) != 0) { ESP_LOGE(TAG, "mbedtls_ctr_drbg_seed returned -0x%x", -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); esp_ret = ESP_ERR_MBEDTLS_CTR_DRBG_SEED_FAILED; goto exit; } @@ -113,7 +113,7 @@ esp_err_t esp_create_mbedtls_handle(const char *hostname, size_t hostlen, const if ((ret = mbedtls_ssl_setup(&tls->ssl, &tls->conf)) != 0) { ESP_LOGE(TAG, "mbedtls_ssl_setup returned -0x%x", -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); esp_ret = ESP_ERR_MBEDTLS_SSL_SETUP_FAILED; goto exit; } @@ -140,8 +140,8 @@ int esp_mbedtls_handshake(esp_tls_t *tls, const esp_tls_cfg_t *cfg) } else { if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE) { ESP_LOGE(TAG, "mbedtls_ssl_handshake returned -0x%x", -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED); + 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); if (cfg->cacert_buf != NULL || cfg->use_global_ca_store == true) { /* This is to check whether handshake failed due to invalid certificate*/ esp_mbedtls_verify_certificate(tls); @@ -164,7 +164,7 @@ ssize_t esp_mbedtls_read(esp_tls_t *tls, char *data, size_t datalen) return 0; } if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE) { - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); ESP_LOGE(TAG, "read error :%d:", ret); } } @@ -185,8 +185,8 @@ ssize_t esp_mbedtls_write(esp_tls_t *tls, const char *data, size_t datalen) ssize_t ret = mbedtls_ssl_write(&tls->ssl, (unsigned char*) data + written, write_len); if (ret <= 0) { if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE && ret != 0) { - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, ESP_ERR_MBEDTLS_SSL_WRITE_FAILED); + 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_WRITE_FAILED); ESP_LOGE(TAG, "write error :%d:", ret); return ret; } else { @@ -217,7 +217,7 @@ void esp_mbedtls_verify_certificate(esp_tls_t *tls) char buf[100]; if ((flags = mbedtls_ssl_get_verify_result(&tls->ssl)) != 0) { ESP_LOGI(TAG, "Failed to verify peer certificate!"); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS_CERT_FLAGS, flags); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS_CERT_FLAGS, flags); bzero(buf, sizeof(buf)); mbedtls_x509_crt_verify_info(buf, sizeof(buf), " ! ", flags); ESP_LOGI(TAG, "verification info: %s", buf); @@ -271,7 +271,7 @@ static esp_err_t set_ca_cert(esp_tls_t *tls, const unsigned char *cacert, size_t int ret = mbedtls_x509_crt_parse(tls->cacert_ptr, cacert, cacert_len); if (ret < 0) { ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%x", -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); return ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED; } mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED); @@ -295,7 +295,7 @@ static esp_err_t set_pki_context(esp_tls_t *tls, const esp_tls_pki_t *pki) ret = mbedtls_x509_crt_parse(pki->public_cert, pki->publiccert_pem_buf, pki->publiccert_pem_bytes); if (ret < 0) { ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%x", -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); return ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED; } @@ -317,14 +317,14 @@ static esp_err_t set_pki_context(esp_tls_t *tls, const esp_tls_pki_t *pki) if (ret < 0) { ESP_LOGE(TAG, "mbedtls_pk_parse_keyfile returned -0x%x", -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); return ESP_ERR_MBEDTLS_PK_PARSE_KEY_FAILED; } ret = mbedtls_ssl_conf_own_cert(&tls->conf, pki->public_cert, pki->pk_key); if (ret < 0) { ESP_LOGE(TAG, "mbedtls_ssl_conf_own_cert returned -0x%x", -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); return ESP_ERR_MBEDTLS_SSL_CONF_OWN_CERT_FAILED; } } else { @@ -359,7 +359,7 @@ esp_err_t set_server_config(esp_tls_cfg_server_t *cfg, esp_tls_t *tls) MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { ESP_LOGE(TAG, "mbedtls_ssl_config_defaults returned %d", ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); return ESP_ERR_MBEDTLS_SSL_CONFIG_DEFAULTS_FAILED; } @@ -421,7 +421,7 @@ esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t /* Hostname set here should match CN in server certificate */ if ((ret = mbedtls_ssl_set_hostname(&tls->ssl, use_host)) != 0) { ESP_LOGE(TAG, "mbedtls_ssl_set_hostname returned -0x%x", -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); free(use_host); return ESP_ERR_MBEDTLS_SSL_SET_HOSTNAME_FAILED; } @@ -433,7 +433,7 @@ esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { ESP_LOGE(TAG, "mbedtls_ssl_config_defaults returned -0x%x", -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); return ESP_ERR_MBEDTLS_SSL_CONFIG_DEFAULTS_FAILED; } @@ -445,7 +445,7 @@ esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t #ifdef CONFIG_MBEDTLS_SSL_ALPN if ((ret = mbedtls_ssl_conf_alpn_protocols(&tls->conf, cfg->alpn_protos) != 0)) { ESP_LOGE(TAG, "mbedtls_ssl_conf_alpn_protocols returned -0x%x", -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); return ESP_ERR_MBEDTLS_SSL_CONF_ALPN_PROTOCOLS_FAILED; } #else @@ -483,7 +483,7 @@ esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t (const unsigned char *)cfg->psk_hint_key->hint, strlen(cfg->psk_hint_key->hint)); if (ret != 0) { ESP_LOGE(TAG, "mbedtls_ssl_conf_psk returned -0x%x", -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); return ESP_ERR_MBEDTLS_SSL_CONF_PSK_FAILED; } #else @@ -570,7 +570,7 @@ int esp_mbedtls_server_session_create(esp_tls_cfg_server_t *cfg, int sockfd, esp esp_err_t esp_ret = esp_create_mbedtls_handle(NULL, 0, cfg, tls); if (esp_ret != ESP_OK) { ESP_LOGE(TAG, "create_ssl_handle failed"); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, esp_ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, esp_ret); tls->conn_state = ESP_TLS_FAIL; return -1; } @@ -703,7 +703,7 @@ static esp_err_t esp_set_atecc608a_pki_context(esp_tls_t *tls, esp_tls_cfg_t *cf ret = mbedtls_x509_crt_parse(&tls->clientcert, (const unsigned char*)cfg->clientcert_buf, cfg->clientcert_bytes); if (ret < 0) { ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%x", -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); return ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED; } } else { @@ -714,14 +714,14 @@ static esp_err_t esp_set_atecc608a_pki_context(esp_tls_t *tls, esp_tls_cfg_t *cf ret = atca_mbedtls_pk_init(&tls->clientkey, 0); if (ret != 0) { ESP_LOGE(TAG, "Failed to parse key from device"); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); return ESP_ERR_ESP_TLS_SE_FAILED; } ret = mbedtls_ssl_conf_own_cert(&tls->conf, &tls->clientcert, &tls->clientkey); if (ret != 0) { ESP_LOGE(TAG, "Failed\n ! mbedtls_ssl_conf_own_cert returned -0x%x", ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); return ESP_ERR_ESP_TLS_SE_FAILED; } return ESP_OK; diff --git a/components/esp-tls/esp_tls_wolfssl.c b/components/esp-tls/esp_tls_wolfssl.c index d929ad04b5..d956e70f9a 100644 --- a/components/esp-tls/esp_tls_wolfssl.c +++ b/components/esp-tls/esp_tls_wolfssl.c @@ -114,7 +114,7 @@ esp_err_t esp_create_wolfssl_handle(const char *hostname, size_t hostlen, const ret = wolfSSL_Init(); if (ret != WOLFSSL_SUCCESS) { ESP_LOGE(TAG, "Init wolfSSL failed: %d", ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_WOLFSSL, -ret); goto exit; } @@ -153,7 +153,7 @@ static esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls tls->priv_ctx = (void *)wolfSSL_CTX_new(wolfTLSv1_2_client_method()); if (!tls->priv_ctx) { ESP_LOGE(TAG, "Set wolfSSL ctx failed"); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_WOLFSSL, -ret); return ESP_ERR_WOLFSSL_CTX_SETUP_FAILED; } @@ -226,7 +226,7 @@ static esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls tls->priv_ssl =(void *)wolfSSL_new( (WOLFSSL_CTX *)tls->priv_ctx); if (!tls->priv_ssl) { ESP_LOGE(TAG, "Create wolfSSL failed"); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_WOLFSSL, -ret); return ESP_ERR_WOLFSSL_SSL_SETUP_FAILED; } @@ -243,7 +243,7 @@ static esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls /* Hostname set here should match CN in server certificate */ if ((ret = wolfSSL_set_tlsext_host_name( (WOLFSSL *)tls->priv_ssl, use_host))!= WOLFSSL_SUCCESS) { ESP_LOGE(TAG, "wolfSSL_set_tlsext_host_name returned -0x%x", -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_WOLFSSL, -ret); free(use_host); return ESP_ERR_WOLFSSL_SSL_SET_HOSTNAME_FAILED; } @@ -256,7 +256,7 @@ static esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls for (; *alpn_list != NULL; alpn_list ++) { ESP_LOGD(TAG, "alpn protocol is %s", *alpn_list); if ((ret = wolfSSL_UseALPN( (WOLFSSL *)tls->priv_ssl, *alpn_list, strlen(*alpn_list), WOLFSSL_ALPN_FAILED_ON_MISMATCH)) != WOLFSSL_SUCCESS) { - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_WOLFSSL, -ret); ESP_LOGE(TAG, "wolfSSL UseALPN failed, returned %d", ret); return ESP_ERR_WOLFSSL_SSL_CONF_ALPN_PROTOCOLS_FAILED; } @@ -329,8 +329,8 @@ int esp_wolfssl_handshake(esp_tls_t *tls, const esp_tls_cfg_t *cfg) int err = wolfSSL_get_error( (WOLFSSL *)tls->priv_ssl, ret); if (err != ESP_TLS_ERR_SSL_WANT_READ && err != ESP_TLS_ERR_SSL_WANT_WRITE) { ESP_LOGE(TAG, "wolfSSL_connect returned -0x%x", -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, ESP_ERR_WOLFSSL_SSL_HANDSHAKE_FAILED); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_WOLFSSL, -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, ESP_ERR_WOLFSSL_SSL_HANDSHAKE_FAILED); if (cfg->cacert_buf != NULL || cfg->use_global_ca_store == true) { /* This is to check whether handshake failed due to invalid certificate*/ esp_wolfssl_verify_certificate(tls); @@ -355,7 +355,7 @@ ssize_t esp_wolfssl_read(esp_tls_t *tls, char *data, size_t datalen) } if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE) { - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_WOLFSSL, -ret); ESP_LOGE(TAG, "read error :%d:", ret); } } @@ -368,8 +368,8 @@ ssize_t esp_wolfssl_write(esp_tls_t *tls, const char *data, size_t datalen) if (ret < 0) { ret = wolfSSL_get_error( (WOLFSSL *)tls->priv_ssl, ret); if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE) { - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, ESP_ERR_WOLFSSL_SSL_WRITE_FAILED); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_WOLFSSL, -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, ESP_ERR_WOLFSSL_SSL_WRITE_FAILED); ESP_LOGE(TAG, "write error :%d:", ret); } @@ -382,7 +382,7 @@ void esp_wolfssl_verify_certificate(esp_tls_t *tls) int flags; if ((flags = wolfSSL_get_verify_result( (WOLFSSL *)tls->priv_ssl)) != X509_V_OK) { ESP_LOGE(TAG, "Failed to verify peer certificate , returned %d!", flags); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL_CERT_FLAGS, flags); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_WOLFSSL_CERT_FLAGS, flags); } else { ESP_LOGI(TAG, "Certificate verified."); } @@ -434,7 +434,7 @@ int esp_wolfssl_server_session_create(esp_tls_cfg_server_t *cfg, int sockfd, esp esp_err_t esp_ret = esp_create_wolfssl_handle(NULL, 0, cfg, tls); if (esp_ret != ESP_OK) { ESP_LOGE(TAG, "create_ssl_handle failed"); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, esp_ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, esp_ret); tls->conn_state = ESP_TLS_FAIL; return -1; } @@ -443,7 +443,7 @@ int esp_wolfssl_server_session_create(esp_tls_cfg_server_t *cfg, int sockfd, esp int ret; while ((ret = wolfSSL_accept((WOLFSSL *)tls->priv_ssl)) != WOLFSSL_SUCCESS) { if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE) { - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_WOLFSSL, -ret); ESP_LOGE(TAG, "wolfSSL_handshake_server returned %d", ret); tls->conn_state = ESP_TLS_FAIL; return ret; diff --git a/components/esp-tls/private_include/esp_tls_error_capture_internal.h b/components/esp-tls/private_include/esp_tls_error_capture_internal.h index d047b543b5..fd065b2be4 100644 --- a/components/esp-tls/private_include/esp_tls_error_capture_internal.h +++ b/components/esp-tls/private_include/esp_tls_error_capture_internal.h @@ -24,43 +24,36 @@ extern "C" { #endif /** -* Definition of different types/sources of error codes reported -* from different components -*/ -typedef enum { - ERR_TYPE_UNKNOWN = 0, - ERR_TYPE_SYSTEM, - ERR_TYPE_MBEDTLS, - ERR_TYPE_MBEDTLS_CERT_FLAGS, - ERR_TYPE_ESP, - ERR_TYPE_WOLFSSL, - ERR_TYPE_WOLFSSL_CERT_FLAGS, -} err_type_t; + * Error tracker logging macro to enable mapping tracking errors internally + * or using an external/global implementation + */ +#define ESP_INT_EVENT_TRACKER_CAPTURE(h, type, code) esp_tls_internal_event_tracker_capture(h, type, code) /** - * Error tracker logging macro, this implementation saves latest errors of - * ERR_TYPE_ESP, ERR_TYPE_ESP_TLS and ERR_TYPE_ESP_TLS_CERT_FLAGS types + * @brief Internal tracker capture error + * + * This implementation saves latest errors of available types + * + * @param[in] h esp-tls error handle + * @param[in] err_type Specific error type + * @param[int] code Error code to capture + * */ -#define ESP_INT_EVENT_TRACKER_CAPTURE(h, type, code) esp_int_event_tracker_capture(h, type, code) - -static inline void esp_int_event_tracker_capture(esp_tls_error_handle_t h, uint32_t type, int code) -{ - if (h) { - if (type == ERR_TYPE_ESP) { - h->last_error = code; - } else if (type == ERR_TYPE_MBEDTLS) { - h->esp_tls_error_code = code; - } else if (type == ERR_TYPE_MBEDTLS_CERT_FLAGS) { - h->esp_tls_flags = code; - } else if (type == ERR_TYPE_WOLFSSL) { - h->esp_tls_error_code = code; - } else if (type == ERR_TYPE_WOLFSSL_CERT_FLAGS) { - h->esp_tls_flags = code; - } - } -} +void esp_tls_internal_event_tracker_capture(esp_tls_error_handle_t h, uint32_t type, int code); +/** + * @brief Create internal tracker storage + * + * @return Error tracker handle if success or NULL if allocation error + */ +esp_tls_error_handle_t esp_tls_internal_event_tracker_create(void); +/** + * @brief Destroy internal tracker storage + * + * @param[in] h esp-tls error handle + */ + void esp_tls_internal_event_tracker_destroy(esp_tls_error_handle_t h); #ifdef __cplusplus } diff --git a/components/tcp_transport/include/esp_transport.h b/components/tcp_transport/include/esp_transport.h index b13063691d..3b65b998e9 100644 --- a/components/tcp_transport/include/esp_transport.h +++ b/components/tcp_transport/include/esp_transport.h @@ -313,7 +313,22 @@ esp_err_t esp_transport_set_parent_transport_func(esp_transport_handle_t t, payl */ esp_tls_error_handle_t esp_transport_get_error_handle(esp_transport_handle_t t); - +/** + * @brief Get and clear last captured socket errno + * + * Socket errno is internally stored whenever any of public facing API + * for reading, writing, polling or connection fails returning negative return code. + * The error code corresponds to the `SO_ERROR` value retrieved from the underlying + * transport socket using `getsockopt()` API. After reading the captured errno, + * the internal value is cleared to 0. + * + * @param[in] t The transport handle + * + * @return + * - >=0 Last captured socket errno + * - -1 Invalid transport handle or invalid transport's internal error storage + */ +int esp_transport_get_errno(esp_transport_handle_t t); #ifdef __cplusplus } diff --git a/components/tcp_transport/private_include/esp_transport_internal.h b/components/tcp_transport/private_include/esp_transport_internal.h index c17fad8427..a2357c2c79 100644 --- a/components/tcp_transport/private_include/esp_transport_internal.h +++ b/components/tcp_transport/private_include/esp_transport_internal.h @@ -36,8 +36,9 @@ struct esp_transport_item_t { trans_func _destroy; /*!< Destroy and free transport */ connect_async_func _connect_async; /*!< non-blocking connect function of this transport */ payload_transfer_func _parent_transfer; /*!< Function returning underlying transport layer */ - get_socket_func _get_socket; - esp_tls_error_handle_t error_handle; /*!< Pointer to esp-tls error handle */ + get_socket_func _get_socket; /*!< Function returning the transport's socket */ + struct esp_transport_error_s* error_handle; /*!< Error handle (based on esp-tls error handle) + * extended with transport's specific errors */ STAILQ_ENTRY(esp_transport_item_t) next; }; @@ -52,5 +53,13 @@ struct esp_transport_item_t { */ int esp_transport_get_socket(esp_transport_handle_t t); +/** + * @brief Captures the current errno + * + * @param[in] t The transport handle + * @param[in] sock_errno Socket errno to store in internal transport structures + * + */ +void esp_transport_capture_errno(esp_transport_handle_t t, int sock_errno); #endif //_ESP_TRANSPORT_INTERNAL_H_ diff --git a/components/tcp_transport/transport.c b/components/tcp_transport/transport.c index 7ebc1fba25..f9b2b38a2c 100644 --- a/components/tcp_transport/transport.c +++ b/components/tcp_transport/transport.c @@ -26,7 +26,16 @@ static const char *TAG = "TRANSPORT"; - +/** + * Transport layer error structure including + * * esp-tls last error storage + * * sock-errno + */ +struct esp_transport_error_s { + struct esp_tls_last_error esp_tls_err_h_base; /*!< esp-tls last error container */ + // additional fields + int sock_errno; /*!< last socket error captured for this transport */ +}; /** * This list will hold all transport available @@ -38,7 +47,7 @@ STAILQ_HEAD(esp_transport_list_t, esp_transport_item_t); */ typedef struct esp_transport_internal { struct esp_transport_list_t list; /*!< List of transports */ - esp_tls_error_handle_t error_handle; /*!< Pointer to the error tracker if enabled */ + struct esp_transport_error_s* error_handle; /*!< Pointer to the transport error container */ } esp_transport_internal_t; static esp_transport_handle_t esp_transport_get_default_parent(esp_transport_handle_t t) @@ -54,7 +63,7 @@ esp_transport_list_handle_t esp_transport_list_init(void) esp_transport_list_handle_t transport = calloc(1, sizeof(esp_transport_internal_t)); ESP_TRANSPORT_MEM_CHECK(TAG, transport, return NULL); STAILQ_INIT(&transport->list); - transport->error_handle = calloc(1, sizeof(esp_tls_last_error_t)); + transport->error_handle = calloc(1, sizeof(struct esp_transport_error_s)); return transport; } @@ -274,15 +283,36 @@ esp_err_t esp_transport_set_parent_transport_func(esp_transport_handle_t t, payl esp_tls_error_handle_t esp_transport_get_error_handle(esp_transport_handle_t t) { if (t) { - return t->error_handle; + return &t->error_handle->esp_tls_err_h_base; } return NULL; } +int esp_transport_get_errno(esp_transport_handle_t t) +{ + if (t && t->error_handle) { + int actual_errno = t->error_handle->sock_errno; + t->error_handle->sock_errno = 0; + return actual_errno; + } + return -1; +} + void esp_transport_set_errors(esp_transport_handle_t t, const esp_tls_error_handle_t error_handle) { - if (t) { - memcpy(t->error_handle, error_handle, sizeof(esp_tls_last_error_t)); + if (t && t->error_handle) { + memcpy(&t->error_handle->esp_tls_err_h_base, error_handle, sizeof(esp_tls_last_error_t)); + int sock_error; + if (esp_tls_get_and_clear_error_type(error_handle, ESP_TLS_ERR_TYPE_SYSTEM, &sock_error) == ESP_OK) { + t->error_handle->sock_errno = sock_error; + } + } +} + +void esp_transport_capture_errno(esp_transport_handle_t t, int sock_errno) +{ + if (t && t->error_handle) { + t->error_handle->sock_errno = sock_errno; } } diff --git a/components/tcp_transport/transport_ssl.c b/components/tcp_transport/transport_ssl.c index 633e931dcf..609f1e0389 100644 --- a/components/tcp_transport/transport_ssl.c +++ b/components/tcp_transport/transport_ssl.c @@ -105,6 +105,7 @@ static int ssl_poll_read(esp_transport_handle_t t, int timeout_ms) int sock_errno = 0; uint32_t optlen = sizeof(sock_errno); getsockopt(ssl->tls->sockfd, SOL_SOCKET, SO_ERROR, &sock_errno, &optlen); + esp_transport_capture_errno(t, sock_errno); ESP_LOGE(TAG, "ssl_poll_read select error %d, errno = %s, fd = %d", sock_errno, strerror(sock_errno), ssl->tls->sockfd); ret = -1; } @@ -127,6 +128,7 @@ static int ssl_poll_write(esp_transport_handle_t t, int timeout_ms) int sock_errno = 0; uint32_t optlen = sizeof(sock_errno); getsockopt(ssl->tls->sockfd, SOL_SOCKET, SO_ERROR, &sock_errno, &optlen); + esp_transport_capture_errno(t, sock_errno); ESP_LOGE(TAG, "ssl_poll_write select error %d, errno = %s, fd = %d", sock_errno, strerror(sock_errno), ssl->tls->sockfd); ret = -1; } diff --git a/components/tcp_transport/transport_tcp.c b/components/tcp_transport/transport_tcp.c index a7e32e6885..57d0156b27 100644 --- a/components/tcp_transport/transport_tcp.c +++ b/components/tcp_transport/transport_tcp.c @@ -107,10 +107,12 @@ static int tcp_connect(esp_transport_handle_t t, const char *host, int port, int int res = select(tcp->sock+1, NULL, &fdset, NULL, &tv); if (res < 0) { ESP_LOGE(TAG, "[sock=%d] select() error: %s", tcp->sock, strerror(errno)); + esp_transport_capture_errno(t, errno); goto error; } else if (res == 0) { ESP_LOGE(TAG, "[sock=%d] select() timeout", tcp->sock); + esp_transport_capture_errno(t, EINPROGRESS); // errno=EINPROGRESS indicates connection timeout goto error; } else { int sockerr; @@ -121,6 +123,7 @@ static int tcp_connect(esp_transport_handle_t t, const char *host, int port, int goto error; } else if (sockerr) { + esp_transport_capture_errno(t, sockerr); ESP_LOGE(TAG, "[sock=%d] delayed connect error: %s", tcp->sock, strerror(sockerr)); goto error; } @@ -187,6 +190,7 @@ static int tcp_poll_read(esp_transport_handle_t t, int timeout_ms) int sock_errno = 0; uint32_t optlen = sizeof(sock_errno); getsockopt(tcp->sock, SOL_SOCKET, SO_ERROR, &sock_errno, &optlen); + esp_transport_capture_errno(t, sock_errno); ESP_LOGE(TAG, "tcp_poll_read select error %d, errno = %s, fd = %d", sock_errno, strerror(sock_errno), tcp->sock); ret = -1; } @@ -210,6 +214,7 @@ static int tcp_poll_write(esp_transport_handle_t t, int timeout_ms) int sock_errno = 0; uint32_t optlen = sizeof(sock_errno); getsockopt(tcp->sock, SOL_SOCKET, SO_ERROR, &sock_errno, &optlen); + esp_transport_capture_errno(t, sock_errno); ESP_LOGE(TAG, "tcp_poll_write select error %d, errno = %s, fd = %d", sock_errno, strerror(sock_errno), tcp->sock); ret = -1; }