diff --git a/components/squeezelite-ota/squeezelite-ota.c b/components/squeezelite-ota/squeezelite-ota.c index 10d6612f..b6949c94 100644 --- a/components/squeezelite-ota/squeezelite-ota.c +++ b/components/squeezelite-ota/squeezelite-ota.c @@ -32,9 +32,13 @@ static struct { char status_text[31]; uint32_t ota_actual_len; uint32_t ota_total_len; - char * actual_url; - bool bOTA_started; + char * redirected_url; + char * current_url; + bool bRedirectFound; + bool bOTAStarted; } ota_status; +uint8_t lastpct=0; +uint8_t newpct=0; static esp_http_client_config_t config; static esp_http_client_config_t ota_config; @@ -45,7 +49,7 @@ const char * ota_get_status(){ } uint8_t ota_get_pct_complete(){ return ota_status.ota_total_len==0?0: - (uint8_t)((uint32_t)ota_status.ota_actual_len/(uint32_t)ota_status.ota_total_len*100); + (uint8_t)((float)ota_status.ota_actual_len/(float)ota_status.ota_total_len*100.0f); } static void __attribute__((noreturn)) task_fatal_error(void) @@ -57,7 +61,7 @@ static void __attribute__((noreturn)) task_fatal_error(void) ; } } - +#define FREE_RESET(p) if(p!=NULL) { free(p); p=NULL; } esp_err_t _http_event_handler(esp_http_client_event_t *evt) { // -------------- @@ -82,35 +86,27 @@ esp_err_t _http_event_handler(esp_http_client_event_t *evt) break; case HTTP_EVENT_ON_CONNECTED: ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED"); - if(!ota_status.bOTA_started){ - ESP_LOGW(TAG, "Resetting the OTA stats"); - ota_status.ota_total_len=0; - ota_status.ota_actual_len=0; - if(ota_status.actual_url!=NULL){ - free(ota_status.actual_url); - ota_status.actual_url=NULL; - } - } - break; - case HTTP_EVENT_HEADER_SENT: - ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT"); - /// strncpy(ota_status,"HTTP_EVENT_HEADER_SENT",sizeof(ota_status)-1); - break; - case HTTP_EVENT_ON_HEADER: - ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, status_code=%d, key=%s, value=%s",esp_http_client_get_status_code(evt->client),evt->header_key, evt->header_value); - ESP_LOGD(TAG,"Heap internal:%zu (min:%zu) external:%zu (min:%zu)\n", + if(ota_status.bOTAStarted) snprintf(ota_status.status_text,sizeof(ota_status.status_text)-1,"Installing..."); + ota_status.ota_total_len=0; + ota_status.ota_actual_len=0; + lastpct=0; + newpct=0; + ESP_LOGD(TAG,"Heap internal:%zu (min:%zu) external:%zu (min:%zu)\n", heap_caps_get_free_size(MALLOC_CAP_INTERNAL), heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL), heap_caps_get_free_size(MALLOC_CAP_SPIRAM), heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM)); + break; + case HTTP_EVENT_HEADER_SENT: + ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT"); + break; + case HTTP_EVENT_ON_HEADER: + ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, status_code=%d, key=%s, value=%s",esp_http_client_get_status_code(evt->client),evt->header_key, evt->header_value); if (strcasecmp(evt->header_key, "location") == 0) { - if(ota_status.actual_url!=NULL) { - free(ota_status.actual_url); - ota_status.actual_url = NULL; - } - ota_status.actual_url=strdup(evt->header_value); - ESP_LOGW(TAG,"OTA will redirect to url: %s",ota_status.actual_url); - ota_status.bOTA_started = true; + 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); + ota_status.bRedirectFound= true; } if (strcasecmp(evt->header_key, "content-length") == 0) { ota_status.ota_total_len = atol(evt->header_value); @@ -118,20 +114,17 @@ esp_err_t _http_event_handler(esp_http_client_event_t *evt) } break; case HTTP_EVENT_ON_DATA: - if(!ota_status.bOTA_started) ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, status_code=%d, len=%d",esp_http_client_get_status_code(evt->client), evt->data_len); - ESP_LOGD(TAG,"Heap internal:%zu (min:%zu) external:%zu (min:%zu)\n", - heap_caps_get_free_size(MALLOC_CAP_INTERNAL), - heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL), - heap_caps_get_free_size(MALLOC_CAP_SPIRAM), - heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM)); - if(esp_http_client_get_status_code(evt->client) == 302){ - // This is an indication of a redirect. Let's follow it - return ESP_OK; - } - if(esp_http_client_get_status_code(evt->client) == 200 ){ - if(!ota_status.bOTA_started) return ESP_OK; + if(!ota_status.bOTAStarted) { + ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, status_code=%d, len=%d",esp_http_client_get_status_code(evt->client), evt->data_len); + } + else if(ota_status.bOTAStarted && esp_http_client_get_status_code(evt->client) == 200 ){ ota_status.ota_actual_len+=evt->data_len; - ESP_LOGD(TAG,"Receiving OTA data chunk len: %d, %d of %d (%d pct)", evt->data_len, ota_status.ota_actual_len, ota_status.ota_total_len, ota_get_pct_complete()); + if(ota_get_pct_complete()%5 == 0) newpct = ota_get_pct_complete(); + if(lastpct!=newpct ) + { + lastpct=newpct; + ESP_LOGD(TAG,"Receiving OTA data chunk len: %d, %d of %d (%d pct)", evt->data_len, ota_status.ota_actual_len, ota_status.ota_total_len, newpct); + } } break; case HTTP_EVENT_ON_FINISH: @@ -168,62 +161,60 @@ static void check_http_redirect(void) ESP_LOGD(TAG, "fetching headers"); esp_http_client_fetch_headers(client); if (err == ESP_OK) { - ESP_LOGI(TAG, "redirect check returned success"); + ESP_LOGI(TAG, "redirect check retrieved headers"); } else { ESP_LOGE(TAG, "redirect check returned %s", esp_err_to_name(err)); } } esp_err_t init_config(esp_http_client_config_t * conf, const char * url){ - memset(&ota_status, 0x00, sizeof(ota_status)); - if(url==NULL || strlen(url)==0){ - ESP_LOGE(TAG,"HTTP OTA called without a url"); - return ESP_ERR_INVALID_ARG; - } memset(conf, 0x00, sizeof(esp_http_client_config_t)); - ota_status.actual_url= strdup(url); - ota_status.bOTA_started=false; conf->cert_pem = (char *)server_cert_pem_start; conf->event_handler = _http_event_handler; - conf->buffer_size = 1024*4; + conf->buffer_size = 1024*2; conf->disable_auto_redirect=true; conf->skip_cert_common_name_check = false; - conf->url = strdup(ota_status.actual_url); + conf->url = strdup(url); conf->max_redirection_count = 0; return ESP_OK; } void ota_task(void *pvParameter) { + char * passedURL=(char *)pvParameter; + memset(&ota_status, 0x00, sizeof(ota_status)); + ESP_LOGD(TAG, "HTTP ota Thread started"); - - if(init_config(&config,(char *)pvParameter)!=ESP_OK){ - if(pvParameter!=NULL) free(pvParameter); + snprintf(ota_status.status_text,sizeof(ota_status.status_text)-1,"Initializing..."); + ota_status.bRedirectFound=false; + if(passedURL==NULL || strlen(passedURL)==0){ + ESP_LOGE(TAG,"HTTP OTA called without a url"); vTaskDelete(NULL); - return; + return ; } - free(pvParameter); + ota_status.current_url= strdup(passedURL); + init_config(&config,ota_status.current_url); + FREE_RESET(pvParameter); + snprintf(ota_status.status_text,sizeof(ota_status.status_text)-1,"Checking for redirect..."); check_http_redirect(); - if(!ota_status.bOTA_started || ota_status.actual_url == NULL){ + if(ota_status.bRedirectFound && ota_status.redirected_url== NULL){ // OTA Failed miserably. Errors would have been logged somewhere - ESP_LOGE(TAG,"Redirect check failed. Bailing out"); + ESP_LOGE(TAG,"Redirect check failed to identify target URL. Bailing out"); vTaskDelete(NULL); } ESP_LOGD(TAG,"Calling esp_https_ota"); - if(init_config(&ota_config,ota_status.actual_url)!=ESP_OK){ - if(pvParameter!=NULL) free(pvParameter); - vTaskDelete(NULL); - return; - } - free(ota_status.actual_url); - ota_status.actual_url=NULL; - + init_config(&ota_config,ota_status.bRedirectFound?ota_status.redirected_url:ota_status.current_url); + ota_status.bOTAStarted = true; + snprintf(ota_status.status_text,sizeof(ota_status.status_text)-1,"Starting OTA..."); esp_err_t err = esp_https_ota(&config); if (err == ESP_OK) { esp_restart(); } else { ESP_LOGE(TAG, "Firmware upgrade failed with error : %s", esp_err_to_name(err)); } + FREE_RESET(ota_status.current_url); + FREE_RESET(ota_status.redirected_url); + vTaskDelete(NULL); } @@ -264,7 +255,7 @@ void start_ota(const char * bin_url) ESP_LOGI(TAG, "Starting ota: %s", urlPtr); - ret=xTaskCreate(&ota_task, "ota_task", 1024*8,(void *) urlPtr, 3, NULL); + ret=xTaskCreate(&ota_task, "ota_task", 1024*10,(void *) urlPtr, 3, NULL); if (ret != pdPASS) { ESP_LOGI(TAG, "create thread %s failed", "ota_task"); } diff --git a/components/wifi-manager/http_server.c b/components/wifi-manager/http_server.c index 03f77f30..f9f49fee 100644 --- a/components/wifi-manager/http_server.c +++ b/components/wifi-manager/http_server.c @@ -33,6 +33,7 @@ function to process requests, decode URLs, serve files, etc. etc. #include "http_server.h" #include "cmd_system.h" + #define NVS_PARTITION_NAME "nvs" /* @brief tag used for ESP serial console messages */ @@ -41,7 +42,8 @@ static const char json_start[] = "{ \"recovery\": %u, \"autoexec\": %u, \"list\" static const char json_end[] = "]}"; static const char template[] = "{ \"%s\": \"%s\" }"; static const char array_separator[]=","; - +static char *s = "\""; +static char *r = "\\\""; /* @brief task handle for the http server */ static TaskHandle_t task_http_server = NULL; extern char current_namespace[]; @@ -69,13 +71,10 @@ extern const uint8_t index_html_end[] asm("_binary_index_html_end"); /* const http headers stored in ROM */ +const static char http_hdr_template[] = "HTTP/1.1 200 OK\nContent-type: %s\nAccept-Ranges: bytes\nContent-Length: %d\nContent-Encoding: %s\n\n"; const static char http_html_hdr[] = "HTTP/1.1 200 OK\nContent-type: text/html\n\n"; const static char http_css_hdr[] = "HTTP/1.1 200 OK\nContent-type: text/css\nCache-Control: public, max-age=31536000\n\n"; const static char http_js_hdr[] = "HTTP/1.1 200 OK\nContent-type: text/javascript\n\n"; -const static char http_jquery_gz_hdr[] = "HTTP/1.1 200 OK\nContent-type: text/javascript\nAccept-Ranges: bytes\nContent-Length: 30604\nContent-Encoding: gzip\n\n"; -const static char http_popper_gz_hdr[] = "HTTP/1.1 200 OK\nContent-type: text/javascript\nAccept-Ranges: bytes\nContent-Length: 7487\nContent-Encoding: gzip\n\n"; -const static char http_bootstrap_js_gz_hdr[] = "HTTP/1.1 200 OK\nContent-type: text/javascript\nAccept-Ranges: bytes\nContent-Length: 15412\nContent-Encoding: gzip\n\n"; -const static char http_bootstrap_css_gz_hdr[] = "HTTP/1.1 200 OK\nContent-type: text/css\nAccept-Ranges: bytes\nContent-Length: 25925\nContent-Encoding: gzip\n\n"; const static char http_400_hdr[] = "HTTP/1.1 400 Bad Request\nContent-Length: 0\n\n"; const static char http_404_hdr[] = "HTTP/1.1 404 Not Found\nContent-Length: 0\n\n"; const static char http_503_hdr[] = "HTTP/1.1 503 Service Unavailable\nContent-Length: 0\n\n"; @@ -85,9 +84,12 @@ const static char http_redirect_hdr_end[] = "/\n\n"; + + void http_server_start(){ + if(task_http_server == NULL){ - xTaskCreate(&http_server, "http_server", 1024*3, NULL, WIFI_MANAGER_TASK_PRIORITY-1, &task_http_server); + xTaskCreate(&http_server, "http_server", 1024*5, NULL, WIFI_MANAGER_TASK_PRIORITY-1, &task_http_server); } } @@ -136,7 +138,7 @@ char* http_server_get_header(char *request, char *header_name, int *len) { } return NULL; } -char* http_server_search_header(char *request, char *header_name, int *len, char * parm_name, int parm_name_max_len, char ** next_position, char * bufEnd) { +char* http_server_search_header(char *request, char *header_name, int *len, char ** parm_name, char ** next_position, char * bufEnd) { *len = 0; char *ret = NULL; char *ptr = NULL; @@ -159,8 +161,14 @@ char* http_server_search_header(char *request, char *header_name, int *len, char currentLength=(int)(ptr-ret); ESP_LOGD(TAG, "Found parameter name end, length : %d", currentLength); // save the parameter name: the string between header name and ":" - strncpy(parm_name,ret,(currentLength>parm_name_max_len?parm_name_max_len:currentLength)); - ESP_LOGD(TAG, "Found parameter name : %s ", parm_name); + *parm_name=malloc(currentLength+1); + if(*parm_name==NULL){ + ESP_LOGE(TAG, "Unable to allocate memory for new header name"); + return NULL; + } + memset(*parm_name, 0x00,currentLength+1); + strncpy(*parm_name,ret,currentLength); + ESP_LOGD(TAG, "Found parameter name : %s ", *parm_name); ptr++; while (*ptr == ' ' && ptr1) { @@ -314,27 +332,25 @@ void http_server_netconn_serve(struct netconn *conn) { autoexec_value = wifi_manager_alloc_get_config(info.key, &l); strreplace(autoexec_value, s, r); ESP_LOGI(TAG,"Namespace %s, key=%s, value=%s", info.namespace_name, info.key,autoexec_value ); - snprintf(buff, locbuflen-1, template, info.key, autoexec_value); - netconn_write(conn, buff, strlen(buff), NETCONN_NOCOPY); - ESP_LOGD(TAG,"Freeing memory for command %s name", autoexec_name); + snprintf(config_buffer, locbuflen-1, template, info.key, autoexec_value); + netconn_write(conn, config_buffer, strlen(config_buffer), NETCONN_NOCOPY); + ESP_LOGD(TAG,"Freeing memory for command [%s] value [%s]", info.key, autoexec_value); free(autoexec_value ); i++; } + it = nvs_entry_next(it); } - free(buff); - + free(config_buffer); netconn_write(conn, json_end, strlen(json_end), NETCONN_NOCOPY); - ESP_LOGD(TAG,"%s", json_end); } } else if(strstr(line, "POST /config.json ")){ ESP_LOGI(TAG,"Serving POST config.json"); - int i=1; int lenA=0; char * last_parm=save_ptr; char * next_parm=save_ptr; - char last_parm_name[41]={0}; + char * last_parm_name=NULL; uint8_t autoexec_flag=0; bool bErrorFound=false; bool bOTA=false; @@ -343,9 +359,8 @@ void http_server_netconn_serve(struct netconn *conn) { while(last_parm!=NULL){ // Search will return ESP_LOGI(TAG, "Getting parameters from X-Custom headers"); - memset(last_parm_name,0x00,sizeof(last_parm_name)); - last_parm = http_server_search_header(next_parm, "X-Custom-", &lenA, last_parm_name, sizeof(last_parm_name)-1,&next_parm,buf+buflen); - if(last_parm!=NULL){ + last_parm = http_server_search_header(next_parm, "X-Custom-", &lenA, &last_parm_name,&next_parm,buf+buflen); + if(last_parm!=NULL && last_parm_name!=NULL){ ESP_LOGI(TAG, "http_server_netconn_serve: config.json/ call, found parameter %s=%s, length %i", last_parm_name, last_parm, lenA); if(strcmp(last_parm_name, "fwurl")==0){ // we're getting a request to do an OTA from that URL @@ -364,14 +379,16 @@ void http_server_netconn_serve(struct netconn *conn) { } else { - char szErrorPrefix[]="{ status: \"value length is too long for "; - char szErrorSuffix[]="{ status: \"value length is too long for "; - netconn_write(conn, szErrorPrefix, strlen(szErrorPrefix), NETCONN_NOCOPY); ESP_LOGE(TAG,"length is too long : %s = %s", last_parm_name, last_parm); last_parm=NULL; + bErrorFound=true; } } } + if(last_parm_name!=NULL) { + free(last_parm_name); + last_parm_name=NULL; + } } if(bErrorFound){ netconn_write(conn, http_400_hdr, sizeof(http_400_hdr) - 1, NETCONN_NOCOPY); //400 invalid request