forked from espressif/esp-idf
tcp_transport: Fix error propogation
- Made tcp_transport_errors codes public to indicate TCP connection issues not covered in socket's errno - Added API to translate tcp_transport_error codes to esp_err_t codes for TCP Transport Co-authored-by: Shubham Kulkarni <shubham.kulkarni@espressif.com>
This commit is contained in:
@@ -53,6 +53,9 @@
|
|||||||
#if __has_include("esp_tls_errors.h")
|
#if __has_include("esp_tls_errors.h")
|
||||||
#include "esp_tls_errors.h"
|
#include "esp_tls_errors.h"
|
||||||
#endif
|
#endif
|
||||||
|
#if __has_include("esp_transport.h")
|
||||||
|
#include "esp_transport.h"
|
||||||
|
#endif
|
||||||
#if __has_include("esp_wifi.h")
|
#if __has_include("esp_wifi.h")
|
||||||
#include "esp_wifi.h"
|
#include "esp_wifi.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -796,6 +799,23 @@ static const esp_err_msg_t esp_err_msg_table[] = {
|
|||||||
# endif
|
# endif
|
||||||
# ifdef ESP_ERR_MEMPROT_AREA_INVALID
|
# ifdef ESP_ERR_MEMPROT_AREA_INVALID
|
||||||
ERR_TBL_IT(ESP_ERR_MEMPROT_AREA_INVALID), /* 53255 0xd007 */
|
ERR_TBL_IT(ESP_ERR_MEMPROT_AREA_INVALID), /* 53255 0xd007 */
|
||||||
|
# endif
|
||||||
|
// components/tcp_transport/include/esp_transport.h
|
||||||
|
# ifdef ESP_ERR_TCP_TRANSPORT_BASE
|
||||||
|
ERR_TBL_IT(ESP_ERR_TCP_TRANSPORT_BASE), /* 57344 0xe000 Starting number of TCP Transport error codes */
|
||||||
|
# endif
|
||||||
|
# ifdef ESP_ERR_TCP_TRANSPORT_CONNECTION_TIMEOUT
|
||||||
|
ERR_TBL_IT(ESP_ERR_TCP_TRANSPORT_CONNECTION_TIMEOUT), /* 57345 0xe001 Connection has timed out */
|
||||||
|
# endif
|
||||||
|
# ifdef ESP_ERR_TCP_TRANSPORT_CONNECTION_CLOSED_BY_FIN
|
||||||
|
ERR_TBL_IT(ESP_ERR_TCP_TRANSPORT_CONNECTION_CLOSED_BY_FIN), /* 57346 0xe002 Read FIN from peer and the connection
|
||||||
|
has closed (in a clean way) */
|
||||||
|
# endif
|
||||||
|
# ifdef ESP_ERR_TCP_TRANSPORT_CONNECTION_FAILED
|
||||||
|
ERR_TBL_IT(ESP_ERR_TCP_TRANSPORT_CONNECTION_FAILED), /* 57347 0xe003 Failed to connect to the peer */
|
||||||
|
# endif
|
||||||
|
# ifdef ESP_ERR_TCP_TRANSPORT_NO_MEM
|
||||||
|
ERR_TBL_IT(ESP_ERR_TCP_TRANSPORT_NO_MEM), /* 57348 0xe004 Memory allocation failed */
|
||||||
# endif
|
# endif
|
||||||
};
|
};
|
||||||
#endif //CONFIG_ESP_ERR_TO_NAME_LOOKUP
|
#endif //CONFIG_ESP_ERR_TO_NAME_LOOKUP
|
||||||
|
@@ -37,6 +37,22 @@ typedef esp_transport_handle_t (*payload_transfer_func)(esp_transport_handle_t);
|
|||||||
|
|
||||||
typedef struct esp_tls_last_error* esp_tls_error_handle_t;
|
typedef struct esp_tls_last_error* esp_tls_error_handle_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Error types for TCP connection issues not covered in socket's errno
|
||||||
|
*/
|
||||||
|
enum esp_tcp_transport_err_t {
|
||||||
|
ERR_TCP_TRANSPORT_NO_MEM = -3,
|
||||||
|
ERR_TCP_TRANSPORT_CONNECTION_FAILED = -2,
|
||||||
|
ERR_TCP_TRANSPORT_CONNECTION_CLOSED_BY_FIN = -1,
|
||||||
|
ERR_TCP_TRANSPORT_CONNECTION_TIMEOUT = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ESP_ERR_TCP_TRANSPORT_BASE (0xe000) /*!< Starting number of TCP Transport error codes */
|
||||||
|
#define ESP_ERR_TCP_TRANSPORT_CONNECTION_TIMEOUT (ESP_ERR_TCP_TRANSPORT_BASE + 1) /*!< Connection has timed out */
|
||||||
|
#define ESP_ERR_TCP_TRANSPORT_CONNECTION_CLOSED_BY_FIN (ESP_ERR_TCP_TRANSPORT_BASE + 2) /*!< Read FIN from peer and the connection has closed (in a clean way) */
|
||||||
|
#define ESP_ERR_TCP_TRANSPORT_CONNECTION_FAILED (ESP_ERR_TCP_TRANSPORT_BASE + 3) /*!< Failed to connect to the peer */
|
||||||
|
#define ESP_ERR_TCP_TRANSPORT_NO_MEM (ESP_ERR_TCP_TRANSPORT_BASE + 4) /*!< Memory allocation failed */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create transport list
|
* @brief Create transport list
|
||||||
*
|
*
|
||||||
@@ -169,7 +185,11 @@ int esp_transport_connect_async(esp_transport_handle_t t, const char *host, int
|
|||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* - Number of bytes was read
|
* - Number of bytes was read
|
||||||
* - (-1) if there are any errors, should check errno
|
* - 0 Read timed-out
|
||||||
|
* - (<0) For other errors
|
||||||
|
*
|
||||||
|
* @note: Please refer to the enum `esp_tcp_transport_err_t` for all the possible return values
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
int esp_transport_read(esp_transport_handle_t t, char *buffer, int len, int timeout_ms);
|
int esp_transport_read(esp_transport_handle_t t, char *buffer, int len, int timeout_ms);
|
||||||
|
|
||||||
@@ -334,6 +354,15 @@ esp_tls_error_handle_t esp_transport_get_error_handle(esp_transport_handle_t t);
|
|||||||
*/
|
*/
|
||||||
int esp_transport_get_errno(esp_transport_handle_t t);
|
int esp_transport_get_errno(esp_transport_handle_t t);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Translates the TCP transport error codes to esp_err_t error codes
|
||||||
|
*
|
||||||
|
* @param[in] error TCP Transport specific error code
|
||||||
|
*
|
||||||
|
* @return Corresponding esp_err_t based error code
|
||||||
|
*/
|
||||||
|
esp_err_t esp_transport_translate_error(enum esp_tcp_transport_err_t error);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -45,18 +45,6 @@ struct esp_transport_item_t {
|
|||||||
STAILQ_ENTRY(esp_transport_item_t) next;
|
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,
|
|
||||||
ERR_TCP_TRANSPORT_NO_MEM,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Captures internal tcp connection error
|
* @brief Captures internal tcp connection error
|
||||||
*
|
*
|
||||||
@@ -67,7 +55,7 @@ enum tcp_transport_errors {
|
|||||||
* @param[in] error Internal tcp-transport's error
|
* @param[in] error Internal tcp-transport's error
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void capture_tcp_transport_error(esp_transport_handle_t t, enum tcp_transport_errors error);
|
void capture_tcp_transport_error(esp_transport_handle_t t, enum esp_tcp_transport_err_t error);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns underlying socket for the supplied transport handle
|
* @brief Returns underlying socket for the supplied transport handle
|
||||||
|
@@ -318,25 +318,19 @@ int esp_transport_get_errno(esp_transport_handle_t t)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void capture_tcp_transport_error(esp_transport_handle_t t, enum tcp_transport_errors error)
|
void capture_tcp_transport_error(esp_transport_handle_t t, enum esp_tcp_transport_err_t error)
|
||||||
{
|
{
|
||||||
esp_tls_last_error_t *err_handle = esp_transport_get_error_handle(t);
|
esp_tls_last_error_t *err_handle = esp_transport_get_error_handle(t);
|
||||||
switch (error) {
|
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:
|
case ERR_TCP_TRANSPORT_CONNECTION_CLOSED_BY_FIN:
|
||||||
err_handle->last_error = ESP_ERR_ESP_TLS_TCP_CLOSED_FIN;
|
err_handle->last_error = ESP_ERR_ESP_TLS_TCP_CLOSED_FIN;
|
||||||
break;
|
break;
|
||||||
|
case ERR_TCP_TRANSPORT_CONNECTION_TIMEOUT:
|
||||||
|
err_handle->last_error = ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT;
|
||||||
|
break;
|
||||||
case ERR_TCP_TRANSPORT_CONNECTION_FAILED:
|
case ERR_TCP_TRANSPORT_CONNECTION_FAILED:
|
||||||
err_handle->last_error = ESP_ERR_ESP_TLS_FAILED_CONNECT_TO_HOST;
|
err_handle->last_error = ESP_ERR_ESP_TLS_FAILED_CONNECT_TO_HOST;
|
||||||
break;
|
break;
|
||||||
case ERR_TCP_TRANSPORT_SETOPT_FAILED:
|
|
||||||
err_handle->last_error = ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED;
|
|
||||||
break;
|
|
||||||
case ERR_TCP_TRANSPORT_NO_MEM:
|
case ERR_TCP_TRANSPORT_NO_MEM:
|
||||||
err_handle->last_error = ESP_ERR_NO_MEM;
|
err_handle->last_error = ESP_ERR_NO_MEM;
|
||||||
break;
|
break;
|
||||||
@@ -368,3 +362,24 @@ int esp_transport_get_socket(esp_transport_handle_t t)
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_transport_translate_error(enum esp_tcp_transport_err_t error)
|
||||||
|
{
|
||||||
|
esp_err_t err = ESP_FAIL;
|
||||||
|
switch (error) {
|
||||||
|
case ERR_TCP_TRANSPORT_CONNECTION_CLOSED_BY_FIN:
|
||||||
|
err = ESP_ERR_TCP_TRANSPORT_CONNECTION_CLOSED_BY_FIN;
|
||||||
|
break;
|
||||||
|
case ERR_TCP_TRANSPORT_CONNECTION_TIMEOUT:
|
||||||
|
err = ESP_ERR_TCP_TRANSPORT_CONNECTION_TIMEOUT;
|
||||||
|
break;
|
||||||
|
case ERR_TCP_TRANSPORT_CONNECTION_FAILED:
|
||||||
|
err = ESP_ERR_TCP_TRANSPORT_CONNECTION_FAILED;
|
||||||
|
break;
|
||||||
|
case ERR_TCP_TRANSPORT_NO_MEM:
|
||||||
|
err = ESP_ERR_TCP_TRANSPORT_NO_MEM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
@@ -174,6 +174,8 @@ static int base_poll_read(esp_transport_handle_t t, int timeout_ms)
|
|||||||
esp_transport_capture_errno(t, sock_errno);
|
esp_transport_capture_errno(t, sock_errno);
|
||||||
ESP_LOGE(TAG, "poll_read select error %d, errno = %s, fd = %d", sock_errno, strerror(sock_errno), ssl->sockfd);
|
ESP_LOGE(TAG, "poll_read select error %d, errno = %s, fd = %d", sock_errno, strerror(sock_errno), ssl->sockfd);
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
} else if (ret == 0) {
|
||||||
|
ESP_LOGD(TAG, "poll_read: select - Timeout before any socket was ready!");
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -197,6 +199,8 @@ static int base_poll_write(esp_transport_handle_t t, int timeout_ms)
|
|||||||
esp_transport_capture_errno(t, sock_errno);
|
esp_transport_capture_errno(t, sock_errno);
|
||||||
ESP_LOGE(TAG, "poll_write select error %d, errno = %s, fd = %d", sock_errno, strerror(sock_errno), ssl->sockfd);
|
ESP_LOGE(TAG, "poll_write select error %d, errno = %s, fd = %d", sock_errno, strerror(sock_errno), ssl->sockfd);
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
} else if (ret == 0) {
|
||||||
|
ESP_LOGD(TAG, "poll_write: select - Timeout before any socket was ready!");
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -242,51 +246,64 @@ static int tcp_write(esp_transport_handle_t t, const char *buffer, int len, int
|
|||||||
|
|
||||||
static int ssl_read(esp_transport_handle_t t, char *buffer, int len, int timeout_ms)
|
static int ssl_read(esp_transport_handle_t t, char *buffer, int len, int timeout_ms)
|
||||||
{
|
{
|
||||||
int poll;
|
|
||||||
transport_esp_tls_t *ssl = ssl_get_context_data(t);
|
transport_esp_tls_t *ssl = ssl_get_context_data(t);
|
||||||
|
|
||||||
if ((poll = esp_transport_poll_read(t, timeout_ms)) <= 0) {
|
int poll = esp_transport_poll_read(t, timeout_ms);
|
||||||
return poll;
|
if (poll == -1) {
|
||||||
|
return ERR_TCP_TRANSPORT_CONNECTION_FAILED;
|
||||||
}
|
}
|
||||||
|
if (poll == 0) {
|
||||||
|
return ERR_TCP_TRANSPORT_CONNECTION_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
int ret = esp_tls_conn_read(ssl->tls, (unsigned char *)buffer, len);
|
int ret = esp_tls_conn_read(ssl->tls, (unsigned char *)buffer, len);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
ESP_LOGE(TAG, "esp_tls_conn_read error, errno=%s", strerror(errno));
|
ESP_LOGE(TAG, "esp_tls_conn_read error, errno=%s", strerror(errno));
|
||||||
|
if (ret == ESP_TLS_ERR_SSL_WANT_READ || ret == ESP_TLS_ERR_SSL_TIMEOUT) {
|
||||||
|
ret = ERR_TCP_TRANSPORT_CONNECTION_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
esp_tls_error_handle_t esp_tls_error_handle;
|
esp_tls_error_handle_t esp_tls_error_handle;
|
||||||
if (esp_tls_get_error_handle(ssl->tls, &esp_tls_error_handle) == ESP_OK) {
|
if (esp_tls_get_error_handle(ssl->tls, &esp_tls_error_handle) == ESP_OK) {
|
||||||
esp_transport_set_errors(t, esp_tls_error_handle);
|
esp_transport_set_errors(t, esp_tls_error_handle);
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGE(TAG, "Error in obtaining the error handle");
|
ESP_LOGE(TAG, "Error in obtaining the error handle");
|
||||||
}
|
}
|
||||||
}
|
} else if (ret == 0) {
|
||||||
if (ret == 0) {
|
|
||||||
if (poll > 0) {
|
if (poll > 0) {
|
||||||
// no error, socket reads 0 while previously detected as readable -> connection has been closed cleanly
|
// 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);
|
capture_tcp_transport_error(t, ERR_TCP_TRANSPORT_CONNECTION_CLOSED_BY_FIN);
|
||||||
}
|
}
|
||||||
ret = -1;
|
ret = ERR_TCP_TRANSPORT_CONNECTION_CLOSED_BY_FIN;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tcp_read(esp_transport_handle_t t, char *buffer, int len, int timeout_ms)
|
static int tcp_read(esp_transport_handle_t t, char *buffer, int len, int timeout_ms)
|
||||||
{
|
{
|
||||||
int poll;
|
|
||||||
transport_esp_tls_t *ssl = ssl_get_context_data(t);
|
transport_esp_tls_t *ssl = ssl_get_context_data(t);
|
||||||
|
|
||||||
if ((poll = esp_transport_poll_read(t, timeout_ms)) <= 0) {
|
int poll = esp_transport_poll_read(t, timeout_ms);
|
||||||
return poll;
|
if (poll == -1) {
|
||||||
|
return ERR_TCP_TRANSPORT_CONNECTION_FAILED;
|
||||||
}
|
}
|
||||||
|
if (poll == 0) {
|
||||||
|
return ERR_TCP_TRANSPORT_CONNECTION_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
int ret = recv(ssl->sockfd, (unsigned char *)buffer, len, 0);
|
int ret = recv(ssl->sockfd, (unsigned char *)buffer, len, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
ESP_LOGE(TAG, "tcp_read error, errno=%s", strerror(errno));
|
ESP_LOGE(TAG, "tcp_read error, errno=%s", strerror(errno));
|
||||||
esp_transport_capture_errno(t, errno);
|
esp_transport_capture_errno(t, errno);
|
||||||
|
if (errno == EAGAIN) {
|
||||||
|
ret = ERR_TCP_TRANSPORT_CONNECTION_TIMEOUT;
|
||||||
}
|
}
|
||||||
if (ret == 0) {
|
} else if (ret == 0) {
|
||||||
if (poll > 0) {
|
if (poll > 0) {
|
||||||
// no error, socket reads 0 while previously detected as readable -> connection has been closed cleanly
|
// 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);
|
capture_tcp_transport_error(t, ERR_TCP_TRANSPORT_CONNECTION_CLOSED_BY_FIN);
|
||||||
}
|
}
|
||||||
ret = -1;
|
ret = ERR_TCP_TRANSPORT_CONNECTION_CLOSED_BY_FIN;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user