From d68624ec4fc5dbd1793961d0ccfe5cfaaf5b3f50 Mon Sep 17 00:00:00 2001 From: 0xFEEDC0DE64 Date: Wed, 8 Feb 2023 15:31:45 +0100 Subject: [PATCH] Add websocket error messages --- .../esp_websocket_client.c | 94 ++++++++++++++++--- 1 file changed, 81 insertions(+), 13 deletions(-) diff --git a/components/esp_websocket_client/esp_websocket_client.c b/components/esp_websocket_client/esp_websocket_client.c index f51ea7add..4a58e0d25 100644 --- a/components/esp_websocket_client/esp_websocket_client.c +++ b/components/esp_websocket_client/esp_websocket_client.c @@ -118,6 +118,8 @@ struct esp_websocket_client { bool selected_for_destroying; EventGroupHandle_t status_bits; SemaphoreHandle_t lock; + size_t errormsg_size; + char *errormsg_buffer; char *rx_buffer; char *tx_buffer; int buffer_size; @@ -214,17 +216,35 @@ static esp_err_t esp_websocket_client_abort_connection(esp_websocket_client_hand return ESP_OK; } -static esp_err_t esp_websocket_client_error_connection(esp_websocket_client_handle_t client) +static esp_err_t esp_websocket_client_error(esp_websocket_client_handle_t client, const char *format, ...) __attribute__ ((format (printf, 2, 3))); +static esp_err_t esp_websocket_client_error(esp_websocket_client_handle_t client, const char *format, ...) { - ESP_WS_CLIENT_STATE_CHECK(TAG, client, return ESP_FAIL); - esp_transport_close(client->transport); + va_list myargs; + va_start(myargs, format); - if (client->config->auto_reconnect) { - client->reconnect_tick_ms = _tick_get_ms(); - ESP_LOGI(TAG, "Reconnect after %d ms", client->wait_timeout_ms); + size_t needed_size = vsnprintf(NULL, 0, format, myargs); + needed_size++; // null terminator + + if (needed_size > client->errormsg_size) { + if (client->errormsg_buffer) { + free(client->errormsg_buffer); + } + client->errormsg_buffer = malloc(needed_size); + if (client->errormsg_buffer == NULL) { + client->errormsg_size = 0; + ESP_LOGE(TAG, "Failed to allocate..."); + return ESP_ERR_NO_MEM; + } + client->errormsg_size = needed_size; } - client->state = WEBSOCKET_STATE_WAIT_TIMEOUT; - esp_websocket_client_dispatch_event(client, WEBSOCKET_EVENT_ERROR, NULL, 0); + + needed_size = vsnprintf(client->errormsg_buffer, client->errormsg_size, format, myargs); + + va_end(myargs); + + ESP_LOGE(TAG, "%s", client->errormsg_buffer); + + esp_websocket_client_dispatch_event(client, WEBSOCKET_EVENT_ERROR, client->errormsg_buffer, needed_size); return ESP_OK; } @@ -356,6 +376,7 @@ static void destroy_and_free_resources(esp_websocket_client_handle_t client) vQueueDelete(client->lock); free(client->tx_buffer); free(client->rx_buffer); + free(client->errormsg_buffer); if (client->status_bits) { vEventGroupDelete(client->status_bits); } @@ -554,6 +575,8 @@ esp_websocket_client_handle_t esp_websocket_client_init(const esp_websocket_clie if (buffer_size <= 0) { buffer_size = WEBSOCKET_BUFFER_SIZE_BYTE; } + client->errormsg_buffer = NULL; + client->errormsg_size = 0; #ifndef CONFIG_ESP_WS_CLIENT_ENABLE_DYNAMIC_BUFFER client->rx_buffer = malloc(buffer_size); ESP_WS_CLIENT_MEM_CHECK(TAG, client->rx_buffer, { @@ -673,8 +696,19 @@ static esp_err_t esp_websocket_client_recv(esp_websocket_client_handle_t client) do { rlen = esp_transport_read(client->transport, client->rx_buffer, client->buffer_size, client->config->network_timeout_ms); if (rlen < 0) { - ESP_LOGE(TAG, "Error read data"); esp_websocket_free_buf(client, false); + esp_tls_error_handle_t error_handle = esp_transport_get_error_handle(client->transport); + if (error_handle) { + ESP_LOGE(TAG, "esp_transport_read() failed with %d, last_error=%s, tls_error_code=%i, tls_flags=%i, errno=%d", + rlen, esp_err_to_name(error_handle->last_error), error_handle->esp_tls_error_code, + error_handle->esp_tls_flags, errno); + esp_websocket_client_error(client, "esp_transport_read() failed with %d, last_error=%s, tls_error_code=%i, tls_flags=%i, errno=%d", + rlen, esp_err_to_name(error_handle->last_error), error_handle->esp_tls_error_code, + error_handle->esp_tls_flags, errno); + } else { + ESP_LOGE(TAG, "esp_transport_read() failed with %d, errno=%d", rlen, errno); + esp_websocket_client_error(client, "esp_transport_read() failed with %d, errno=%d", rlen, errno); + } return ESP_FAIL; } client->payload_len = esp_transport_ws_get_read_payload_len(client->transport); @@ -748,8 +782,19 @@ static void esp_websocket_client_task(void *pv) client->config->port, client->config->network_timeout_ms); if (result < 0) { - ESP_LOGE(TAG, "Error transport connect %i", result); - esp_websocket_client_error_connection(client); + esp_tls_error_handle_t error_handle = esp_transport_get_error_handle(client->transport); + if (error_handle) { + ESP_LOGE(TAG, "esp_transport_connect() failed with %d, last_error=%s, tls_error_code=%i, tls_flags=%i, errno=%d", + result, esp_err_to_name(error_handle->last_error), error_handle->esp_tls_error_code, + error_handle->esp_tls_flags, errno); + esp_websocket_client_error(client, "esp_transport_connect() failed with %d, last_error=%s, tls_error_code=%i, tls_flags=%i, errno=%d", + result, esp_err_to_name(error_handle->last_error), error_handle->esp_tls_error_code, + error_handle->esp_tls_flags, errno); + } else { + ESP_LOGE(TAG, "esp_transport_connect() failed with %d, errno=%d", result, errno); + esp_websocket_client_error(client, "esp_transport_connect() failed with %d, errno=%d", result, errno); + } + esp_websocket_client_abort_connection(client); break; } ESP_LOGD(TAG, "Transport connected to %s://%s:%d", client->config->scheme, client->config->host, client->config->port); @@ -776,6 +821,7 @@ static void esp_websocket_client_task(void *pv) if ( _tick_get_ms() - client->pingpong_tick_ms > client->config->pingpong_timeout_sec * 1000 ) { if (client->wait_for_pong_resp) { ESP_LOGE(TAG, "Error, no PONG received for more than %d seconds after PING", client->config->pingpong_timeout_sec); + esp_websocket_client_error(client, "Error, no PONG received for more than %d seconds after PING", client->config->pingpong_timeout_sec); esp_websocket_client_abort_connection(client); break; } @@ -822,7 +868,18 @@ static void esp_websocket_client_task(void *pv) if (WEBSOCKET_STATE_CONNECTED == client->state) { read_select = esp_transport_poll_read(client->transport, 1000); //Poll every 1000ms if (read_select < 0) { - ESP_LOGE(TAG, "Network error: esp_transport_poll_read() returned %d, errno=%d", read_select, errno); + esp_tls_error_handle_t error_handle = esp_transport_get_error_handle(client->transport); + if (error_handle) { + ESP_LOGE(TAG, "esp_transport_poll_read() returned %d, last_error=%s, tls_error_code=%i, tls_flags=%i, errno=%d", + read_select, esp_err_to_name(error_handle->last_error), error_handle->esp_tls_error_code, + error_handle->esp_tls_flags, errno); + esp_websocket_client_error(client, "esp_transport_poll_read() returned %d, last_error=%s, tls_error_code=%i, tls_flags=%i, errno=%d", + read_select, esp_err_to_name(error_handle->last_error), error_handle->esp_tls_error_code, + error_handle->esp_tls_flags, errno); + } else { + ESP_LOGE(TAG, "esp_transport_poll_read() returned %d, errno=%d", read_select, errno); + esp_websocket_client_error(client, "esp_transport_poll_read() returned %d, errno=%d", read_select, errno); + } esp_websocket_client_abort_connection(client); } } else if (WEBSOCKET_STATE_WAIT_TIMEOUT == client->state) { @@ -1019,8 +1076,19 @@ int esp_websocket_client_send_with_opcode(esp_websocket_client_handle_t client, (timeout == portMAX_DELAY) ? -1 : timeout * portTICK_PERIOD_MS); if (wlen < 0 || (wlen == 0 && need_write != 0)) { ret = wlen; - ESP_LOGE(TAG, "Network error: esp_transport_write() returned %d, errno=%d", ret, errno); esp_websocket_free_buf(client, true); + esp_tls_error_handle_t error_handle = esp_transport_get_error_handle(client->transport); + if (error_handle) { + ESP_LOGE(TAG, "esp_transport_write() returned %d, last_error=%s, tls_error_code=%i, tls_flags=%i, errno=%d", + ret, esp_err_to_name(error_handle->last_error), error_handle->esp_tls_error_code, + error_handle->esp_tls_flags, errno); + esp_websocket_client_error(client, "esp_transport_write() returned %d, last_error=%s, tls_error_code=%i, tls_flags=%i, errno=%d", + ret, esp_err_to_name(error_handle->last_error), error_handle->esp_tls_error_code, + error_handle->esp_tls_flags, errno); + } else { + ESP_LOGE(TAG, "esp_transport_write() returned %d, errno=%d", ret, errno); + esp_websocket_client_error(client, "esp_transport_write() returned %d, errno=%d", ret, errno); + } esp_websocket_client_abort_connection(client); goto unlock_and_return; }