Skip to content

Add Memory Map to create buffer and Task Memory Region as well CPU core #690

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 141 additions & 19 deletions components/esp_websocket_client/esp_websocket_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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; \
Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -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...");
Expand All @@ -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;
Expand All @@ -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));
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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
Expand All @@ -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;
Expand All @@ -658,15 +705,17 @@ 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));
}

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) {
Expand Down Expand Up @@ -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;
});
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down