diff --git a/doc/ota_updates/ota_updates.md b/doc/ota_updates/ota_updates.md index b7963a114..8af5be15a 100644 --- a/doc/ota_updates/ota_updates.md +++ b/doc/ota_updates/ota_updates.md @@ -340,6 +340,7 @@ function sendFile($path) { header('Content-Type: application/octet-stream', true); header('Content-Disposition: attachment; filename='.basename($path)); header('Content-Length: '.filesize($path), true); + header('x-MD5: '.md5_file($path), true); readfile($path); } diff --git a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp index 33907465c..291729280 100644 --- a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp +++ b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp @@ -23,106 +23,95 @@ * */ + #include "ESP8266httpUpdate.h" -ESP8266HTTPUpdate::ESP8266HTTPUpdate(void) { +ESP8266HTTPUpdate::ESP8266HTTPUpdate(void) { } ESP8266HTTPUpdate::~ESP8266HTTPUpdate(void) { - } -t_httpUpdate_return ESP8266HTTPUpdate::update(const char * host, uint16_t port, const char * url, const char * current_version) { - WiFiClient tcp; - DEBUG_HTTP_UPDATE("[httpUpdate] connected to %s:%u %s .... ", host, port, url); - - if(!tcp.connect(host, port)) { - DEBUG_HTTP_UPDATE("failed.\n"); - return HTTP_UPDATE_FAILED; - } - DEBUG_HTTP_UPDATE("ok.\n"); - return update(tcp, host, url, current_version); +/** + * + * @param url const char * + * @param current_version const char * + * @param httpsFingerprint const char * + * @return t_httpUpdate_return + */ +t_httpUpdate_return ESP8266HTTPUpdate::update(const char * url, const char * current_version, const char * httpsFingerprint) { + httpClient http; + http.begin(url, httpsFingerprint); + return handleUpdate(&http, current_version); } -t_httpUpdate_return ESP8266HTTPUpdate::update(WiFiClient& tcp, const char* host, const char* url, const char * current_version) { +/** + * + * @param host const char * + * @param port uint16_t + * @param url const char * + * @param current_version const char * + * @param httpsFingerprint const char * + * @return + */ +t_httpUpdate_return ESP8266HTTPUpdate::update(const char * host, uint16_t port, const char * url, const char * current_version, bool https, const char * httpsFingerprint) { + httpClient http; + http.begin(host, port, url, https, httpsFingerprint); + return handleUpdate(&http, current_version); +} + +t_httpUpdate_return ESP8266HTTPUpdate::update(String host, uint16_t port, String url, String current_version, bool https, String httpsFingerprint) { + httpClient http; + http.begin(host, port, url, https, httpsFingerprint); + return handleUpdate(&http, current_version.c_str()); +} + +/** + * + * @param http httpClient * + * @param current_version const char * + * @return t_httpUpdate_return + */ +t_httpUpdate_return ESP8266HTTPUpdate::handleUpdate(httpClient * http, const char * current_version) { + t_httpUpdate_return ret = HTTP_UPDATE_FAILED; - // set Timeout for readBytesUntil and readStringUntil - tcp.setTimeout(2000); - tcp.setNoDelay(true); - String req = "GET "; + http->setUserAgent("ESP8266-http-Update"); + http->addHeader("x-ESP8266-STA-MAC", WiFi.macAddress()); + http->addHeader("x-ESP8266-AP-MAC", WiFi.softAPmacAddress()); + http->addHeader("x-ESP8266-free-space", String(ESP.getFreeSketchSpace())); + http->addHeader("x-ESP8266-sketch-size", String(ESP.getSketchSize())); + http->addHeader("x-ESP8266-chip-size", String(ESP.getFlashChipRealSize())); + http->addHeader("x-ESP8266-sdk-version", ESP.getSdkVersion()); - req += url; - req += " HTTP/1.1\r\n" - "Host: "; - req += host; - req += "\r\n" - "Connection: close\r\n" - "User-Agent: ESP8266-http-Update\r\n" - "x-ESP8266-STA-MAC: "; - req += WiFi.macAddress(); - req += "\r\n" - "x-ESP8266-AP-MAC: "; - req += WiFi.softAPmacAddress(); - req += "\r\n" - "x-ESP8266-free-space: "; - req += ESP.getFreeSketchSpace(); - req += "\r\n" - "x-ESP8266-sketch-size: "; - req += ESP.getSketchSize(); - req += "\r\n" - "x-ESP8266-chip-size: "; - req += ESP.getFlashChipRealSize(); - req += "\r\n" - "x-ESP8266-sdk-version: "; - req += ESP.getSdkVersion(); - - if(current_version[0] != 0x00) { - req += "\r\n" - "x-ESP8266-version: "; - req += current_version; + if(current_version && current_version[0] != 0x00) { + http->addHeader("x-ESP8266-version", current_version); } - req += "\r\n" - "\r\n"; + const char * headerkeys[] = { "x-MD5" }; + size_t headerkeyssize = sizeof(headerkeys) / sizeof(char*); - tcp.write(req.c_str(), req.length()); + // track these headers + http->collectHeaders(headerkeys, headerkeyssize); - uint32_t code = 0; - size_t len = 0; - while(true) { - String headerLine = tcp.readStringUntil('\n'); - headerLine.trim(); // remove \r - - if(headerLine.length() > 0) { - DEBUG_HTTP_UPDATE("[httpUpdate][Header] RX: %s\n", headerLine.c_str()); - if(headerLine.startsWith("HTTP/1.")) { - // 9 = lenght of "HTTP/1.x " - code = headerLine.substring(9, headerLine.indexOf(' ', 9)).toInt(); - } else if(headerLine.startsWith("Content-Length: ")) { - // 16 = lenght of "Content-Length: " - len = headerLine.substring(16).toInt(); - } - } else { - break; - } - } + int code = http->GET(); + int len = http->getSize(); DEBUG_HTTP_UPDATE("[httpUpdate] Header read fin.\n"); DEBUG_HTTP_UPDATE("[httpUpdate] Server header:\n"); DEBUG_HTTP_UPDATE("[httpUpdate] - code: %d\n", code); DEBUG_HTTP_UPDATE("[httpUpdate] - len: %d\n", len); + if(http->hasHeader("x-MD5")) { + DEBUG_HTTP_UPDATE("[httpUpdate] - MD5: %s\n", http->header("x-MD5").c_str()); + } + DEBUG_HTTP_UPDATE("[httpUpdate] ESP8266 info:\n"); DEBUG_HTTP_UPDATE("[httpUpdate] - free Space: %d\n", ESP.getFreeSketchSpace()); DEBUG_HTTP_UPDATE("[httpUpdate] - current Sketch Size: %d\n", ESP.getSketchSize()); - if(current_version[0] != 0x00) { - DEBUG_HTTP_UPDATE("[httpUpdate] - current version: %s\n", current_version); - } - switch(code) { case 200: ///< OK (Start Update) if(len > 0) { @@ -131,15 +120,17 @@ t_httpUpdate_return ESP8266HTTPUpdate::update(WiFiClient& tcp, const char* host, DEBUG_HTTP_UPDATE("[httpUpdate] FreeSketchSpace to low (%d) needed: %d\n", ESP.getFreeSketchSpace(), len); } else { + WiFiClient * tcp = http->getStreamPtr(); + WiFiUDP::stopAll(); - WiFiClient::stopAllExcept(&tcp); + WiFiClient::stopAllExcept(tcp); delay(100); - if(ESP.updateSketch(tcp, len, false, false)) { + if(runUpdate(*tcp, len, http->header("x-MD5"))) { ret = HTTP_UPDATE_OK; DEBUG_HTTP_UPDATE("[httpUpdate] Update ok\n"); - tcp.stop(); + http->end(); ESP.restart(); } else { ret = HTTP_UPDATE_FAILED; @@ -148,7 +139,7 @@ t_httpUpdate_return ESP8266HTTPUpdate::update(WiFiClient& tcp, const char* host, } } else { ret = HTTP_UPDATE_FAILED; - DEBUG_HTTP_UPDATE("[httpUpdate] Content-Length is 0?!\n"); + DEBUG_HTTP_UPDATE("[httpUpdate] Content-Length is 0 or net set by Server?!\n"); } break; case 304: @@ -164,11 +155,42 @@ t_httpUpdate_return ESP8266HTTPUpdate::update(WiFiClient& tcp, const char* host, break; } + http->end(); + return ret; } -t_httpUpdate_return ESP8266HTTPUpdate::update(String host, uint16_t port, String url, String current_version) { - return update(host.c_str(), port, url.c_str(), current_version.c_str()); +/** + * write Update to flash + * @param in Stream& + * @param size uint32_t + * @param md5 String + * @return true if Update ok + */ +bool ESP8266HTTPUpdate::runUpdate(Stream& in, uint32_t size, String md5) { + + if(!Update.begin(size)) { + DEBUG_HTTP_UPDATE("[httpUpdate] Update.begin failed!\n"); + return false; + } + + if(md5.length()) { + Update.setMD5(md5.c_str()); + } + + if(Update.writeStream(in) != size) { + DEBUG_HTTP_UPDATE("[httpUpdate] Update.writeStream failed!\n"); + return false; + } + + if(!Update.end()) { + DEBUG_HTTP_UPDATE("[httpUpdate] Update.end failed!\n"); + return false; + } + + return true; } + + ESP8266HTTPUpdate ESPhttpUpdate; diff --git a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h index 3f72bc98e..406d8de3f 100644 --- a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h +++ b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h @@ -28,8 +28,9 @@ #include #include -#include #include +#include +#include //#define DEBUG_HTTP_UPDATE(...) Serial1.printf( __VA_ARGS__ ) @@ -48,9 +49,13 @@ class ESP8266HTTPUpdate { ESP8266HTTPUpdate(void); ~ESP8266HTTPUpdate(void); - t_httpUpdate_return update(const char * host, uint16_t port, const char * url = "/", const char * current_version = ""); - t_httpUpdate_return update(String host, uint16_t port, String url = "/", String current_version = ""); - t_httpUpdate_return update(WiFiClient& client, const char* host, const char* url = "/", const char * current_version = ""); + t_httpUpdate_return update(const char * url, const char * current_version = "", const char * httpsFingerprint = ""); + t_httpUpdate_return update(const char * host, uint16_t port, const char * url = "/", const char * current_version = "", bool https = false, const char * httpsFingerprint = ""); + t_httpUpdate_return update(String host, uint16_t port, String url = "/", String current_version = "", bool https = false, String httpsFingerprint = ""); + + protected: + t_httpUpdate_return handleUpdate(httpClient * http, const char * current_version); + bool runUpdate(Stream& in, uint32_t size, String md5); }; extern ESP8266HTTPUpdate ESPhttpUpdate;