I don’t know if I can create new topics here since there is a new support method. If the support now is only via email, please just inform me about.
I am on ESP8266 SDK, and in my test application I have only one task/thread, which is related to mbedTLS, where I use it to write to Google’s Firebase database. After the write is finished, there is a 4 seconds delay, and then it writes again, and this is the loop, the task keep writing on the database.
On main(), I am monitoring the current heap memory available, and keeping in a variable the minimum value that was reached. Every 500ms I send both values (minimum and current values) via UART.
void min_heap (void)
{
static uint32_t min_free = UINT32_MAX;
for (;;)
{
uint32_t current = esp_get_free_heap_size();
if (current < min_free)
{
min_free = current;
}
ESP_LOGI(TAG, "HEAP. MIN=%d, NOW=%d...\r\n", min_free, current);
vTaskDelay(500/portTICK_PERIOD_MS);
}
}
As stated I have only one thread, and I have observed that the minimum value of free heap memory is reaching very low values like 2444 bytes (a little more than 2KB), whereas the ESP8266 has 64KB of RAM. If I just don’t create this task, the minimum heap value observed is 61KB (after some minutes running).
Why is my free heap reaching values that are so low? It seems there is a problem when freeing the memory after ssl usage for each loop iteration. This compromises the system I’m trying to develop.
Here is the code of my task:
static void https_write_task (void *pvParameters)
{
char writeREQUEST[2048];
char buf[512];
int ret, flags, len;
/////////////////////////////////////////////////////////////////////////////
//HTTP CONTENT
/////////////////////////////////////////////////////////////////////////////
char msg[128];
int msg_len;
static uint16_t number = 1;
char content_length_string[128];
sprintf (msg, "{\"value\":\"%d\"}", number++);
msg_len = strlen(msg);
sprintf (content_length_string, "Content-Length: %d\r\n", msg_len);
strcpy (writeREQUEST, "PUT "WEB_URL" HTTP/1.0\r\n");
strcat (writeREQUEST, "Host: "WEB_SERVER"\r\n");
strcat (writeREQUEST, "User-Agent: esp-idf/1.0 esp32\r\n");
strcat (writeREQUEST, "Content-Type: application/json\r\n");
strcat (writeREQUEST, content_length_string);
strcat (writeREQUEST, "\r\n");
strcat (writeREQUEST, msg);
/////////////////////////////////////////////////////////////////////////////
mbedtls_ssl_context ssl;
mbedtls_net_context server_fd;
mbedtls_ssl_session ssl_session;
while (1)
{
mbedtls_ssl_init(&ssl);
/* Hostname set here should match CN in server certificate */
if((ret = mbedtls_ssl_set_hostname(&ssl, WEB_SERVER)) != 0)
{
ESP_LOGE(TAG, "mbedtls_ssl_set_hostname returned -0x%x", -ret);
abort();
}
if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0)
{
ESP_LOGE(TAG, "mbedtls_ssl_setup returned -0x%x\n\n", -ret);
goto exit;
}
mbedtls_net_init(&server_fd);
//ESP_LOGI(TAG, "Connecting to %s:%s...", WEB_SERVER, WEB_PORT);
if ((ret = mbedtls_net_connect(&server_fd, WEB_SERVER, WEB_PORT, MBEDTLS_NET_PROTO_TCP)) != 0)
{
//ESP_LOGE(TAG, "mbedtls_net_connect returned -%x", -ret);
goto exit;
}
//ESP_LOGI(TAG, "Connected.");
mbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL);
mbedtls_net_set_nonblock(&server_fd);
//ESP_LOGI(TAG, "Performing the SSL/TLS handshake...");
while ((ret = mbedtls_ssl_handshake(&ssl)) != 0)
{
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
{
//ESP_LOGE(TAG, "mbedtls_ssl_handshake returned -0x%x", -ret);
goto exit;
}
vTaskDelay(50/portTICK_PERIOD_MS);
}
//ESP_LOGI(TAG, "Verifying peer X.509 certificate...");
if ((flags = mbedtls_ssl_get_verify_result(&ssl)) != 0)
{
/* In real life, we probably want to close connection if ret != 0 */
//ESP_LOGW(TAG, "Failed to verify peer certificate!");
bzero(buf, sizeof(buf));
mbedtls_x509_crt_verify_info(buf, sizeof(buf), " ! ", flags);
//ESP_LOGW(TAG, "verification info: %s", buf);
}
else
{
//ESP_LOGI(TAG, "Certificate verified.");
}
mbedtls_ssl_get_session(&ssl, &ssl_session);
//ESP_LOGI(TAG, "Cipher suite is %s", mbedtls_ssl_get_ciphersuite(&ssl));
//ESP_LOGI(TAG, "Writing HTTP request...");
size_t written_bytes = 0;
do
{
vTaskDelay(50/portTICK_PERIOD_MS);
ret = mbedtls_ssl_write(&ssl, (const unsigned char *)writeREQUEST + written_bytes, strlen(writeREQUEST) - written_bytes);
if (ret >= 0)
{
//ESP_LOGI(TAG, "%d bytes written", ret);
written_bytes += ret;
}
else if (ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret != MBEDTLS_ERR_SSL_WANT_READ)
{
//ESP_LOGE(TAG, "mbedtls_ssl_write returned -0x%x", -ret);
goto exit;
}
} while(written_bytes < strlen(writeREQUEST));
//ESP_LOGI(TAG, "Reading HTTP response...");
do
{
vTaskDelay(50/portTICK_PERIOD_MS);
len = sizeof(buf) - 1;
bzero(buf, sizeof(buf));
ret = mbedtls_ssl_read(&ssl, (unsigned char *)buf, len);
if(ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE)
continue;
if(ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY)
{
//ESP_LOGI(TAG, "#### PEER CLOSE NOTIFY ####");
ret = 0;
break;
}
if(ret < 0)
{
//ESP_LOGE(TAG, "mbedtls_ssl_read returned -0x%x", -ret);
break;
}
if(ret == 0)
{
//ESP_LOGI(TAG, "connection closed");
break;
}
len = ret;
//ESP_LOGD(TAG, "%d bytes read", len);
/* Print response directly to stdout as it is read */
for(int i = 0; i < len; i++)
{
//putchar(buf[i]);
}
} while(1);
mbedtls_ssl_close_notify(&ssl);
exit:
//mbedtls_ssl_session_reset(&ssl);
mbedtls_ssl_session_free(&ssl_session);
mbedtls_ssl_free(&ssl);
mbedtls_net_free(&server_fd);
//4 seconds delay, the will write again
vTaskDelay(4000 / portTICK_PERIOD_MS);
/////////////////////////////////////////////////////////////////////////////
// UPDATE HTTP CONTENT
/////////////////////////////////////////////////////////////////////////////
sprintf (msg, "{\"value\":\"%d\"}", number++);
msg_len = strlen(msg);
sprintf (content_length_string, "Content-Length: %d\r\n", msg_len);
strcpy (writeREQUEST, "PUT " WEB_URL " HTTP/1.0\r\n");
strcat (writeREQUEST, "Host: "WEB_SERVER"\r\n");
strcat (writeREQUEST, "User-Agent: esp-idf/1.0 esp32\r\n");
strcat (writeREQUEST, "Content-Type: application/json\r\n");
strcat (writeREQUEST, content_length_string);
strcat (writeREQUEST, "\r\n");
strcat (writeREQUEST, msg);
/////////////////////////////////////////////////////////////////////////////
}
}
If needed, here is my setup:
void mbedTlsInit()
{
int ret;
mbedtls_x509_crt_init(&cacert);
mbedtls_ctr_drbg_init(&ctr_drbg);
mbedtls_ssl_config_init(&conf);
mbedtls_entropy_init(&entropy);
if((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0)) != 0)
{
ESP_LOGE(TAG, "mbedtls_ctr_drbg_seed returned %d", ret);
abort();
}
ret = mbedtls_x509_crt_parse(&cacert, server_root_cert_pem_start, server_root_cert_pem_end-server_root_cert_pem_start);
if(ret < 0)
{
ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret);
abort();
}
if((ret = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
{
ESP_LOGE(TAG, "mbedtls_ssl_config_defaults returned %d", ret);
abort();
}
mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
mbedtls_ssl_conf_ca_chain(&conf, &cacert, NULL);
mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);
}
And here is the result of my log, the strings sent via UART every 500ms.
I was not able to put the log directly in this post due to limit of characters, but it can be seen here:
At menuconfig of the example, the maximum fragment lenght for incoming and outgoing messages are both set to 2.5KB.
EDIT
Another test I did was to place a semaphore before the start of the while loop of “https_write_task”, and give the semaphore via UART, so then the loop execute one time completely. This was my results in terms of free heap memory after the N iterations.
before iteration 1: 51.8 (KB)
after iteration 1: 32.8
after iteration 2: 31.3
after iteration 3: 28.2
after iteration 4: 24.6
after iteration 5: 24.6
after iteration 6: 20.9
after iteration 7: 20.9
after iteration 8: 19.7
after iteration 9: 17.2
after iteration 10: 17.2
after iteration 11: 17.2
after iteration 12: 17.2
after iteration 13: 17.2
after iteration 14: 15.2
after iteration 21: 15
after iteration 25: 14.1
after iteration 26: 13.4
after iteration 32: 11.3
after iteration 38: 10.3
after iteration 39: 9.4
after iteration 41: 7.5
after iteration 47: 6
after iteration 61: 5.7
after iteration 65: 4.6
On the menuconfig of mbedTLS component we have these options:
Memory allocation strategies available are:
Changing to “Default alloc mode” gives the same results, minium heap reaching very low values like 2.2KB.
Regards.