From 45e7976c50ef33d059e7b78384d0ffd519dbae25 Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Sun, 20 Jun 2021 10:43:05 -0700 Subject: [PATCH] Fix stopAllExcept with WiFiClientSecure (#8136) Fixes #8079 Because WiFiClientSecure inherits WiFiClient, and WiFiClientSecureCtx also inherits WiFiClient, they both end up in the list of TCP connections that are used for WiFiClient::stopAllExcept(). This would cause the underlying SSL connection to be closed whenever you attempted to stopAllExcept(WiFiClientSecure) Fix by adding a "_owned"(by) pointer in the WiFiClient object which points to nullptr (default case) or to the associated lower-layer connection. When stopping all connections except one, only look at the lowermost connections. --- libraries/ESP8266WiFi/src/WiFiClient.cpp | 19 +++++++++++++++---- libraries/ESP8266WiFi/src/WiFiClient.h | 1 + .../ESP8266WiFi/src/WiFiClientSecureBearSSL.h | 4 ++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/libraries/ESP8266WiFi/src/WiFiClient.cpp b/libraries/ESP8266WiFi/src/WiFiClient.cpp index 39f57b0637..decc7d7ac0 100644 --- a/libraries/ESP8266WiFi/src/WiFiClient.cpp +++ b/libraries/ESP8266WiFi/src/WiFiClient.cpp @@ -77,14 +77,14 @@ WiFiClient* SList::_s_first = 0; WiFiClient::WiFiClient() -: _client(0) +: _client(0), _owned(0) { _timeout = 5000; WiFiClient::_add(this); } WiFiClient::WiFiClient(ClientContext* client) -: _client(client) +: _client(client), _owned(0) { _timeout = 5000; _client->ref(); @@ -106,6 +106,7 @@ WiFiClient::WiFiClient(const WiFiClient& other) _client = other._client; _timeout = other._timeout; _localPort = other._localPort; + _owned = other._owned; if (_client) _client->ref(); WiFiClient::_add(this); @@ -118,6 +119,7 @@ WiFiClient& WiFiClient::operator=(const WiFiClient& other) _client = other._client; _timeout = other._timeout; _localPort = other._localPort; + _owned = other._owned; if (_client) _client->ref(); return *this; @@ -382,9 +384,18 @@ void WiFiClient::stopAll() void WiFiClient::stopAllExcept(WiFiClient* except) { + // Stop all will look at the lowest-level wrapper connections only + while (except->_owned) { + except = except->_owned; + } for (WiFiClient* it = _s_first; it; it = it->_next) { - if (it != except) { - it->stop(); + WiFiClient* conn = it; + // Find the lowest-level owner of the current list entry + while (conn->_owned) { + conn = conn->_owned; + } + if (conn != except) { + conn->stop(); } } } diff --git a/libraries/ESP8266WiFi/src/WiFiClient.h b/libraries/ESP8266WiFi/src/WiFiClient.h index e178d3a483..038e8032df 100644 --- a/libraries/ESP8266WiFi/src/WiFiClient.h +++ b/libraries/ESP8266WiFi/src/WiFiClient.h @@ -144,6 +144,7 @@ class WiFiClient : public Client, public SList { void _err(int8_t err); ClientContext* _client; + WiFiClient* _owned; static uint16_t _localPort; }; diff --git a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.h b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.h index 8ed5edcd9d..166c29c603 100644 --- a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.h +++ b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.h @@ -232,8 +232,8 @@ class WiFiClientSecure : public WiFiClient { public: - WiFiClientSecure():_ctx(new WiFiClientSecureCtx()) { } - WiFiClientSecure(const WiFiClientSecure &rhs): WiFiClient(), _ctx(rhs._ctx) { } + 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; // The shared-ptrs handle themselves automatically