Updater: Better flow for performing updates; added MD5 validation.

This commit is contained in:
Fabian Schlenz 2019-11-28 06:48:16 +01:00
parent 07b1ea3a5c
commit b805d1b183
4 changed files with 58 additions and 69 deletions

View File

@ -1,8 +1,10 @@
#pragma once #pragma once
#include "http_client_wrapper.h"
class Updater { class Updater {
public: public:
static void run(); static void run(uint16_t spiffs_version = 0);
static bool do_update(int cmd, String url); static bool do_update(int cmd, String url, String expected_md5);
static void update_spiffs(); static bool read_line(String* dst, HTTPClientWrapper* http, String expected_key);
}; };

View File

@ -136,9 +136,7 @@ void setup() {
} }
#ifdef OTA_UPDATE_URL #ifdef OTA_UPDATE_URL
if (spiffs_version < OTA_VERSION) { Updater::run(spiffs_version);
Updater::run();
}
#endif #endif
INFO("Initialization completed.\n"); INFO("Initialization completed.\n");

View File

@ -4,7 +4,8 @@
#include "updater.h" #include "updater.h"
#include "http_client_wrapper.h" #include "http_client_wrapper.h"
void Updater::run() { void Updater::run(uint16_t spiffs_version) {
bool update_image = true;
DEBUG("Updater is running...\n"); DEBUG("Updater is running...\n");
HTTPClientWrapper* http = new HTTPClientWrapper(); HTTPClientWrapper* http = new HTTPClientWrapper();
DEBUG("Requesting update info...\n"); DEBUG("Requesting update info...\n");
@ -13,47 +14,74 @@ void Updater::run() {
ERROR("Updater failed requesting %s.\n", OTA_UPDATE_URL); ERROR("Updater failed requesting %s.\n", OTA_UPDATE_URL);
return; return;
} }
String line = http->readUntil("\n");
if (!line.startsWith("VERSION=")) { String line_str = "";
ERROR("Expected first line to be VERSION.\n"); if (!read_line(&line_str, http, "VERSION")) {
return; return;
} }
uint16_t version = line.substring(8).toInt(); uint16_t version = line_str.toInt();
if (version==0) { if (version==0) {
ERROR("Could not parse version number.\n"); ERROR("Could not parse version number.\n");
return; return;
} }
DEBUG("Found version %d. My version is %d.\n", version, OTA_VERSION); DEBUG("Found version %d. My version is %d.\n", version, OTA_VERSION);
if (version <= OTA_VERSION) { if (version <= OTA_VERSION) {
if (spiffs_version>0 && spiffs_version < version) {
update_image = false;
DEBUG("SPIFFS needs an update. Continuing.\n");
} else {
return; return;
} }
line = http->readUntil("\n"); }
if (!line.startsWith("IMAGE_PATH=")) {
ERROR("Expected second line to be IMAGE_PATH.\n"); String image_path = "";
if (!read_line(&image_path, http, "IMAGE_PATH")) {
return; return;
} }
String image_path = line.substring(11);
image_path.trim(); String image_md5 = "";
line = http->readUntil("\n"); if (!read_line(&image_md5, http, "IMAGE_MD5")) {
if (!line.startsWith("SPIFFS_PATH=")) { return;
ERROR("Expected third line to be SPIFFS_PATH.\n"); }
String spiffs_path = "";
if (!read_line(&spiffs_path, http, "SPIFFS_PATH")) {
return;
}
String spiffs_md5 = "";
if (!read_line(&spiffs_md5, http, "SPIFFS_MD5")) {
return; return;
} }
String spiffs_path = line.substring(12);
spiffs_path.trim();
http->close(); http->close();
delete http; delete http;
result = do_update(U_FLASH, image_path); result = true;
if (update_image) {
result = do_update(U_FLASH, image_path, image_md5);
}
if (result) { if (result) {
do_update(U_SPIFFS, spiffs_path); do_update(U_SPIFFS, spiffs_path, spiffs_md5);
} }
DEBUG("Done. Rebooting...\n"); DEBUG("Done. Rebooting...\n");
ESP.restart(); ESP.restart();
} }
bool Updater::do_update(int command, String url) { bool Updater::read_line(String* dst, HTTPClientWrapper* http, String expected_key) {
expected_key += "=";
String line = http->readUntil("\n");
if (!line.startsWith(expected_key)) {
ERROR("Expected line start with '%s', but it started with '%s'.\n", expected_key.c_str(), line.c_str());
return false;
}
line = line.substring(expected_key.length());
line.trim();
dst->concat(line);
return true;
}
bool Updater::do_update(int command, String url, String expected_md5) {
HTTPClientWrapper* http = new HTTPClientWrapper(); HTTPClientWrapper* http = new HTTPClientWrapper();
bool result = http->get(url); bool result = http->get(url);
if (!result) { if (!result) {
@ -66,10 +94,11 @@ bool Updater::do_update(int command, String url) {
ERROR("Update could not be started.\n"); ERROR("Update could not be started.\n");
return false; return false;
} }
Update.setMD5(expected_md5.c_str());
uint8_t buf[512]; uint8_t buf[512];
uint16_t len; uint16_t len;
while((len = http->read(buf, 512))) { while((len = http->read(buf, 512))) {
Update.write(buf, 512); Update.write(buf, len);
} }
http->close(); http->close();
@ -77,51 +106,9 @@ bool Updater::do_update(int command, String url) {
result = Update.end(); result = Update.end();
if (!result) { if (!result) {
ERROR("Writing the update failed somewhere. Aborted.\n"); const char* error = Update.errorString();
ERROR("Writing the update failed. The error was: %s\n", error);
return false; return false;
} }
return true; return true;
} }
void Updater::update_spiffs() {
HTTPClientWrapper* http = new HTTPClientWrapper();
DEBUG("Requesting update info...\n");
bool result = http->get(OTA_UPDATE_URL);
if (!result) {
ERROR("Updater failed requesting %s.\n", OTA_UPDATE_URL);
return;
}
String line = http->readUntil("\n");
if (!line.startsWith("VERSION=")) {
ERROR("Expected first line to be VERSION.\n");
return;
}
uint16_t version = line.substring(8).toInt();
if (version==0) {
ERROR("Could not parse version number.\n");
return;
} else if (version > OTA_VERSION) {
DEBUG("Found newer version %d. My version is %d. Starting full update!\n", version, OTA_VERSION);
run();
} else {
DEBUG("Loading SPIFFS image.\n");
line = http->readUntil("\n");
if (!line.startsWith("IMAGE_PATH=")) {
ERROR("Expected second line to be IMAGE_PATH.\n");
return;
}
line = http->readUntil("\n");
if (!line.startsWith("SPIFFS_PATH=")) {
ERROR("Expected third line to be SPIFFS_PATH.\n");
return;
}
String spiffs_path = line.substring(12);
spiffs_path.trim();
do_update(U_SPIFFS, spiffs_path);
DEBUG("Done. Rebooting...\n");
delay(500);
ESP.restart();
}
http->close();
delete http;
}

View File

@ -1,3 +1,5 @@
VERSION=1 VERSION=1
IMAGE_PATH=https://files.schle.nz/esmp3/firmware.bin IMAGE_PATH=https://files.schle.nz/esmp3/firmware.bin
IMAGE_MD5=ead8d94ae8a3c9f46e7ee65e2270fd69
SPIFFS_PATH=https://files.schle.nz/esmp3/spiffs.bin SPIFFS_PATH=https://files.schle.nz/esmp3/spiffs.bin
SPIFFS_MD5=9f3902e3312863da8326e7fbe9485c9e