diff --git a/cores/esp8266/Stream.h b/cores/esp8266/Stream.h index f39bb423f2..322ada96d5 100644 --- a/cores/esp8266/Stream.h +++ b/cores/esp8266/Stream.h @@ -65,7 +65,7 @@ class Stream: public Print { // parsing methods - void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second + virtual void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second unsigned long getTimeout () const { return _timeout; } bool find(const char *target); // reads data from the stream until the target string is found diff --git a/libraries/ESP8266HTTPClient/examples/BasicHttpsClient/BasicHttpsClient.ino b/libraries/ESP8266HTTPClient/examples/BasicHttpsClient/BasicHttpsClient.ino index 62bfc93a9a..3eb3c59acc 100644 --- a/libraries/ESP8266HTTPClient/examples/BasicHttpsClient/BasicHttpsClient.ino +++ b/libraries/ESP8266HTTPClient/examples/BasicHttpsClient/BasicHttpsClient.ino @@ -41,11 +41,33 @@ void loop() { std::unique_ptr client(new BearSSL::WiFiClientSecure); +#if 1 // 1=secure, 0=insecure + client->setFingerprint(fingerprint_sni_cloudflaressl_com); + + // date needs to be setup + configTime("UTC", "pool.ntp.org"); + time_t now; + while (time(&now) < 24 * 3600) { + Serial.println("waiting for NTP time to be set..."); + delay(1000); + } + Serial.printf("date: %s", ctime(&now)); + +#else // Or, if you happy to ignore the SSL certificate, then use the following line instead: - // client->setInsecure(); + client->setInsecure(); +#endif HTTPClient https; + https.setWallTime(10000); // do not exceed 10s while getting data + client->setWallTime(20000); // do not exceed 20s during handshake + + // Try to reduce RAM footprint when SSL server allows it + constexpr int sslbufsize = 1024; + bool mfln = client->probeMaxFragmentLength(jigsaw_host, jigsaw_port, sslbufsize); + Serial.printf("Can reduce SSL footprint to %d bytes in RAM: %s\n", sslbufsize, mfln ? "yes" : "no"); + if (mfln) { client->setBufferSizes(sslbufsize, sslbufsize); } Serial.print("[HTTPS] begin...\n"); if (https.begin(*client, jigsaw_host, jigsaw_port)) { // HTTPS diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp index 480699e453..3e1a345e70 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp @@ -216,7 +216,7 @@ void HTTPClient::disconnect(bool preserveClient) } if(_reuse && _canReuse) { - DEBUG_HTTPCLIENT("[HTTP-Client][end] tcp keep open for reuse\n"); + DEBUG_HTTPCLIENT("[HTTP-Client][end] tcp kept open for reuse\n"); } else { DEBUG_HTTPCLIENT("[HTTP-Client][end] tcp stop\n"); if(_client) { @@ -303,15 +303,12 @@ void HTTPClient::setAuthorization(String auth) } /** - * set the timeout for the TCP connection + * set the wall time for operations * @param timeout unsigned int */ -void HTTPClient::setTimeout(uint16_t timeout) +void HTTPClient::setWallTime(unsigned long wallTime) { - _tcpTimeout = timeout; - if(connected()) { - _client->setTimeout(timeout); - } + _wallTime.reset(wallTime?: esp8266::polledTimeout::oneShotMs::neverExpires); } /** @@ -794,8 +791,6 @@ bool HTTPClient::connect(void) return false; } - _client->setTimeout(_tcpTimeout); - if(!_client->connect(_host.c_str(), _port)) { DEBUG_HTTPCLIENT("[HTTP-Client] failed connect to %s:%u\n", _host.c_str(), _port); return false; @@ -879,7 +874,6 @@ bool HTTPClient::sendHeader(const char * type) */ int HTTPClient::handleHeaderResponse() { - if(!connected()) { return HTTPC_ERROR_NOT_CONNECTED; } @@ -891,7 +885,7 @@ int HTTPClient::handleHeaderResponse() String transferEncoding; _transferEncoding = HTTPC_TE_IDENTITY; - unsigned long lastDataTime = millis(); + _wallTime.reset(); while(connected()) { size_t len = _client->available(); @@ -899,8 +893,6 @@ int HTTPClient::handleHeaderResponse() int headerSeparator = -1; String headerLine = _client->readStringUntil('\n'); - lastDataTime = millis(); - DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] RX: '%s'\n", headerLine.c_str()); if (headerLine.startsWith(F("HTTP/1."))) { @@ -978,7 +970,7 @@ int HTTPClient::handleHeaderResponse() } } else { - if((millis() - lastDataTime) > _tcpTimeout) { + if(_wallTime) { return HTTPC_ERROR_READ_TIMEOUT; } esp_yield(); diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h index bc8a42d33e..97a34d44d0 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h @@ -29,6 +29,7 @@ #include #include #include +#include #include @@ -152,7 +153,7 @@ typedef std::unique_ptr TransportTraitsPtr; class HTTPClient { public: - HTTPClient() = default; + HTTPClient(): _wallTime(HTTPCLIENT_DEFAULT_TCP_TIMEOUT) {}; ~HTTPClient() = default; HTTPClient(HTTPClient&&) = default; HTTPClient& operator=(HTTPClient&&) = default; @@ -177,7 +178,8 @@ class HTTPClient void setAuthorization(const char * user, const char * password); void setAuthorization(const char * auth); void setAuthorization(String auth); - void setTimeout(uint16_t timeout); + void setWallTime(unsigned long wallTime); + [[deprecated("use setWallTime() instead")]] void setTimeout(unsigned long wallTime) { setWallTime(wallTime); } // Redirections void setFollowRedirects(followRedirects_t follow); @@ -256,7 +258,7 @@ class HTTPClient String _host; uint16_t _port = 0; bool _reuse = true; - uint16_t _tcpTimeout = HTTPCLIENT_DEFAULT_TCP_TIMEOUT; + esp8266::polledTimeout::oneShotMs _wallTime; bool _useHTTP10 = false; String _uri; @@ -314,6 +316,7 @@ int HTTPClient::writeToStream(S * output) } } else if(_transferEncoding == HTTPC_TE_CHUNKED) { int size = 0; + _wallTime.reset(); while(1) { if(!connected()) { return returnError(HTTPC_ERROR_CONNECTION_LOST); @@ -360,6 +363,10 @@ int HTTPClient::writeToStream(S * output) return returnError(HTTPC_ERROR_READ_TIMEOUT); } + if (_wallTime) { + return returnError(HTTPC_ERROR_READ_TIMEOUT); + } + esp_yield(); } } else { diff --git a/libraries/ESP8266WiFi/src/WiFiClient.cpp b/libraries/ESP8266WiFi/src/WiFiClient.cpp index fb10209ec0..42120e99ad 100644 --- a/libraries/ESP8266WiFi/src/WiFiClient.cpp +++ b/libraries/ESP8266WiFi/src/WiFiClient.cpp @@ -216,7 +216,7 @@ size_t WiFiClient::write(const uint8_t *buf, size_t size) { return 0; } - _client->setTimeout(_timeout); + _client->setTimeout(_timeout); // context write uses timeout return _client->write((const char*)buf, size); } @@ -238,7 +238,6 @@ size_t WiFiClient::write_P(PGM_P buf, size_t size) { return 0; } - _client->setTimeout(_timeout); StreamConstPtr nopeek(buf, size); return nopeek.sendAll(this); } @@ -463,3 +462,10 @@ void WiFiClient::peekConsume (size_t consume) if (_client) _client->peekConsume(consume); } + +void WiFiClient::setTimeout (unsigned long timeout) +{ + Client::setTimeout(timeout); + if (_client) + _client->setTimeout(timeout); +} diff --git a/libraries/ESP8266WiFi/src/WiFiClient.h b/libraries/ESP8266WiFi/src/WiFiClient.h index 711adb6204..c9a8a30338 100644 --- a/libraries/ESP8266WiFi/src/WiFiClient.h +++ b/libraries/ESP8266WiFi/src/WiFiClient.h @@ -64,6 +64,7 @@ class WiFiClient : public Client, public SList { // - https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rh-copy virtual std::unique_ptr clone() const; + virtual void setTimeout (unsigned long timeout) override; virtual uint8_t status(); virtual int connect(IPAddress ip, uint16_t port) override; virtual int connect(const char *host, uint16_t port) override; diff --git a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp index 7bc0c70df6..84737ef283 100644 --- a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp +++ b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp @@ -31,7 +31,6 @@ extern "C" { } #include "debug.h" #include "ESP8266WiFi.h" -#include "PolledTimeout.h" #include "WiFiClient.h" #include "WiFiClientSecureBearSSL.h" #include "StackThunk.h" @@ -68,10 +67,9 @@ extern "C" { namespace BearSSL { -void WiFiClientSecureCtx::_clear() { - // TLS handshake may take more than the 5 second default timeout - _timeout = 15000; +constexpr auto defaultWallTime = 10000UL; +void WiFiClientSecureCtx::_clear() { _sc = nullptr; _sc_svr = nullptr; _eng = nullptr; @@ -103,7 +101,7 @@ void WiFiClientSecureCtx::_clearAuthenticationSettings() { } -WiFiClientSecureCtx::WiFiClientSecureCtx() : WiFiClient() { +WiFiClientSecureCtx::WiFiClientSecureCtx() : WiFiClient(), _wallTime(defaultWallTime) { _clear(); _clearAuthenticationSettings(); _certStore = nullptr; // Don't want to remove cert store on a clear, should be long lived @@ -124,7 +122,7 @@ WiFiClientSecureCtx::~WiFiClientSecureCtx() { WiFiClientSecureCtx::WiFiClientSecureCtx(ClientContext* client, const X509List *chain, const PrivateKey *sk, int iobuf_in_size, int iobuf_out_size, ServerSessions *cache, - const X509List *client_CA_ta, int tls_min, int tls_max) { + const X509List *client_CA_ta, int tls_min, int tls_max): _wallTime(defaultWallTime) { _clear(); _clearAuthenticationSettings(); stack_thunk_add_ref(); @@ -145,7 +143,7 @@ WiFiClientSecureCtx::WiFiClientSecureCtx(ClientContext *client, const X509List *chain, unsigned cert_issuer_key_type, const PrivateKey *sk, int iobuf_in_size, int iobuf_out_size, ServerSessions *cache, - const X509List *client_CA_ta, int tls_min, int tls_max) { + const X509List *client_CA_ta, int tls_min, int tls_max): _wallTime(defaultWallTime) { _clear(); _clearAuthenticationSettings(); stack_thunk_add_ref(); @@ -204,7 +202,10 @@ bool WiFiClientSecureCtx::stop(unsigned int maxWaitMs) { } bool WiFiClientSecureCtx::flush(unsigned int maxWaitMs) { + auto savedTimeout = _timeout; + _timeout = std::max(1U, maxWaitMs); (void) _run_until(BR_SSL_SENDAPP); + _timeout = savedTimeout; return WiFiClient::flush(maxWaitMs); } @@ -246,7 +247,6 @@ void WiFiClientSecureCtx::_freeSSL() { _recvapp_len = 0; // This connection is toast _handshake_done = false; - _timeout = 15000; } bool WiFiClientSecureCtx::_clientConnected() { @@ -462,7 +462,7 @@ size_t WiFiClientSecureCtx::peekBytes(uint8_t *buffer, size_t length) { } _startMillis = millis(); - while ((_pollRecvBuffer() < (int) length) && ((millis() - _startMillis) < 5000)) { + while ((_pollRecvBuffer() < (int)length) && ((millis() - _startMillis) < _timeout)) { yield(); } @@ -539,6 +539,7 @@ int WiFiClientSecureCtx::_run_until(unsigned target, bool blocking) { br_ssl_engine_sendrec_ack(_eng, wlen); } no_work = 0; + loopTimeout.reset(); continue; } @@ -582,6 +583,7 @@ int WiFiClientSecureCtx::_run_until(unsigned target, bool blocking) { br_ssl_engine_recvrec_ack(_eng, rlen); } no_work = 0; + loopTimeout.reset(); continue; } } @@ -602,6 +604,14 @@ int WiFiClientSecureCtx::_run_until(unsigned target, bool blocking) { } bool WiFiClientSecureCtx::_wait_for_handshake() { + +#if defined(DEBUG_ESP_PORT) + if constexpr (F_CPU != 160000000L) { + DEBUG_ESP_PORT.printf_P((PGM_P)PSTR("BSSL: Please enable 160MHz build\n")); + } +#endif + + _wallTime.reset(); _handshake_done = false; while (!_handshake_done && _clientConnected()) { int ret = _run_until(BR_SSL_SENDAPP); @@ -612,6 +622,10 @@ bool WiFiClientSecureCtx::_wait_for_handshake() { if (br_ssl_engine_current_state(_eng) & BR_SSL_SENDAPP) { _handshake_done = true; } + if (_wallTime) { + DEBUG_BSSL("handshake too long\n"); + break; + } optimistic_yield(1000); } return _handshake_done; @@ -1206,9 +1220,6 @@ bool WiFiClientSecureCtx::_connectSSL(const char* hostName) { _x509_insecure = nullptr; _x509_knownkey = nullptr; - // reduce timeout after successful handshake to fail fast if server stop accepting our data for whathever reason - if (ret) _timeout = 5000; - return ret; } @@ -1673,4 +1684,11 @@ bool WiFiClientSecure::probeMaxFragmentLength(IPAddress ip, uint16_t port, uint1 return _SendAbort(probe, supportsLen); } -}; +void WiFiClientSecure::setTimeout (unsigned long timeout) +{ + WiFiClient::setTimeout(timeout); + if (_ctx) + _ctx->setTimeout(timeout); +} + +}; // namespace BearSSL diff --git a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.h b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.h index e0cb44928f..ca27bca936 100644 --- a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.h +++ b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.h @@ -28,6 +28,7 @@ #include #include "BearSSLHelpers.h" #include "CertStoreBearSSL.h" +#include "PolledTimeout.h" namespace BearSSL { @@ -147,6 +148,9 @@ class WiFiClientSecureCtx : public WiFiClient { // consume bytes after use (see peekBuffer) virtual void peekConsume (size_t consume) override; + // install a wall-time used during handshake + void setWallTime (unsigned long wallTime) { _wallTime.reset(wallTime?: esp8266::polledTimeout::oneShotMs::neverExpires); } + protected: bool _connectSSL(const char *hostName); // Do initial SSL handshake @@ -235,6 +239,8 @@ class WiFiClientSecureCtx : public WiFiClient { bool _installServerX509Validator(const X509List *client_CA_ta); // Setup X509 client cert validation, if supplied uint8_t *_streamLoad(Stream& stream, size_t size); + + esp8266::polledTimeout::oneShotMs _wallTime; }; // class WiFiClientSecureCtx @@ -373,6 +379,12 @@ class WiFiClientSecure : public WiFiClient { void disableKeepAlive() override { _ctx->disableKeepAlive(); }; + // override setTimeout and forward to context + virtual void setTimeout (unsigned long timeout) override; + + // install a wall-time used during handshake + void setWallTime (unsigned long wallTime) { _ctx->setWallTime(wallTime); } + private: std::shared_ptr _ctx; diff --git a/libraries/ESP8266httpUpdate/examples/httpUpdate/httpUpdate.ino b/libraries/ESP8266httpUpdate/examples/httpUpdate/httpUpdate.ino index b9da7f8cb4..ed7f38f61b 100644 --- a/libraries/ESP8266httpUpdate/examples/httpUpdate/httpUpdate.ino +++ b/libraries/ESP8266httpUpdate/examples/httpUpdate/httpUpdate.ino @@ -27,7 +27,7 @@ void setup() { Serial.println(); - ESPhttpUpdate.setClientTimeout(2000); // default was 8000 + ESPhttpUpdate.setWallTime(2000); // default was 8000 WiFi.mode(WIFI_STA); WiFiMulti.addAP(APSSID, APPSK); diff --git a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp index 9cd5d62801..256d971560 100755 --- a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp +++ b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp @@ -28,12 +28,12 @@ #include ESP8266HTTPUpdate::ESP8266HTTPUpdate(void) - : _httpClientTimeout(8000) + : _httpWallTime(8000) { } -ESP8266HTTPUpdate::ESP8266HTTPUpdate(int httpClientTimeout) - : _httpClientTimeout(httpClientTimeout) +ESP8266HTTPUpdate::ESP8266HTTPUpdate(int httpWallTime) + : _httpWallTime(httpWallTime) { } @@ -164,7 +164,7 @@ 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(_httpClientTimeout); + http.setWallTime(_httpWallTime); http.setFollowRedirects(_followRedirects); http.setUserAgent(F("ESP8266-http-Update")); http.addHeader(F("x-ESP8266-Chip-ID"), String(ESP.getChipId())); diff --git a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h index 803988d3be..45ae03349f 100755 --- a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h +++ b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h @@ -132,9 +132,8 @@ class ESP8266HTTPUpdate int getLastError(void); String getLastErrorString(void); - void setClientTimeout(int timeout) { - _httpClientTimeout = timeout; - } + [[deprecated("use setWallTime()")]] void setClientTimeout(int wallTime) { setWallTime(wallTime); } + void setWallTime(int wallTime) { _httpWallTime = wallTime; } protected: t_httpUpdate_return handleUpdate(HTTPClient& http, const String& currentVersion, bool spiffs = false); bool runUpdate(Stream& in, uint32_t size, const String& md5, int command = U_FLASH); @@ -154,7 +153,7 @@ class ESP8266HTTPUpdate String _auth; String _md5Sum; private: - int _httpClientTimeout; + unsigned long _httpWallTime; followRedirects_t _followRedirects = HTTPC_DISABLE_FOLLOW_REDIRECTS; // Callbacks pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy