mirror of
https://github.com/espressif/esp-idf.git
synced 2025-09-30 19:19:21 +00:00
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.
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
@@ -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_
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user