From 5d609fd29475c44c7b752b6cbf4128527f4977d3 Mon Sep 17 00:00:00 2001 From: johnm545 <52096239+johnm545@users.noreply.github.com> Date: Tue, 17 Sep 2019 14:03:34 +1000 Subject: [PATCH] Fix WiFiClientSecure::available() blocking on dropped connections (#6449) * Fix WiFiClientSecure::available blocking Added a check of WiFiClient::availableForWrite to prevent blocking writes when the _run_until blocking flag is false * change availForWrite from int to size_t * add timeout to _run_until loop fixes #6464 * use polledTimeout with _timeout millis --- .../src/WiFiClientSecureBearSSL.cpp | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp index c5a09cedb..773f68cfd 100644 --- a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp +++ b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp @@ -32,6 +32,7 @@ extern "C" { } #include "debug.h" #include "ESP8266WiFi.h" +#include "PolledTimeout.h" #include "WiFiClient.h" #include "WiFiClientSecureBearSSL.h" #include "StackThunk.h" @@ -437,12 +438,17 @@ int WiFiClientSecure::_run_until(unsigned target, bool blocking) { DEBUG_BSSL("_run_until: Not connected\n"); return -1; } - for (int no_work = 0; blocking || no_work < 2;) { - if (blocking) { - // Only for blocking operations can we afford to yield() - optimistic_yield(100); + + esp8266::polledTimeout::oneShotMs loopTimeout(_timeout); + + for (int no_work = 0; blocking || no_work < 2;) { + optimistic_yield(100); + + if (loopTimeout) { + DEBUG_BSSL("_run_until: Timeout\n"); + return -1; } - + int state; state = br_ssl_engine_current_state(_eng); if (state & BR_SSL_CLOSED) { @@ -461,8 +467,19 @@ int WiFiClientSecure::_run_until(unsigned target, bool blocking) { unsigned char *buf; size_t len; int wlen; + size_t availForWrite; buf = br_ssl_engine_sendrec_buf(_eng, &len); + availForWrite = WiFiClient::availableForWrite(); + + if (!blocking && len > availForWrite) { + /* + writes on WiFiClient will block if len > availableForWrite() + this is needed to prevent available() calls from blocking + on dropped connections + */ + len = availForWrite; + } wlen = WiFiClient::write(buf, len); if (wlen <= 0) { /*