From 391d7bf271529e72d8bace030a863e187777d46d Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 22 Jan 2021 21:00:22 +0100 Subject: [PATCH] tcp_transport: Add TCP transport connection errors Transport's error_handle is used to capture different types of errors including esp_err_t from esp-tls and socket/system errors. This change adds the following error codes for TCP transport: * connection closed by a FIN flag (clean closure from server) * DNS resolution problem * connection timeout These errors are already defined in esp-tls component and since this component will be used in the future for both TCP and SSL transport, we currently report these issues in transport::error_handle::esp_tls_last_error of standard esp error type (esp_err_t) Closes https://github.com/espressif/esp-mqtt/issues/182 --- components/esp-tls/esp_tls.h | 66 +------------ components/esp-tls/esp_tls_errors.h | 96 +++++++++++++++++++ .../private_include/esp_transport_internal.h | 23 +++++ components/tcp_transport/transport.c | 23 +++++ components/tcp_transport/transport_ssl.c | 4 + components/tcp_transport/transport_tcp.c | 15 ++- 6 files changed, 161 insertions(+), 66 deletions(-) create mode 100644 components/esp-tls/esp_tls_errors.h diff --git a/components/esp-tls/esp_tls.h b/components/esp-tls/esp_tls.h index a3ab33b3d4e7..b2fb0c1cdda0 100644 --- a/components/esp-tls/esp_tls.h +++ b/components/esp-tls/esp_tls.h @@ -18,6 +18,7 @@ #include #include #include "esp_err.h" +#include "esp_tls_errors.h" #ifdef CONFIG_ESP_TLS_USING_MBEDTLS #include "mbedtls/platform.h" #include "mbedtls/net_sockets.h" @@ -36,71 +37,6 @@ extern "C" { #endif -#define ESP_ERR_ESP_TLS_BASE 0x8000 /*!< Starting number of ESP-TLS error codes */ -#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 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) /*!< 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 */ -#define ESP_ERR_MBEDTLS_SSL_CONF_PSK_FAILED (ESP_ERR_ESP_TLS_BASE + 0x11) /*!< mbedtls api returned failed */ -#define ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT (ESP_ERR_ESP_TLS_BASE + 0x12) /*!< new connection in esp_tls_low_level_conn connection timeouted */ -#define ESP_ERR_WOLFSSL_SSL_SET_HOSTNAME_FAILED (ESP_ERR_ESP_TLS_BASE + 0x13) /*!< wolfSSL api returned error */ -#define ESP_ERR_WOLFSSL_SSL_CONF_ALPN_PROTOCOLS_FAILED (ESP_ERR_ESP_TLS_BASE + 0x14) /*!< wolfSSL api returned error */ -#define ESP_ERR_WOLFSSL_CERT_VERIFY_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x15) /*!< wolfSSL api returned error */ -#define ESP_ERR_WOLFSSL_KEY_VERIFY_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x16) /*!< wolfSSL api returned error */ -#define ESP_ERR_WOLFSSL_SSL_HANDSHAKE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x17) /*!< wolfSSL api returned failed */ -#define ESP_ERR_WOLFSSL_CTX_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x18) /*!< wolfSSL api returned failed */ -#define ESP_ERR_WOLFSSL_SSL_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x19) /*!< wolfSSL api returned failed */ -#define ESP_ERR_WOLFSSL_SSL_WRITE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x1A) /*!< wolfSSL api returned failed */ - -#define ESP_ERR_ESP_TLS_SE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x1B) /*< esp-tls use Secure Element returned failed */ -#ifdef CONFIG_ESP_TLS_USING_MBEDTLS -#define ESP_TLS_ERR_SSL_WANT_READ MBEDTLS_ERR_SSL_WANT_READ -#define ESP_TLS_ERR_SSL_WANT_WRITE MBEDTLS_ERR_SSL_WANT_WRITE -#define ESP_TLS_ERR_SSL_TIMEOUT MBEDTLS_ERR_SSL_TIMEOUT -#elif CONFIG_ESP_TLS_USING_WOLFSSL /* CONFIG_ESP_TLS_USING_MBEDTLS */ -#define ESP_TLS_ERR_SSL_WANT_READ WOLFSSL_ERROR_WANT_READ -#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; - -/** -* @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 esp_tls_error_code; /*!< esp_tls error code from last esp_tls failed api */ - int esp_tls_flags; /*!< last certification verification flags */ -} esp_tls_last_error_t; - /** * @brief ESP-TLS Connection State */ diff --git a/components/esp-tls/esp_tls_errors.h b/components/esp-tls/esp_tls_errors.h new file mode 100644 index 000000000000..3b39b562097f --- /dev/null +++ b/components/esp-tls/esp_tls_errors.h @@ -0,0 +1,96 @@ +// Copyright 2021 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_TLS_ERRORS_H_ +#define _ESP_TLS_ERRORS_H_ + +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ESP_ERR_ESP_TLS_BASE 0x8000 /*!< Starting number of ESP-TLS error codes */ +#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 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) /*!< 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 */ +#define ESP_ERR_MBEDTLS_SSL_CONF_PSK_FAILED (ESP_ERR_ESP_TLS_BASE + 0x11) /*!< mbedtls api returned failed */ +#define ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT (ESP_ERR_ESP_TLS_BASE + 0x12) /*!< new connection in esp_tls_low_level_conn connection timeouted */ +#define ESP_ERR_WOLFSSL_SSL_SET_HOSTNAME_FAILED (ESP_ERR_ESP_TLS_BASE + 0x13) /*!< wolfSSL api returned error */ +#define ESP_ERR_WOLFSSL_SSL_CONF_ALPN_PROTOCOLS_FAILED (ESP_ERR_ESP_TLS_BASE + 0x14) /*!< wolfSSL api returned error */ +#define ESP_ERR_WOLFSSL_CERT_VERIFY_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x15) /*!< wolfSSL api returned error */ +#define ESP_ERR_WOLFSSL_KEY_VERIFY_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x16) /*!< wolfSSL api returned error */ +#define ESP_ERR_WOLFSSL_SSL_HANDSHAKE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x17) /*!< wolfSSL api returned failed */ +#define ESP_ERR_WOLFSSL_CTX_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x18) /*!< wolfSSL api returned failed */ +#define ESP_ERR_WOLFSSL_SSL_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x19) /*!< wolfSSL api returned failed */ +#define ESP_ERR_WOLFSSL_SSL_WRITE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x1A) /*!< wolfSSL api returned failed */ + +#define ESP_ERR_ESP_TLS_SE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x1B) /*< esp-tls use Secure Element returned failed */ +#define ESP_ERR_ESP_TLS_TCP_CLOSED_FIN (ESP_ERR_ESP_TLS_BASE + 0x1C) /*< esp-tls's TPC transport connection has benn closed (in a clean way) */ + +#ifdef CONFIG_ESP_TLS_USING_MBEDTLS +#define ESP_TLS_ERR_SSL_WANT_READ MBEDTLS_ERR_SSL_WANT_READ +#define ESP_TLS_ERR_SSL_WANT_WRITE MBEDTLS_ERR_SSL_WANT_WRITE +#define ESP_TLS_ERR_SSL_TIMEOUT MBEDTLS_ERR_SSL_TIMEOUT +#elif CONFIG_ESP_TLS_USING_WOLFSSL /* CONFIG_ESP_TLS_USING_MBEDTLS */ +#define ESP_TLS_ERR_SSL_WANT_READ WOLFSSL_ERROR_WANT_READ +#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_TCP_CONNECTION, /*!< Errors related to TCP layer, extending errno */ + 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; + +/** +* @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 esp_tls_error_code; /*!< esp_tls error code from last esp_tls failed api */ + int esp_tls_flags; /*!< last certification verification flags */ +} esp_tls_last_error_t; + +#ifdef __cplusplus +} +#endif + +#endif //_ESP_TLS_ERRORS_H_ diff --git a/components/tcp_transport/private_include/esp_transport_internal.h b/components/tcp_transport/private_include/esp_transport_internal.h index 21fda1a4ea6f..56a26ba0762c 100644 --- a/components/tcp_transport/private_include/esp_transport_internal.h +++ b/components/tcp_transport/private_include/esp_transport_internal.h @@ -44,6 +44,29 @@ struct esp_transport_item_t { STAILQ_ENTRY(esp_transport_item_t) next; }; +/** + * @brief Internal error types for TCP connection issues not covered in socket's errno + */ +enum tcp_transport_errors { + ERR_TCP_TRANSPORT_CONNECTION_TIMEOUT, + ERR_TCP_TRANSPORT_CANNOT_RESOLVE_HOSTNAME, + ERR_TCP_TRANSPORT_CONNECTION_CLOSED_BY_FIN, + ERR_TCP_TRANSPORT_CONNECTION_FAILED, + ERR_TCP_TRANSPORT_SETOPT_FAILED, +}; + +/** + * @brief Captures internal tcp connection error + * + * This is internally translated to esp-tls return codes of esp_err_t type, since the esp-tls + * will be used as TCP transport layer + * + * @param[in] t The transport handle + * @param[in] error Internal tcp-transport's error + * + */ +void capture_tcp_transport_error(esp_transport_handle_t t, enum tcp_transport_errors error); + /** * @brief Returns underlying socket for the supplied transport handle * diff --git a/components/tcp_transport/transport.c b/components/tcp_transport/transport.c index f9b2b38a2c7e..f35212d2a9f6 100644 --- a/components/tcp_transport/transport.c +++ b/components/tcp_transport/transport.c @@ -23,6 +23,7 @@ #include "esp_transport.h" #include "esp_transport_internal.h" #include "esp_transport_utils.h" +#include "esp_tls_errors.h" static const char *TAG = "TRANSPORT"; @@ -298,6 +299,28 @@ int esp_transport_get_errno(esp_transport_handle_t t) return -1; } +void capture_tcp_transport_error(esp_transport_handle_t t, enum tcp_transport_errors error) +{ + esp_tls_last_error_t *err_handle = esp_transport_get_error_handle(t); + switch (error) { + case ERR_TCP_TRANSPORT_CONNECTION_TIMEOUT: + err_handle->last_error = ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT; + break; + case ERR_TCP_TRANSPORT_CANNOT_RESOLVE_HOSTNAME: + err_handle->last_error = ESP_ERR_ESP_TLS_CANNOT_RESOLVE_HOSTNAME; + break; + case ERR_TCP_TRANSPORT_CONNECTION_CLOSED_BY_FIN: + err_handle->last_error = ESP_ERR_ESP_TLS_TCP_CLOSED_FIN; + break; + case ERR_TCP_TRANSPORT_CONNECTION_FAILED: + err_handle->last_error = ESP_ERR_ESP_TLS_FAILED_CONNECT_TO_HOST; + break; + case ERR_TCP_TRANSPORT_SETOPT_FAILED: + err_handle->last_error = ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED; + break; + } +} + void esp_transport_set_errors(esp_transport_handle_t t, const esp_tls_error_handle_t error_handle) { if (t && t->error_handle) { diff --git a/components/tcp_transport/transport_ssl.c b/components/tcp_transport/transport_ssl.c index 9e3854d7c209..1d698ca909fa 100644 --- a/components/tcp_transport/transport_ssl.c +++ b/components/tcp_transport/transport_ssl.c @@ -166,6 +166,10 @@ static int ssl_read(esp_transport_handle_t t, char *buffer, int len, int timeout esp_transport_set_errors(t, ssl->tls->error_handle); } if (ret == 0) { + if (poll > 0) { + // no error, socket reads 0 while previously detected as readable -> connection has been closed cleanly + capture_tcp_transport_error(t, ERR_TCP_TRANSPORT_CONNECTION_CLOSED_BY_FIN); + } ret = -1; } return ret; diff --git a/components/tcp_transport/transport_tcp.c b/components/tcp_transport/transport_tcp.c index d61626f4f1ad..4d498e69ad27 100644 --- a/components/tcp_transport/transport_tcp.c +++ b/components/tcp_transport/transport_tcp.c @@ -26,6 +26,7 @@ #include "esp_transport_utils.h" #include "esp_transport.h" #include "esp_transport_internal.h" +#include "esp_tls_errors.h" static const char *TAG = "TRANS_TCP"; @@ -33,6 +34,7 @@ typedef struct { int sock; } transport_tcp_t; + static int resolve_dns(const char *host, struct sockaddr_in *ip) { const struct addrinfo hints = { @@ -91,6 +93,7 @@ static int tcp_connect(esp_transport_handle_t t, const char *host, int port, int //if stream_host is not ip address, resolve it AF_INET,servername,&serveraddr.sin_addr if (inet_pton(AF_INET, host, &remote_ip.sin_addr) != 1) { if (resolve_dns(host, &remote_ip) < 0) { + capture_tcp_transport_error(t, ERR_TCP_TRANSPORT_CANNOT_RESOLVE_HOSTNAME); return -1; } } @@ -120,10 +123,12 @@ static int tcp_connect(esp_transport_handle_t t, const char *host, int port, int int flags; if ((flags = fcntl(tcp->sock, F_GETFL, NULL)) < 0) { ESP_LOGE(TAG, "[sock=%d] get file flags error: %s", tcp->sock, strerror(errno)); + capture_tcp_transport_error(t, ERR_TCP_TRANSPORT_SETOPT_FAILED); goto error; } if (fcntl(tcp->sock, F_SETFL, flags |= O_NONBLOCK) < 0) { ESP_LOGE(TAG, "[sock=%d] set nonblocking error: %s", tcp->sock, strerror(errno)); + capture_tcp_transport_error(t, ERR_TCP_TRANSPORT_SETOPT_FAILED); goto error; } @@ -146,7 +151,7 @@ static int tcp_connect(esp_transport_handle_t t, const char *host, int port, int } else if (res == 0) { ESP_LOGE(TAG, "[sock=%d] select() timeout", tcp->sock); - esp_transport_capture_errno(t, EINPROGRESS); // errno=EINPROGRESS indicates connection timeout + capture_tcp_transport_error(t, ERR_TCP_TRANSPORT_CONNECTION_TIMEOUT); goto error; } else { int sockerr; @@ -154,11 +159,13 @@ static int tcp_connect(esp_transport_handle_t t, const char *host, int port, int if (getsockopt(tcp->sock, SOL_SOCKET, SO_ERROR, (void*)(&sockerr), &len) < 0) { ESP_LOGE(TAG, "[sock=%d] getsockopt() error: %s", tcp->sock, strerror(errno)); + capture_tcp_transport_error(t, ERR_TCP_TRANSPORT_SETOPT_FAILED); goto error; } else if (sockerr) { esp_transport_capture_errno(t, sockerr); ESP_LOGE(TAG, "[sock=%d] delayed connect error: %s", tcp->sock, strerror(sockerr)); + capture_tcp_transport_error(t, ERR_TCP_TRANSPORT_CONNECTION_FAILED); goto error; } } @@ -170,10 +177,12 @@ static int tcp_connect(esp_transport_handle_t t, const char *host, int port, int // Reset socket to blocking if ((flags = fcntl(tcp->sock, F_GETFL, NULL)) < 0) { ESP_LOGE(TAG, "[sock=%d] get file flags error: %s", tcp->sock, strerror(errno)); + capture_tcp_transport_error(t, ERR_TCP_TRANSPORT_SETOPT_FAILED); goto error; } if (fcntl(tcp->sock, F_SETFL, flags & ~O_NONBLOCK) < 0) { ESP_LOGE(TAG, "[sock=%d] reset blocking error: %s", tcp->sock, strerror(errno)); + capture_tcp_transport_error(t, ERR_TCP_TRANSPORT_SETOPT_FAILED); goto error; } return tcp->sock; @@ -202,6 +211,10 @@ static int tcp_read(esp_transport_handle_t t, char *buffer, int len, int timeout } int read_len = read(tcp->sock, buffer, len); if (read_len == 0) { + if (poll > 0) { + // no error, socket reads 0 while previously detected as readable -> connection has been closed cleanly + capture_tcp_transport_error(t, ERR_TCP_TRANSPORT_CONNECTION_CLOSED_BY_FIN); + } return -1; } return read_len;