From cdf416cb730ad4e51d02bdb289691fa5adb2fb2f Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Thu, 31 Dec 2020 09:52:08 +0800 Subject: [PATCH] partial fix for #608 - when a new TCP API connection arrives, close old one completely --- src/esp32/WiFiServerAPI.cpp | 33 ++++++++++++++++++++++----------- src/esp32/WiFiServerAPI.h | 6 +++++- src/mesh/PhoneAPI.cpp | 8 +++++++- src/mesh/PhoneAPI.h | 7 +++++-- 4 files changed, 39 insertions(+), 15 deletions(-) diff --git a/src/esp32/WiFiServerAPI.cpp b/src/esp32/WiFiServerAPI.cpp index 3b11c2ae..fac955cc 100644 --- a/src/esp32/WiFiServerAPI.cpp +++ b/src/esp32/WiFiServerAPI.cpp @@ -28,18 +28,19 @@ void WiFiServerAPI::onConnectionChanged(bool connected) } } -void WiFiServerAPI::loop() +/// override close to also shutdown the TCP link +void WiFiServerAPI::close() { + client.stop(); // drop tcp connection + StreamAPI::close(); +} + +bool WiFiServerAPI::loop() { if (client.connected()) { StreamAPI::loop(); - } else if(isConnected) { - // If our API link was up, shut it down - - DEBUG_MSG("Client dropped connection, closing API client\n"); - // Note: we can't call delete here because this object includes other state - // besides the stream API. Instead kill it later when we start a new instance - // delete this; - close(); + return true; + } else { + return false; } } @@ -58,15 +59,25 @@ int32_t WiFiServerPort::runOnce() auto client = available(); if (client) { // Close any previous connection (see FIXME in header file) - if (openAPI) + if (openAPI) { + DEBUG_MSG("Force closing previous TCP connection\n"); delete openAPI; + } openAPI = new WiFiServerAPI(client); } if (openAPI) { // Allow idle processing so the API can read from its incoming stream - openAPI->loop(); + if(!openAPI->loop()) { + // If our API link was up, shut it down + + DEBUG_MSG("Client dropped connection, closing API client\n"); + // Note: we can't call delete here because this object includes other state + // besides the stream API. Instead kill it later when we start a new instance + delete openAPI; + openAPI = NULL; + } return 0; // run fast while our API server is running } else return 100; // only check occasionally for incoming connections diff --git a/src/esp32/WiFiServerAPI.h b/src/esp32/WiFiServerAPI.h index 19f99cbc..96380020 100644 --- a/src/esp32/WiFiServerAPI.h +++ b/src/esp32/WiFiServerAPI.h @@ -18,7 +18,11 @@ class WiFiServerAPI : public StreamAPI virtual ~WiFiServerAPI(); - virtual void loop(); // Check for dropped client connections + /// @return true if we want to keep running, or false if we are ready to be destroyed + virtual bool loop(); // Check for dropped client connections + + /// override close to also shutdown the TCP link + virtual void close(); protected: /// Hookable to find out when connection changes diff --git a/src/mesh/PhoneAPI.cpp b/src/mesh/PhoneAPI.cpp index a0cad427..545ef2b9 100644 --- a/src/mesh/PhoneAPI.cpp +++ b/src/mesh/PhoneAPI.cpp @@ -21,11 +21,17 @@ void PhoneAPI::init() observe(&service.fromNumChanged); } +PhoneAPI::~PhoneAPI() { + close(); +} + void PhoneAPI::close() { unobserve(); state = STATE_SEND_NOTHING; + bool oldConnected = isConnected; isConnected = false; - onConnectionChanged(isConnected); + if(oldConnected != isConnected) + onConnectionChanged(isConnected); } void PhoneAPI::checkConnectionTimeout() diff --git a/src/mesh/PhoneAPI.h b/src/mesh/PhoneAPI.h index 202f7fa2..3cfd9744 100644 --- a/src/mesh/PhoneAPI.h +++ b/src/mesh/PhoneAPI.h @@ -55,12 +55,15 @@ class PhoneAPI public: PhoneAPI(); + /// Destructor - calls close() + virtual ~PhoneAPI(); + /// Do late init that can't happen at constructor time virtual void init(); // Call this when the client drops the connection, resets the state to STATE_SEND_NOTHING - // Unregisters our observer - void close(); + // Unregisters our observer. A closed connection **can** be reopened by calling init again. + virtual void close(); /** * Handle a ToRadio protobuf