Skip to content

Commit e5ea7b3

Browse files
committed
introduce wall time
1 parent ae64f5b commit e5ea7b3

File tree

5 files changed

+44
-59
lines changed

5 files changed

+44
-59
lines changed

libraries/ESP8266HTTPClient/examples/BasicHttpsClient/BasicHttpsClient.ino

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ void loop() {
6060
#endif
6161

6262
HTTPClient https;
63-
https.setTimeout(4000); // or: client->setTimeout(4000);
64-
client->setHandshakeTimeout(10000);
63+
https.setWalTime(10000); // do not exceed 10s while getting data
64+
client->setWallTime(20000); // do not exceed 20s during handshake
6565

6666
// Try to reduce RAM footprint when SSL server allows it
6767
constexpr int sslbufsize = 1024;

libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,6 @@ bool HTTPClient::begin(WiFiClient &client, const String& url) {
8686

8787
_port = (protocol == "https" ? 443 : 80);
8888
_client = client.clone();
89-
if (_deferredTimeout) {
90-
_client->setTimeout(_deferredTimeout);
91-
}
9289

9390
return beginInternal(url, protocol.c_str());
9491
}
@@ -112,9 +109,6 @@ bool HTTPClient::begin(WiFiClient &client, const String& host, uint16_t port, co
112109
}
113110

114111
_client = client.clone();
115-
if (_deferredTimeout) {
116-
_client->setTimeout(_deferredTimeout);
117-
}
118112

119113
clear();
120114

@@ -309,17 +303,12 @@ void HTTPClient::setAuthorization(String auth)
309303
}
310304

311305
/**
312-
* set the timeout for the TCP connection
306+
* set the wall time for operations
313307
* @param timeout unsigned int
314308
*/
315-
void HTTPClient::setTimeout(uint16_t timeout)
309+
void HTTPClient::setWallTime(unsigned long wallTime)
316310
{
317-
if(connected()) {
318-
_client->setTimeout(timeout);
319-
}
320-
else {
321-
_deferredTimeout = timeout;
322-
}
311+
_wallTime.reset(wallTime?: esp8266::polledTimeout::oneShotMs::neverExpires);
323312
}
324313

325314
/**
@@ -885,7 +874,6 @@ bool HTTPClient::sendHeader(const char * type)
885874
*/
886875
int HTTPClient::handleHeaderResponse()
887876
{
888-
889877
if(!connected()) {
890878
return HTTPC_ERROR_NOT_CONNECTED;
891879
}
@@ -897,16 +885,14 @@ int HTTPClient::handleHeaderResponse()
897885
String transferEncoding;
898886

899887
_transferEncoding = HTTPC_TE_IDENTITY;
900-
unsigned long lastDataTime = millis();
888+
_wallTime.reset();
901889

902890
while(connected()) {
903891
size_t len = _client->available();
904892
if(len > 0) {
905893
int headerSeparator = -1;
906894
String headerLine = _client->readStringUntil('\n');
907895

908-
lastDataTime = millis();
909-
910896
DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] RX: '%s'\n", headerLine.c_str());
911897

912898
if (headerLine.startsWith(F("HTTP/1."))) {
@@ -984,7 +970,7 @@ int HTTPClient::handleHeaderResponse()
984970
}
985971

986972
} else {
987-
if((millis() - lastDataTime) > _client.get()->getTimeout()) {
973+
if(_wallTime) {
988974
return HTTPC_ERROR_READ_TIMEOUT;
989975
}
990976
esp_yield();

libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <Arduino.h>
3030
#include <StreamString.h>
3131
#include <WiFiClient.h>
32+
#include <PolledTimeout.h>
3233

3334
#include <memory>
3435

@@ -42,6 +43,8 @@
4243
#define DEBUG_HTTPCLIENT(...) do { (void)0; } while (0)
4344
#endif
4445

46+
#define HTTPCLIENT_DEFAULT_TCP_TIMEOUT (5000)
47+
4548
/// HTTP client errors
4649
#define HTTPC_ERROR_CONNECTION_FAILED (-1)
4750
#define HTTPC_ERROR_SEND_HEADER_FAILED (-2)
@@ -150,7 +153,7 @@ typedef std::unique_ptr<TransportTraits> TransportTraitsPtr;
150153
class HTTPClient
151154
{
152155
public:
153-
HTTPClient() = default;
156+
HTTPClient(): _wallTime(HTTPCLIENT_DEFAULT_TCP_TIMEOUT) {};
154157
~HTTPClient() = default;
155158
HTTPClient(HTTPClient&&) = default;
156159
HTTPClient& operator=(HTTPClient&&) = default;
@@ -175,7 +178,8 @@ class HTTPClient
175178
void setAuthorization(const char * user, const char * password);
176179
void setAuthorization(const char * auth);
177180
void setAuthorization(String auth);
178-
void setTimeout(uint16_t timeout);
181+
void setWallTime(unsigned long wallTime);
182+
[[deprecated("use setWallTime() instead")]] void setTimeout(unsigned long wallTime) { setWallTime(wallTime); }
179183

180184
// Redirections
181185
void setFollowRedirects(followRedirects_t follow);
@@ -254,7 +258,7 @@ class HTTPClient
254258
String _host;
255259
uint16_t _port = 0;
256260
bool _reuse = true;
257-
uint16_t _deferredTimeout = 0;
261+
esp8266::polledTimeout::oneShotMs _wallTime;
258262
bool _useHTTP10 = false;
259263

260264
String _uri;
@@ -312,6 +316,7 @@ int HTTPClient::writeToStream(S * output)
312316
}
313317
} else if(_transferEncoding == HTTPC_TE_CHUNKED) {
314318
int size = 0;
319+
_wallTime.reset();
315320
while(1) {
316321
if(!connected()) {
317322
return returnError(HTTPC_ERROR_CONNECTION_LOST);
@@ -358,6 +363,10 @@ int HTTPClient::writeToStream(S * output)
358363
return returnError(HTTPC_ERROR_READ_TIMEOUT);
359364
}
360365

366+
if (_wallTime) {
367+
return returnError(HTTPC_ERROR_READ_TIMEOUT);
368+
}
369+
361370
esp_yield();
362371
}
363372
} else {

libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ extern "C" {
3131
}
3232
#include "debug.h"
3333
#include "ESP8266WiFi.h"
34-
#include "PolledTimeout.h"
3534
#include "WiFiClient.h"
3635
#include "WiFiClientSecureBearSSL.h"
3736
#include "StackThunk.h"
@@ -68,6 +67,8 @@ extern "C" {
6867

6968
namespace BearSSL {
7069

70+
constexpr auto defaultWallTime = 10000UL;
71+
7172
void WiFiClientSecureCtx::_clear() {
7273
_sc = nullptr;
7374
_sc_svr = nullptr;
@@ -80,7 +81,7 @@ void WiFiClientSecureCtx::_clear() {
8081
_now = 0; // You can override or ensure time() is correct w/configTime
8182
_ta = nullptr;
8283
setBufferSizes(16384, 512); // Minimum safe
83-
_set_handshake_done(false); // refreshes _timeout
84+
_handshake_done = false;
8485
_recvapp_buf = nullptr;
8586
_recvapp_len = 0;
8687
_oom_err = false;
@@ -100,7 +101,7 @@ void WiFiClientSecureCtx::_clearAuthenticationSettings() {
100101
}
101102

102103

103-
WiFiClientSecureCtx::WiFiClientSecureCtx() : WiFiClient() {
104+
WiFiClientSecureCtx::WiFiClientSecureCtx() : WiFiClient(), _wallTime(defaultWallTime) {
104105
_clear();
105106
_clearAuthenticationSettings();
106107
_certStore = nullptr; // Don't want to remove cert store on a clear, should be long lived
@@ -121,7 +122,7 @@ WiFiClientSecureCtx::~WiFiClientSecureCtx() {
121122
WiFiClientSecureCtx::WiFiClientSecureCtx(ClientContext* client,
122123
const X509List *chain, const PrivateKey *sk,
123124
int iobuf_in_size, int iobuf_out_size, ServerSessions *cache,
124-
const X509List *client_CA_ta, int tls_min, int tls_max) {
125+
const X509List *client_CA_ta, int tls_min, int tls_max): _wallTime(defaultWallTime) {
125126
_clear();
126127
_clearAuthenticationSettings();
127128
stack_thunk_add_ref();
@@ -142,7 +143,7 @@ WiFiClientSecureCtx::WiFiClientSecureCtx(ClientContext *client,
142143
const X509List *chain,
143144
unsigned cert_issuer_key_type, const PrivateKey *sk,
144145
int iobuf_in_size, int iobuf_out_size, ServerSessions *cache,
145-
const X509List *client_CA_ta, int tls_min, int tls_max) {
146+
const X509List *client_CA_ta, int tls_min, int tls_max): _wallTime(defaultWallTime) {
146147
_clear();
147148
_clearAuthenticationSettings();
148149
stack_thunk_add_ref();
@@ -201,13 +202,10 @@ bool WiFiClientSecureCtx::stop(unsigned int maxWaitMs) {
201202
}
202203

203204
bool WiFiClientSecureCtx::flush(unsigned int maxWaitMs) {
204-
auto savedRuntime = _runtimeTimeout;
205-
auto savedHandshake = _handshakeTimeout;
206-
_runtimeTimeout = maxWaitMs;
207-
_handshakeTimeout = maxWaitMs;
205+
auto savedTimeout = _timeout;
206+
_timeout = std::max(1U, maxWaitMs);
208207
(void) _run_until(BR_SSL_SENDAPP);
209-
_runtimeTimeout = savedRuntime;
210-
_handshakeTimeout = savedHandshake;
208+
_timeout = savedTimeout;
211209
return WiFiClient::flush(maxWaitMs);
212210
}
213211

@@ -248,7 +246,7 @@ void WiFiClientSecureCtx::_freeSSL() {
248246
_recvapp_buf = nullptr;
249247
_recvapp_len = 0;
250248
// This connection is toast
251-
_set_handshake_done(false); // refreshes _timeout
249+
_handshake_done = false;
252250
}
253251

254252
bool WiFiClientSecureCtx::_clientConnected() {
@@ -463,7 +461,6 @@ size_t WiFiClientSecureCtx::peekBytes(uint8_t *buffer, size_t length) {
463461
return 0;
464462
}
465463

466-
_updateStreamTimeout();
467464
_startMillis = millis();
468465
while ((_pollRecvBuffer() < (int)length) && ((millis() - _startMillis) < _timeout)) {
469466
yield();
@@ -486,10 +483,7 @@ int WiFiClientSecureCtx::_run_until(unsigned target, bool blocking) {
486483
return -1;
487484
}
488485

489-
// _run_until() is called prior to inherited read/write methods
490-
// -> refreshing _timeout here, which is also used by ancestors
491-
DEBUG_BSSL("_run_until starts, timeout=%lu\n", _updateStreamTimeout());
492-
esp8266::polledTimeout::oneShotMs loopTimeout(_updateStreamTimeout());
486+
esp8266::polledTimeout::oneShotMs loopTimeout(_timeout);
493487

494488
for (int no_work = 0; blocking || no_work < 2;) {
495489
optimistic_yield(100);
@@ -617,15 +611,20 @@ bool WiFiClientSecureCtx::_wait_for_handshake() {
617611
}
618612
#endif
619613

620-
_set_handshake_done(false); // refreshes _timeout
614+
_wallTime.reset();
615+
_handshake_done = false;
621616
while (!_handshake_done && _clientConnected()) {
622617
int ret = _run_until(BR_SSL_SENDAPP);
623618
if (ret < 0) {
624619
DEBUG_BSSL("_wait_for_handshake: failed\n");
625620
break;
626621
}
627622
if (br_ssl_engine_current_state(_eng) & BR_SSL_SENDAPP) {
628-
_set_handshake_done(true); // refreshes _timeout
623+
_handshake_done = true;
624+
}
625+
if (_wallTime) {
626+
DEBUG_BSSL("handshake too long\n");
627+
break;
629628
}
630629
optimistic_yield(1000);
631630
}
@@ -1221,8 +1220,6 @@ bool WiFiClientSecureCtx::_connectSSL(const char* hostName) {
12211220
_x509_insecure = nullptr;
12221221
_x509_knownkey = nullptr;
12231222

1224-
// _timeout has been refreshed to normal operation as _handshake_done turned to true
1225-
12261223
return ret;
12271224
}
12281225

@@ -1691,7 +1688,7 @@ void WiFiClientSecure::setTimeout (unsigned long timeout)
16911688
{
16921689
WiFiClient::setTimeout(timeout);
16931690
if (_ctx)
1694-
_ctx->setRuntimeTimeout(timeout);
1691+
_ctx->setTimeout(timeout);
16951692
}
16961693

16971694
}; // namespace BearSSL

libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.h

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <bearssl/bearssl.h>
2929
#include "BearSSLHelpers.h"
3030
#include "CertStoreBearSSL.h"
31+
#include "PolledTimeout.h"
3132

3233
namespace BearSSL {
3334

@@ -147,9 +148,8 @@ class WiFiClientSecureCtx : public WiFiClient {
147148
// consume bytes after use (see peekBuffer)
148149
virtual void peekConsume (size_t consume) override;
149150

150-
void setRuntimeTimeout (unsigned long timeout) { _runtimeTimeout = timeout; }
151-
void setHandshakeTimeout (unsigned long timeout) { _handshakeTimeout = timeout; }
152-
unsigned long getHandshakeTimeout () const { return _handshakeTimeout; }
151+
// install a wall-time used during handshake
152+
void setWallTime (unsigned long wallTime) { _wallTime.reset(wallTime?: esp8266::polledTimeout::oneShotMs::neverExpires); }
153153

154154
protected:
155155
bool _connectSSL(const char *hostName); // Do initial SSL handshake
@@ -240,13 +240,7 @@ class WiFiClientSecureCtx : public WiFiClient {
240240

241241
uint8_t *_streamLoad(Stream& stream, size_t size);
242242

243-
// timeout management
244-
245-
unsigned long _updateStreamTimeout () { setTimeout(_handshake_done? _runtimeTimeout: _handshakeTimeout); return getTimeout(); }
246-
void _set_handshake_done (bool handshake_done) { _handshake_done = handshake_done; _updateStreamTimeout(); }
247-
248-
unsigned long _runtimeTimeout = 5000, _handshakeTimeout = 15000;
249-
243+
esp8266::polledTimeout::oneShotMs _wallTime;
250244
}; // class WiFiClientSecureCtx
251245

252246

@@ -373,9 +367,8 @@ class WiFiClientSecure : public WiFiClient {
373367
// override setTimeout and forward to context
374368
virtual void setTimeout (unsigned long timeout) override;
375369

376-
// allowing user to set timeout used during handshake
377-
void setHandshakeTimeout (unsigned long timeout) { _ctx->setHandshakeTimeout(timeout); }
378-
unsigned long getHandshakeTimeout () const { return _ctx->getHandshakeTimeout(); }
370+
// install a wall-time used during handshake
371+
void setWallTime (unsigned long wallTime) { _ctx->setWallTime(wallTime); }
379372

380373
private:
381374
std::shared_ptr<WiFiClientSecureCtx> _ctx;

0 commit comments

Comments
 (0)