From 93d57fabe23687d0e0bddb6739b1795d6fe92e3f Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 27 Jan 2016 13:45:10 +0300 Subject: [PATCH 1/8] Remove overloads of HTTPClient::begin which take const char* Since the data is stored as Strings internally, these methods do not serve as an optimisation --- .../src/ESP8266HTTPClient.cpp | 27 ++----------------- .../ESP8266HTTPClient/src/ESP8266HTTPClient.h | 5 +--- 2 files changed, 3 insertions(+), 29 deletions(-) diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp index fd11c0360..d39511140 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp @@ -78,15 +78,6 @@ HTTPClient::~HTTPClient() { } } -/** - * phasing the url for all needed informations - * @param url const char * - * @param httpsFingerprint const char * - */ -void HTTPClient::begin(const char *url, const char * httpsFingerprint) { - begin(String(url), String(httpsFingerprint)); -} - /** * phasing the url for all needed informations * @param url String @@ -158,18 +149,7 @@ void HTTPClient::begin(String url, String httpsFingerprint) { } -/** - * begin - * @param host const char * - * @param port uint16_t - * @param url const char * - * @param https bool - * @param httpsFingerprint const char * - */ -void HTTPClient::begin(const char *host, uint16_t port, const char * url, bool https, const char * httpsFingerprint) { - - DEBUG_HTTPCLIENT("[HTTP-Client][begin] host: %s port:%d url: %s https: %d httpsFingerprint: %s\n", host, port, url, https, httpsFingerprint); - +void HTTPClient::begin(String host, uint16_t port, String url, bool https, String httpsFingerprint) { _host = host; _port = port; _url = url; @@ -181,10 +161,7 @@ void HTTPClient::begin(const char *host, uint16_t port, const char * url, bool h _Headers = ""; -} - -void HTTPClient::begin(String host, uint16_t port, String url, bool https, String httpsFingerprint) { - begin(host.c_str(), port, url.c_str(), https, httpsFingerprint.c_str()); + DEBUG_HTTPCLIENT("[HTTP-Client][begin] host: %s port:%d url: %s https: %d httpsFingerprint: %s\n", host, port, url, https, httpsFingerprint); } /** diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h index 0b865c2a6..c83f482df 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h @@ -125,14 +125,11 @@ class HTTPClient { HTTPClient(); ~HTTPClient(); - void begin(const char *url, const char * httpsFingerprint = ""); void begin(String url, String httpsFingerprint = ""); - - void begin(const char *host, uint16_t port, const char * url = "/", bool https = false, const char * httpsFingerprint = ""); void begin(String host, uint16_t port, String url = "/", bool https = false, String httpsFingerprint = ""); void end(void); - + bool connected(void); void setReuse(bool reuse); /// keep-alive From cae40392255a5a26ddbfcba59d02b076d2e389d4 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 5 Apr 2016 00:25:13 +0300 Subject: [PATCH 2/8] HTTPClient: decouple transport layer handling --- .../src/ESP8266HTTPClient.cpp | 320 ++++++++++-------- .../ESP8266HTTPClient/src/ESP8266HTTPClient.h | 83 +++-- 2 files changed, 218 insertions(+), 185 deletions(-) diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp index d39511140..1829e9812 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp @@ -30,138 +30,178 @@ #include "ESP8266HTTPClient.h" +class TransportTraits { +public: + virtual std::unique_ptr create() + { + return std::unique_ptr(new WiFiClient()); + } + + virtual bool verify(WiFiClient& client, const char* host) + { + return true; + } +}; + +class TLSTraits : public TransportTraits { +public: + TLSTraits(const String& fingerprint) : + _fingerprint(fingerprint) + { + } + + std::unique_ptr create() override + { + return std::unique_ptr(new WiFiClientSecure()); + } + + bool verify(WiFiClient& client, const char* host) override + { + auto wcs = reinterpret_cast(client); + return wcs.verify(_fingerprint.c_str(), host); + } + +protected: + String _fingerprint; +}; + /** - * constractor + * constructor */ -HTTPClient::HTTPClient() { - _tcp = NULL; - _tcps = NULL; - - _port = 0; - - _reuse = false; - _tcpTimeout = HTTPCLIENT_DEFAULT_TCP_TIMEOUT; - _useHTTP10 = false; - - _https = false; - - _userAgent = "ESP8266HTTPClient"; - - _headerKeysCount = 0; - _currentHeaders = NULL; - - _returnCode = 0; - _size = -1; - _canReuse = false; - _transferEncoding = HTTPC_TE_IDENTITY; - +HTTPClient::HTTPClient() +{ } /** - * deconstractor + * destructor */ -HTTPClient::~HTTPClient() { - - if(_tcps) { - _tcps->stop(); - delete _tcps; - _tcps = NULL; - _tcp = NULL; - } else if(_tcp) { +HTTPClient::~HTTPClient() +{ + if(_tcp) { _tcp->stop(); - delete _tcp; - _tcp = NULL; } - if(_currentHeaders) { delete[] _currentHeaders; } } -/** - * phasing the url for all needed informations - * @param url String - * @param httpsFingerprint String - */ -void HTTPClient::begin(String url, String httpsFingerprint) { - - DEBUG_HTTPCLIENT("[HTTP-Client][begin] url: %s\n", url.c_str()); - - _httpsFingerprint = httpsFingerprint; - _returnCode = 0; - _size = -1; - - _Headers = ""; - - String protocol; - // check for : (http: or https: - int index = url.indexOf(':'); - //int index2; - bool hasPort = false; - if(index >= 0) { - protocol = url.substring(0, index); - url.remove(0, (index + 3)); // remove http:// or https:// - - index = url.indexOf('/'); - String host = url.substring(0, index); - url.remove(0, index); // remove host part - - // get Authorization - index = host.indexOf('@'); - if(index >= 0) { - // auth info - String auth = host.substring(0, index); - host.remove(0, index + 1); // remove auth part including @ - _base64Authorization = base64::encode(auth); - } - - // get port - index = host.indexOf(':'); - if(index >= 0) { - _host = host.substring(0, index); // hostname - host.remove(0, (index + 1)); // remove hostname + : - _port = host.toInt(); // get port - hasPort = true; - } else { - _host = host; - } - - _url = url; - - if(protocol.equalsIgnoreCase("http")) { - _https = false; - if(!hasPort) { - _port = 80; - } - } else if(protocol.equalsIgnoreCase("https")) { - _https = true; - if(!hasPort) { - _port = 443; - } - } else { - DEBUG_HTTPCLIENT("[HTTP-Client][begin] protocol: %s unknown?!\n", protocol.c_str()); - return; - } +bool HTTPClient::begin(String url, String httpsFingerprint) { + if (httpsFingerprint.length() == 0) { + return false; } - - DEBUG_HTTPCLIENT("[HTTP-Client][begin] host: %s port: %d url: %s https: %d httpsFingerprint: %s\n", _host.c_str(), _port, _url.c_str(), _https, _httpsFingerprint.c_str()); - + if (!begin(url)) { + return false; + } + _transportTraits = TransportTraitsPtr(new TLSTraits(httpsFingerprint)); + DEBUG_HTTPCLIENT("[HTTP-Client][begin] httpsFingerprint: %s\n", httpsFingerprint.c_str()); + return true; } -void HTTPClient::begin(String host, uint16_t port, String url, bool https, String httpsFingerprint) { - _host = host; - _port = port; - _url = url; - _https = https; - _httpsFingerprint = httpsFingerprint; - +void HTTPClient::clear() +{ _returnCode = 0; _size = -1; + _headers = ""; +} - _Headers = ""; - DEBUG_HTTPCLIENT("[HTTP-Client][begin] host: %s port:%d url: %s https: %d httpsFingerprint: %s\n", host, port, url, https, httpsFingerprint); +/** + * parsing the url for all needed parameters + * @param url String + */ +bool HTTPClient::begin(String url) +{ + DEBUG_HTTPCLIENT("[HTTP-Client][begin] url: %s\n", url.c_str()); + bool hasPort = false; + clear(); + + // check for : (http: or https: + int index = url.indexOf(':'); + if(index < 0) { + DEBUG_HTTPCLIENT("[HTTP-Client][begin] failed to parse protocol\n"); + return false; + } + + _protocol = url.substring(0, index); + url.remove(0, (index + 3)); // remove http:// or https:// + + index = url.indexOf('/'); + String host = url.substring(0, index); + url.remove(0, index); // remove host part + + // get Authorization + index = host.indexOf('@'); + if(index >= 0) { + // auth info + String auth = host.substring(0, index); + host.remove(0, index + 1); // remove auth part including @ + _base64Authorization = base64::encode(auth); + } + + // get port + index = host.indexOf(':'); + if(index >= 0) { + _host = host.substring(0, index); // hostname + host.remove(0, (index + 1)); // remove hostname + : + _port = host.toInt(); // get port + hasPort = true; + } else { + _host = host; + } + _uri = url; + + if(_protocol.equalsIgnoreCase("http")) { + if(!hasPort) { + _port = 80; + } + } else if(_protocol.equalsIgnoreCase("https")) { + if(!hasPort) { + _port = 443; + } + } else { + DEBUG_HTTPCLIENT("[HTTP-Client][begin] protocol: %s unknown?!\n", protocol.c_str()); + return false; + } + _transportTraits = TransportTraitsPtr(new TransportTraits()); + DEBUG_HTTPCLIENT("[HTTP-Client][begin] host: %s port: %d url: %s\n", _host.c_str(), _port, _uri.c_str()); + return true; +} + +bool HTTPClient::begin(String host, uint16_t port, String uri) +{ + clear(); + _host = host; + _port = port; + _uri = uri; + _transportTraits = TransportTraitsPtr(new TransportTraits()); + DEBUG_HTTPCLIENT("[HTTP-Client][begin] host: %s port: %d uri: %s\n", host.c_str(), port, uri.c_str()); + return true; +} + +bool HTTPClient::begin(String host, uint16_t port, String uri, bool https, String httpsFingerprint) +{ + if (https) { + return begin(host, port, uri, httpsFingerprint); + } + else { + return begin(host, port, uri); + } +} + +bool HTTPClient::begin(String host, uint16_t port, String uri, String httpsFingerprint) +{ + clear(); + _host = host; + _port = port; + _uri = uri; + + if (httpsFingerprint.length() == 0) { + return false; + } + _transportTraits = TransportTraitsPtr(new TLSTraits(httpsFingerprint)); + DEBUG_HTTPCLIENT("[HTTP-Client][begin] host: %s port: %d url: %s httpsFingerprint: %s\n", host.c_str(), port, uri.c_str(), httpsFingerprint.c_str()); + return true; } /** @@ -469,31 +509,30 @@ int HTTPClient::getSize(void) { } /** - * deprecated Note: this is not working with https! * returns the stream of the tcp connection * @return WiFiClient */ -WiFiClient & HTTPClient::getStream(void) { +WiFiClient& HTTPClient::getStream(void) { if(connected()) { return *_tcp; } - DEBUG_HTTPCLIENT("[HTTP-Client] no stream to return!?\n"); - - // todo return error? + DEBUG_HTTPCLIENT("[HTTP-Client] getStream: not connected\n"); + static WiFiClient empty; + return empty; } /** * returns the stream of the tcp connection * @return WiFiClient * */ -WiFiClient * HTTPClient::getStreamPtr(void) { +WiFiClient* HTTPClient::getStreamPtr(void) { if(connected()) { - return _tcp; + return _tcp.get(); } - DEBUG_HTTPCLIENT("[HTTP-Client] no stream to return!?\n"); - return NULL; + DEBUG_HTTPCLIENT("[HTTP-Client] getStreamPtr: not connected\n"); + return nullptr; } /** @@ -642,9 +681,9 @@ void HTTPClient::addHeader(const String& name, const String& value, bool first) headerLine += "\r\n"; if(first) { - _Headers = headerLine + _Headers; + _headers = headerLine + _headers; } else { - _Headers += headerLine; + _headers += headerLine; } } @@ -706,24 +745,13 @@ bool HTTPClient::connect(void) { return true; } - if(_https) { - DEBUG_HTTPCLIENT("[HTTP-Client] connect https...\n"); - if(_tcps) { - delete _tcps; - _tcps = NULL; - _tcp = NULL; - } - _tcps = new WiFiClientSecure(); - _tcp = _tcps; - } else { - DEBUG_HTTPCLIENT("[HTTP-Client] connect http...\n"); - if(_tcp) { - delete _tcp; - _tcp = NULL; - } - _tcp = new WiFiClient(); + if (!_transportTraits) { + DEBUG_HTTPCLIENT("[HTTP-Client] _transportTraits is null (HTTPClient::begin not called?)\n"); + return false; } + _tcp = _transportTraits->create(); + if(!_tcp->connect(_host.c_str(), _port)) { DEBUG_HTTPCLIENT("[HTTP-Client] failed connect to %s:%u\n", _host.c_str(), _port); return false; @@ -731,14 +759,10 @@ bool HTTPClient::connect(void) { DEBUG_HTTPCLIENT("[HTTP-Client] connected to %s:%u\n", _host.c_str(), _port); - if(_https && _httpsFingerprint.length() > 0) { - if(_tcps->verify(_httpsFingerprint.c_str(), _host.c_str())) { - DEBUG_HTTPCLIENT("[HTTP-Client] https certificate matches\n"); - } else { - DEBUG_HTTPCLIENT("[HTTP-Client] https certificate doesn't match!\n"); - _tcp->stop(); - return false; - } + if (!_transportTraits->verify(*_tcp, _host.c_str())) { + DEBUG_HTTPCLIENT("[HTTP-Client] transport level verify failed\n"); + _tcp->stop(); + return false; } // set Timeout for readBytesUntil and readStringUntil @@ -760,7 +784,7 @@ bool HTTPClient::sendHeader(const char * type) { return false; } - String header = String(type) + " " + _url + " HTTP/1."; + String header = String(type) + " " + _uri + " HTTP/1."; if(_useHTTP10) { header += "0"; @@ -788,7 +812,7 @@ bool HTTPClient::sendHeader(const char * type) { header += "Authorization: Basic " + _base64Authorization + "\r\n"; } - header += _Headers + "\r\n"; + header += _headers + "\r\n"; return (_tcp->write(header.c_str(), header.length()) == header.length()); } diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h index c83f482df..27db371a5 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h @@ -25,6 +25,10 @@ #ifndef ESP8266HTTPClient_H_ #define ESP8266HTTPClient_H_ +#include +#include +#include + #ifdef DEBUG_ESP_HTTP_CLIENT #ifdef DEBUG_ESP_PORT #define DEBUG_HTTPCLIENT(...) DEBUG_ESP_PORT.printf( __VA_ARGS__ ) @@ -120,16 +124,23 @@ typedef enum { HTTPC_TE_CHUNKED } transferEncoding_t; +class TransportTraits; +typedef std::unique_ptr TransportTraitsPtr; + class HTTPClient { public: HTTPClient(); ~HTTPClient(); - void begin(String url, String httpsFingerprint = ""); - void begin(String host, uint16_t port, String url = "/", bool https = false, String httpsFingerprint = ""); + bool begin(String url); + bool begin(String url, String httpsFingerprint); + bool begin(String host, uint16_t port, String uri = "/"); + bool begin(String host, uint16_t port, String uri, String httpsFingerprint); + // deprecated, use the overload above instead + bool begin(String host, uint16_t port, String uri, bool https, String httpsFingerprint) __attribute__ ((deprecated)); void end(void); - + bool connected(void); void setReuse(bool reuse); /// keep-alive @@ -161,53 +172,51 @@ class HTTPClient { int getSize(void); - WiFiClient & getStream(void) __attribute__ ((deprecated)) ; - WiFiClient * getStreamPtr(void); - int writeToStream(Stream * stream); + WiFiClient& getStream(void); + WiFiClient* getStreamPtr(void); + int writeToStream(Stream* stream); String getString(void); static String errorToString(int error); protected: - struct RequestArgument { - String key; - String value; + String key; + String value; }; - - WiFiClient * _tcp; - WiFiClientSecure * _tcps; - - /// request handling - String _host; - uint16_t _port; - bool _reuse; - uint16_t _tcpTimeout; - bool _useHTTP10; - - String _url; - bool _https; - String _httpsFingerprint; - - String _Headers; - String _userAgent; - String _base64Authorization; - - /// Response handling - RequestArgument* _currentHeaders; - size_t _headerKeysCount; - - int _returnCode; - int _size; - bool _canReuse; - transferEncoding_t _transferEncoding; - + void clear(); int returnError(int error); bool connect(void); bool sendHeader(const char * type); int handleHeaderResponse(); int writeToStreamDataBlock(Stream * stream, int len); + + + TransportTraitsPtr _transportTraits; + std::unique_ptr _tcp; + + /// request handling + String _host; + uint16_t _port = 0; + bool _reuse = false; + uint16_t _tcpTimeout = HTTPCLIENT_DEFAULT_TCP_TIMEOUT; + bool _useHTTP10 = false; + + String _uri; + String _protocol; + String _headers; + String _userAgent = "ESP8266HTTPClient"; + String _base64Authorization; + + /// Response handling + RequestArgument* _currentHeaders = nullptr; + size_t _headerKeysCount = 0; + + int _returnCode = 0; + int _size = -1; + bool _canReuse = false; + transferEncoding_t _transferEncoding = HTTPC_TE_IDENTITY; }; From c450023a321c4f375336e0ff56b833e7e3c5ca0d Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 5 Apr 2016 01:56:29 +0300 Subject: [PATCH 3/8] ESP8266httpUpdate: decouple HTTPS overloads --- .../src/ESP8266httpUpdate.cpp | 748 +++++++++--------- .../ESP8266httpUpdate/src/ESP8266httpUpdate.h | 190 +++-- 2 files changed, 489 insertions(+), 449 deletions(-) diff --git a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp index 5d2fb2782..ee4365385 100644 --- a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp +++ b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp @@ -1,365 +1,383 @@ -/** - * - * @file ESP8266HTTPUpdate.cpp - * @date 21.06.2015 - * @author Markus Sattler - * - * Copyright (c) 2015 Markus Sattler. All rights reserved. - * This file is part of the ESP8266 Http Updater. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "ESP8266httpUpdate.h" -#include - -extern "C" uint32_t _SPIFFS_start; -extern "C" uint32_t _SPIFFS_end; - -ESP8266HTTPUpdate::ESP8266HTTPUpdate(void) { -} - -ESP8266HTTPUpdate::~ESP8266HTTPUpdate(void) { -} - -/** - * - * @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, bool reboot) { - HTTPClient http; - http.begin(url, httpsFingerprint); - return handleUpdate(&http, current_version, reboot, false); -} - -/** - * - * @param url const char * - * @param current_version const char * - * @param httpsFingerprint const char * - * @return t_httpUpdate_return - */ -t_httpUpdate_return ESP8266HTTPUpdate::updateSpiffs(const char * url, const char * current_version, const char * httpsFingerprint, bool reboot) { - HTTPClient http; - http.begin(url, httpsFingerprint); - return handleUpdate(&http, current_version, reboot, true); -} - -/** - * - * @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, bool reboot) { - HTTPClient http; - http.begin(host, port, url, https, httpsFingerprint); - return handleUpdate(&http, current_version, reboot, false); -} - -t_httpUpdate_return ESP8266HTTPUpdate::update(String host, uint16_t port, String url, String current_version, bool https, String httpsFingerprint, bool reboot) { - HTTPClient http; - http.begin(host, port, url, https, httpsFingerprint); - return handleUpdate(&http, current_version.c_str(), reboot, false); -} - -/** - * return error code as int - * @return int error code - */ -int ESP8266HTTPUpdate::getLastError(void){ - return lastError; -} - -/** - * return error code as String - * @return String error - */ -String ESP8266HTTPUpdate::getLastErrorString(void) { - - if(lastError == 0) { - return String(); // no error - } - - // error from Update class - if(lastError > 0) { - StreamString error; - Update.printError(error); - error.trim(); // remove line ending - return "Update error: " + error; - } - - // error from http client - if(lastError > -100) { - return "HTTP error: " + HTTPClient::errorToString(lastError); - } - - switch(lastError) { - case HTTP_UE_TOO_LESS_SPACE: - return String("To less space"); - case HTTP_UE_SERVER_NOT_REPORT_SIZE: - return String("Server not Report Size"); - case HTTP_UE_SERVER_FILE_NOT_FOUND: - return String("File not Found (404)"); - case HTTP_UE_SERVER_FORBIDDEN: - return String("Forbidden (403)"); - case HTTP_UE_SERVER_WRONG_HTTP_CODE: - return String("Wrong HTTP code"); - case HTTP_UE_SERVER_FAULTY_MD5: - return String("Faulty MD5"); - case HTTP_UE_BIN_VERIFY_HEADER_FAILED: - return String("Verify bin header failed"); - case HTTP_UE_BIN_FOR_WRONG_FLASH: - return String("bin for wrong flash size"); - } - - return String(); -} - - -/** - * - * @param http HTTPClient * - * @param current_version const char * - * @return t_httpUpdate_return - */ -t_httpUpdate_return ESP8266HTTPUpdate::handleUpdate(HTTPClient * http, const char * current_version, bool reboot, bool spiffs) { - - t_httpUpdate_return ret = HTTP_UPDATE_FAILED; - - // use HTTP/1.0 for update since the update handler not support any transfer Encoding - http->useHTTP10(true); - http->setTimeout(8000); - 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()); - - if(spiffs) { - http->addHeader("x-ESP8266-mode", "spiffs"); - } else { - http->addHeader("x-ESP8266-mode", "sketch"); - } - - if(current_version && current_version[0] != 0x00) { - http->addHeader("x-ESP8266-version", current_version); - } - - const char * headerkeys[] = { "x-MD5" }; - size_t headerkeyssize = sizeof(headerkeys) / sizeof(char*); - - // track these headers - http->collectHeaders(headerkeys, headerkeyssize); - - - int code = http->GET(); - int len = http->getSize(); - - if(code <= 0) { - DEBUG_HTTP_UPDATE("[httpUpdate] HTTP error: %s\n", http->errorToString(code).c_str()); - lastError = code; - http->end(); - return HTTP_UPDATE_FAILED; - } - - - 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 && current_version[0] != 0x00) { - DEBUG_HTTP_UPDATE("[httpUpdate] - current version: %s\n", current_version); - } - - switch(code) { - case HTTP_CODE_OK: ///< OK (Start Update) - if(len > 0) { - bool startUpdate = true; - if(spiffs) { - size_t spiffsSize = ((size_t) &_SPIFFS_end - (size_t) &_SPIFFS_start); - if(len > (int) spiffsSize) { - DEBUG_HTTP_UPDATE("[httpUpdate] spiffsSize to low (%d) needed: %d\n", spiffsSize, len); - startUpdate = false; - } - } else { - if(len > (int) ESP.getFreeSketchSpace()) { - DEBUG_HTTP_UPDATE("[httpUpdate] FreeSketchSpace to low (%d) needed: %d\n", ESP.getFreeSketchSpace(), len); - startUpdate = false; - } - } - - if(!startUpdate) { - lastError = HTTP_UE_TOO_LESS_SPACE; - ret = HTTP_UPDATE_FAILED; - } else { - - WiFiClient * tcp = http->getStreamPtr(); - - WiFiUDP::stopAll(); - WiFiClient::stopAllExcept(tcp); - - delay(100); - - int command; - - if(spiffs) { - command = U_SPIFFS; - DEBUG_HTTP_UPDATE("[httpUpdate] runUpdate spiffs...\n"); - } else { - command = U_FLASH; - DEBUG_HTTP_UPDATE("[httpUpdate] runUpdate flash...\n"); - } - - if(!spiffs) { - uint8_t buf[4]; - if(tcp->peekBytes(&buf[0], 4) != 4) { - DEBUG_HTTP_UPDATE("[httpUpdate] peekBytes magic header failed\n"); - lastError = HTTP_UE_BIN_VERIFY_HEADER_FAILED; - http->end(); - return HTTP_UPDATE_FAILED; - } - - // check for valid first magic byte - if(buf[0] != 0xE9) { - DEBUG_HTTP_UPDATE("[httpUpdate] magic header not starts with 0xE9\n"); - lastError = HTTP_UE_BIN_VERIFY_HEADER_FAILED; - http->end(); - return HTTP_UPDATE_FAILED; - - } - - uint32_t bin_flash_size = ESP.magicFlashChipSize((buf[3] & 0xf0) >> 4); - - // check if new bin fits to SPI flash - if(bin_flash_size > ESP.getFlashChipRealSize()) { - DEBUG_HTTP_UPDATE("[httpUpdate] magic header, new bin not fits SPI Flash\n"); - lastError = HTTP_UE_BIN_FOR_WRONG_FLASH; - http->end(); - return HTTP_UPDATE_FAILED; - } - } - - if(runUpdate(*tcp, len, http->header("x-MD5"), command)) { - ret = HTTP_UPDATE_OK; - DEBUG_HTTP_UPDATE("[httpUpdate] Update ok\n"); - http->end(); - - if(reboot) { - ESP.restart(); - } - - } else { - ret = HTTP_UPDATE_FAILED; - DEBUG_HTTP_UPDATE("[httpUpdate] Update failed\n"); - } - } - } else { - lastError = HTTP_UE_SERVER_NOT_REPORT_SIZE; - ret = HTTP_UPDATE_FAILED; - DEBUG_HTTP_UPDATE("[httpUpdate] Content-Length is 0 or not set by Server?!\n"); - } - break; - case HTTP_CODE_NOT_MODIFIED: - ///< Not Modified (No updates) - ret = HTTP_UPDATE_NO_UPDATES; - break; - case HTTP_CODE_NOT_FOUND: - lastError = HTTP_UE_SERVER_FILE_NOT_FOUND; - ret = HTTP_UPDATE_FAILED; - break; - case HTTP_CODE_FORBIDDEN: - lastError = HTTP_UE_SERVER_FORBIDDEN; - ret = HTTP_UPDATE_FAILED; - break; - default: - lastError = HTTP_UE_SERVER_WRONG_HTTP_CODE; - ret = HTTP_UPDATE_FAILED; - DEBUG_HTTP_UPDATE("[httpUpdate] HTTP Code is (%d)\n", code); - //http->writeToStream(&Serial1); - break; - } - - http->end(); - return ret; -} - -/** - * 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, int command) { - - StreamString error; - - if(!Update.begin(size, command)) { - lastError = Update.getError(); - Update.printError(error); - error.trim(); // remove line ending - DEBUG_HTTP_UPDATE("[httpUpdate] Update.begin failed! (%s)\n", error.c_str()); - return false; - } - - if(md5.length()) { - if(!Update.setMD5(md5.c_str())) { - lastError = HTTP_UE_SERVER_FAULTY_MD5; - DEBUG_HTTP_UPDATE("[httpUpdate] Update.setMD5 failed! (%s)\n", md5.c_str()); - return false; - } - } - - if(Update.writeStream(in) != size) { - lastError = Update.getError(); - Update.printError(error); - error.trim(); // remove line ending - DEBUG_HTTP_UPDATE("[httpUpdate] Update.writeStream failed! (%s)\n", error.c_str()); - return false; - } - - if(!Update.end()) { - lastError = Update.getError(); - Update.printError(error); - error.trim(); // remove line ending - DEBUG_HTTP_UPDATE("[httpUpdate] Update.end failed! (%s)\n", error.c_str()); - return false; - } - - return true; -} - - - -ESP8266HTTPUpdate ESPhttpUpdate; +/** + * + * @file ESP8266HTTPUpdate.cpp + * @date 21.06.2015 + * @author Markus Sattler + * + * Copyright (c) 2015 Markus Sattler. All rights reserved. + * This file is part of the ESP8266 Http Updater. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "ESP8266httpUpdate.h" +#include + +extern "C" uint32_t _SPIFFS_start; +extern "C" uint32_t _SPIFFS_end; + +ESP8266HTTPUpdate::ESP8266HTTPUpdate(void) { +} + +ESP8266HTTPUpdate::~ESP8266HTTPUpdate(void) { +} + +t_httpUpdate_return ESP8266HTTPUpdate::update(const String& url, const String& currentVersion, + const String& httpsFingerprint, bool reboot) +{ + rebootOnUpdate(reboot); + return update(url, currentVersion, httpsFingerprint); +} + +t_httpUpdate_return ESP8266HTTPUpdate::update(const String& url, const String& currentVersion) +{ + HTTPClient http; + http.begin(url); + return handleUpdate(http, currentVersion, false); +} + +t_httpUpdate_return ESP8266HTTPUpdate::update(const String& url, const String& currentVersion, + const String& httpsFingerprint) +{ + HTTPClient http; + http.begin(url, httpsFingerprint); + return handleUpdate(http, currentVersion, false); +} + + +t_httpUpdate_return ESP8266HTTPUpdate::updateSpiffs(const String& url, const String& currentVersion, const String& httpsFingerprint) +{ + HTTPClient http; + http.begin(url, httpsFingerprint); + return handleUpdate(http, currentVersion, true); +} + +t_httpUpdate_return ESP8266HTTPUpdate::updateSpiffs(const String& url, const String& currentVersion) +{ + HTTPClient http; + http.begin(url); + return handleUpdate(http, currentVersion, true); +} + +t_httpUpdate_return ESP8266HTTPUpdate::update(const String& host, uint16_t port, const String& uri, const String& currentVersion, + bool https, const String& httpsFingerprint, bool reboot) +{ + rebootOnUpdate(reboot); + if (httpsFingerprint.length() == 0) { + return update(host, port, uri, currentVersion); + } + else { + return update(host, port, uri, currentVersion, httpsFingerprint); + } +} + +t_httpUpdate_return ESP8266HTTPUpdate::update(const String& host, uint16_t port, const String& uri, + const String& currentVersion) +{ + HTTPClient http; + http.begin(host, port, uri); + return handleUpdate(http, currentVersion, false); +} +t_httpUpdate_return ESP8266HTTPUpdate::update(const String& host, uint16_t port, const String& url, + const String& currentVersion, const String& httpsFingerprint) +{ + HTTPClient http; + http.begin(host, port, url, httpsFingerprint); + return handleUpdate(http, currentVersion, false); + +} + +/** + * return error code as int + * @return int error code + */ +int ESP8266HTTPUpdate::getLastError(void){ + return _lastError; +} + +/** + * return error code as String + * @return String error + */ +String ESP8266HTTPUpdate::getLastErrorString(void) { + + if(_lastError == 0) { + return String(); // no error + } + + // error from Update class + if(_lastError > 0) { + StreamString error; + Update.printError(error); + error.trim(); // remove line ending + return "Update error: " + error; + } + + // error from http client + if(_lastError > -100) { + return "HTTP error: " + HTTPClient::errorToString(_lastError); + } + + switch(_lastError) { + case HTTP_UE_TOO_LESS_SPACE: + return String("To less space"); + case HTTP_UE_SERVER_NOT_REPORT_SIZE: + return String("Server not Report Size"); + case HTTP_UE_SERVER_FILE_NOT_FOUND: + return String("File not Found (404)"); + case HTTP_UE_SERVER_FORBIDDEN: + return String("Forbidden (403)"); + case HTTP_UE_SERVER_WRONG_HTTP_CODE: + return String("Wrong HTTP code"); + case HTTP_UE_SERVER_FAULTY_MD5: + return String("Faulty MD5"); + case HTTP_UE_BIN_VERIFY_HEADER_FAILED: + return String("Verify bin header failed"); + case HTTP_UE_BIN_FOR_WRONG_FLASH: + return String("bin for wrong flash size"); + } + + return String(); +} + + +/** + * + * @param http HTTPClient * + * @param currentVersion const char * + * @return t_httpUpdate_return + */ +t_httpUpdate_return ESP8266HTTPUpdate::handleUpdate(HTTPClient& http, const String& currentVersion, bool spiffs) { + + t_httpUpdate_return ret = HTTP_UPDATE_FAILED; + + // use HTTP/1.0 for update since the update handler not support any transfer Encoding + http.useHTTP10(true); + http.setTimeout(8000); + 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()); + + if(spiffs) { + http.addHeader("x-ESP8266-mode", "spiffs"); + } else { + http.addHeader("x-ESP8266-mode", "sketch"); + } + + if(currentVersion && currentVersion[0] != 0x00) { + http.addHeader("x-ESP8266-version", currentVersion); + } + + const char * headerkeys[] = { "x-MD5" }; + size_t headerkeyssize = sizeof(headerkeys) / sizeof(char*); + + // track these headers + http.collectHeaders(headerkeys, headerkeyssize); + + + int code = http.GET(); + int len = http.getSize(); + + if(code <= 0) { + DEBUG_HTTP_UPDATE("[httpUpdate] HTTP error: %s\n", http.errorToString(code).c_str()); + _lastError = code; + http.end(); + return HTTP_UPDATE_FAILED; + } + + + 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(currentVersion && currentVersion[0] != 0x00) { + DEBUG_HTTP_UPDATE("[httpUpdate] - current version: %s\n", currentVersion); + } + + switch(code) { + case HTTP_CODE_OK: ///< OK (Start Update) + if(len > 0) { + bool startUpdate = true; + if(spiffs) { + size_t spiffsSize = ((size_t) &_SPIFFS_end - (size_t) &_SPIFFS_start); + if(len > (int) spiffsSize) { + DEBUG_HTTP_UPDATE("[httpUpdate] spiffsSize to low (%d) needed: %d\n", spiffsSize, len); + startUpdate = false; + } + } else { + if(len > (int) ESP.getFreeSketchSpace()) { + DEBUG_HTTP_UPDATE("[httpUpdate] FreeSketchSpace to low (%d) needed: %d\n", ESP.getFreeSketchSpace(), len); + startUpdate = false; + } + } + + if(!startUpdate) { + _lastError = HTTP_UE_TOO_LESS_SPACE; + ret = HTTP_UPDATE_FAILED; + } else { + + WiFiClient * tcp = http.getStreamPtr(); + + WiFiUDP::stopAll(); + WiFiClient::stopAllExcept(tcp); + + delay(100); + + int command; + + if(spiffs) { + command = U_SPIFFS; + DEBUG_HTTP_UPDATE("[httpUpdate] runUpdate spiffs...\n"); + } else { + command = U_FLASH; + DEBUG_HTTP_UPDATE("[httpUpdate] runUpdate flash...\n"); + } + + if(!spiffs) { + uint8_t buf[4]; + if(tcp->peekBytes(&buf[0], 4) != 4) { + DEBUG_HTTP_UPDATE("[httpUpdate] peekBytes magic header failed\n"); + _lastError = HTTP_UE_BIN_VERIFY_HEADER_FAILED; + http.end(); + return HTTP_UPDATE_FAILED; + } + + // check for valid first magic byte + if(buf[0] != 0xE9) { + DEBUG_HTTP_UPDATE("[httpUpdate] magic header not starts with 0xE9\n"); + _lastError = HTTP_UE_BIN_VERIFY_HEADER_FAILED; + http.end(); + return HTTP_UPDATE_FAILED; + + } + + uint32_t bin_flash_size = ESP.magicFlashChipSize((buf[3] & 0xf0) >> 4); + + // check if new bin fits to SPI flash + if(bin_flash_size > ESP.getFlashChipRealSize()) { + DEBUG_HTTP_UPDATE("[httpUpdate] magic header, new bin not fits SPI Flash\n"); + _lastError = HTTP_UE_BIN_FOR_WRONG_FLASH; + http.end(); + return HTTP_UPDATE_FAILED; + } + } + + if(runUpdate(*tcp, len, http.header("x-MD5"), command)) { + ret = HTTP_UPDATE_OK; + DEBUG_HTTP_UPDATE("[httpUpdate] Update ok\n"); + http.end(); + + if(_rebootOnUpdate) { + ESP.restart(); + } + + } else { + ret = HTTP_UPDATE_FAILED; + DEBUG_HTTP_UPDATE("[httpUpdate] Update failed\n"); + } + } + } else { + _lastError = HTTP_UE_SERVER_NOT_REPORT_SIZE; + ret = HTTP_UPDATE_FAILED; + DEBUG_HTTP_UPDATE("[httpUpdate] Content-Length is 0 or not set by Server?!\n"); + } + break; + case HTTP_CODE_NOT_MODIFIED: + ///< Not Modified (No updates) + ret = HTTP_UPDATE_NO_UPDATES; + break; + case HTTP_CODE_NOT_FOUND: + _lastError = HTTP_UE_SERVER_FILE_NOT_FOUND; + ret = HTTP_UPDATE_FAILED; + break; + case HTTP_CODE_FORBIDDEN: + _lastError = HTTP_UE_SERVER_FORBIDDEN; + ret = HTTP_UPDATE_FAILED; + break; + default: + _lastError = HTTP_UE_SERVER_WRONG_HTTP_CODE; + ret = HTTP_UPDATE_FAILED; + DEBUG_HTTP_UPDATE("[httpUpdate] HTTP Code is (%d)\n", code); + //http.writeToStream(&Serial1); + break; + } + + http.end(); + return ret; +} + +/** + * 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, int command) { + + StreamString error; + + if(!Update.begin(size, command)) { + _lastError = Update.getError(); + Update.printError(error); + error.trim(); // remove line ending + DEBUG_HTTP_UPDATE("[httpUpdate] Update.begin failed! (%s)\n", error.c_str()); + return false; + } + + if(md5.length()) { + if(!Update.setMD5(md5.c_str())) { + _lastError = HTTP_UE_SERVER_FAULTY_MD5; + DEBUG_HTTP_UPDATE("[httpUpdate] Update.setMD5 failed! (%s)\n", md5.c_str()); + return false; + } + } + + if(Update.writeStream(in) != size) { + _lastError = Update.getError(); + Update.printError(error); + error.trim(); // remove line ending + DEBUG_HTTP_UPDATE("[httpUpdate] Update.writeStream failed! (%s)\n", error.c_str()); + return false; + } + + if(!Update.end()) { + _lastError = Update.getError(); + Update.printError(error); + error.trim(); // remove line ending + DEBUG_HTTP_UPDATE("[httpUpdate] Update.end failed! (%s)\n", error.c_str()); + return false; + } + + return true; +} + + + +ESP8266HTTPUpdate ESPhttpUpdate; diff --git a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h index 81f03385f..765cc3569 100644 --- a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h +++ b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h @@ -1,84 +1,106 @@ -/** - * - * @file ESP8266HTTPUpdate.h - * @date 21.06.2015 - * @author Markus Sattler - * - * Copyright (c) 2015 Markus Sattler. All rights reserved. - * This file is part of the ESP8266 Http Updater. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifndef ESP8266HTTPUPDATE_H_ -#define ESP8266HTTPUPDATE_H_ - -#include -#include -#include -#include -#include - -#ifdef DEBUG_ESP_HTTP_UPDATE -#ifdef DEBUG_ESP_PORT -#define DEBUG_HTTP_UPDATE(...) DEBUG_ESP_PORT.printf( __VA_ARGS__ ) -#endif -#endif - -#ifndef DEBUG_HTTP_UPDATE -#define DEBUG_HTTP_UPDATE(...) -#endif - -/// note we use HTTP client errors too so we start at 100 -#define HTTP_UE_TOO_LESS_SPACE (-100) -#define HTTP_UE_SERVER_NOT_REPORT_SIZE (-101) -#define HTTP_UE_SERVER_FILE_NOT_FOUND (-102) -#define HTTP_UE_SERVER_FORBIDDEN (-103) -#define HTTP_UE_SERVER_WRONG_HTTP_CODE (-104) -#define HTTP_UE_SERVER_FAULTY_MD5 (-105) -#define HTTP_UE_BIN_VERIFY_HEADER_FAILED (-106) -#define HTTP_UE_BIN_FOR_WRONG_FLASH (-107) - -typedef enum { - HTTP_UPDATE_FAILED, - HTTP_UPDATE_NO_UPDATES, - HTTP_UPDATE_OK -} t_httpUpdate_return; - -class ESP8266HTTPUpdate { - public: - ESP8266HTTPUpdate(void); - ~ESP8266HTTPUpdate(void); - - t_httpUpdate_return update(const char * url, const char * current_version = "", const char * httpsFingerprint = "", bool reboot = true); - t_httpUpdate_return update(const char * host, uint16_t port, const char * url = "/", const char * current_version = "", bool https = false, const char * httpsFingerprint = "", bool reboot = true); - t_httpUpdate_return update(String host, uint16_t port, String url = "/", String current_version = "", bool https = false, String httpsFingerprint = "", bool reboot = true); - - t_httpUpdate_return updateSpiffs(const char * url, const char * current_version = "", const char * httpsFingerprint = "", bool reboot = false); - - int getLastError(void); - String getLastErrorString(void); - - protected: - t_httpUpdate_return handleUpdate(HTTPClient * http, const char * current_version, bool reboot = true, bool spiffs = false); - bool runUpdate(Stream& in, uint32_t size, String md5, int command = U_FLASH); - - int lastError; -}; - -extern ESP8266HTTPUpdate ESPhttpUpdate; - -#endif /* ESP8266HTTPUPDATE_H_ */ +/** + * + * @file ESP8266HTTPUpdate.h + * @date 21.06.2015 + * @author Markus Sattler + * + * Copyright (c) 2015 Markus Sattler. All rights reserved. + * This file is part of the ESP8266 Http Updater. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef ESP8266HTTPUPDATE_H_ +#define ESP8266HTTPUPDATE_H_ + +#include +#include +#include +#include +#include + +#ifdef DEBUG_ESP_HTTP_UPDATE +#ifdef DEBUG_ESP_PORT +#define DEBUG_HTTP_UPDATE(...) DEBUG_ESP_PORT.printf( __VA_ARGS__ ) +#endif +#endif + +#ifndef DEBUG_HTTP_UPDATE +#define DEBUG_HTTP_UPDATE(...) +#endif + +/// note we use HTTP client errors too so we start at 100 +#define HTTP_UE_TOO_LESS_SPACE (-100) +#define HTTP_UE_SERVER_NOT_REPORT_SIZE (-101) +#define HTTP_UE_SERVER_FILE_NOT_FOUND (-102) +#define HTTP_UE_SERVER_FORBIDDEN (-103) +#define HTTP_UE_SERVER_WRONG_HTTP_CODE (-104) +#define HTTP_UE_SERVER_FAULTY_MD5 (-105) +#define HTTP_UE_BIN_VERIFY_HEADER_FAILED (-106) +#define HTTP_UE_BIN_FOR_WRONG_FLASH (-107) + +enum HTTPUpdateResult { + HTTP_UPDATE_FAILED, + HTTP_UPDATE_NO_UPDATES, + HTTP_UPDATE_OK +}; + +typedef HTTPUpdateResult t_httpUpdate_return; // backward compatibility + +class ESP8266HTTPUpdate { + public: + ESP8266HTTPUpdate(void); + ~ESP8266HTTPUpdate(void); + + void rebootOnUpdate(bool reboot) { _rebootOnUpdate = reboot; } + + // This function is deprecated, use rebootOnUpdate and the next one instead + t_httpUpdate_return update(const String& url, const String& currentVersion, + const String& httpsFingerprint, bool reboot) __attribute__((deprecated)); + t_httpUpdate_return update(const String& url, const String& currentVersion = ""); + t_httpUpdate_return update(const String& url, const String& currentVersion, + const String& httpsFingerprint); + + // This function is deprecated, use one of the overloads below along with rebootOnUpdate + t_httpUpdate_return update(const String& host, uint16_t port, const String& uri, const String& currentVersion, + bool https, const String& httpsFingerprint, bool reboot) __attribute__((deprecated)); + + t_httpUpdate_return update(const String& host, uint16_t port, const String& uri = "/", + const String& currentVersion = ""); + t_httpUpdate_return update(const String& host, uint16_t port, const String& url, + const String& currentVersion, const String& httpsFingerprint); + + // This function is deprecated, use rebootOnUpdate and the next one instead + t_httpUpdate_return updateSpiffs(const String& url, const String& currentVersion, + const String& httpsFingerprint, bool reboot) __attribute__((deprecated)); + t_httpUpdate_return updateSpiffs(const String& url, const String& currentVersion = ""); + t_httpUpdate_return updateSpiffs(const String& url, const String& currentVersion, const String& httpsFingerprint); + + + int getLastError(void); + String getLastErrorString(void); + + protected: + t_httpUpdate_return handleUpdate(HTTPClient& http, const String& currentVersion, bool spiffs = false); + bool runUpdate(Stream& in, uint32_t size, String md5, int command = U_FLASH); + + int _lastError; + bool _rebootOnUpdate = true; +}; + +extern ESP8266HTTPUpdate ESPhttpUpdate; + +#endif /* ESP8266HTTPUPDATE_H_ */ From bbc5e9ba01009bb42a5463dff87f4b08e10b2c9f Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 5 Apr 2016 01:57:09 +0300 Subject: [PATCH 4/8] Update library versions --- libraries/ESP8266HTTPClient/library.properties | 2 +- libraries/ESP8266httpUpdate/library.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/ESP8266HTTPClient/library.properties b/libraries/ESP8266HTTPClient/library.properties index ab96e9a9e..871617105 100644 --- a/libraries/ESP8266HTTPClient/library.properties +++ b/libraries/ESP8266HTTPClient/library.properties @@ -1,5 +1,5 @@ name=ESP8266HTTPClient -version=1.0 +version=1.1 author=Markus Sattler maintainer=Markus Sattler sentence=http Client for ESP8266 diff --git a/libraries/ESP8266httpUpdate/library.properties b/libraries/ESP8266httpUpdate/library.properties index ca5f75f6e..2116c04a0 100644 --- a/libraries/ESP8266httpUpdate/library.properties +++ b/libraries/ESP8266httpUpdate/library.properties @@ -1,5 +1,5 @@ name=ESP8266httpUpdate -version=1.0 +version=1.1 author=Markus Sattler maintainer=Markus Sattler sentence=Http Update for ESP8266 From bf7f33d91847ef301b46e4842a253090bc59a62b Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 5 Apr 2016 02:04:42 +0300 Subject: [PATCH 5/8] Fix code formatting --- .../src/ESP8266HTTPClient.cpp | 180 ++++++----- .../ESP8266HTTPClient/src/ESP8266HTTPClient.h | 141 ++++----- .../src/ESP8266httpUpdate.cpp | 288 +++++++++--------- .../ESP8266httpUpdate/src/ESP8266httpUpdate.h | 64 ++-- 4 files changed, 361 insertions(+), 312 deletions(-) diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp index 1829e9812..033fd3e84 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp @@ -30,7 +30,8 @@ #include "ESP8266HTTPClient.h" -class TransportTraits { +class TransportTraits +{ public: virtual std::unique_ptr create() { @@ -43,7 +44,8 @@ public: } }; -class TLSTraits : public TransportTraits { +class TLSTraits : public TransportTraits +{ public: TLSTraits(const String& fingerprint) : _fingerprint(fingerprint) @@ -86,7 +88,8 @@ HTTPClient::~HTTPClient() } -bool HTTPClient::begin(String url, String httpsFingerprint) { +bool HTTPClient::begin(String url, String httpsFingerprint) +{ if (httpsFingerprint.length() == 0) { return false; } @@ -183,8 +186,7 @@ bool HTTPClient::begin(String host, uint16_t port, String uri, bool https, Strin { if (https) { return begin(host, port, uri, httpsFingerprint); - } - else { + } else { return begin(host, port, uri); } } @@ -208,7 +210,8 @@ bool HTTPClient::begin(String host, uint16_t port, String uri, String httpsFinge * end * called after the payload is handled */ -void HTTPClient::end(void) { +void HTTPClient::end(void) +{ if(connected()) { if(_tcp->available() > 0) { DEBUG_HTTPCLIENT("[HTTP-Client][end] still data in buffer (%d), clean up.\n", _tcp->available()); @@ -231,7 +234,8 @@ void HTTPClient::end(void) { * connected * @return connected status */ -bool HTTPClient::connected() { +bool HTTPClient::connected() +{ if(_tcp) { return (_tcp->connected() || (_tcp->available() > 0)); } @@ -243,7 +247,8 @@ bool HTTPClient::connected() { * keep-alive * @param reuse bool */ -void HTTPClient::setReuse(bool reuse) { +void HTTPClient::setReuse(bool reuse) +{ _reuse = reuse; } @@ -251,7 +256,8 @@ void HTTPClient::setReuse(bool reuse) { * set User Agent * @param userAgent const char * */ -void HTTPClient::setUserAgent(const char * userAgent) { +void HTTPClient::setUserAgent(const char * userAgent) +{ _userAgent = userAgent; } @@ -260,7 +266,8 @@ void HTTPClient::setUserAgent(const char * userAgent) { * @param user const char * * @param password const char * */ -void HTTPClient::setAuthorization(const char * user, const char * password) { +void HTTPClient::setAuthorization(const char * user, const char * password) +{ if(user && password) { String auth = user; auth += ":"; @@ -273,7 +280,8 @@ void HTTPClient::setAuthorization(const char * user, const char * password) { * set the Authorizatio for the http request * @param auth const char * base64 */ -void HTTPClient::setAuthorization(const char * auth) { +void HTTPClient::setAuthorization(const char * auth) +{ if(auth) { _base64Authorization = auth; } @@ -283,7 +291,8 @@ void HTTPClient::setAuthorization(const char * auth) { * set the timeout for the TCP connection * @param timeout unsigned int */ -void HTTPClient::setTimeout(uint16_t timeout) { +void HTTPClient::setTimeout(uint16_t timeout) +{ _tcpTimeout = timeout; if(connected()) { _tcp->setTimeout(timeout); @@ -294,7 +303,8 @@ void HTTPClient::setTimeout(uint16_t timeout) { * use HTTP1.0 * @param timeout */ -void HTTPClient::useHTTP10(bool useHTTP10) { +void HTTPClient::useHTTP10(bool useHTTP10) +{ _useHTTP10 = useHTTP10; } @@ -302,7 +312,8 @@ void HTTPClient::useHTTP10(bool useHTTP10) { * send a GET request * @return http code */ -int HTTPClient::GET() { +int HTTPClient::GET() +{ return sendRequest("GET"); } @@ -312,11 +323,13 @@ int HTTPClient::GET() { * @param size size_t * @return http code */ -int HTTPClient::POST(uint8_t * payload, size_t size) { +int HTTPClient::POST(uint8_t * payload, size_t size) +{ return sendRequest("POST", payload, size); } -int HTTPClient::POST(String payload) { +int HTTPClient::POST(String payload) +{ return POST((uint8_t *) payload.c_str(), payload.length()); } @@ -326,7 +339,8 @@ int HTTPClient::POST(String payload) { * @param payload String data for the message body * @return */ -int HTTPClient::sendRequest(const char * type, String payload) { +int HTTPClient::sendRequest(const char * type, String payload) +{ return sendRequest(type, (uint8_t *) payload.c_str(), payload.length()); } @@ -337,7 +351,8 @@ int HTTPClient::sendRequest(const char * type, String payload) { * @param size size_t size for the message body if 0 not send * @return -1 if no info or > 0 when Content-Length is set by server */ -int HTTPClient::sendRequest(const char * type, uint8_t * payload, size_t size) { +int HTTPClient::sendRequest(const char * type, uint8_t * payload, size_t size) +{ // connect to server if(!connect()) { return returnError(HTTPC_ERROR_CONNECTION_REFUSED); @@ -370,7 +385,8 @@ int HTTPClient::sendRequest(const char * type, uint8_t * payload, size_t size) { * @param size size_t size for the message body if 0 not Content-Length is send * @return -1 if no info or > 0 when Content-Length is set by server */ -int HTTPClient::sendRequest(const char * type, Stream * stream, size_t size) { +int HTTPClient::sendRequest(const char * type, Stream * stream, size_t size) +{ if(!stream) { return returnError(HTTPC_ERROR_NO_STREAM); @@ -485,7 +501,8 @@ int HTTPClient::sendRequest(const char * type, Stream * stream, size_t size) { free(buff); if(size && (int) size != bytesWritten) { - DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] Stream payload bytesWritten %d and size %d mismatch!.\n", bytesWritten, size); DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] ERROR SEND PAYLOAD FAILED!"); + DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] Stream payload bytesWritten %d and size %d mismatch!.\n", bytesWritten, size); + DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] ERROR SEND PAYLOAD FAILED!"); return returnError(HTTPC_ERROR_SEND_PAYLOAD_FAILED); } else { DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] Stream payload written: %d\n", bytesWritten); @@ -504,7 +521,8 @@ int HTTPClient::sendRequest(const char * type, Stream * stream, size_t size) { * size of message body / payload * @return -1 if no info or > 0 when Content-Length is set by server */ -int HTTPClient::getSize(void) { +int HTTPClient::getSize(void) +{ return _size; } @@ -512,7 +530,8 @@ int HTTPClient::getSize(void) { * returns the stream of the tcp connection * @return WiFiClient */ -WiFiClient& HTTPClient::getStream(void) { +WiFiClient& HTTPClient::getStream(void) +{ if(connected()) { return *_tcp; } @@ -526,7 +545,8 @@ WiFiClient& HTTPClient::getStream(void) { * returns the stream of the tcp connection * @return WiFiClient * */ -WiFiClient* HTTPClient::getStreamPtr(void) { +WiFiClient* HTTPClient::getStreamPtr(void) +{ if(connected()) { return _tcp.get(); } @@ -540,7 +560,8 @@ WiFiClient* HTTPClient::getStreamPtr(void) { * @param stream Stream * * @return bytes written ( negative values are error codes ) */ -int HTTPClient::writeToStream(Stream * stream) { +int HTTPClient::writeToStream(Stream * stream) +{ if(!stream) { return returnError(HTTPC_ERROR_NO_STREAM); @@ -616,7 +637,8 @@ int HTTPClient::writeToStream(Stream * stream) { * return all payload as String (may need lot of ram or trigger out of memory!) * @return String */ -String HTTPClient::getString(void) { +String HTTPClient::getString(void) +{ StreamString sstring; if(_size) { @@ -636,32 +658,33 @@ String HTTPClient::getString(void) { * @param error int * @return String */ -String HTTPClient::errorToString(int error) { +String HTTPClient::errorToString(int error) +{ switch(error) { - case HTTPC_ERROR_CONNECTION_REFUSED: - return String("connection refused"); - case HTTPC_ERROR_SEND_HEADER_FAILED: - return String("send header failed"); - case HTTPC_ERROR_SEND_PAYLOAD_FAILED: - return String("send payload failed"); - case HTTPC_ERROR_NOT_CONNECTED: - return String("not connected"); - case HTTPC_ERROR_CONNECTION_LOST: - return String("connection lost"); - case HTTPC_ERROR_NO_STREAM: - return String("no stream"); - case HTTPC_ERROR_NO_HTTP_SERVER: - return String("no HTTP server"); - case HTTPC_ERROR_TOO_LESS_RAM: - return String("too less ram"); - case HTTPC_ERROR_ENCODING: - return String("Transfer-Encoding not supported"); - case HTTPC_ERROR_STREAM_WRITE: - return String("Stream write error"); - case HTTPC_ERROR_READ_TIMEOUT: - return String("read Timeout"); - default: - return String(); + case HTTPC_ERROR_CONNECTION_REFUSED: + return String("connection refused"); + case HTTPC_ERROR_SEND_HEADER_FAILED: + return String("send header failed"); + case HTTPC_ERROR_SEND_PAYLOAD_FAILED: + return String("send payload failed"); + case HTTPC_ERROR_NOT_CONNECTED: + return String("not connected"); + case HTTPC_ERROR_CONNECTION_LOST: + return String("connection lost"); + case HTTPC_ERROR_NO_STREAM: + return String("no stream"); + case HTTPC_ERROR_NO_HTTP_SERVER: + return String("no HTTP server"); + case HTTPC_ERROR_TOO_LESS_RAM: + return String("too less ram"); + case HTTPC_ERROR_ENCODING: + return String("Transfer-Encoding not supported"); + case HTTPC_ERROR_STREAM_WRITE: + return String("Stream write error"); + case HTTPC_ERROR_READ_TIMEOUT: + return String("read Timeout"); + default: + return String(); } } @@ -671,7 +694,8 @@ String HTTPClient::errorToString(int error) { * @param value * @param first */ -void HTTPClient::addHeader(const String& name, const String& value, bool first) { +void HTTPClient::addHeader(const String& name, const String& value, bool first) +{ // not allow set of Header handled by code if(!name.equalsIgnoreCase("Connection") && !name.equalsIgnoreCase("User-Agent") && !name.equalsIgnoreCase("Host") && !(_base64Authorization.length() && name.equalsIgnoreCase("Authorization"))) { @@ -689,44 +713,55 @@ void HTTPClient::addHeader(const String& name, const String& value, bool first) } -void HTTPClient::collectHeaders(const char* headerKeys[], const size_t headerKeysCount) { +void HTTPClient::collectHeaders(const char* headerKeys[], const size_t headerKeysCount) +{ _headerKeysCount = headerKeysCount; - if(_currentHeaders) + if(_currentHeaders) { delete[] _currentHeaders; + } _currentHeaders = new RequestArgument[_headerKeysCount]; for(size_t i = 0; i < _headerKeysCount; i++) { _currentHeaders[i].key = headerKeys[i]; } } -String HTTPClient::header(const char* name) { +String HTTPClient::header(const char* name) +{ for(size_t i = 0; i < _headerKeysCount; ++i) { - if(_currentHeaders[i].key == name) + if(_currentHeaders[i].key == name) { return _currentHeaders[i].value; + } } return String(); } -String HTTPClient::header(size_t i) { - if(i < _headerKeysCount) +String HTTPClient::header(size_t i) +{ + if(i < _headerKeysCount) { return _currentHeaders[i].value; + } return String(); } -String HTTPClient::headerName(size_t i) { - if(i < _headerKeysCount) +String HTTPClient::headerName(size_t i) +{ + if(i < _headerKeysCount) { return _currentHeaders[i].key; + } return String(); } -int HTTPClient::headers() { +int HTTPClient::headers() +{ return _headerKeysCount; } -bool HTTPClient::hasHeader(const char* name) { +bool HTTPClient::hasHeader(const char* name) +{ for(size_t i = 0; i < _headerKeysCount; ++i) { - if((_currentHeaders[i].key == name) && (_currentHeaders[i].value.length() > 0)) + if((_currentHeaders[i].key == name) && (_currentHeaders[i].value.length() > 0)) { return true; + } } return false; } @@ -735,7 +770,8 @@ bool HTTPClient::hasHeader(const char* name) { * init TCP connection and handle ssl verify if needed * @return true if connection is ok */ -bool HTTPClient::connect(void) { +bool HTTPClient::connect(void) +{ if(connected()) { DEBUG_HTTPCLIENT("[HTTP-Client] connect. already connected, try reuse!\n"); @@ -779,7 +815,8 @@ bool HTTPClient::connect(void) { * @param type (GET, POST, ...) * @return status */ -bool HTTPClient::sendHeader(const char * type) { +bool HTTPClient::sendHeader(const char * type) +{ if(!connected()) { return false; } @@ -793,9 +830,9 @@ bool HTTPClient::sendHeader(const char * type) { } header += "\r\n" - "Host: " + _host + "\r\n" - "User-Agent: " + _userAgent + "\r\n" - "Connection: "; + "Host: " + _host + "\r\n" + "User-Agent: " + _userAgent + "\r\n" + "Connection: "; if(_reuse) { header += "keep-alive"; @@ -821,7 +858,8 @@ bool HTTPClient::sendHeader(const char * type) { * reads the response from the server * @return int http code */ -int HTTPClient::handleHeaderResponse() { +int HTTPClient::handleHeaderResponse() +{ if(!connected()) { return HTTPC_ERROR_NOT_CONNECTED; @@ -912,7 +950,8 @@ int HTTPClient::handleHeaderResponse() { * @param size int * @return < 0 = error >= 0 = size written */ -int HTTPClient::writeToStreamDataBlock(Stream * stream, int size) { +int HTTPClient::writeToStreamDataBlock(Stream * stream, int size) +{ int buff_size = HTTP_TCP_BUFFER_SIZE; int len = size; int bytesWritten = 0; @@ -1022,7 +1061,8 @@ int HTTPClient::writeToStreamDataBlock(Stream * stream, int size) { * @param error * @return error */ -int HTTPClient::returnError(int error) { +int HTTPClient::returnError(int error) +{ if(error < 0) { DEBUG_HTTPCLIENT("[HTTP-Client][returnError] error(%d): %s\n", error, errorToString(error).c_str()); if(connected()) { diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h index 27db371a5..d8c926359 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h @@ -127,96 +127,97 @@ typedef enum { class TransportTraits; typedef std::unique_ptr TransportTraitsPtr; -class HTTPClient { - public: - HTTPClient(); - ~HTTPClient(); +class HTTPClient +{ +public: + HTTPClient(); + ~HTTPClient(); - bool begin(String url); - bool begin(String url, String httpsFingerprint); - bool begin(String host, uint16_t port, String uri = "/"); - bool begin(String host, uint16_t port, String uri, String httpsFingerprint); - // deprecated, use the overload above instead - bool begin(String host, uint16_t port, String uri, bool https, String httpsFingerprint) __attribute__ ((deprecated)); + bool begin(String url); + bool begin(String url, String httpsFingerprint); + bool begin(String host, uint16_t port, String uri = "/"); + bool begin(String host, uint16_t port, String uri, String httpsFingerprint); + // deprecated, use the overload above instead + bool begin(String host, uint16_t port, String uri, bool https, String httpsFingerprint) __attribute__ ((deprecated)); - void end(void); + void end(void); - bool connected(void); + bool connected(void); - void setReuse(bool reuse); /// keep-alive - void setUserAgent(const char * userAgent); - void setAuthorization(const char * user, const char * password); - void setAuthorization(const char * auth); - void setTimeout(uint16_t timeout); + void setReuse(bool reuse); /// keep-alive + void setUserAgent(const char * userAgent); + void setAuthorization(const char * user, const char * password); + void setAuthorization(const char * auth); + void setTimeout(uint16_t timeout); - void useHTTP10(bool usehttp10 = true); + void useHTTP10(bool usehttp10 = true); - /// request handling - int GET(); - int POST(uint8_t * payload, size_t size); - int POST(String payload); - int sendRequest(const char * type, String payload); - int sendRequest(const char * type, uint8_t * payload = NULL, size_t size = 0); - int sendRequest(const char * type, Stream * stream, size_t size = 0); + /// request handling + int GET(); + int POST(uint8_t * payload, size_t size); + int POST(String payload); + int sendRequest(const char * type, String payload); + int sendRequest(const char * type, uint8_t * payload = NULL, size_t size = 0); + int sendRequest(const char * type, Stream * stream, size_t size = 0); - void addHeader(const String& name, const String& value, bool first = false); + void addHeader(const String& name, const String& value, bool first = false); - /// Response handling - void collectHeaders(const char* headerKeys[], const size_t headerKeysCount); - String header(const char* name); // get request header value by name - String header(size_t i); // get request header value by number - String headerName(size_t i); // get request header name by number - int headers(); // get header count - bool hasHeader(const char* name); // check if header exists + /// Response handling + void collectHeaders(const char* headerKeys[], const size_t headerKeysCount); + String header(const char* name); // get request header value by name + String header(size_t i); // get request header value by number + String headerName(size_t i); // get request header name by number + int headers(); // get header count + bool hasHeader(const char* name); // check if header exists - int getSize(void); + int getSize(void); - WiFiClient& getStream(void); - WiFiClient* getStreamPtr(void); - int writeToStream(Stream* stream); - String getString(void); + WiFiClient& getStream(void); + WiFiClient* getStreamPtr(void); + int writeToStream(Stream* stream); + String getString(void); - static String errorToString(int error); + static String errorToString(int error); - protected: - struct RequestArgument { - String key; - String value; - }; +protected: + struct RequestArgument { + String key; + String value; + }; - void clear(); - int returnError(int error); - bool connect(void); - bool sendHeader(const char * type); - int handleHeaderResponse(); - int writeToStreamDataBlock(Stream * stream, int len); + void clear(); + int returnError(int error); + bool connect(void); + bool sendHeader(const char * type); + int handleHeaderResponse(); + int writeToStreamDataBlock(Stream * stream, int len); - TransportTraitsPtr _transportTraits; - std::unique_ptr _tcp; + TransportTraitsPtr _transportTraits; + std::unique_ptr _tcp; - /// request handling - String _host; - uint16_t _port = 0; - bool _reuse = false; - uint16_t _tcpTimeout = HTTPCLIENT_DEFAULT_TCP_TIMEOUT; - bool _useHTTP10 = false; + /// request handling + String _host; + uint16_t _port = 0; + bool _reuse = false; + uint16_t _tcpTimeout = HTTPCLIENT_DEFAULT_TCP_TIMEOUT; + bool _useHTTP10 = false; - String _uri; - String _protocol; - String _headers; - String _userAgent = "ESP8266HTTPClient"; - String _base64Authorization; + String _uri; + String _protocol; + String _headers; + String _userAgent = "ESP8266HTTPClient"; + String _base64Authorization; - /// Response handling - RequestArgument* _currentHeaders = nullptr; - size_t _headerKeysCount = 0; + /// Response handling + RequestArgument* _currentHeaders = nullptr; + size_t _headerKeysCount = 0; - int _returnCode = 0; - int _size = -1; - bool _canReuse = false; - transferEncoding_t _transferEncoding = HTTPC_TE_IDENTITY; + int _returnCode = 0; + int _size = -1; + bool _canReuse = false; + transferEncoding_t _transferEncoding = HTTPC_TE_IDENTITY; }; diff --git a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp index ee4365385..910d8f901 100644 --- a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp +++ b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp @@ -29,70 +29,70 @@ extern "C" uint32_t _SPIFFS_start; extern "C" uint32_t _SPIFFS_end; -ESP8266HTTPUpdate::ESP8266HTTPUpdate(void) { +ESP8266HTTPUpdate::ESP8266HTTPUpdate(void) +{ } -ESP8266HTTPUpdate::~ESP8266HTTPUpdate(void) { +ESP8266HTTPUpdate::~ESP8266HTTPUpdate(void) +{ } -t_httpUpdate_return ESP8266HTTPUpdate::update(const String& url, const String& currentVersion, - const String& httpsFingerprint, bool reboot) +HTTPUpdateResult ESP8266HTTPUpdate::update(const String& url, const String& currentVersion, + const String& httpsFingerprint, bool reboot) { rebootOnUpdate(reboot); return update(url, currentVersion, httpsFingerprint); } -t_httpUpdate_return ESP8266HTTPUpdate::update(const String& url, const String& currentVersion) +HTTPUpdateResult ESP8266HTTPUpdate::update(const String& url, const String& currentVersion) { HTTPClient http; http.begin(url); return handleUpdate(http, currentVersion, false); } -t_httpUpdate_return ESP8266HTTPUpdate::update(const String& url, const String& currentVersion, - const String& httpsFingerprint) +HTTPUpdateResult ESP8266HTTPUpdate::update(const String& url, const String& currentVersion, + const String& httpsFingerprint) { HTTPClient http; http.begin(url, httpsFingerprint); return handleUpdate(http, currentVersion, false); } - -t_httpUpdate_return ESP8266HTTPUpdate::updateSpiffs(const String& url, const String& currentVersion, const String& httpsFingerprint) +HTTPUpdateResult ESP8266HTTPUpdate::updateSpiffs(const String& url, const String& currentVersion, const String& httpsFingerprint) { HTTPClient http; http.begin(url, httpsFingerprint); return handleUpdate(http, currentVersion, true); } -t_httpUpdate_return ESP8266HTTPUpdate::updateSpiffs(const String& url, const String& currentVersion) +HTTPUpdateResult ESP8266HTTPUpdate::updateSpiffs(const String& url, const String& currentVersion) { HTTPClient http; http.begin(url); return handleUpdate(http, currentVersion, true); } -t_httpUpdate_return ESP8266HTTPUpdate::update(const String& host, uint16_t port, const String& uri, const String& currentVersion, - bool https, const String& httpsFingerprint, bool reboot) +HTTPUpdateResult ESP8266HTTPUpdate::update(const String& host, uint16_t port, const String& uri, const String& currentVersion, + bool https, const String& httpsFingerprint, bool reboot) { rebootOnUpdate(reboot); if (httpsFingerprint.length() == 0) { return update(host, port, uri, currentVersion); - } - else { + } else { return update(host, port, uri, currentVersion, httpsFingerprint); } } -t_httpUpdate_return ESP8266HTTPUpdate::update(const String& host, uint16_t port, const String& uri, - const String& currentVersion) +HTTPUpdateResult ESP8266HTTPUpdate::update(const String& host, uint16_t port, const String& uri, + const String& currentVersion) { HTTPClient http; http.begin(host, port, uri); return handleUpdate(http, currentVersion, false); } -t_httpUpdate_return ESP8266HTTPUpdate::update(const String& host, uint16_t port, const String& url, - const String& currentVersion, const String& httpsFingerprint) +HTTPUpdateResult ESP8266HTTPUpdate::update(const String& host, uint16_t port, const String& url, + const String& currentVersion, const String& httpsFingerprint) { HTTPClient http; http.begin(host, port, url, httpsFingerprint); @@ -104,15 +104,17 @@ t_httpUpdate_return ESP8266HTTPUpdate::update(const String& host, uint16_t port, * return error code as int * @return int error code */ -int ESP8266HTTPUpdate::getLastError(void){ - return _lastError; +int ESP8266HTTPUpdate::getLastError(void) +{ + return _lastError; } /** * return error code as String * @return String error */ -String ESP8266HTTPUpdate::getLastErrorString(void) { +String ESP8266HTTPUpdate::getLastErrorString(void) +{ if(_lastError == 0) { return String(); // no error @@ -132,22 +134,22 @@ String ESP8266HTTPUpdate::getLastErrorString(void) { } switch(_lastError) { - case HTTP_UE_TOO_LESS_SPACE: - return String("To less space"); - case HTTP_UE_SERVER_NOT_REPORT_SIZE: - return String("Server not Report Size"); - case HTTP_UE_SERVER_FILE_NOT_FOUND: - return String("File not Found (404)"); - case HTTP_UE_SERVER_FORBIDDEN: - return String("Forbidden (403)"); - case HTTP_UE_SERVER_WRONG_HTTP_CODE: - return String("Wrong HTTP code"); - case HTTP_UE_SERVER_FAULTY_MD5: - return String("Faulty MD5"); - case HTTP_UE_BIN_VERIFY_HEADER_FAILED: - return String("Verify bin header failed"); - case HTTP_UE_BIN_FOR_WRONG_FLASH: - return String("bin for wrong flash size"); + case HTTP_UE_TOO_LESS_SPACE: + return String("To less space"); + case HTTP_UE_SERVER_NOT_REPORT_SIZE: + return String("Server not Report Size"); + case HTTP_UE_SERVER_FILE_NOT_FOUND: + return String("File not Found (404)"); + case HTTP_UE_SERVER_FORBIDDEN: + return String("Forbidden (403)"); + case HTTP_UE_SERVER_WRONG_HTTP_CODE: + return String("Wrong HTTP code"); + case HTTP_UE_SERVER_FAULTY_MD5: + return String("Faulty MD5"); + case HTTP_UE_BIN_VERIFY_HEADER_FAILED: + return String("Verify bin header failed"); + case HTTP_UE_BIN_FOR_WRONG_FLASH: + return String("bin for wrong flash size"); } return String(); @@ -158,11 +160,12 @@ String ESP8266HTTPUpdate::getLastErrorString(void) { * * @param http HTTPClient * * @param currentVersion const char * - * @return t_httpUpdate_return + * @return HTTPUpdateResult */ -t_httpUpdate_return ESP8266HTTPUpdate::handleUpdate(HTTPClient& http, const String& currentVersion, bool spiffs) { +HTTPUpdateResult ESP8266HTTPUpdate::handleUpdate(HTTPClient& http, const String& currentVersion, bool spiffs) +{ - t_httpUpdate_return ret = HTTP_UPDATE_FAILED; + HTTPUpdateResult ret = HTTP_UPDATE_FAILED; // use HTTP/1.0 for update since the update handler not support any transfer Encoding http.useHTTP10(true); @@ -221,111 +224,111 @@ t_httpUpdate_return ESP8266HTTPUpdate::handleUpdate(HTTPClient& http, const Stri } switch(code) { - case HTTP_CODE_OK: ///< OK (Start Update) - if(len > 0) { - bool startUpdate = true; - if(spiffs) { - size_t spiffsSize = ((size_t) &_SPIFFS_end - (size_t) &_SPIFFS_start); - if(len > (int) spiffsSize) { - DEBUG_HTTP_UPDATE("[httpUpdate] spiffsSize to low (%d) needed: %d\n", spiffsSize, len); - startUpdate = false; - } - } else { - if(len > (int) ESP.getFreeSketchSpace()) { - DEBUG_HTTP_UPDATE("[httpUpdate] FreeSketchSpace to low (%d) needed: %d\n", ESP.getFreeSketchSpace(), len); - startUpdate = false; - } - } - - if(!startUpdate) { - _lastError = HTTP_UE_TOO_LESS_SPACE; - ret = HTTP_UPDATE_FAILED; - } else { - - WiFiClient * tcp = http.getStreamPtr(); - - WiFiUDP::stopAll(); - WiFiClient::stopAllExcept(tcp); - - delay(100); - - int command; - - if(spiffs) { - command = U_SPIFFS; - DEBUG_HTTP_UPDATE("[httpUpdate] runUpdate spiffs...\n"); - } else { - command = U_FLASH; - DEBUG_HTTP_UPDATE("[httpUpdate] runUpdate flash...\n"); - } - - if(!spiffs) { - uint8_t buf[4]; - if(tcp->peekBytes(&buf[0], 4) != 4) { - DEBUG_HTTP_UPDATE("[httpUpdate] peekBytes magic header failed\n"); - _lastError = HTTP_UE_BIN_VERIFY_HEADER_FAILED; - http.end(); - return HTTP_UPDATE_FAILED; - } - - // check for valid first magic byte - if(buf[0] != 0xE9) { - DEBUG_HTTP_UPDATE("[httpUpdate] magic header not starts with 0xE9\n"); - _lastError = HTTP_UE_BIN_VERIFY_HEADER_FAILED; - http.end(); - return HTTP_UPDATE_FAILED; - - } - - uint32_t bin_flash_size = ESP.magicFlashChipSize((buf[3] & 0xf0) >> 4); - - // check if new bin fits to SPI flash - if(bin_flash_size > ESP.getFlashChipRealSize()) { - DEBUG_HTTP_UPDATE("[httpUpdate] magic header, new bin not fits SPI Flash\n"); - _lastError = HTTP_UE_BIN_FOR_WRONG_FLASH; - http.end(); - return HTTP_UPDATE_FAILED; - } - } - - if(runUpdate(*tcp, len, http.header("x-MD5"), command)) { - ret = HTTP_UPDATE_OK; - DEBUG_HTTP_UPDATE("[httpUpdate] Update ok\n"); - http.end(); - - if(_rebootOnUpdate) { - ESP.restart(); - } - - } else { - ret = HTTP_UPDATE_FAILED; - DEBUG_HTTP_UPDATE("[httpUpdate] Update failed\n"); - } + case HTTP_CODE_OK: ///< OK (Start Update) + if(len > 0) { + bool startUpdate = true; + if(spiffs) { + size_t spiffsSize = ((size_t) &_SPIFFS_end - (size_t) &_SPIFFS_start); + if(len > (int) spiffsSize) { + DEBUG_HTTP_UPDATE("[httpUpdate] spiffsSize to low (%d) needed: %d\n", spiffsSize, len); + startUpdate = false; } } else { - _lastError = HTTP_UE_SERVER_NOT_REPORT_SIZE; - ret = HTTP_UPDATE_FAILED; - DEBUG_HTTP_UPDATE("[httpUpdate] Content-Length is 0 or not set by Server?!\n"); + if(len > (int) ESP.getFreeSketchSpace()) { + DEBUG_HTTP_UPDATE("[httpUpdate] FreeSketchSpace to low (%d) needed: %d\n", ESP.getFreeSketchSpace(), len); + startUpdate = false; + } } - break; - case HTTP_CODE_NOT_MODIFIED: - ///< Not Modified (No updates) - ret = HTTP_UPDATE_NO_UPDATES; - break; - case HTTP_CODE_NOT_FOUND: - _lastError = HTTP_UE_SERVER_FILE_NOT_FOUND; + + if(!startUpdate) { + _lastError = HTTP_UE_TOO_LESS_SPACE; + ret = HTTP_UPDATE_FAILED; + } else { + + WiFiClient * tcp = http.getStreamPtr(); + + WiFiUDP::stopAll(); + WiFiClient::stopAllExcept(tcp); + + delay(100); + + int command; + + if(spiffs) { + command = U_SPIFFS; + DEBUG_HTTP_UPDATE("[httpUpdate] runUpdate spiffs...\n"); + } else { + command = U_FLASH; + DEBUG_HTTP_UPDATE("[httpUpdate] runUpdate flash...\n"); + } + + if(!spiffs) { + uint8_t buf[4]; + if(tcp->peekBytes(&buf[0], 4) != 4) { + DEBUG_HTTP_UPDATE("[httpUpdate] peekBytes magic header failed\n"); + _lastError = HTTP_UE_BIN_VERIFY_HEADER_FAILED; + http.end(); + return HTTP_UPDATE_FAILED; + } + + // check for valid first magic byte + if(buf[0] != 0xE9) { + DEBUG_HTTP_UPDATE("[httpUpdate] magic header not starts with 0xE9\n"); + _lastError = HTTP_UE_BIN_VERIFY_HEADER_FAILED; + http.end(); + return HTTP_UPDATE_FAILED; + + } + + uint32_t bin_flash_size = ESP.magicFlashChipSize((buf[3] & 0xf0) >> 4); + + // check if new bin fits to SPI flash + if(bin_flash_size > ESP.getFlashChipRealSize()) { + DEBUG_HTTP_UPDATE("[httpUpdate] magic header, new bin not fits SPI Flash\n"); + _lastError = HTTP_UE_BIN_FOR_WRONG_FLASH; + http.end(); + return HTTP_UPDATE_FAILED; + } + } + + if(runUpdate(*tcp, len, http.header("x-MD5"), command)) { + ret = HTTP_UPDATE_OK; + DEBUG_HTTP_UPDATE("[httpUpdate] Update ok\n"); + http.end(); + + if(_rebootOnUpdate) { + ESP.restart(); + } + + } else { + ret = HTTP_UPDATE_FAILED; + DEBUG_HTTP_UPDATE("[httpUpdate] Update failed\n"); + } + } + } else { + _lastError = HTTP_UE_SERVER_NOT_REPORT_SIZE; ret = HTTP_UPDATE_FAILED; - break; - case HTTP_CODE_FORBIDDEN: - _lastError = HTTP_UE_SERVER_FORBIDDEN; - ret = HTTP_UPDATE_FAILED; - break; - default: - _lastError = HTTP_UE_SERVER_WRONG_HTTP_CODE; - ret = HTTP_UPDATE_FAILED; - DEBUG_HTTP_UPDATE("[httpUpdate] HTTP Code is (%d)\n", code); - //http.writeToStream(&Serial1); - break; + DEBUG_HTTP_UPDATE("[httpUpdate] Content-Length is 0 or not set by Server?!\n"); + } + break; + case HTTP_CODE_NOT_MODIFIED: + ///< Not Modified (No updates) + ret = HTTP_UPDATE_NO_UPDATES; + break; + case HTTP_CODE_NOT_FOUND: + _lastError = HTTP_UE_SERVER_FILE_NOT_FOUND; + ret = HTTP_UPDATE_FAILED; + break; + case HTTP_CODE_FORBIDDEN: + _lastError = HTTP_UE_SERVER_FORBIDDEN; + ret = HTTP_UPDATE_FAILED; + break; + default: + _lastError = HTTP_UE_SERVER_WRONG_HTTP_CODE; + ret = HTTP_UPDATE_FAILED; + DEBUG_HTTP_UPDATE("[httpUpdate] HTTP Code is (%d)\n", code); + //http.writeToStream(&Serial1); + break; } http.end(); @@ -339,7 +342,8 @@ t_httpUpdate_return ESP8266HTTPUpdate::handleUpdate(HTTPClient& http, const Stri * @param md5 String * @return true if Update ok */ -bool ESP8266HTTPUpdate::runUpdate(Stream& in, uint32_t size, String md5, int command) { +bool ESP8266HTTPUpdate::runUpdate(Stream& in, uint32_t size, String md5, int command) +{ StreamString error; diff --git a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h index 765cc3569..af6931b15 100644 --- a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h +++ b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h @@ -60,45 +60,49 @@ enum HTTPUpdateResult { typedef HTTPUpdateResult t_httpUpdate_return; // backward compatibility -class ESP8266HTTPUpdate { - public: - ESP8266HTTPUpdate(void); - ~ESP8266HTTPUpdate(void); +class ESP8266HTTPUpdate +{ +public: + ESP8266HTTPUpdate(void); + ~ESP8266HTTPUpdate(void); - void rebootOnUpdate(bool reboot) { _rebootOnUpdate = reboot; } + void rebootOnUpdate(bool reboot) + { + _rebootOnUpdate = reboot; + } - // This function is deprecated, use rebootOnUpdate and the next one instead - t_httpUpdate_return update(const String& url, const String& currentVersion, - const String& httpsFingerprint, bool reboot) __attribute__((deprecated)); - t_httpUpdate_return update(const String& url, const String& currentVersion = ""); - t_httpUpdate_return update(const String& url, const String& currentVersion, - const String& httpsFingerprint); + // This function is deprecated, use rebootOnUpdate and the next one instead + t_httpUpdate_return update(const String& url, const String& currentVersion, + const String& httpsFingerprint, bool reboot) __attribute__((deprecated)); + t_httpUpdate_return update(const String& url, const String& currentVersion = ""); + t_httpUpdate_return update(const String& url, const String& currentVersion, + const String& httpsFingerprint); - // This function is deprecated, use one of the overloads below along with rebootOnUpdate - t_httpUpdate_return update(const String& host, uint16_t port, const String& uri, const String& currentVersion, - bool https, const String& httpsFingerprint, bool reboot) __attribute__((deprecated)); + // This function is deprecated, use one of the overloads below along with rebootOnUpdate + t_httpUpdate_return update(const String& host, uint16_t port, const String& uri, const String& currentVersion, + bool https, const String& httpsFingerprint, bool reboot) __attribute__((deprecated)); - t_httpUpdate_return update(const String& host, uint16_t port, const String& uri = "/", - const String& currentVersion = ""); - t_httpUpdate_return update(const String& host, uint16_t port, const String& url, - const String& currentVersion, const String& httpsFingerprint); + t_httpUpdate_return update(const String& host, uint16_t port, const String& uri = "/", + const String& currentVersion = ""); + t_httpUpdate_return update(const String& host, uint16_t port, const String& url, + const String& currentVersion, const String& httpsFingerprint); - // This function is deprecated, use rebootOnUpdate and the next one instead - t_httpUpdate_return updateSpiffs(const String& url, const String& currentVersion, - const String& httpsFingerprint, bool reboot) __attribute__((deprecated)); - t_httpUpdate_return updateSpiffs(const String& url, const String& currentVersion = ""); - t_httpUpdate_return updateSpiffs(const String& url, const String& currentVersion, const String& httpsFingerprint); + // This function is deprecated, use rebootOnUpdate and the next one instead + t_httpUpdate_return updateSpiffs(const String& url, const String& currentVersion, + const String& httpsFingerprint, bool reboot) __attribute__((deprecated)); + t_httpUpdate_return updateSpiffs(const String& url, const String& currentVersion = ""); + t_httpUpdate_return updateSpiffs(const String& url, const String& currentVersion, const String& httpsFingerprint); - int getLastError(void); - String getLastErrorString(void); + int getLastError(void); + String getLastErrorString(void); - protected: - t_httpUpdate_return handleUpdate(HTTPClient& http, const String& currentVersion, bool spiffs = false); - bool runUpdate(Stream& in, uint32_t size, String md5, int command = U_FLASH); +protected: + t_httpUpdate_return handleUpdate(HTTPClient& http, const String& currentVersion, bool spiffs = false); + bool runUpdate(Stream& in, uint32_t size, String md5, int command = U_FLASH); - int _lastError; - bool _rebootOnUpdate = true; + int _lastError; + bool _rebootOnUpdate = true; }; extern ESP8266HTTPUpdate ESPhttpUpdate; From a455f22587869fe58983cb5931072301c6242a46 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 5 Apr 2016 02:21:42 +0300 Subject: [PATCH 6/8] HTTPClient, HTTPUpdate: save some RAM by moving strings into flash --- .../src/ESP8266HTTPClient.cpp | 54 ++++++++++--------- .../ESP8266HTTPClient/src/ESP8266HTTPClient.h | 2 +- .../src/ESP8266httpUpdate.cpp | 40 +++++++------- 3 files changed, 50 insertions(+), 46 deletions(-) diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp index 033fd3e84..bad89074b 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp @@ -256,7 +256,7 @@ void HTTPClient::setReuse(bool reuse) * set User Agent * @param userAgent const char * */ -void HTTPClient::setUserAgent(const char * userAgent) +void HTTPClient::setUserAgent(const String& userAgent) { _userAgent = userAgent; } @@ -359,7 +359,7 @@ int HTTPClient::sendRequest(const char * type, uint8_t * payload, size_t size) } if(payload && size > 0) { - addHeader("Content-Length", String(size)); + addHeader(F("Content-Length"), String(size)); } // send Header @@ -644,8 +644,8 @@ String HTTPClient::getString(void) if(_size) { // try to reserve needed memmory if(!sstring.reserve((_size + 1))) { - DEBUG_HTTPCLIENT("[HTTP-Client][getString] too less memory to reserve as string! need: %d\n", (_size + 1)); - return String("--too less memory--"); + DEBUG_HTTPCLIENT("[HTTP-Client][getString] not enough memory to reserve a string! need: %d\n", (_size + 1)); + return ""; } } @@ -662,27 +662,27 @@ String HTTPClient::errorToString(int error) { switch(error) { case HTTPC_ERROR_CONNECTION_REFUSED: - return String("connection refused"); + return F("connection refused"); case HTTPC_ERROR_SEND_HEADER_FAILED: - return String("send header failed"); + return F("send header failed"); case HTTPC_ERROR_SEND_PAYLOAD_FAILED: - return String("send payload failed"); + return F("send payload failed"); case HTTPC_ERROR_NOT_CONNECTED: - return String("not connected"); + return F("not connected"); case HTTPC_ERROR_CONNECTION_LOST: - return String("connection lost"); + return F("connection lost"); case HTTPC_ERROR_NO_STREAM: - return String("no stream"); + return F("no stream"); case HTTPC_ERROR_NO_HTTP_SERVER: - return String("no HTTP server"); + return F("no HTTP server"); case HTTPC_ERROR_TOO_LESS_RAM: - return String("too less ram"); + return F("too less ram"); case HTTPC_ERROR_ENCODING: - return String("Transfer-Encoding not supported"); + return F("Transfer-Encoding not supported"); case HTTPC_ERROR_STREAM_WRITE: - return String("Stream write error"); + return F("Stream write error"); case HTTPC_ERROR_READ_TIMEOUT: - return String("read Timeout"); + return F("read Timeout"); default: return String(); } @@ -698,7 +698,10 @@ void HTTPClient::addHeader(const String& name, const String& value, bool first) { // not allow set of Header handled by code - if(!name.equalsIgnoreCase("Connection") && !name.equalsIgnoreCase("User-Agent") && !name.equalsIgnoreCase("Host") && !(_base64Authorization.length() && name.equalsIgnoreCase("Authorization"))) { + if(!name.equalsIgnoreCase(F("Connection")) && + !name.equalsIgnoreCase(F("User-Agent")) && + !name.equalsIgnoreCase(F("Host")) && + !(name.equalsIgnoreCase(F("Authorization")) && _base64Authorization.length())){ String headerLine = name; headerLine += ": "; headerLine += value; @@ -821,7 +824,7 @@ bool HTTPClient::sendHeader(const char * type) return false; } - String header = String(type) + " " + _uri + " HTTP/1."; + String header = String(type) + " " + _uri + F(" HTTP/1."); if(_useHTTP10) { header += "0"; @@ -829,24 +832,25 @@ bool HTTPClient::sendHeader(const char * type) header += "1"; } - header += "\r\n" - "Host: " + _host + "\r\n" - "User-Agent: " + _userAgent + "\r\n" - "Connection: "; + header += String(F("\r\nHost: ")) + _host + + F("\r\nUser-Agent: ") + _userAgent + + F("\r\nConnection: "); if(_reuse) { - header += "keep-alive"; + header += F("keep-alive"); } else { - header += "close"; + header += F("close"); } header += "\r\n"; if(!_useHTTP10) { - header += "Accept-Encoding: identity;q=1,chunked;q=0.1,*;q=0\r\n"; + header += F("Accept-Encoding: identity;q=1,chunked;q=0.1,*;q=0\r\n"); } if(_base64Authorization.length()) { - header += "Authorization: Basic " + _base64Authorization + "\r\n"; + header += F("Authorization: Basic "); + header += _base64Authorization; + header += "\r\n"; } header += _headers + "\r\n"; diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h index d8c926359..1f5ef7fbc 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h @@ -145,7 +145,7 @@ public: bool connected(void); void setReuse(bool reuse); /// keep-alive - void setUserAgent(const char * userAgent); + void setUserAgent(const String& userAgent); void setAuthorization(const char * user, const char * password); void setAuthorization(const char * auth); void setTimeout(uint16_t timeout); diff --git a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp index 910d8f901..b0020aad7 100644 --- a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp +++ b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp @@ -125,31 +125,31 @@ String ESP8266HTTPUpdate::getLastErrorString(void) StreamString error; Update.printError(error); error.trim(); // remove line ending - return "Update error: " + error; + return String(F("Update error: ")) + error; } // error from http client if(_lastError > -100) { - return "HTTP error: " + HTTPClient::errorToString(_lastError); + return String(F("HTTP error: ")) + HTTPClient::errorToString(_lastError); } switch(_lastError) { case HTTP_UE_TOO_LESS_SPACE: - return String("To less space"); + return F("To less space"); case HTTP_UE_SERVER_NOT_REPORT_SIZE: - return String("Server not Report Size"); + return F("Server not Report Size"); case HTTP_UE_SERVER_FILE_NOT_FOUND: - return String("File not Found (404)"); + return F("File not Found (404)"); case HTTP_UE_SERVER_FORBIDDEN: - return String("Forbidden (403)"); + return F("Forbidden (403)"); case HTTP_UE_SERVER_WRONG_HTTP_CODE: - return String("Wrong HTTP code"); + return F("Wrong HTTP code"); case HTTP_UE_SERVER_FAULTY_MD5: - return String("Faulty MD5"); + return F("Faulty MD5"); case HTTP_UE_BIN_VERIFY_HEADER_FAILED: - return String("Verify bin header failed"); + return F("Verify bin header failed"); case HTTP_UE_BIN_FOR_WRONG_FLASH: - return String("bin for wrong flash size"); + return F("bin for wrong flash size"); } return String(); @@ -170,22 +170,22 @@ HTTPUpdateResult ESP8266HTTPUpdate::handleUpdate(HTTPClient& http, const String& // use HTTP/1.0 for update since the update handler not support any transfer Encoding http.useHTTP10(true); http.setTimeout(8000); - 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()); + http.setUserAgent(F("ESP8266-http-Update")); + http.addHeader(F("x-ESP8266-STA-MAC"), WiFi.macAddress()); + http.addHeader(F("x-ESP8266-AP-MAC"), WiFi.softAPmacAddress()); + http.addHeader(F("x-ESP8266-free-space"), String(ESP.getFreeSketchSpace())); + http.addHeader(F("x-ESP8266-sketch-size"), String(ESP.getSketchSize())); + http.addHeader(F("x-ESP8266-chip-size"), String(ESP.getFlashChipRealSize())); + http.addHeader(F("x-ESP8266-sdk-version"), ESP.getSdkVersion()); if(spiffs) { - http.addHeader("x-ESP8266-mode", "spiffs"); + http.addHeader(F("x-ESP8266-mode"), F("spiffs")); } else { - http.addHeader("x-ESP8266-mode", "sketch"); + http.addHeader(F("x-ESP8266-mode"), F("sketch")); } if(currentVersion && currentVersion[0] != 0x00) { - http.addHeader("x-ESP8266-version", currentVersion); + http.addHeader(F("x-ESP8266-version"), currentVersion); } const char * headerkeys[] = { "x-MD5" }; From 46380003d5f31a6a77029c4fb928dbb738ca4f19 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 13 Apr 2016 14:02:10 +0300 Subject: [PATCH 7/8] Fix compilation when debug is enabled --- libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp index bad89074b..70ac6450e 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp @@ -163,7 +163,7 @@ bool HTTPClient::begin(String url) _port = 443; } } else { - DEBUG_HTTPCLIENT("[HTTP-Client][begin] protocol: %s unknown?!\n", protocol.c_str()); + DEBUG_HTTPCLIENT("[HTTP-Client][begin] protocol: %s unknown?!\n", _protocol.c_str()); return false; } _transportTraits = TransportTraitsPtr(new TransportTraits()); From 84daa1a108d0d29b45df94a70da12298ef0beae8 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 13 Apr 2016 14:03:11 +0300 Subject: [PATCH 8/8] Add explicit cast (#1903) --- libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp index 70ac6450e..383af599a 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp @@ -855,7 +855,7 @@ bool HTTPClient::sendHeader(const char * type) header += _headers + "\r\n"; - return (_tcp->write(header.c_str(), header.length()) == header.length()); + return (_tcp->write((const uint8_t *) header.c_str(), header.length()) == header.length()); } /**