8000 Respect timeout with SSL by d-a-v · Pull Request #8899 · esp8266/Arduino · GitHub
[go: up one dir, main page]

Skip to content

Respect timeout with SSL #8899

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
reduce footprint, add WiFiClientSecure::setNegociationTimeout(ms)
  • Loading branch information
d-a-v committed Mar 29, 2023
commit 74cabd107da3d2c767c9d0533e7e0560ffc4f04f
6 changes: 3 additions & 3 deletions libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ bool HTTPClient::begin(WiFiClient &client, const String& host, uint16_t port, co
_canReuse = false;
disconnect(true);
}

_client = client.clone();
if (_deferredTimeout) {
_client->setTimeout(_deferredTimeout);
Expand Down Expand Up @@ -491,7 +491,7 @@ int HTTPClient::sendRequest(const char * type, const uint8_t * payload, size_t s
//
redirect = false;
if (
_followRedirects != HTTPC_DISABLE_FOLLOW_REDIRECTS &&
_followRedirects != HTTPC_DISABLE_FOLLOW_REDIRECTS &&
redirectCount < _redirectLimit &&
_location.length() > 0
) {
Expand All @@ -504,7 +504,7 @@ int HTTPClient::sendRequest(const char * type, const uint8_t * payload, size_t s
// (the RFC require user to accept the redirection)
_followRedirects == HTTPC_FORCE_FOLLOW_REDIRECTS ||
// allow GET and HEAD methods without force
!strcmp(type, "GET") ||
!strcmp(type, "GET") ||
!strcmp(type, "HEAD")
) {
redirectCount += 1;
Expand Down
35 changes: 21 additions & 14 deletions libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ namespace BearSSL {

void WiFiClientSecureCtx::_clear() {
// TLS handshake may take more than the 5 second default timeout
_minimalTimeout = 15000;
_timeout = std::max(_userTimeout, _minimalTimeout);
_negociationTimeout = _userFacingStream? _userFacingStream->getNegociationTimeout(): 15000;
updateStreamTimeout();

_sc = nullptr;
_sc_svr = nullptr;
Expand Down Expand Up @@ -104,7 +104,7 @@ void WiFiClientSecureCtx::_clearAuthenticationSettings() {
}


WiFiClientSecureCtx::WiFiClientSecureCtx() : WiFiClient() {
WiFiClientSecureCtx::WiFiClientSecureCtx(const WiFiClientSecure* alter) : WiFiClient(), _userFacingStream(alter) {
_clear();
_clearAuthenticationSettings();
_certStore = nullptr; // Don't want to remove cert store on a clear, should be long lived
Expand All @@ -122,10 +122,11 @@ WiFiClientSecureCtx::~WiFiClientSecureCtx() {
stack_thunk_del_ref();
}

WiFiClientSecureCtx::WiFiClientSecureCtx(ClientContext* client,
WiFiClientSecureCtx::WiFiClientSecureCtx(const WiFiClientSecure* alter,
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):_userFacingStream(alter) {
_clear();
_clearAuthenticationSettings();
stack_thunk_add_ref();
Expand All @@ -142,11 +143,12 @@ WiFiClientSecureCtx::WiFiClientSecureCtx(ClientContext* client,
}
}

WiFiClientSecureCtx::WiFiClientSecureCtx(ClientContext *client,
WiFiClientSecureCtx::WiFiClientSecureCtx(const WiFiClientSecure* alter,
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): _userFacingStream(alter) {
_clear();
_clearAuthenticationSettings();
stack_thunk_add_ref();
Expand Down Expand Up @@ -248,8 +250,8 @@ void WiFiClientSecureCtx::_freeSSL() {
// This connection is toast
_handshake_done = false;

_minimalTimeout = 15000;
_timeout = std::max(_userTimeout, _minimalTimeout);
_negociationTimeout = _userFacingStream? _userFacingStream->getNegociationTimeout(): 15000;
updateStreamTimeout();
}

bool WiFiClientSecureCtx::_clientConnected() {
Expand Down Expand Up @@ -465,7 +467,7 @@ size_t WiFiClientSecureCtx::peekBytes(uint8_t *buffer, size_t length) {
return 0;
}

_timeout = std::max(_userTimeout, _minimalTimeout);
updateStreamTimeout();
_startMillis = millis();
while ((_pollRecvBuffer() < (int)length) && ((millis() - _startMillis) < _timeout)) {
yield();
Expand All @@ -490,7 +492,7 @@ int WiFiClientSecureCtx::_run_until(unsigned target, bool blocking) {

// _run_until() is called prior to inherited read/write methods
// -> refreshing _timeout here, which is also used by ancestors
_timeout = std::max(_userTimeout, _minimalTimeout);
updateStreamTimeout();
esp8266::polledTimeout::oneShotMs loopTimeout(_timeout);

for (int no_work = 0; blocking || no_work < 2;) {
Expand Down Expand Up @@ -1215,8 +1217,8 @@ bool WiFiClientSecureCtx::_connectSSL(const char* hostName) {
_x509_knownkey = nullptr;

// reduce timeout after successful handshake to fail fast if server stop accepting our data for whathever reason
if (ret) _minimalTimeout = 0;
_timeout = std::max(_userTimeout, _minimalTimeout);
if (ret) _negociationTimeout = 0;
updateStreamTimeout();

return ret;
}
Expand Down Expand Up @@ -1682,4 +1684,9 @@ bool WiFiClientSecure::probeMaxFragmentLength(IPAddress ip, uint16_t port, uint1
return _SendAbort(probe, supportsLen);
}

};
void WiFiClientSecureCtx::updateStreamTimeout ()
{
_timeout = std::max(_userFacingStream? _userFacingStream->getTimeout(): 5000, _negociationTimeout);
}

}; // namespace BearSSL
65 changes: 37 additions & 28 deletions libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@

namespace BearSSL {

class WiFiClientSecure;

class WiFiClientSecureCtx : public WiFiClient {
public:
WiFiClientSecureCtx();
WiFiClientSecureCtx(const WiFiClientSecure* alter);
WiFiClientSecureCtx(const WiFiClientSecureCtx &rhs) = delete;
~WiFiClientSecureCtx() override;

Expand Down Expand Up @@ -216,10 +218,12 @@ class WiFiClientSecureCtx : public WiFiClient {

// Methods for handling server.available() call which returns a client connection.
friend class WiFiClientSecure; // access to private context constructors
WiFiClientSecureCtx(ClientContext *client, const X509List *chain, unsigned cert_issuer_key_type,
WiFiClientSecureCtx(const WiFiClientSecure* alter,
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);
WiFiClientSecureCtx(ClientContext* client, const X509List *chain, const PrivateKey *sk,
WiFiClientSecureCtx(const WiFiClientSecure* alter,
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);

Expand All @@ -237,8 +241,10 @@ class WiFiClientSecureCtx : public WiFiClient {
uint8_t *_streamLoad(Stream& stream, size_t size);

// timeout management
unsigned long _userTimeout = 5000, _minimalTimeout = 0;
void setUpstreamTimeout (unsigned long timeout) { _userTimeout = timeout; }
unsigned long _negociationTimeout = 0; // negociation timeout
const WiFiClientSecure* _userFacingStream = nullptr; // user-facing WiFiClientSecure
void setStream (const WiFiClientSecure* upStream) { _userFacingStream = upStream; }
void updateStreamTimeout ();

}; // class WiFiClientSecureCtx

Expand All @@ -259,34 +265,36 @@ class WiFiClientSecure : public WiFiClient {

public:

WiFiClientSecure():_ctx(new WiFiClientSecureCtx()) { _owned = _ctx.get(); }
WiFiClientSecure(const WiFiClientSecure &rhs): WiFiClient(), _ctx(rhs._ctx) { if (_ctx) _owned = _ctx.get(); _timeout = rhs._timeout; }
WiFiClientSecure():_ctx(new WiFiClientSecureCtx(this)) { _owned = _ctx.get(); }
WiFiClientSecure(const WiFiClientSecure &rhs): _ctx(rhs._ctx), _userNegociationTimeout(rhs._userNegociationTimeout) {
if (_ctx) { _owned = _ctx.get(); _ctx->setStream(this); }
}
~WiFiClientSecure() override { _ctx = nullptr; }

WiFiClientSecure& operator=(const WiFiClientSecure&) = default;

std::unique_ptr<WiFiClient> clone() const override { return std::unique_ptr<WiFiClient>(new WiFiClientSecure(*this)); }

uint8_t status() override { return _ctx->status(); }
int connect(IPAddress ip, uint16_t port) override { uto(); return _ctx->connect(ip, port); }
int connect(const String& host, uint16_t port) override { uto(); return _ctx->connect(host, port); }
int connect(const char* name, uint16_t port) override { uto(); return _ctx->connect(name, port); }
int connect(IPAddress ip, uint16_t port) override { return _ctx->connect(ip, port); }
int connect(const String& host, uint16_t port) override { return _ctx->connect(host, port); }
int connect(const char* name, uint16_t port) override { return _ctx->connect(name, port); }

uint8_t connected() override { return _ctx->connected(); }
size_t write(const uint8_t *buf, size_t size) override { uto(); return _ctx->write(buf, size); }
size_t write_P(PGM_P buf, size_t size) override { uto(); return _ctx->write_P(buf, size); }
size_t write(const char *buf) { uto(); return write((const uint8_t*)buf, strlen(buf)); }
size_t write_P(const char *buf) { uto(); return write_P((PGM_P)buf, strlen_P(buf)); }
size_t write(Stream& stream) /* Note this is not virtual */ { uto(); return _ctx->write(stream); }
int read(uint8_t *buf, size_t size) override { uto(); return _ctx->read(buf, size); }
int available() override { uto(); return _ctx->available(); }
int availableForWrite() override { uto(); return _ctx->availableForWrite(); }
int read() override { uto(); return _ctx->read(); }
int peek() override { uto(); return _ctx->peek(); }
size_t peekBytes(uint8_t *buffer, size_t length) override { uto(); return _ctx->peekBytes(buffer, length); }
size_t write(const uint8_t *buf, size_t size) override { return _ctx->write(buf, size); }
size_t write_P(PGM_P buf, size_t size) override { return _ctx->write_P(buf, size); }
size_t write(const char *buf) { return write((const uint8_t*)buf, strlen(buf)); }
size_t write_P(const char *buf) { return write_P((PGM_P)buf, strlen_P(buf)); }
size_t write(Stream& stream) /* Note this is not virtual */ { return _ctx->write(stream); }
int read(uint8_t *buf, size_t size) override { return _ctx->read(buf, size); }
int available() override { return _ctx->available(); }
int availableForWrite() override { return _ctx->availableForWrite(); }
int read() override { return _ctx->read(); }
int peek() override { return _ctx->peek(); }
size_t peekBytes(uint8_t *buffer, size_t length) override { return _ctx->peekBytes(buffer, length); }
bool flush(unsigned int maxWaitMs) { return _ctx->flush(maxWaitMs); }
bool stop(unsigned int maxWaitMs) { return _ctx->stop(maxWaitMs); }
void flush() override { uto(); (void)flush(0); }
void flush() override { (void)flush(0); }
void stop() override { (void)stop(0); }

IPAddress remoteIP() override { return _ctx->remoteIP(); }
Expand Down Expand Up @@ -363,27 +371,28 @@ class WiFiClientSecure : public WiFiClient {
// consume bytes after use (see peekBuffer)
virtual void peekConsume (size_t consume) override { return _ctx->peekConsume(consume); }

// allowing to change timeout during negociation
void setNegociationTimeout (unsigned long timeout) { _userNegociationTimeout = timeout; }
unsigned long getNegociationTimeout () const { return _userNegociationTimeout; }

private:
std::shared_ptr<WiFiClientSecureCtx> _ctx;
unsigned long _userNegociationTimeout = 15000; // negociation timeout initializer

// Methods for handling server.available() call which returns a client connection.
friend class WiFiServerSecure; // Server needs to access these constructors
WiFiClientSecure(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):
_ctx(new WiFiClientSecureCtx(client, chain, cert_issuer_key_type, sk, iobuf_in_size, iobuf_out_size, cache, client_CA_ta, tls_min, tls_max)) {
_ctx(new WiFiClientSecureCtx(this, client, chain, cert_issuer_key_type, sk, iobuf_in_size, iobuf_out_size, cache, client_CA_ta, tls_min, tls_max)) {
}

WiFiClientSecure(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):
_ctx(new WiFiClientSecureCtx(client, chain, sk, iobuf_in_size, iobuf_out_size, cache, client_CA_ta, tls_min, tls_max)) {
_ctx(new WiFiClientSecureCtx(this, client, chain, sk, iobuf_in_size, iobuf_out_size, cache, client_CA_ta, tls_min, tls_max)) {
}

// set _ctx user timeout according to Arduino's Stream::_timeout
// (set/getTimeout are not virtual: no easy way to propagate value)
inline void uto () { _ctx->setUpstreamTimeout(_timeout); }

}; // class WiFiClientSecure

}; // namespace BearSSL
Expand Down
0