Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cores/esp8266/Stream.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,33 @@ void loop() {

std::unique_ptr<BearSSL::WiFiClientSecure> 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
Expand Down
20 changes: 6 additions & 14 deletions libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
}

/**
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -879,7 +874,6 @@ bool HTTPClient::sendHeader(const char * type)
*/
int HTTPClient::handleHeaderResponse()
{

if(!connected()) {
return HTTPC_ERROR_NOT_CONNECTED;
}
Expand All @@ -891,16 +885,14 @@ int HTTPClient::handleHeaderResponse()
String transferEncoding;

_transferEncoding = HTTPC_TE_IDENTITY;
unsigned long lastDataTime = millis();
_wallTime.reset();

while(connected()) {
size_t len = _client->available();
if(len > 0) {
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."))) {
Expand Down Expand Up @@ -978,7 +970,7 @@ int HTTPClient::handleHeaderResponse()
}

} else {
if((millis() - lastDataTime) > _tcpTimeout) {
if(_wallTime) {
return HTTPC_ERROR_READ_TIMEOUT;
}
esp_yield();
Expand Down
13 changes: 10 additions & 3 deletions libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <Arduino.h>
#include <StreamString.h>
#include <WiFiClient.h>
#include <PolledTimeout.h>

#include <memory>

Expand Down Expand Up @@ -152,7 +153,7 @@ typedef std::unique_ptr<TransportTraits> TransportTraitsPtr;
class HTTPClient
{
public:
HTTPClient() = default;
HTTPClient(): _wallTime(HTTPCLIENT_DEFAULT_TCP_TIMEOUT) {};
~HTTPClient() = default;
HTTPClient(HTTPClient&&) = default;
HTTPClient& operator=(HTTPClient&&) = default;
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 {
Expand Down
10 changes: 8 additions & 2 deletions libraries/ESP8266WiFi/src/WiFiClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand All @@ -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);
}
Expand Down Expand Up @@ -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);
}
1 change: 1 addition & 0 deletions libraries/ESP8266WiFi/src/WiFiClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class WiFiClient : public Client, public SList<WiFiClient> {
// - https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rh-copy
virtual std::unique_ptr<WiFiClient> 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;
Expand Down
44 changes: 31 additions & 13 deletions libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ extern "C" {
}
#include "debug.h"
#include "ESP8266WiFi.h"
#include "PolledTimeout.h"
#include "WiFiClient.h"
#include "WiFiClientSecureBearSSL.h"
#include "StackThunk.h"
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -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();
Expand All @@ -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();
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -246,7 +247,6 @@ void WiFiClientSecureCtx::_freeSSL() {
_recvapp_len = 0;
// This connection is toast
_handshake_done = false;
_timeout = 15000;
}

bool WiFiClientSecureCtx::_clientConnected() {
Expand Down Expand Up @@ -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();
}

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}
}
Expand All @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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
12 changes: 12 additions & 0 deletions libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <bearssl/bearssl.h>
#include "BearSSLHelpers.h"
#include "CertStoreBearSSL.h"
#include "PolledTimeout.h"

namespace BearSSL {

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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


Expand Down Expand Up @@ -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<WiFiClientSecureCtx> _ctx;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading