From 587739391ca119fb6f3f6c3c31bad4296cc8911b Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 16 Apr 2019 11:58:38 +0200 Subject: [PATCH] esp-tls: extending error handle to contain error descriptors with last mbedtls failure and latest certificate verification result flags, reworked tcp_transport to use this error handle --- components/esp-tls/esp_tls.c | 57 +++++++++---- components/esp-tls/esp_tls.h | 81 ++++++++++++++----- .../esp_tls_error_capture_internal.h | 33 +++++--- .../esp_http_client/lib/include/http_utils.h | 8 +- components/mqtt/esp-mqtt | 2 +- components/tcp_transport/CMakeLists.txt | 5 +- components/tcp_transport/component.mk | 6 +- .../tcp_transport/include/esp_transport.h | 20 +++-- .../esp_transport_ssl_internal.h | 30 +++++++ .../esp_transport_utils.h | 14 ++-- components/tcp_transport/transport.c | 29 +++---- components/tcp_transport/transport_ssl.c | 9 ++- examples/protocols/mqtt/ssl/main/app_main.c | 6 +- 13 files changed, 210 insertions(+), 90 deletions(-) create mode 100644 components/tcp_transport/private_include/esp_transport_ssl_internal.h rename components/tcp_transport/{include => private_include}/esp_transport_utils.h (88%) diff --git a/components/esp-tls/esp_tls.c b/components/esp-tls/esp_tls.c index 7adc02dc20..65cd789f39 100644 --- a/components/esp-tls/esp_tls.c +++ b/components/esp-tls/esp_tls.c @@ -81,7 +81,7 @@ static ssize_t tls_read(esp_tls_t *tls, char *data, size_t datalen) return 0; } if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); ESP_LOGE(TAG, "read error :%d:", ret); } } @@ -626,7 +626,7 @@ static int esp_tls_low_level_conn(const char *hostname, int hostlen, int port, c } else { if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_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_MBEDTLS, -ret); ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED); if (cfg->cacert_pem_buf != NULL || cfg->use_global_ca_store == true) { /* This is to check whether handshake failed due to invalid certificate*/ @@ -653,10 +653,31 @@ static int esp_tls_low_level_conn(const char *hostname, int hostlen, int port, c /** * @brief Create a new TLS/SSL connection */ -int esp_tls_conn_new(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg, esp_tls_t *tls) +esp_tls_t *esp_tls_conn_new(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg) { + esp_tls_t *tls = (esp_tls_t *)calloc(1, sizeof(esp_tls_t)); + if (!tls) { + return NULL; + } /* esp_tls_conn_new() API establishes connection in a blocking manner thus this loop ensures that esp_tls_conn_new() API returns only after connection is established unless there is an error*/ + while (1) { + int ret = esp_tls_low_level_conn(hostname, hostlen, port, cfg, tls); + if (ret == 1) { + return tls; + } else if (ret == -1) { + esp_tls_conn_delete(tls); + ESP_LOGE(TAG, "Failed to open new connection"); + return NULL; + } + } + return NULL; +} + +int esp_tls_conn_new_sync(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg, esp_tls_t *tls) +{ + /* esp_tls_conn_new_sync() is a sync alternative to esp_tls_conn_new_async() with symetric function prototype + it is an alternative to esp_tls_conn_new() which is left for compatibility reasons */ while (1) { int ret = esp_tls_low_level_conn(hostname, hostlen, port, cfg, tls); if (ret == 1) { @@ -666,7 +687,7 @@ int esp_tls_conn_new(const char *hostname, int hostlen, int port, const esp_tls_ return -1; } } - return NULL; + return 0; } /* @@ -703,7 +724,7 @@ esp_tls_t *esp_tls_conn_http_new(const char *url, const esp_tls_cfg_t *cfg) esp_tls_t *tls = esp_tls_init(); if (!tls) return NULL; /* Connect to host */ - if (esp_tls_conn_new(&url[u.field_data[UF_HOST].off], u.field_data[UF_HOST].len, + if (esp_tls_conn_new_sync(&url[u.field_data[UF_HOST].off], u.field_data[UF_HOST].len, get_port(url, &u), cfg, tls) == 1) { return tls; } @@ -782,19 +803,27 @@ esp_tls_t *esp_tls_init() if (!tls) { return NULL; } - tls->error_handle = calloc(1, sizeof(esp_err_t)); + tls->error_handle = calloc(1, sizeof(esp_tls_last_error_t)); + if (!tls->error_handle) { + free(tls); + return NULL; + } tls->server_fd.fd = tls->sockfd = -1; return tls; } -esp_err_t esp_tls_get_and_clear_last_error(esp_tls_t* tls) +esp_err_t esp_tls_get_and_clear_last_error(esp_tls_error_handle_t h, int *mbedtls_code, int *mbedtls_flags) { - if (tls && tls->error_handle) { - esp_err_t last_err = tls->error_handle->last_error; - if (last_err != ESP_OK) { - tls->error_handle->last_error = ESP_OK; - return last_err; - } + if (!h) { + return ESP_ERR_INVALID_STATE; } - return ESP_OK; + esp_err_t last_err = h->last_error; + if (mbedtls_code) { + *mbedtls_code = h->mbedtls_error_code; + } + if (mbedtls_flags) { + *mbedtls_flags = h->mbedtls_flags; + } + memset(h, 0, sizeof(esp_tls_last_error_t)); + return last_err; } diff --git a/components/esp-tls/esp_tls.h b/components/esp-tls/esp_tls.h index 3e0f50bb6d..1c2f785ea5 100644 --- a/components/esp-tls/esp_tls.h +++ b/components/esp-tls/esp_tls.h @@ -35,21 +35,30 @@ extern "C" { #define ESP_ERR_ESP_TLS_CANNOT_RESOLVE_HOSTNAME (ESP_ERR_ESP_TLS_BASE + 0x01) /*!< Error if hostname couldn't be resolved upon tls connection */ #define ESP_ERR_ESP_TLS_CANNOT_CREATE_SOCKET (ESP_ERR_ESP_TLS_BASE + 0x02) /*!< Failed to create socket */ #define ESP_ERR_ESP_TLS_UNSUPPORTED_PROTOCOL_FAMILY (ESP_ERR_ESP_TLS_BASE + 0x03) /*!< Unsupported protocol family */ -#define ESP_ERR_ESP_TLS_FAILED_CONNECT_TO_HOST (ESP_ERR_ESP_TLS_BASE + 0x04) /*!< Failed to connnect to host */ +#define ESP_ERR_ESP_TLS_FAILED_CONNECT_TO_HOST (ESP_ERR_ESP_TLS_BASE + 0x04) /*!< Failed to connect to host */ #define ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED (ESP_ERR_ESP_TLS_BASE + 0x05) /*!< failed to set socket option */ -#define ESP_ERR_MBEDTLS_CERT_PARTLY_OK (ESP_ERR_ESP_TLS_BASE + 0x06) /*!< embedtls parse certificates was partly successful */ -#define ESP_ERR_MBEDTLS_CTR_DRBG_SEED_FAILED (ESP_ERR_ESP_TLS_BASE + 0x07) /*!< embedtls api returned failed */ -#define ESP_ERR_MBEDTLS_SSL_SET_HOSTNAME_FAILED (ESP_ERR_ESP_TLS_BASE + 0x08) /*!< embedtls api returned failed */ -#define ESP_ERR_MBEDTLS_SSL_CONFIG_DEFAULTS_FAILED (ESP_ERR_ESP_TLS_BASE + 0x09) /*!< embedtls api returned failed */ -#define ESP_ERR_MBEDTLS_SSL_CONF_ALPN_PROTOCOLS_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0A) /*!< embedtls api returned failed */ -#define ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0B) /*!< embedtls api returned failed */ -#define ESP_ERR_MBEDTLS_SSL_CONF_OWN_CERT_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0C) /*!< embedtls api returned failed */ -#define ESP_ERR_MBEDTLS_SSL_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0D) /*!< embedtls api returned failed */ -#define ESP_ERR_MBEDTLS_SSL_WRITE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0E) /*!< embedtls api returned failed */ -#define ESP_ERR_MBEDTLS_PK_PARSE_KEY_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0F) /*!< embedtls api returned failed */ -#define ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x10) /*!< embedtls api returned failed */ +#define ESP_ERR_MBEDTLS_CERT_PARTLY_OK (ESP_ERR_ESP_TLS_BASE + 0x06) /*!< mbedtls parse certificates was partly successful */ +#define ESP_ERR_MBEDTLS_CTR_DRBG_SEED_FAILED (ESP_ERR_ESP_TLS_BASE + 0x07) /*!< mbedtls api returned error */ +#define ESP_ERR_MBEDTLS_SSL_SET_HOSTNAME_FAILED (ESP_ERR_ESP_TLS_BASE + 0x08) /*!< mbedtls api returned error */ +#define ESP_ERR_MBEDTLS_SSL_CONFIG_DEFAULTS_FAILED (ESP_ERR_ESP_TLS_BASE + 0x09) /*!< mbedtls api returned error */ +#define ESP_ERR_MBEDTLS_SSL_CONF_ALPN_PROTOCOLS_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0A) /*!< mbedtls api returned error */ +#define ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0B) /*!< mbedtls api returned error */ +#define ESP_ERR_MBEDTLS_SSL_CONF_OWN_CERT_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0C) /*!< mbedtls api returned error */ +#define ESP_ERR_MBEDTLS_SSL_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0D) /*!< mbedtls api returned error */ +#define ESP_ERR_MBEDTLS_SSL_WRITE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0E) /*!< mbedtls api returned error */ +#define ESP_ERR_MBEDTLS_PK_PARSE_KEY_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0F) /*!< mbedtls api returned failed */ +#define ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x10) /*!< mbedtls api returned failed */ -typedef struct esp_error_private* esp_error_handle_t; +typedef struct esp_tls_last_error* esp_tls_error_handle_t; + +/** +* @brief Error structure containing relevant errors in case tls error occurred +*/ +typedef struct esp_tls_last_error { + esp_err_t last_error; /*!< error code (based on ESP_ERR_ESP_TLS_BASE) of the last occurred error */ + int mbedtls_error_code; /*!< mbedtls error code from last mbedtls failed api */ + int mbedtls_flags; /*!< last certification verification flags */ +} esp_tls_last_error_t; /** * @brief ESP-TLS Connection State @@ -207,7 +216,7 @@ typedef struct esp_tls { - ESP_TLS_CLIENT - ESP_TLS_SERVER */ - esp_error_handle_t error_handle; /*!< handle to internal error descriptor */ + esp_tls_error_handle_t error_handle; /*!< handle to error descriptor */ } esp_tls_t; @@ -222,15 +231,39 @@ typedef struct esp_tls { */ esp_tls_t *esp_tls_init(); + + + /** * @brief Create a new blocking TLS/SSL connection * * This function establishes a TLS/SSL connection with the specified host in blocking manner. - * + * + * Note: This API is present for backward compatibility reasons. Alternative function + * with the same functionality is `esp_tls_conn_new_sync` (and its asynchronous version + * `esp_tls_conn_new_async`) + * * @param[in] hostname Hostname of the host. * @param[in] hostlen Length of hostname. * @param[in] port Port number of the host. - * @param[in] cfg TLS configuration as esp_tls_cfg_t. If you wish to open + * @param[in] cfg TLS configuration as esp_tls_cfg_t. If you wish to open + * non-TLS connection, keep this NULL. For TLS connection, + * a pass pointer to esp_tls_cfg_t. At a minimum, this + * structure should be zero-initialized. + * + * @return pointer to esp_tls_t, or NULL if connection couldn't be opened. + */ +esp_tls_t *esp_tls_conn_new(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg) __attribute__ ((deprecated)); + +/** + * @brief Create a new blocking TLS/SSL connection + * + * This function establishes a TLS/SSL connection with the specified host in blocking manner. + * + * @param[in] hostname Hostname of the host. + * @param[in] hostlen Length of hostname. + * @param[in] port Port number of the host. + * @param[in] cfg TLS configuration as esp_tls_cfg_t. If you wish to open * non-TLS connection, keep this NULL. For TLS connection, * a pass pointer to esp_tls_cfg_t. At a minimum, this * structure should be zero-initialized. @@ -241,7 +274,7 @@ esp_tls_t *esp_tls_init(); * - 1 If connection establishment is successful. * - 0 Reserved for connection state is in progress. */ -int esp_tls_conn_new(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg, esp_tls_t *tls); +int esp_tls_conn_new_sync(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg, esp_tls_t *tls); /** * @brief Create a new blocking TLS/SSL connection with a given "HTTP" url @@ -413,15 +446,21 @@ mbedtls_x509_crt *esp_tls_get_global_ca_store(); void esp_tls_free_global_ca_store(); /** - * @brief Returns last error in esp_tls (if any) and clears it. + * @brief Returns last error in esp_tls with detailed mbedtls related error codes. + * The error information is cleared internally upon return * - * @param[in] tls pointer to esp-tls as esp-tls handle. + * @param[in] h esp-tls error handle. + * @param[out] mbedtls_code last error code returned from mbedtls api (set to zero if none) + * This pointer could be NULL if caller does not care about mbedtls_code + * @param[out] mbedtls_flags last certification verification flags (set to zero if none) + * This pointer could be NULL if caller does not care about mbedtls_flags * * @return - * - ESP_OK if no error occurred + * - ESP_ERR_INVALID_STATE if invalid parameters + * - ESP_OK (0) if no error occurred * - specific error code (based on ESP_ERR_ESP_TLS_BASE) otherwise */ -esp_err_t esp_tls_get_and_clear_last_error(esp_tls_t* tls); +esp_err_t esp_tls_get_and_clear_last_error(esp_tls_error_handle_t h, int *mbedtls_code, int *mbedtls_flags); #ifdef CONFIG_ESP_TLS_SERVER /** 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 aabd5587b3..89ee4435cf 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 @@ -19,6 +19,9 @@ * This version is internal to esp-tls component and only saves single esp_err of last occurred error */ +#ifdef __cplusplus +extern "C" { +#endif /** * Definition of different types/sources of error codes reported @@ -33,16 +36,26 @@ typedef enum { } err_type_t; /** -* Internal structure for error description -* - contains only the last error of esp_err_t in this implementation -*/ -typedef struct esp_error_private { - esp_err_t last_error; -} esp_error_private_t; - -/** - * Error tracker logging macro, this implementation only saves the ERR_TYPE_ESP error, other types are ignored + * Error tracker logging macro, this implementation saves latest errors of + * ERR_TYPE_ESP, ERR_TYPE_MBEDTLS and ERR_TYPE_MBEDTLS_CERT_FLAGS types */ -#define ESP_INT_EVENT_TRACKER_CAPTURE(h, type, code) do { if (h && type==ERR_TYPE_ESP) { h->last_error = code; } } while (0) +#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->mbedtls_error_code = code; + } else if (type == ERR_TYPE_MBEDTLS_CERT_FLAGS) { + h->mbedtls_flags = code; + } + } +} + +#ifdef __cplusplus +} +#endif #endif //__ESP_TLS_ERROR_CAPTURE_INTERNAL_H__ diff --git a/components/esp_http_client/lib/include/http_utils.h b/components/esp_http_client/lib/include/http_utils.h index d57840228f..14c3b10c4e 100644 --- a/components/esp_http_client/lib/include/http_utils.h +++ b/components/esp_http_client/lib/include/http_utils.h @@ -16,7 +16,7 @@ #ifndef _HTTP_UTILS_H_ #define _HTTP_UTILS_H_ #include -#include "esp_transport_utils.h" + /** * @brief Assign new_str to *str pointer, and realloc *str if it not NULL * @@ -80,7 +80,9 @@ char *http_utils_join_string(const char *first_str, int len_first, const char *s int http_utils_str_starts_with(const char *str, const char *start); -#define HTTP_MEM_CHECK(TAG, a, action) ESP_TRANSPORT_MEM_CHECK(TAG, a, action) - +#define HTTP_MEM_CHECK(TAG, a, action) if (!(a)) { \ + ESP_LOGE(TAG,"%s:%d (%s): %s", __FILE__, __LINE__, __FUNCTION__, "Memory exhausted"); \ + action; \ + } #endif diff --git a/components/mqtt/esp-mqtt b/components/mqtt/esp-mqtt index 65bf2255d7..0cc4077bd3 160000 --- a/components/mqtt/esp-mqtt +++ b/components/mqtt/esp-mqtt @@ -1 +1 @@ -Subproject commit 65bf2255d74c79e3c6abe3e3f791ba8d42efdee3 +Subproject commit 0cc4077bd3e10bb93456ff2785309ec9237a5906 diff --git a/components/tcp_transport/CMakeLists.txt b/components/tcp_transport/CMakeLists.txt index f1821db60f..9d5028a1b6 100644 --- a/components/tcp_transport/CMakeLists.txt +++ b/components/tcp_transport/CMakeLists.txt @@ -4,5 +4,6 @@ idf_component_register(SRCS "transport.c" "transport_ws.c" "transport_utils.c" "transport_strcasestr.c" - INCLUDE_DIRS include - REQUIRES lwip esp-tls) \ No newline at end of file + INCLUDE_DIRS "include" + PRIVATE_INCLUDE_DIRS "private_include" + REQUIRES lwip esp-tls) diff --git a/components/tcp_transport/component.mk b/components/tcp_transport/component.mk index 308f64f0ea..c81b547721 100644 --- a/components/tcp_transport/component.mk +++ b/components/tcp_transport/component.mk @@ -1,4 +1,2 @@ -# -# Component Makefile -# -# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) +COMPONENT_ADD_INCLUDEDIRS := include +COMPONENT_PRIV_INCLUDEDIRS := private_include \ No newline at end of file diff --git a/components/tcp_transport/include/esp_transport.h b/components/tcp_transport/include/esp_transport.h index bd4d33f67c..9dd7ff4495 100644 --- a/components/tcp_transport/include/esp_transport.h +++ b/components/tcp_transport/include/esp_transport.h @@ -33,6 +33,8 @@ typedef int (*poll_func)(esp_transport_handle_t t, int timeout_ms); typedef int (*connect_async_func)(esp_transport_handle_t t, const char *host, int port, int timeout_ms); typedef esp_transport_handle_t (*payload_transfer_func)(esp_transport_handle_t); +typedef struct esp_tls_last_error* esp_tls_error_handle_t; + /** * @brief Create transport list * @@ -299,23 +301,19 @@ esp_err_t esp_transport_set_async_connect_func(esp_transport_handle_t t, connect esp_err_t esp_transport_set_parent_transport_func(esp_transport_handle_t t, payload_transfer_func _parent_transport); /** - * @brief Returns last error in esp_tls (if any) and clears it. + * @brief Returns esp_tls error handle. + * Warning: The returned pointer is valid only as long as esp_transport_handle_t exists. Once transport + * handle gets destroyed, this value (esp_tls_error_handle_t) is freed automatically. * * @param[in] A transport handle * * @return - * - ESP_OK if no error occurred - * - specific error code (based on ESP_ERR_ESP_TLS_BASE) otherwise + * - valid pointer of esp_error_handle_t + * - NULL if invalid transport handle */ -esp_err_t get_and_clear_last_error(esp_transport_handle_t t); +esp_tls_error_handle_t esp_transport_get_error_handle(esp_transport_handle_t t); + -/** - * @brief Sets error to common transport handle - * - * @param[in] A transport handle - * - */ -void esp_transport_set_error(esp_transport_handle_t t, esp_err_t err); #ifdef __cplusplus } diff --git a/components/tcp_transport/private_include/esp_transport_ssl_internal.h b/components/tcp_transport/private_include/esp_transport_ssl_internal.h new file mode 100644 index 0000000000..8b794e05b9 --- /dev/null +++ b/components/tcp_transport/private_include/esp_transport_ssl_internal.h @@ -0,0 +1,30 @@ +// Copyright 2015-2019 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. + +#ifndef _ESP_TRANSPORT_INTERNAL_H_ +#define _ESP_TRANSPORT_INTERNAL_H_ + +/** + * @brief Sets error to common transport handle + * + * Note: This function copies the supplied error handle object to tcp_transport's internal + * error handle object + * + * @param[in] A transport handle + * + */ +void esp_transport_set_errors(esp_transport_handle_t t, const esp_tls_error_handle_t error_handle); + + +#endif /* _ESP_TRANSPORT_INTERNAL_H_ */ diff --git a/components/tcp_transport/include/esp_transport_utils.h b/components/tcp_transport/private_include/esp_transport_utils.h similarity index 88% rename from components/tcp_transport/include/esp_transport_utils.h rename to components/tcp_transport/private_include/esp_transport_utils.h index 405b4f6b46..6a9d1d02c7 100644 --- a/components/tcp_transport/include/esp_transport_utils.h +++ b/components/tcp_transport/private_include/esp_transport_utils.h @@ -20,6 +20,15 @@ extern "C" { #endif +/** + * @brief Utility macro to be used for NULL ptr check after malloc + * + */ +#define ESP_TRANSPORT_MEM_CHECK(TAG, a, action) if (!(a)) { \ + ESP_LOGE(TAG,"%s:%d (%s): %s", __FILE__, __LINE__, __FUNCTION__, "Memory exhausted"); \ + action; \ + } + /** * @brief Convert milliseconds to timeval struct * @@ -29,11 +38,6 @@ extern "C" { void esp_transport_utils_ms_to_timeval(int timeout_ms, struct timeval *tv); -#define ESP_TRANSPORT_MEM_CHECK(TAG, a, action) if (!(a)) { \ - ESP_LOGE(TAG,"%s:%d (%s): %s", __FILE__, __LINE__, __FUNCTION__, "Memory exhausted"); \ - action; \ - } - #ifdef __cplusplus } #endif diff --git a/components/tcp_transport/transport.c b/components/tcp_transport/transport.c index 3db2a69b6c..ddceba93c9 100644 --- a/components/tcp_transport/transport.c +++ b/components/tcp_transport/transport.c @@ -15,6 +15,7 @@ #include #include +#include #include "sys/queue.h" #include "esp_log.h" @@ -42,7 +43,7 @@ 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 */ - esp_err_t* error_handle; /*!< Pointer to the last error */ + esp_tls_error_handle_t error_handle; /*!< Pointer to esp-tls error handle */ STAILQ_ENTRY(esp_transport_item_t) next; }; @@ -58,7 +59,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_err_t* error_handle; /*!< Pointer to the error tracker if enabled */ + esp_tls_error_handle_t error_handle; /*!< Pointer to the error tracker if enabled */ } esp_transport_internal_t; static esp_transport_handle_t esp_transport_get_default_parent(esp_transport_handle_t t) @@ -74,7 +75,7 @@ esp_transport_list_handle_t esp_transport_list_init() 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_err_t)); + transport->error_handle = calloc(1, sizeof(esp_tls_last_error_t)); return transport; } @@ -88,7 +89,7 @@ esp_err_t esp_transport_list_add(esp_transport_list_handle_t h, esp_transport_ha strcpy(t->scheme, scheme); STAILQ_INSERT_TAIL(&h->list, t, next); // Each transport in a list to share the same error tracker - t->error_handle = h->error_handle; + t->error_handle = h->error_handle; return ESP_OK; } @@ -291,17 +292,17 @@ esp_err_t esp_transport_set_parent_transport_func(esp_transport_handle_t t, payl return ESP_OK; } -esp_err_t get_and_clear_last_error(esp_transport_handle_t t) +esp_tls_error_handle_t esp_transport_get_error_handle(esp_transport_handle_t t) { - esp_err_t err = *(t->error_handle); - *(t->error_handle) = 0; - return err; -} - -void esp_transport_set_error(esp_transport_handle_t t, esp_err_t err) -{ - if (t) { - *t->error_handle = err; + if (t) { + return t->error_handle; } return NULL; +} + +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)); + } } \ No newline at end of file diff --git a/components/tcp_transport/transport_ssl.c b/components/tcp_transport/transport_ssl.c index 67b21999de..1651a2f87f 100644 --- a/components/tcp_transport/transport_ssl.c +++ b/components/tcp_transport/transport_ssl.c @@ -24,6 +24,7 @@ #include "esp_transport.h" #include "esp_transport_ssl.h" #include "esp_transport_utils.h" +#include "esp_transport_ssl_internal.h" static const char *TAG = "TRANS_SSL"; @@ -70,9 +71,9 @@ static int ssl_connect(esp_transport_handle_t t, const char *host, int port, int ssl->cfg.timeout_ms = timeout_ms; ssl->ssl_initialized = true; ssl->tls = esp_tls_init(); - if (esp_tls_conn_new(host, strlen(host), port, &ssl->cfg, ssl->tls) < 0) { + if (esp_tls_conn_new_sync(host, strlen(host), port, &ssl->cfg, ssl->tls) < 0) { ESP_LOGE(TAG, "Failed to open a new connection"); - esp_transport_set_error(t, esp_tls_get_and_clear_last_error(ssl->tls)); + esp_transport_set_errors(t, ssl->tls->error_handle); esp_tls_conn_delete(ssl->tls); ssl->tls = NULL; return -1; @@ -115,7 +116,7 @@ static int ssl_write(esp_transport_handle_t t, const char *buffer, int len, int ret = esp_tls_conn_write(ssl->tls, (const unsigned char *) buffer, len); if (ret < 0) { ESP_LOGE(TAG, "esp_tls_conn_write error, errno=%s", strerror(errno)); - esp_transport_set_error(t, esp_tls_get_and_clear_last_error(ssl->tls)); + esp_transport_set_errors(t, ssl->tls->error_handle); } return ret; } @@ -133,7 +134,7 @@ static int ssl_read(esp_transport_handle_t t, char *buffer, int len, int timeout ret = esp_tls_conn_read(ssl->tls, (unsigned char *)buffer, len); if (ret < 0) { ESP_LOGE(TAG, "esp_tls_conn_read error, errno=%s", strerror(errno)); - esp_transport_set_error(t, esp_tls_get_and_clear_last_error(ssl->tls)); + esp_transport_set_errors(t, ssl->tls->error_handle); } if (ret == 0) { ret = -1; diff --git a/examples/protocols/mqtt/ssl/main/app_main.c b/examples/protocols/mqtt/ssl/main/app_main.c index fa50e16949..e819c8fdc8 100644 --- a/examples/protocols/mqtt/ssl/main/app_main.c +++ b/examples/protocols/mqtt/ssl/main/app_main.c @@ -29,6 +29,7 @@ #include "esp_log.h" #include "mqtt_client.h" +#include "esp_tls.h" static const char *TAG = "MQTTS_EXAMPLE"; @@ -79,7 +80,10 @@ static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event) break; case MQTT_EVENT_ERROR: ESP_LOGI(TAG, "MQTT_EVENT_ERROR"); - ESP_LOGI(TAG, "Error code: 0x%x", event->last_err); + int mbedtls_err = 0; + esp_err_t err = esp_tls_get_and_clear_last_error(event->error_handle, &mbedtls_err, NULL); + ESP_LOGI(TAG, "Last esp error code: 0x%x", err); + ESP_LOGI(TAG, "Last mbedtls failure: 0x%x", mbedtls_err); break; default: ESP_LOGI(TAG, "Other event id:%d", event->event_id);