From 5d8f176a20fd941e1bf62546b7e606a78131a4a2 Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Wed, 21 Mar 2018 12:20:47 -0700 Subject: [PATCH 1/2] Fix WebServerSecure streamFile() ESP8266WebServerSecure's streamFile was using the base class' method which did not use SSL encrypt before transmitting, leading to failure. Add a new template method and required support for WiFiClientSecure::write(Stream&) (using a local temp buffer since the SSL libs do not grok Arduino Streams at all). Fixes #4544 --- .../src/ESP8266WebServerSecure.h | 6 +++++ .../ESP8266WiFi/src/WiFiClientSecure.cpp | 23 +++++++++++++++++++ libraries/ESP8266WiFi/src/WiFiClientSecure.h | 1 + 3 files changed, 30 insertions(+) diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServerSecure.h b/libraries/ESP8266WebServer/src/ESP8266WebServerSecure.h index ec6c344a48..730860324a 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServerSecure.h +++ b/libraries/ESP8266WebServer/src/ESP8266WebServerSecure.h @@ -42,6 +42,12 @@ class ESP8266WebServerSecure : public ESP8266WebServer void handleClient() override; void close() override; + template + size_t streamFile(T &file, const String& contentType) { + _streamFileCore(file.size(), file.name(), contentType); + return _currentClientSecure.write(file); + } + private: size_t _currentClientWrite (const char *bytes, size_t len) override { return _currentClientSecure.write((const uint8_t *)bytes, len); } size_t _currentClientWrite_P (PGM_P bytes, size_t len) override { return _currentClientSecure.write_P(bytes, len); } diff --git a/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp b/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp index 8a7d71e99f..b72a89a1a6 100644 --- a/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp +++ b/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp @@ -564,6 +564,29 @@ size_t WiFiClientSecure::write_P(PGM_P buf, size_t size) return write(copy, size); } +// The axTLS bare libs don't understand anything about Arduino Streams, +// so we have to manually read and send individual chunks. +size_t WiFiClientSecure::write(Stream& stream) +{ + size_t totalSent = 0; + size_t countRead; + size_t countSent; + if (!_ssl) + { + return 0; + } + do { + uint8_t temp[128]; // Arbitrary temporary chunk size + countSent = 0; + countRead = stream.readBytes(temp, sizeof(temp)); + if (countRead) { + countSent = write(temp, countRead); + totalSent += countSent; + } + } while ( (countSent == countRead) && (countSent > 0) ); + return totalSent; +} + int WiFiClientSecure::read(uint8_t *buf, size_t size) { if (!_ssl) { diff --git a/libraries/ESP8266WiFi/src/WiFiClientSecure.h b/libraries/ESP8266WiFi/src/WiFiClientSecure.h index 73ec587f1d..7047fdfec0 100644 --- a/libraries/ESP8266WiFi/src/WiFiClientSecure.h +++ b/libraries/ESP8266WiFi/src/WiFiClientSecure.h @@ -43,6 +43,7 @@ class WiFiClientSecure : public WiFiClient { uint8_t connected() override; size_t write(const uint8_t *buf, size_t size) override; size_t write_P(PGM_P buf, size_t size) override; + size_t write(Stream& stream); // Note this is not virtual int read(uint8_t *buf, size_t size) override; int available() override; int read() override; From 6ed795fab66a1fd9f1c9428ee06aee1e6615bcc2 Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Wed, 21 Mar 2018 13:08:09 -0700 Subject: [PATCH 2/2] Match ClientContext buffer and yield() behavior ClientContext sends out 256 bytes at a time and gives a yield after each chunk to ensure the WDT doesn't fire. Mimic that behavior in WiFiClientSecure::write(Stream&). --- libraries/ESP8266WiFi/src/WiFiClientSecure.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp b/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp index b72a89a1a6..02ddac5795 100644 --- a/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp +++ b/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp @@ -576,13 +576,14 @@ size_t WiFiClientSecure::write(Stream& stream) return 0; } do { - uint8_t temp[128]; // Arbitrary temporary chunk size + uint8_t temp[256]; // Temporary chunk size same as ClientContext countSent = 0; countRead = stream.readBytes(temp, sizeof(temp)); if (countRead) { countSent = write(temp, countRead); totalSent += countSent; } + yield(); // Feed the WDT } while ( (countSent == countRead) && (countSent > 0) ); return totalSent; }