Skip to content

Commit

Permalink
get rid of pointer, reverting to first proposal
Browse files Browse the repository at this point in the history
  • Loading branch information
d-a-v committed Apr 1, 2023
1 parent d97e0fb commit cc1951a
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,14 @@ void loop() {

HTTPClient https;
https.setTimeout(4000); // or: client->setTimeout(4000);
client->setNegociationTimeout(10000);
client->setHandshakeTimeout(10000);

#if 1
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); }
#endif

Serial.print("[HTTPS] begin...\n");
if (https.begin(*client, jigsaw_host, jigsaw_port)) { // HTTPS
Expand Down
48 changes: 19 additions & 29 deletions libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,6 @@ extern "C" {
namespace BearSSL {

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

_sc = nullptr;
_sc_svr = nullptr;
_eng = nullptr;
Expand All @@ -84,7 +80,7 @@ void WiFiClientSecureCtx::_clear() {
_now = 0; // You can override or ensure time() is correct w/configTime
_ta = nullptr;
setBufferSizes(16384, 512); // Minimum safe
_handshake_done = false;
_set_handshake_done(false); // refreshes _timeout
_recvapp_buf = nullptr;
_recvapp_len = 0;
_oom_err = false;
Expand All @@ -104,7 +100,7 @@ void WiFiClientSecureCtx::_clearAuthenticationSettings() {
}


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

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

WiFiClientSecureCtx::WiFiClientSecureCtx(const WiFiClientSecure* alter,
ClientContext *client,
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): _userFacingStream(alter) {
const X509List *client_CA_ta, int tls_min, int tls_max) {
_clear();
_clearAuthenticationSettings();
stack_thunk_add_ref();
Expand Down Expand Up @@ -207,7 +201,13 @@ bool WiFiClientSecureCtx::stop(unsigned int maxWaitMs) {
}

bool WiFiClientSecureCtx::flush(unsigned int maxWaitMs) {
auto savedNormal = _normalTimeout;
auto savedHandshake = _handshakeTimeout;
_normalTimeout = maxWaitMs;
_handshakeTimeout = maxWaitMs;
(void) _run_until(BR_SSL_SENDAPP);
_normalTimeout = savedNormal;
_handshakeTimeout = savedHandshake;
return WiFiClient::flush(maxWaitMs);
}

Expand Down Expand Up @@ -248,10 +248,7 @@ void WiFiClientSecureCtx::_freeSSL() {
_recvapp_buf = nullptr;
_recvapp_len = 0;
// This connection is toast
_handshake_done = false;

_negociationTimeout = _userFacingStream? _userFacingStream->getNegociationTimeout(): 15000;
updateStreamTimeout();
_set_handshake_done(false); // refreshes _timeout
}

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

updateStreamTimeout();
_updateStreamTimeout();
_startMillis = millis();
while ((_pollRecvBuffer() < (int)length) && ((millis() - _startMillis) < _timeout)) {
yield();
Expand All @@ -491,8 +488,8 @@ 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
updateStreamTimeout();
esp8266::polledTimeout::oneShotMs loopTimeout(_timeout);
DEBUG_BSSL("_run_until starts, timeout=%lu\n", _updateStreamTimeout());
esp8266::polledTimeout::oneShotMs loopTimeout(_updateStreamTimeout());

for (int no_work = 0; blocking || no_work < 2;) {
optimistic_yield(100);
Expand Down Expand Up @@ -611,15 +608,15 @@ int WiFiClientSecureCtx::_run_until(unsigned target, bool blocking) {
}

bool WiFiClientSecureCtx::_wait_for_handshake() {
_handshake_done = false;
_set_handshake_done(false); // refreshes _timeout
while (!_handshake_done && _clientConnected()) {
int ret = _run_until(BR_SSL_SENDAPP);
if (ret < 0) {
DEBUG_BSSL("_wait_for_handshake: failed\n");
break;
}
if (br_ssl_engine_current_state(_eng) & BR_SSL_SENDAPP) {
_handshake_done = true;
_set_handshake_done(true); // refreshes _timeout
}
optimistic_yield(1000);
}
Expand Down Expand Up @@ -1215,9 +1212,7 @@ 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) _negociationTimeout = 0;
updateStreamTimeout();
// _timeout has been refreshed to normal operation as _handshake_done turned to true

return ret;
}
Expand Down Expand Up @@ -1683,9 +1678,4 @@ 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
82 changes: 44 additions & 38 deletions libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class WiFiClientSecure;

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

Expand Down Expand Up @@ -149,6 +149,10 @@ class WiFiClientSecureCtx : public WiFiClient {
// consume bytes after use (see peekBuffer)
virtual void peekConsume (size_t consume) override;

void setNormalTimeout (unsigned long timeout) { _normalTimeout = timeout; }
void setHandshakeTimeout (unsigned long timeout) { _handshakeTimeout = timeout; }
unsigned long getHandshakeTimeout () const { return _handshakeTimeout; }

protected:
bool _connectSSL(const char *hostName); // Do initial SSL handshake

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

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

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

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

unsigned long _updateStreamTimeout () { return _timeout = _handshake_done? _normalTimeout: _handshakeTimeout; }
void _set_handshake_done (bool handshake_done) { _handshake_done = handshake_done; _updateStreamTimeout(); }

unsigned long _normalTimeout = 5000, _handshakeTimeout = 15000;

}; // class WiFiClientSecureCtx

Expand All @@ -265,35 +268,33 @@ class WiFiClientSecure : public WiFiClient {

public:

WiFiClientSecure():_ctx(new WiFiClientSecureCtx(this)) { _owned = _ctx.get(); }
WiFiClientSecure(const WiFiClientSecure &rhs): WiFiClient(), _ctx(rhs._ctx), _userNegociationTimeout(rhs._userNegociationTimeout) {
if (_ctx) { _owned = _ctx.get(); _ctx->setStream(this); }
}
WiFiClientSecure():_ctx(new WiFiClientSecureCtx()) { _owned = _ctx.get(); }
WiFiClientSecure(const WiFiClientSecure &rhs): WiFiClient(), _ctx(rhs._ctx) { if (_ctx) _owned = _ctx.get(); }
~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 { 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 { 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); }
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); }

uint8_t connected() override { uto(); 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); }
bool flush(unsigned int maxWaitMs) { uto(); return _ctx->flush(maxWaitMs); }
bool stop(unsigned int maxWaitMs) { uto(); return _ctx->stop(maxWaitMs); }
void flush() override { (void)flush(0); }
void stop() override { (void)stop(0); }

Expand Down Expand Up @@ -362,7 +363,7 @@ class WiFiClientSecure : public WiFiClient {
virtual bool hasPeekBufferAPI () const override { return true; }

// return number of byte accessible by peekBuffer()
virtual size_t peekAvailable () override { return _ctx->available(); }
virtual size_t peekAvailable () override { return available(); }

// return a pointer to available data buffer (size = peekAvailable())
// semantic forbids any kind of read() before calling peekConsume()
Expand All @@ -371,28 +372,33 @@ 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; }
// allowing user to set timeout used during handshake
void setHandshakeTimeout (unsigned long timeout) { _ctx->setHandshakeTimeout(timeout); }
unsigned long getHandshakeTimeout () const { return _ctx->getHandshakeTimeout(); }

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(this, client, chain, cert_issuer_key_type, sk, iobuf_in_size, iobuf_out_size, cache, client_CA_ta, tls_min, 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)) {
}

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

// (because Stream::setTimeout() is not virtual,)
// forward user timeout from Stream:: to SSL context
// this is internally called on every user operations
inline void uto () { _ctx->setNormalTimeout(_timeout); }


}; // class WiFiClientSecure

}; // namespace BearSSL
Expand Down

0 comments on commit cc1951a

Please sign in to comment.