diff --git a/Makefile b/Makefile index 1886763a..9639bad0 100644 --- a/Makefile +++ b/Makefile @@ -13,9 +13,8 @@ #recovery: EXTRA_CPPFLAGS+=-DRECOVERY_APPLICATION=1 PROJECT_NAME?=squeezelite -EXTRA_CPPFLAGS+= -Wno-error=maybe-uninitialized \ - -I$(PROJECT_PATH)/main - +EXTRA_CPPFLAGS+= -I$(PROJECT_PATH)/main +#/-Wno-error=maybe-uninitialized include $(IDF_PATH)/make/project.mk # for future gcc version, this could be needed: CPPFLAGS+= -Wno-error=format-overflow -Wno-error=stringop-truncation diff --git a/components/cmd_system/cmd_system.c b/components/cmd_system/cmd_system.c index 02f6e0ad..dd452e41 100644 --- a/components/cmd_system/cmd_system.c +++ b/components/cmd_system/cmd_system.c @@ -28,7 +28,8 @@ #include "platform_esp32.h" #include "config.h" #include "esp_sleep.h" -#include "driver/uart.h" // for the uart driver access +#include "driver/uart.h" +#include "messaging.h" #ifdef CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS #define WITH_TASKS_INFO 1 @@ -130,7 +131,7 @@ esp_err_t guided_boot(esp_partition_subtype_t partition_subtype) if(it == NULL){ ESP_LOGE(TAG,"Unable initialize partition iterator!"); - set_status_message(ERROR, "Reboot failed. Cannot iterate through partitions"); + messaging_post_message(MESSAGING_ERROR,MESSAGING_CLASS_SYSTEM,"Reboot failed. Cannot iterate through partitions"); } else { @@ -144,18 +145,19 @@ esp_err_t guided_boot(esp_partition_subtype_t partition_subtype) if(err!=ESP_OK){ ESP_LOGE(TAG,"Unable to set partition as active for next boot. %s",esp_err_to_name(err)); bFound=false; - set_status_message(ERROR, "Unable to select partition for reboot."); + messaging_post_message(MESSAGING_ERROR,MESSAGING_CLASS_SYSTEM,"Unable to select partition for reboot."); } else{ ESP_LOGW(TAG, "Application partition %s sub type %u is selected for boot", partition->label,partition_subtype); bFound=true; - set_status_message(WARNING, "Rebooting!"); + messaging_post_message(MESSAGING_WARNING,MESSAGING_CLASS_SYSTEM,"Reboot failed. Cannot iterate through partitions"); } } else { ESP_LOGE(TAG,"partition type %u not found! Unable to reboot to recovery.",partition_subtype); - set_status_message(ERROR, "Partition not found."); + messaging_post_message(MESSAGING_ERROR,MESSAGING_CLASS_SYSTEM,"partition type %u not found! Unable to reboot to recovery.",partition_subtype); + } ESP_LOGD(TAG, "Yielding to other processes"); taskYIELD(); diff --git a/components/services/messaging.c b/components/services/messaging.c index 1f4ef6af..f8841baa 100644 --- a/components/services/messaging.c +++ b/components/services/messaging.c @@ -14,6 +14,7 @@ #include "nvs_utilities.h" #include "platform_esp32.h" #include "messaging.h" +#include "trace.h" /************************************ * Globals */ @@ -137,12 +138,12 @@ cJSON * messaging_retrieve_messages(RingbufHandle_t buf_handle){ else { json_message = cJSON_CreateObject(); cJSON_AddStringToObject(json_message, "message", message->message); + vRingbufferReturnItem(buf_handle, (void *)message); cJSON_AddStringToObject(json_message, "type", messaging_get_type_desc(message->type)); cJSON_AddStringToObject(json_message, "class", messaging_get_class_desc(message->msg_class)); cJSON_AddNumberToObject(json_message,"sent_time",message->sent_time); cJSON_AddNumberToObject(json_message,"current_time",esp_timer_get_time() / 1000); cJSON_AddItemToArray(json_messages,json_message); - vRingbufferReturnItem(buf_handle, (void *)message); } } return json_messages; diff --git a/components/squeezelite-ota/squeezelite-ota.c b/components/squeezelite-ota/squeezelite-ota.c index 2cfdac7a..5110baae 100644 --- a/components/squeezelite-ota/squeezelite-ota.c +++ b/components/squeezelite-ota/squeezelite-ota.c @@ -29,8 +29,9 @@ #include "esp_spi_flash.h" #include "sdkconfig.h" #include "messaging.h" - +#include "trace.h" #include "esp_ota_ops.h" + extern const char * get_certificate(); #ifdef CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 @@ -57,16 +58,12 @@ typedef enum { OTA_TYPE_INVALID } ota_type_t; static struct { - char status_text[81]; uint32_t actual_image_len; uint32_t total_image_len; uint32_t remain_image_len; - char * redirected_url; - char * current_url; ota_type_t ota_type; char * bin; bool bOTAStarted; - bool bInitialized; uint8_t lastpct; uint8_t newpct; struct timeval OTA_start; @@ -99,10 +96,22 @@ void sendMessaging(messaging_types type,const char * fmt, ...){ if(str_len>0){ msg_str = malloc(str_len); vsnprintf(msg_str,str_len,fmt,args); + if(type == MESSAGING_WARNING){ + ESP_LOGW(TAG,"%s",msg_str); + } + else if (type == MESSAGING_ERROR){ + ESP_LOGE(TAG,"%s",msg_str); + } + else + ESP_LOGI(TAG,"%s",msg_str); + } + else { + ESP_LOGW(TAG, "Sending empty string message"); } va_end(args); - cJSON_AddStringToObject(msg,"ota_dsc",msg_str); + + cJSON_AddStringToObject(msg,"ota_dsc",str_or_unknown(msg_str)); free(msg_str); cJSON_AddNumberToObject(msg,"ota_pct", ota_get_pct_complete() ); char * json_msg = cJSON_PrintUnformatted(msg); @@ -150,7 +159,7 @@ esp_err_t _http_event_handler(esp_http_client_event_t *evt) case HTTP_EVENT_ON_CONNECTED: ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED"); - if(ota_status.bOTAStarted) sendMessaging(MESSAGING_INFO,"Installing..."); + if(ota_status.bOTAStarted) sendMessaging(MESSAGING_INFO,"Connecting to URL..."); ota_status.total_image_len=0; ota_status.actual_image_len=0; ota_status.lastpct=0; @@ -165,9 +174,7 @@ esp_err_t _http_event_handler(esp_http_client_event_t *evt) case HTTP_EVENT_ON_HEADER: ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s",evt->header_key, evt->header_value); if (strcasecmp(evt->header_key, "location") == 0) { - FREE_RESET(ota_status.redirected_url); - ota_status.redirected_url=strdup(evt->header_value); - ESP_LOGW(TAG,"OTA will redirect to url: %s",ota_status.redirected_url); + ESP_LOGW(TAG,"OTA will redirect to url: %s",evt->header_value); } if (strcasecmp(evt->header_key, "content-length") == 0) { ota_status.total_image_len = atol(evt->header_value); @@ -191,7 +198,6 @@ esp_err_t _http_event_handler(esp_http_client_event_t *evt) esp_err_t init_config(ota_thread_parms_t * p_ota_thread_parms){ memset(&ota_config, 0x00, sizeof(ota_config)); - ota_status.bInitialized = true; sendMessaging(MESSAGING_INFO,"Initializing..."); ota_status.ota_type= OTA_TYPE_INVALID; if(p_ota_thread_parms->url !=NULL && strlen(p_ota_thread_parms->url)>0 ){ @@ -208,14 +214,14 @@ esp_err_t init_config(ota_thread_parms_t * p_ota_thread_parms){ switch (ota_status.ota_type) { case OTA_TYPE_HTTP: - ota_status.current_url= p_ota_thread_parms->url; ota_config.cert_pem =get_certificate(); ota_config.event_handler = _http_event_handler; ota_config.buffer_size = BUFFSIZE; - ota_config.disable_auto_redirect=false; + ota_config.disable_auto_redirect=true; ota_config.skip_cert_common_name_check = false; - ota_config.url = strdup(ota_status.current_url); + ota_config.url = strdup(p_ota_thread_parms->url); ota_config.max_redirection_count = 3; + ota_write_data = heap_caps_malloc(ota_config.buffer_size+1 , MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); //ota_write_data = malloc(ota_config.buffer_size+1); if(ota_write_data== NULL){ @@ -295,14 +301,14 @@ esp_err_t _erase_last_boot_app_partition(esp_partition_t *ota_partition) if(i%2) { sendMessaging(MESSAGING_INFO,"Erasing flash (%u/%u)",i,num_passes); } - vTaskDelay(200/ portTICK_PERIOD_MS); // wait here for a short amount of time. This will help with reducing WDT errors + //vTaskDelay(200/ portTICK_PERIOD_MS); // wait here for a short amount of time. This will help with reducing WDT errors } if(remain_size>0){ err=esp_partition_erase_range(ota_partition, ota_partition->size-remain_size, remain_size); if(err!=ESP_OK) return err; } sendMessaging(MESSAGING_INFO,"Erasing flash complete."); - taskYIELD(); + return ESP_OK; } @@ -321,28 +327,32 @@ static bool process_again(int status_code) static esp_err_t _http_handle_response_code(esp_http_client_handle_t http_client, int status_code) { esp_err_t err=ESP_OK; - if (status_code == HttpStatus_MovedPermanently || status_code == HttpStatus_Found) { + if (status_code == HttpStatus_MovedPermanently || status_code == HttpStatus_Found ) { ESP_LOGW(TAG, "Handling HTTP redirection. "); err = esp_http_client_set_redirection(http_client); if (err != ESP_OK) { ESP_LOGE(TAG, "URL redirection Failed. %s", esp_err_to_name(err)); return err; } + ESP_LOGW(TAG, "Done Handling HTTP redirection. "); + } else if (status_code == HttpStatus_Unauthorized) { ESP_LOGW(TAG, "Handling Unauthorized. "); esp_http_client_add_auth(http_client); } ESP_LOGD(TAG, "Redirection done, checking if we need to read the data. "); if (process_again(status_code)) { - char * local_buff = heap_caps_malloc(ota_config.buffer_size+1, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + ESP_LOGD(TAG, "We have to read some more data. Allocating buffer size %u",ota_config.buffer_size+1); + char local_buff_var[501]={}; + //char * local_buff = heap_caps_malloc(ota_config.buffer_size+1, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); //char * local_buff = malloc(ota_config.buffer_size+1); - if(local_buff==NULL){ - ESP_LOGE(TAG,"Failed to allocate internal memory buffer for http processing"); - return ESP_ERR_NO_MEM; - } +// if(local_buff==NULL){ +// ESP_LOGE(TAG,"Failed to allocate internal memory buffer for http processing"); +// return ESP_ERR_NO_MEM; +// } while (1) { - ESP_LOGD(TAG, "Reading data chunk. "); - int data_read = esp_http_client_read(http_client, local_buff, ota_config.buffer_size); + ESP_LOGD(TAG, "Buffer successfully allocated. Reading data chunk. "); + int data_read = esp_http_client_read(http_client, local_buff_var, sizeof(local_buff_var)); if (data_read < 0) { ESP_LOGE(TAG, "Error: SSL data read error"); err= ESP_FAIL; @@ -353,7 +363,7 @@ static esp_err_t _http_handle_response_code(esp_http_client_handle_t http_client break; } } - FREE_RESET(local_buff); + //FREE_RESET(local_buff); } return err; @@ -379,8 +389,6 @@ static esp_err_t _http_connect(esp_http_client_handle_t http_client) status_code = esp_http_client_get_status_code(http_client); ESP_LOGD(TAG, "HTTP status code was %d",status_code); - - err = _http_handle_response_code(http_client, status_code); if (err != ESP_OK) { return err; @@ -395,11 +403,7 @@ void ota_task_cleanup(const char * message, ...){ va_start(args, message); sendMessaging(MESSAGING_ERROR,message, args); va_end(args); - ESP_LOGE(TAG, "%s",ota_status.status_text); } - - FREE_RESET(ota_status.redirected_url); - FREE_RESET(ota_status.current_url); FREE_RESET(ota_status.bin); FREE_RESET(ota_write_data); if(ota_http_client!=NULL) { @@ -603,7 +607,7 @@ esp_err_t process_recovery_ota(const char * bin_url, char * bin_buffer, uint32_t if(bin_url){ ota_thread_parms.url =strdup(bin_url); - ESP_LOGI(TAG, "Starting ota on core %u for : %s", OTA_CORE,bin_url); + ESP_LOGI(TAG, "Starting ota on core %u for : %s", OTA_CORE,ota_thread_parms.url); } else { ota_thread_parms.bin = bin_buffer; @@ -614,8 +618,7 @@ esp_err_t process_recovery_ota(const char * bin_url, char * bin_buffer, uint32_t char * num_buffer=config_alloc_get(NVS_TYPE_STR, "ota_stack"); if(num_buffer!=NULL) { stack_size= atol(num_buffer); - free(num_buffer); - num_buffer=NULL; + FREE_AND_NULL(num_buffer); } else { ESP_LOGW(TAG,"OTA stack size config not found"); @@ -624,8 +627,7 @@ esp_err_t process_recovery_ota(const char * bin_url, char * bin_buffer, uint32_t num_buffer=config_alloc_get(NVS_TYPE_STR, "ota_prio"); if(num_buffer!=NULL) { task_priority= atol(num_buffer); - free(num_buffer); - num_buffer=NULL; + FREE_AND_NULL(num_buffer); } else { ESP_LOGW(TAG,"OTA task priority not found"); diff --git a/components/telnet/telnet.c b/components/telnet/telnet.c index 3b4f900e..cd9bfadb 100644 --- a/components/telnet/telnet.c +++ b/components/telnet/telnet.c @@ -38,7 +38,7 @@ #include "config.h" #include "nvs_utilities.h" #include "platform_esp32.h" - +#include "trace.h" /************************************ * Globals @@ -148,12 +148,14 @@ static void telnet_task(void *data) { int rc = bind(serverSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)); if (rc < 0) { ESP_LOGE(tag, "bind: %d (%s)", errno, strerror(errno)); + close(serverSocket); return; } rc = listen(serverSocket, 5); if (rc < 0) { ESP_LOGE(tag, "listen: %d (%s)", errno, strerror(errno)); + close(serverSocket); return; } @@ -171,6 +173,7 @@ static void telnet_task(void *data) { ESP_LOGD(tag, "Telnet connection terminated"); } } + close(serverSocket); vTaskDelete(NULL); } diff --git a/components/tools/trace.h b/components/tools/trace.h index ae24c70a..82c20434 100644 --- a/components/tools/trace.h +++ b/components/tools/trace.h @@ -28,5 +28,20 @@ #define STR(macro) QUOTE(macro) #endif #define ESP_LOG_DEBUG_EVENT(tag,e) ESP_LOGD(tag,"evt: " e) +#ifndef STR_OR_ALT +#define STR_OR_ALT(str,alt) (str?str:alt) +#endif +extern const char unknown_string_placeholder[]; +extern const char * str_or_unknown(const char * str); + +#ifndef FREE_AND_NULL +#define FREE_AND_NULL(x) if(x) { free(x); x=NULL; } +#endif + +#ifndef CASE_TO_STR +#define CASE_TO_STR(x) case x: return STR(x); break; +#endif +#define START_FREE_MEM_CHECK(a) size_t a=heap_caps_get_free_size(MALLOC_CAP_INTERNAL); +#define CHECK_RESET_FREE_MEM_CHECK(a,b) ESP_LOGV(__FUNCTION__ ,b "Mem used: %i",a-heap_caps_get_free_size(MALLOC_CAP_INTERNAL)); a=heap_caps_get_free_size(MALLOC_CAP_INTERNAL) diff --git a/components/wifi-manager/component.mk b/components/wifi-manager/component.mk index a11cccff..e3d9cd0d 100644 --- a/components/wifi-manager/component.mk +++ b/components/wifi-manager/component.mk @@ -8,6 +8,6 @@ # COMPONENT_EMBED_FILES := style.css code.js index.html bootstrap.min.css.gz jquery.min.js.gz popper.min.js.gz bootstrap.min.js.gz COMPONENT_ADD_INCLUDEDIRS := . -CFLAGS += -D LOG_LOCAL_LEVEL=ESP_LOG_INFO +CFLAGS += -D LOG_LOCAL_LEVEL=ESP_LOG_DEBUG diff --git a/components/wifi-manager/http_server_handlers.c b/components/wifi-manager/http_server_handlers.c index 6599f996..5e6f7b25 100644 --- a/components/wifi-manager/http_server_handlers.c +++ b/components/wifi-manager/http_server_handlers.c @@ -51,6 +51,7 @@ function to process requests, decode URLs, serve files, etc. etc. #include "lwip/ip_addr.h" #include "messaging.h" #include "platform_esp32.h" +#include "trace.h" #define HTTP_STACK_SIZE (5*1024) const char str_na[]="N/A"; @@ -148,6 +149,7 @@ char * http_alloc_get_socket_address(httpd_req_t *req, u8_t local, in_port_t * p int s = httpd_req_to_sockfd(req); if(s == -1) { + free(ipstr); return strdup("httpd_req_to_sockfd error"); } ESP_LOGV_LOC(TAG,"httpd socket descriptor: %u", s); @@ -239,24 +241,31 @@ bool is_captive_portal_host_name(httpd_req_t *req){ /* Custom function to free context */ void free_ctx_func(void *ctx) { + START_FREE_MEM_CHECK(ff); session_context_t * context = (session_context_t *)ctx; if(context){ + ESP_LOGD(TAG, "Freeing up socket context"); FREE_AND_NULL(context->auth_token); FREE_AND_NULL(context->sess_ip_address); free(context); + CHECK_RESET_FREE_MEM_CHECK(ff,"free_ctx"); } } session_context_t* get_session_context(httpd_req_t *req){ + START_FREE_MEM_CHECK(ff); if (! req->sess_ctx) { + ESP_LOGD(TAG,"New connection context. Allocating session buffer"); req->sess_ctx = malloc(sizeof(session_context_t)); memset(req->sess_ctx,0x00,sizeof(session_context_t)); req->free_ctx = free_ctx_func; // get the remote IP address only once per session } session_context_t *ctx_data = (session_context_t*)req->sess_ctx; + FREE_AND_NULL(ctx_data->sess_ip_address); ctx_data->sess_ip_address = http_alloc_get_socket_address(req, 0, &ctx_data->port); ESP_LOGD_LOC(TAG, "serving %s to peer %s port %u", req->uri, ctx_data->sess_ip_address , ctx_data->port); + CHECK_RESET_FREE_MEM_CHECK(ff,"get sess context"); return (session_context_t *)req->sess_ctx; } @@ -1043,25 +1052,34 @@ esp_err_t redirect_ev_handler(httpd_req_t *req){ esp_err_t messages_get_handler(httpd_req_t *req){ ESP_LOGD_LOC(TAG, "serving [%s]", req->uri); + START_FREE_MEM_CHECK(before); + START_FREE_MEM_CHECK(all); if(!is_user_authenticated(req)){ // todo: redirect to login page // return ESP_OK; } + CHECK_RESET_FREE_MEM_CHECK(before, "after user auth"); esp_err_t err = set_content_type_from_req(req); if(err != ESP_OK){ return err; } - + CHECK_RESET_FREE_MEM_CHECK(before, "after set_content_type"); cJSON * json_messages= messaging_retrieve_messages(messaging); + CHECK_RESET_FREE_MEM_CHECK(before, "after receiving messages"); if(json_messages!=NULL){ char * json_text= cJSON_Print(json_messages); + CHECK_RESET_FREE_MEM_CHECK(before, "after json print"); httpd_resp_send(req, (const char *)json_text, strlen(json_text)); - cJSON_free(json_messages); + CHECK_RESET_FREE_MEM_CHECK(before, "after http send"); free(json_text); + CHECK_RESET_FREE_MEM_CHECK(before, "after free json message"); + cJSON_free(json_messages); + CHECK_RESET_FREE_MEM_CHECK(before, "after free json"); } else { httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR , "Unable to retrieve messages"); } + CHECK_RESET_FREE_MEM_CHECK(all, "before returning"); return ESP_OK; } diff --git a/components/wifi-manager/wifi_manager.c b/components/wifi-manager/wifi_manager.c index 084ff142..667d01d6 100644 --- a/components/wifi-manager/wifi_manager.c +++ b/components/wifi-manager/wifi_manager.c @@ -60,6 +60,7 @@ Contains the freeRTOS task and all necessary support #include "config.h" #include "trace.h" #include "cmd_system.h" +#include "messaging.h" #include "http_server_handlers.h" #include "monitor.h" @@ -850,20 +851,6 @@ void wifi_manager_connect_async(){ wifi_manager_send_message(ORDER_CONNECT_STA, (void*)CONNECTION_REQUEST_USER); } -void set_status_message(message_severity_t severity, const char * message){ - if(ip_info_cjson==NULL){ - ip_info_cjson = wifi_manager_get_new_json(&ip_info_cjson); - } - if(ip_info_cjson==NULL){ - ESP_LOGE(TAG, "Error setting status message. Unable to allocate cJSON."); - return; - } - cJSON * item=cJSON_GetObjectItem(ip_info_cjson, "message"); - item = wifi_manager_get_new_json(&item); - cJSON_AddItemToObject(item, "severity", cJSON_CreateString(severity==INFO?"INFO":severity==WARNING?"WARNING":severity==ERROR?"ERROR":"" )); - cJSON_AddItemToObject(item, "text", cJSON_CreateString(message)); -} - char* wifi_manager_alloc_get_ip_info_json(){ return cJSON_PrintUnformatted(ip_info_cjson); @@ -1142,6 +1129,7 @@ void wifi_manager( void * pvParameters ){ if(esp_wifi_scan_start(&scan_config, false)!=ESP_OK){ ESP_LOGW(TAG, "Unable to start scan; wifi is trying to connect"); // set_status_message(WARNING, "Wifi Connecting. Cannot start scan."); + messaging_post_message(MESSAGING_WARNING,MESSAGING_CLASS_SYSTEM,"Wifi connecting. Cannot start scan."); } else { xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_SCAN_BIT); diff --git a/components/wifi-manager/wifi_manager_http_server.c b/components/wifi-manager/wifi_manager_http_server.c index 2e98a7b9..373cad3f 100644 --- a/components/wifi-manager/wifi_manager_http_server.c +++ b/components/wifi-manager/wifi_manager_http_server.c @@ -124,7 +124,7 @@ esp_err_t http_server_start() strlcpy(rest_context->base_path, "/res/", sizeof(rest_context->base_path)); httpd_config_t config = HTTPD_DEFAULT_CONFIG(); - config.max_uri_handlers = 20; + config.max_uri_handlers = 25; config.max_open_sockets = 5; config.uri_match_fn = httpd_uri_match_wildcard; //todo: use the endpoint below to configure session token? diff --git a/main/platform_esp32.h b/main/platform_esp32.h index 545086a0..3443e069 100644 --- a/main/platform_esp32.h +++ b/main/platform_esp32.h @@ -31,28 +31,4 @@ extern bool wait_for_wifi(); extern void console_start(); extern pthread_cond_t wifi_connect_suspend_cond; extern pthread_t wifi_connect_suspend_mutex; -typedef enum { - INFO, - WARNING, - ERROR -} message_severity_t; -extern void set_status_message(message_severity_t severity, const char * message); -#ifndef STR_OR_ALT -#define STR_OR_ALT(str,alt) (str?str:alt) -#endif -extern const char unknown_string_placeholder[]; -extern const char * str_or_unknown(const char * str); - -#ifndef FREE_AND_NULL -#define FREE_AND_NULL(x) if(x) { free(x); x=NULL; } -#endif -#ifndef QUOTE -#define QUOTE(name) #name -#endif -#ifndef STR -#define STR(macro) QUOTE(macro) -#endif -#ifndef CASE_TO_STR -#define CASE_TO_STR(x) case x: return STR(x); break; -#endif