diff --git a/components/esp_websocket_client/esp_websocket_client.c b/components/esp_websocket_client/esp_websocket_client.c index f943a86895..d1ab66bac5 100644 --- a/components/esp_websocket_client/esp_websocket_client.c +++ b/components/esp_websocket_client/esp_websocket_client.c @@ -30,7 +30,7 @@ static const char *TAG = "websocket_client"; #define WEBSOCKET_BUFFER_SIZE_BYTE (1024) #define WEBSOCKET_RECONNECT_TIMEOUT_MS (10*1000) #define WEBSOCKET_TASK_PRIORITY (5) -#define WEBSOCKET_TASK_STACK (4*1024) +#define WEBSOCKET_TASK_STACK (7*1024) #define WEBSOCKET_NETWORK_TIMEOUT_MS (10*1000) #define WEBSOCKET_PING_INTERVAL_SEC (10) #define WEBSOCKET_EVENT_QUEUE_SIZE (1) @@ -39,6 +39,12 @@ static const char *TAG = "websocket_client"; #define WEBSOCKET_KEEP_ALIVE_INTERVAL (5) #define WEBSOCKET_KEEP_ALIVE_COUNT (3) +#define VALID_MEMORY_FLAGS (MALLOC_CAP_EXEC | MALLOC_CAP_32BIT | MALLOC_CAP_8BIT | MALLOC_CAP_DMA | \ + MALLOC_CAP_PID2 | MALLOC_CAP_PID3 | MALLOC_CAP_PID4 | MALLOC_CAP_PID5 | \ + MALLOC_CAP_PID6 | MALLOC_CAP_PID7 | MALLOC_CAP_SPIRAM | MALLOC_CAP_INTERNAL | \ + MALLOC_CAP_DEFAULT | MALLOC_CAP_IRAM_8BIT | MALLOC_CAP_RETENTION | \ + MALLOC_CAP_RTCRAM | MALLOC_CAP_TCM | MALLOC_CAP_INVALID) + #define ESP_WS_CLIENT_MEM_CHECK(TAG, a, action) if (!(a)) { \ ESP_LOGE(TAG,"%s(%d): %s", __FUNCTION__, __LINE__, "Memory exhausted"); \ action; \ @@ -139,6 +145,8 @@ struct esp_websocket_client { int payload_offset; esp_transport_keep_alive_t keep_alive_cfg; struct ifreq *if_name; + int memory_type; + int core; }; static uint64_t _tick_get_ms(void) @@ -154,14 +162,17 @@ static esp_err_t esp_websocket_new_buf(esp_websocket_client_handle_t client, boo free(client->tx_buffer); } - client->tx_buffer = calloc(1, client->buffer_size); + // client->tx_buffer = calloc(1, client->buffer_size); + client->tx_buffer = heap_caps_calloc(1, client->buffer_size,client->memory_type); + ESP_WS_CLIENT_MEM_CHECK(TAG, client->tx_buffer, return ESP_ERR_NO_MEM); } else { if (client->rx_buffer) { free(client->rx_buffer); } - client->rx_buffer = calloc(1, client->buffer_size); + // client->rx_buffer = calloc(1, client->buffer_size); + client->rx_buffer = heap_caps_calloc(1, client->buffer_size,client->memory_type); ESP_WS_CLIENT_MEM_CHECK(TAG, client->rx_buffer, return ESP_ERR_NO_MEM); } #endif @@ -255,7 +266,8 @@ static esp_err_t esp_websocket_client_error(esp_websocket_client_handle_t client if (client->errormsg_buffer) { free(client->errormsg_buffer); } - client->errormsg_buffer = malloc(needed_size); + // client->errormsg_buffer = malloc(needed_size); + client->errormsg_buffer = heap_caps_malloc(needed_size,client->memory_type); if (client->errormsg_buffer == NULL) { client->errormsg_size = 0; ESP_LOGE(TAG, "Failed to allocate..."); @@ -274,7 +286,8 @@ static esp_err_t esp_websocket_client_error(esp_websocket_client_handle_t client return ESP_OK; } -static char *http_auth_basic(const char *username, const char *password) +// static char *http_auth_basic(const char *username, const char *password) +static char *http_auth_basic(const char *username, const char *password, int memory_type) { int out; char *user_info = NULL; @@ -291,7 +304,8 @@ static char *http_auth_basic(const char *username, const char *password) } esp_crypto_base64_encode(NULL, 0, &n, (const unsigned char *)user_info, strlen(user_info)); - digest = calloc(1, strlen(WS_HTTP_BASIC_AUTH) + n + 1); + // digest = calloc(1, strlen(WS_HTTP_BASIC_AUTH) + n + 1); + digest = heap_caps_calloc(1, strlen(WS_HTTP_BASIC_AUTH) + n + 1,memory_type); if (digest) { strcpy(digest, WS_HTTP_BASIC_AUTH); esp_crypto_base64_encode((unsigned char *)digest + 6, n, (size_t *)&out, (const unsigned char *)user_info, strlen(user_info)); @@ -338,7 +352,8 @@ static esp_err_t esp_websocket_client_set_config(esp_websocket_client_handle_t c if (cfg->username && cfg->password) { free(cfg->auth); - cfg->auth = http_auth_basic(cfg->username, cfg->password); + // cfg->auth = http_auth_basic(cfg->username, cfg->password); + cfg->auth = http_auth_basic(cfg->username, cfg->password, client->memory_type); ESP_WS_CLIENT_MEM_CHECK(TAG, cfg->auth, return ESP_ERR_NO_MEM); } @@ -636,9 +651,39 @@ static int esp_websocket_client_send_with_exact_opcode(esp_websocket_client_hand esp_websocket_client_handle_t esp_websocket_client_init(const esp_websocket_client_config_t *config) { - esp_websocket_client_handle_t client = calloc(1, sizeof(struct esp_websocket_client)); + int memory_type = 0; + if ((config->memory_type & ~VALID_MEMORY_FLAGS) != 0) { + ESP_LOGE(TAG, "Invalid memory_type flags set.\n"); + return NULL; + } + else if (config->memory_type == 0) { + memory_type = MALLOC_CAP_DEFAULT; //MALLOC_CAP_DEFAULT + ESP_LOGI(TAG,"memory_type is not set, using MALLOC_CAP_DEFAULT memory [%d] versus external [%d].\n",memory_type,MALLOC_CAP_SPIRAM); + } else { + memory_type = config->memory_type; + ESP_LOGI(TAG,"memory_type is set to caps %d \n", config->memory_type); + } + + // esp_websocket_client_handle_t client = calloc(1, sizeof(struct esp_websocket_client)); + esp_websocket_client_handle_t client = heap_caps_calloc(1, sizeof(struct esp_websocket_client),memory_type); + ESP_WS_CLIENT_MEM_CHECK(TAG, client, return NULL); + + if (config->core){ + if (config->core >2){ + ESP_LOGW("TAG", "Invalid core affinity flag set, using default tskNO_AFFINITY.\n"); + client->core = tskNO_AFFINITY; + } + else{ + client->core = config->core; + } + } + else { + ESP_LOGW("TAG", "Invalid core affinity flag set, using default tskNO_AFFINITY.\n"); + client->core = tskNO_AFFINITY; + } + esp_event_loop_args_t event_args = { .queue_size = WEBSOCKET_EVENT_QUEUE_SIZE, .task_name = NULL // no task will be created @@ -650,6 +695,8 @@ esp_websocket_client_handle_t esp_websocket_client_init(const esp_websocket_clie return NULL; } + client->memory_type = memory_type; + if (config->keep_alive_enable == true) { client->keep_alive_cfg.keep_alive_enable = true; client->keep_alive_cfg.keep_alive_idle = (config->keep_alive_idle == 0) ? WEBSOCKET_KEEP_ALIVE_IDLE : config->keep_alive_idle; @@ -658,7 +705,8 @@ esp_websocket_client_handle_t esp_websocket_client_init(const esp_websocket_clie } if (config->if_name) { - client->if_name = calloc(1, sizeof(struct ifreq) + 1); + // client->if_name = calloc(1, sizeof(struct ifreq) + 1); + client->if_name = heap_caps_calloc(1, sizeof(struct ifreq) + 1,memory_type); ESP_WS_CLIENT_MEM_CHECK(TAG, client->if_name, goto _websocket_init_fail); memcpy(client->if_name, config->if_name, sizeof(struct ifreq)); } @@ -666,7 +714,8 @@ esp_websocket_client_handle_t esp_websocket_client_init(const esp_websocket_clie client->lock = xSemaphoreCreateRecursiveMutex(); ESP_WS_CLIENT_MEM_CHECK(TAG, client->lock, goto _websocket_init_fail); - client->config = calloc(1, sizeof(websocket_config_storage_t)); + // client->config = calloc(1, sizeof(websocket_config_storage_t)); + client->config = heap_caps_calloc(1, sizeof(websocket_config_storage_t),memory_type); ESP_WS_CLIENT_MEM_CHECK(TAG, client->config, goto _websocket_init_fail); if (config->transport == WEBSOCKET_TRANSPORT_OVER_TCP) { @@ -732,11 +781,13 @@ esp_websocket_client_handle_t esp_websocket_client_init(const esp_websocket_clie client->errormsg_buffer = NULL; client->errormsg_size = 0; #ifndef CONFIG_ESP_WS_CLIENT_ENABLE_DYNAMIC_BUFFER - client->rx_buffer = malloc(buffer_size); + // client->rx_buffer = malloc(buffer_size); + client->rx_buffer = heap_caps_malloc(buffer_size,client->memory_type); ESP_WS_CLIENT_MEM_CHECK(TAG, client->rx_buffer, { goto _websocket_init_fail; }); - client->tx_buffer = malloc(buffer_size); + // client->tx_buffer = malloc(buffer_size); + client->tx_buffer = heap_caps_malloc(buffer_size,client->memory_type); ESP_WS_CLIENT_MEM_CHECK(TAG, client->tx_buffer, { goto _websocket_init_fail; }); @@ -866,7 +917,8 @@ esp_err_t esp_websocket_client_append_header(esp_websocket_client_handle_t clien // If no previous headers exist if (cfg->headers == NULL) { - cfg->headers = (char *)malloc(len); + // cfg->headers = (char *)malloc(len); + cfg->headers = (char *)heap_caps_malloc(len,client->memory_type); if (cfg->headers == NULL) { ESP_LOGE(TAG, "Failed to allocate..."); return ESP_ERR_NO_MEM; @@ -880,7 +932,8 @@ esp_err_t esp_websocket_client_append_header(esp_websocket_client_handle_t clien size_t new_len = current_len + len; // Allocate memory for new headers - char *new_headers = (char *)malloc(new_len); + // char *new_headers = (char *)malloc(new_len); + char *new_headers = (char *)heap_caps_malloc(new_len,client->memory_type); if (new_headers == NULL) { ESP_LOGE(TAG, "Failed to allocate..."); return ESP_ERR_NO_MEM; @@ -1135,11 +1188,79 @@ esp_err_t esp_websocket_client_start(esp_websocket_client_handle_t client) } } - if (xTaskCreate(esp_websocket_client_task, client->config->task_name ? client->config->task_name : "websocket_task", - client->config->task_stack, client, client->config->task_prio, &client->task_handle) != pdTRUE) { - ESP_LOGE(TAG, "Error create websocket task"); - return ESP_FAIL; + // if (xTaskCreate(esp_websocket_client_task, client->config->task_name ? client->config->task_name : "websocket_task", + // client->config->task_stack, client, client->config->task_prio, &client->task_handle) != pdTRUE) { + // ESP_LOGE(TAG, "Error create websocket task"); + // return ESP_FAIL; + // } + + if (!client->core) { + // No core affinity + if (!client->memory_type) { + // Default memory + if (xTaskCreatePinnedToCoreWithCaps(esp_websocket_client_task, + client->config->task_name ? client->config->task_name : "websocket_task", + client->config->task_stack, + client, + client->config->task_prio, + &client->task_handle, + tskNO_AFFINITY, + MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) != pdTRUE) { + ESP_LOGE(TAG, "Failed to create websocket task without core affinity using default memory"); + return ESP_FAIL; + } + ESP_LOGD(TAG, "Websocket task created without core affinity using default memory"); + } else { + // Specific memory type without core affinity + if (xTaskCreatePinnedToCoreWithCaps(esp_websocket_client_task, + client->config->task_name ? client->config->task_name : "websocket_task", + client->config->task_stack, + client, + client->config->task_prio, + &client->task_handle, + tskNO_AFFINITY, + client->memory_type) != pdTRUE) { + ESP_LOGE(TAG, "Failed to create websocket task without core affinity using specified memory type"); + return ESP_FAIL; + } + ESP_LOGD(TAG, "Websocket task created without core affinity using specified memory type"); + } + } + else { + // With core affinity + if (!client->memory_type) { + // Default memory with core affinity + if (xTaskCreatePinnedToCoreWithCaps(esp_websocket_client_task, + client->config->task_name ? client->config->task_name : "websocket_task", + client->config->task_stack, + client, + client->config->task_prio, + &client->task_handle, + client->core, + MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) != pdTRUE) { + ESP_LOGE(TAG, "Failed to create websocket task with core affinity using default memory (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)"); + return ESP_FAIL; + } + ESP_LOGD(TAG, "Websocket task created with core affinity using default memory (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)"); + } + else { + // Specific memory type with core affinity + if (xTaskCreatePinnedToCoreWithCaps(esp_websocket_client_task, + client->config->task_name ? client->config->task_name : "websocket_task", + client->config->task_stack, + client, + client->config->task_prio, + &client->task_handle, + client->core, + client->memory_type) != pdTRUE) { + ESP_LOGE(TAG, "Failed to create websocket task with core affinity using specified memory type"); + return ESP_FAIL; + } + ESP_LOGD(TAG, "Websocket task created with core affinity using specified memory type (%d)", client->memory_type); + } } + + xEventGroupClearBits(client->status_bits, STOPPED_BIT | CLOSE_FRAME_SENT_BIT); ESP_LOGI(TAG, "Started"); return ESP_OK; @@ -1174,7 +1295,8 @@ static int esp_websocket_client_send_close(esp_websocket_client_handle_t client, uint8_t *close_status_data = NULL; // RFC6455#section-5.5.1: The Close frame MAY contain a body (indicated by total_len >= 2) if (total_len >= 2) { - close_status_data = calloc(1, total_len); + // close_status_data = calloc(1, total_len); + close_status_data = heap_caps_calloc(1, total_len,client->memory_type); ESP_WS_CLIENT_MEM_CHECK(TAG, close_status_data, return -1); // RFC6455#section-5.5.1: The first two bytes of the body MUST be a 2-byte representing a status uint16_t *code_network_order = (uint16_t *) close_status_data;