From ddade99c43cb38ff3e2499877902b2c60ad69b96 Mon Sep 17 00:00:00 2001 From: Sven Steckmann Date: Thu, 17 Oct 2019 12:57:28 +0200 Subject: [PATCH 1/7] DNS server stop independent of webserver type In some situations (not passing a WebServer instance from external) the DNS server was not stopped in _stopPortal(). Maybe the intention was here not to stopped an externally passed WebServer but I see no use-case for the dns server here. Fixed this to remove the enum handling in the next step. --- src/AutoConnect.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/AutoConnect.cpp b/src/AutoConnect.cpp index 0c5a046..bedce03 100644 --- a/src/AutoConnect.cpp +++ b/src/AutoConnect.cpp @@ -385,13 +385,11 @@ void AutoConnect::end(void) { } _stopPortal(); + _dnsServer.reset(); + if (_webServer) { switch (_webServerAlloc) { case AC_WEBSERVER_HOSTED: - if (_dnsServer) { - _dnsServer->stop(); - _dnsServer.reset(); - } _webServer.reset(); break; case AC_WEBSERVER_PARASITIC: @@ -686,7 +684,7 @@ bool AutoConnect::_loadAvailCredential(const char* ssid) { * Stops DNS server and flush tcp sending. */ void AutoConnect::_stopPortal(void) { - if (_dnsServer && _webServerAlloc == AC_WEBSERVER_HOSTED) + if (_dnsServer) _dnsServer->stop(); if (_webServer) { From 88f4447777b700de83e0d59699b625121ba8903a Mon Sep 17 00:00:00 2001 From: Sven Steckmann Date: Thu, 17 Oct 2019 13:04:50 +0200 Subject: [PATCH 2/7] Make handling of WebServerClass instance easier Adding a custom deleter to unique_ptr in case of using the reference. This makes the code less error prone and easier to read since we will only have to use the creation of the pointer the correct way. --- src/AutoConnect.cpp | 21 ++++----------------- src/AutoConnect.h | 9 ++------- 2 files changed, 6 insertions(+), 24 deletions(-) diff --git a/src/AutoConnect.cpp b/src/AutoConnect.cpp index bedce03..d6bc673 100644 --- a/src/AutoConnect.cpp +++ b/src/AutoConnect.cpp @@ -22,6 +22,7 @@ #define SET_HOSTNAME(x) do { WiFi.setHostname(x); } while(0) #endif + /** * AutoConnect default constructor. This entry activates WebServer * internally and the web server is allocated internal. @@ -30,7 +31,6 @@ AutoConnect::AutoConnect() { _initialize(); _webServer.reset(nullptr); _dnsServer.reset(nullptr); - _webServerAlloc = AC_WEBSERVER_HOSTED; } /** @@ -40,9 +40,8 @@ AutoConnect::AutoConnect() { */ AutoConnect::AutoConnect(WebServerClass& webServer) { _initialize(); - _webServer.reset(&webServer); + _webServer = WebserverUP(&webServer, [](WebServerClass*){}); _dnsServer.reset(nullptr); - _webServerAlloc = AC_WEBSERVER_PARASITIC; } void AutoConnect::_initialize(void) { @@ -386,18 +385,7 @@ void AutoConnect::end(void) { _stopPortal(); _dnsServer.reset(); - - if (_webServer) { - switch (_webServerAlloc) { - case AC_WEBSERVER_HOSTED: - _webServer.reset(); - break; - case AC_WEBSERVER_PARASITIC: - _webServer.release(); - break; - } - } - + _webServer.reset(); } /** @@ -453,8 +441,7 @@ void AutoConnect::_startWebServer(void) { // Boot Web server if (!_webServer) { // Only when hosting WebServer internally - _webServer.reset(new WebServerClass(AUTOCONNECT_HTTPPORT)); - _webServerAlloc = AC_WEBSERVER_HOSTED; + _webServer = WebserverUP(new WebServerClass(AUTOCONNECT_HTTPPORT), std::default_delete() ); AC_DBG("WebServer allocated\n"); } // Discard the original the not found handler to redirect captive portal detection. diff --git a/src/AutoConnect.h b/src/AutoConnect.h index d6c605f..ee800fb 100644 --- a/src/AutoConnect.h +++ b/src/AutoConnect.h @@ -218,11 +218,6 @@ class AutoConnect { void onNotFound(WebServerClass::THandlerFunction fn); protected: - enum _webServerAllocateType { - AC_WEBSERVER_PARASITIC, - AC_WEBSERVER_HOSTED - }; - typedef enum _webServerAllocateType AC_WEBSERVER_TYPE; typedef enum { AC_RECONNECT_SET, AC_RECONNECT_RESET @@ -271,9 +266,9 @@ class AutoConnect { size_t _freeHeapSize; /** Servers which works in concert. */ - std::unique_ptr _webServer; + typedef std::unique_ptr > WebserverUP; + WebserverUP _webServer = WebserverUP(nullptr, std::default_delete()); std::unique_ptr _dnsServer; - AC_WEBSERVER_TYPE _webServerAlloc; /** * Dynamically hold one page of AutoConnect menu. From c7ffe5d4c7d270ca97904a22d1640aa26f978131 Mon Sep 17 00:00:00 2001 From: Sven Steckmann Date: Thu, 17 Oct 2019 13:56:38 +0200 Subject: [PATCH 3/7] Remove compiler warnings by adding some braces. --- src/AutoConnect.cpp | 15 ++++++++++----- src/AutoConnectAux.cpp | 3 ++- src/AutoConnectAuxImpl.h | 24 ++++++++++++++++-------- src/AutoConnectElementJson.h | 27 ++++++++++++++++++--------- 4 files changed, 46 insertions(+), 23 deletions(-) diff --git a/src/AutoConnect.cpp b/src/AutoConnect.cpp index d6bc673..f0f0923 100644 --- a/src/AutoConnect.cpp +++ b/src/AutoConnect.cpp @@ -295,8 +295,9 @@ bool AutoConnect::config(AutoConnectConfig& Config) { * by Config method. */ bool AutoConnect::_config(void) { - if (static_cast(_apConfig.apip) == 0U || static_cast(_apConfig.gateway) == 0U || static_cast(_apConfig.netmask) == 0U) + if (static_cast(_apConfig.apip) == 0U || static_cast(_apConfig.gateway) == 0U || static_cast(_apConfig.netmask) == 0U) { AC_DBG("Warning: Contains invalid SoftAPIP address(es).\n"); + } bool rc = WiFi.softAPConfig(_apConfig.apip, _apConfig.gateway, _apConfig.netmask); AC_DBG("SoftAP configure %s, %s, %s %s\n", _apConfig.apip.toString().c_str(), _apConfig.gateway.toString().c_str(), _apConfig.netmask.toString().c_str(), rc ? "" : "failed"); return rc; @@ -316,8 +317,9 @@ bool AutoConnect::_configSTA(const IPAddress& ip, const IPAddress& gateway, cons bool rc; AC_DBG("WiFi.config(IP=%s, Gateway=%s, Subnetmask=%s, DNS1=%s, DNS2=%s)\n", ip.toString().c_str(), gateway.toString().c_str(), netmask.toString().c_str(), dns1.toString().c_str(), dns2.toString().c_str()); - if (!(rc = WiFi.config(ip, gateway, netmask, dns1, dns2))) + if (!(rc = WiFi.config(ip, gateway, netmask, dns1, dns2))) { AC_DBG("failed\n"); + } #ifdef ARDUINO_ARCH_ESP8266 AC_DBG("DHCP client(%s)\n", wifi_station_dhcpc_status() == DHCP_STOPPED ? "STOPPED" : "STARTED"); #endif @@ -524,17 +526,20 @@ void AutoConnect::handleRequest(void) { // Save current credential if (_apConfig.autoSave == AC_SAVECREDENTIAL_AUTO) { AutoConnectCredential credit(_apConfig.boundaryOffset); - if (credit.save(&_credential)) + if (credit.save(&_credential)) { AC_DBG("%.*s credential saved\n", sizeof(_credential.ssid), reinterpret_cast(_credential.ssid)); - else + } + else { AC_DBG("credential %.*s save failed\n", sizeof(_credential.ssid), reinterpret_cast(_credential.ssid)); + } } // Ensures that keeps a connection with the current AP while the portal behaves. _setReconnect(AC_RECONNECT_SET); } - else + else { AC_DBG("%.*s has no BSSID, saving is unavailable\n", sizeof(_credential.ssid), reinterpret_cast(_credential.ssid)); + } // Activate AutoConnectUpdate if it is attached and incorporate // it into the AutoConnect menu. diff --git a/src/AutoConnectAux.cpp b/src/AutoConnectAux.cpp index b52a067..0b84f01 100644 --- a/src/AutoConnectAux.cpp +++ b/src/AutoConnectAux.cpp @@ -303,8 +303,9 @@ void AutoConnectAux::upload(const String& requestUri, const HTTPUpload& upload) _upload = _uploadHandler; AC_DBG_DUMB("enabled\n"); } - else + else { AC_DBG_DUMB("missing\n"); + } } } diff --git a/src/AutoConnectAuxImpl.h b/src/AutoConnectAuxImpl.h index 649d302..84f3cb0 100644 --- a/src/AutoConnectAuxImpl.h +++ b/src/AutoConnectAuxImpl.h @@ -272,8 +272,9 @@ AutoConnectButtonJson& AutoConnectAux::getElement(const String& name) { if (elm) { if (elm->typeOf() == AC_Button) return *(reinterpret_cast(elm)); - else + else { AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf()); + } } return reinterpret_cast(_nullElement()); } @@ -289,8 +290,9 @@ AutoConnectCheckboxJson& AutoConnectAux::getElement(const String& name) { if (elm) { if (elm->typeOf() == AC_Checkbox) return *(reinterpret_cast(elm)); - else + else { AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf()); + } } return reinterpret_cast(_nullElement()); } @@ -306,8 +308,9 @@ AutoConnectFileJson& AutoConnectAux::getElement(const String& name) { if (elm) { if (elm->typeOf() == AC_File) return *(reinterpret_cast(elm)); - else + else { AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf()); + } } return reinterpret_cast(_nullElement()); } @@ -323,8 +326,9 @@ AutoConnectInputJson& AutoConnectAux::getElement(const String& name) { if (elm) { if (elm->typeOf() == AC_Input) return *(reinterpret_cast(elm)); - else + else { AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf()); + } } return reinterpret_cast(_nullElement()); } @@ -340,8 +344,9 @@ AutoConnectRadioJson& AutoConnectAux::getElement(const String& name) { if (elm) { if (elm->typeOf() == AC_Radio) return *(reinterpret_cast(elm)); - else + else { AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf()); + } } return reinterpret_cast(_nullElement()); } @@ -357,8 +362,9 @@ AutoConnectSelectJson& AutoConnectAux::getElement(const String& name) { if (elm) { if (elm->typeOf() == AC_Select) return *(reinterpret_cast(elm)); - else + else { AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf()); + } } return reinterpret_cast(_nullElement()); } @@ -374,8 +380,9 @@ AutoConnectSubmitJson& AutoConnectAux::getElement(const String& name) { if (elm) { if (elm->typeOf() == AC_Submit) return *(reinterpret_cast(elm)); - else + else { AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf()); + } } return reinterpret_cast(_nullElement()); } @@ -391,8 +398,9 @@ AutoConnectTextJson& AutoConnectAux::getElement(const String& name) { if (elm) { if (elm->typeOf() == AC_Text) return *(reinterpret_cast(elm)); - else + else { AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf()); + } } return reinterpret_cast(_nullElement()); } diff --git a/src/AutoConnectElementJson.h b/src/AutoConnectElementJson.h index 2cb9486..ad4d06a 100644 --- a/src/AutoConnectElementJson.h +++ b/src/AutoConnectElementJson.h @@ -309,64 +309,73 @@ class AutoConnectTextJson : public AutoConnectElementJson, public AutoConnectTex */ template<> inline AutoConnectButtonJson& AutoConnectElementJson::as(void) { - if (typeOf() != AC_Button) + if (typeOf() != AC_Button) { AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf()); + } return *(reinterpret_cast(this)); } template<> inline AutoConnectCheckboxJson& AutoConnectElementJson::as(void) { - if (typeOf() != AC_Checkbox) + if (typeOf() != AC_Checkbox) { AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf()); + } return *(reinterpret_cast(this)); } template<> inline AutoConnectFileJson& AutoConnectElementJson::as(void) { - if (typeOf() != AC_File) + if (typeOf() != AC_File) { AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf()); + } return *(reinterpret_cast(this)); } template<> inline AutoConnectInputJson& AutoConnectElementJson::as(void) { - if (typeOf() != AC_Input) + if (typeOf() != AC_Input) { AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf()); + } return *(reinterpret_cast(this)); } template<> inline AutoConnectRadioJson& AutoConnectElementJson::as(void) { - if (typeOf() != AC_Radio) + if (typeOf() != AC_Radio) { AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf()); + } return *(reinterpret_cast(this)); } template<> inline AutoConnectSelectJson& AutoConnectElementJson::as(void) { - if (typeOf() != AC_Select) + if (typeOf() != AC_Select) { AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf()); + } return *(reinterpret_cast(this)); } template<> inline AutoConnectStyleJson& AutoConnectElementJson::as(void) { - if (typeOf() != AC_Style) + if (typeOf() != AC_Style) { AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf()); + } return *(reinterpret_cast(this)); } template<> inline AutoConnectSubmitJson& AutoConnectElementJson::as(void) { - if (typeOf() != AC_Submit) + if (typeOf() != AC_Submit) { AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf()); + } return *(reinterpret_cast(this)); } template<> inline AutoConnectTextJson& AutoConnectElementJson::as(void) { - if (typeOf() != AC_Text) + if (typeOf() != AC_Text) { AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf()); + } return *(reinterpret_cast(this)); } From 908d6771c27cf5ed83589d151cf88bbd0f72313c Mon Sep 17 00:00:00 2001 From: Sven Steckmann Date: Thu, 17 Oct 2019 13:56:53 +0200 Subject: [PATCH 4/7] Remove unused rst compiler warning. --- src/AutoConnect.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/AutoConnect.cpp b/src/AutoConnect.cpp index f0f0923..e5296f9 100644 --- a/src/AutoConnect.cpp +++ b/src/AutoConnect.cpp @@ -1054,8 +1054,7 @@ void AutoConnect::_setReconnect(const AC_STARECONNECT_t order) { if (order == AC_RECONNECT_SET) { _disconnectEventId = WiFi.onEvent([](WiFiEvent_t e, WiFiEventInfo_t info) { AC_DBG("STA lost connection:%d\n", info.disconnected.reason); - bool rst = WiFi.reconnect(); - AC_DBG("STA connection %s\n", rst ? "restored" : "failed"); + AC_DBG("STA connection %s\n", WiFi.reconnect() ? "restored" : "failed"); }, WiFiEvent_t::SYSTEM_EVENT_AP_STADISCONNECTED); AC_DBG("Event<%d> handler registered\n", static_cast(WiFiEvent_t::SYSTEM_EVENT_AP_STADISCONNECTED)); } From 6d37959fb3e520097e575978adb29500532935dd Mon Sep 17 00:00:00 2001 From: Sven Steckmann Date: Thu, 17 Oct 2019 13:59:50 +0200 Subject: [PATCH 5/7] Remove _initialize method and replace it by delegating constructor. * This is more straight forward with C++11 and the way todo. * Also move some initializations to the header file. * Remove assignment of empty String("") since this is an assignment with a default constructed object which is already default constructed. * Remove reset of unique_ptr: They are per default initialized as empty nullptr. --- src/AutoConnect.cpp | 33 +++++++++------------------------ src/AutoConnect.h | 13 ++++++------- 2 files changed, 15 insertions(+), 31 deletions(-) diff --git a/src/AutoConnect.cpp b/src/AutoConnect.cpp index e5296f9..4de87d3 100644 --- a/src/AutoConnect.cpp +++ b/src/AutoConnect.cpp @@ -27,10 +27,12 @@ * AutoConnect default constructor. This entry activates WebServer * internally and the web server is allocated internal. */ -AutoConnect::AutoConnect() { - _initialize(); - _webServer.reset(nullptr); - _dnsServer.reset(nullptr); +AutoConnect::AutoConnect() +: _scanCount( 0 ) +, _connectTimeout( AUTOCONNECT_TIMEOUT ) +, _menuTitle( _apConfig.title ) +{ + memset(&_credential, 0x00, sizeof(station_config_t)); } /** @@ -38,27 +40,10 @@ AutoConnect::AutoConnect() { * User's added URI handler response can be included in handleClient method. * @param webServer A reference of ESP8266WebServer instance. */ -AutoConnect::AutoConnect(WebServerClass& webServer) { - _initialize(); +AutoConnect::AutoConnect(WebServerClass& webServer) +: AutoConnect() +{ _webServer = WebserverUP(&webServer, [](WebServerClass*){}); - _dnsServer.reset(nullptr); -} - -void AutoConnect::_initialize(void) { - _rfConnect = false; - _rfReset = false; - _rfDisconnect = false; - _responsePage = nullptr; - _currentPageElement = nullptr; - _menuTitle = _apConfig.title; - _connectTimeout = AUTOCONNECT_TIMEOUT; - _scanCount = 0; - memset(&_credential, 0x00, sizeof(station_config_t)); -#ifdef ARDUINO_ARCH_ESP32 - _disconnectEventId = -1; // The member available for ESP32 only -#endif - _aux = nullptr; - _auxUri = String(""); } /** diff --git a/src/AutoConnect.h b/src/AutoConnect.h index ee800fb..afd0d9b 100644 --- a/src/AutoConnect.h +++ b/src/AutoConnect.h @@ -222,7 +222,6 @@ class AutoConnect { AC_RECONNECT_SET, AC_RECONNECT_RESET } AC_STARECONNECT_t; - void _initialize(void); bool _config(void); bool _configSTA(const IPAddress& ip, const IPAddress& gateway, const IPAddress& netmask, const IPAddress& dns1, const IPAddress& dns2); bool _getConfigSTA(station_config_t* config); @@ -275,8 +274,8 @@ class AutoConnect { * Every time a GET/POST HTTP request occurs, an AutoConnect * menu page corresponding to the URI is generated. */ - PageBuilder* _responsePage; - PageElement* _currentPageElement; + PageBuilder* _responsePage = nullptr; + PageElement* _currentPageElement = nullptr; /** Extended pages made up with AutoConnectAux */ AutoConnectAux* _aux = nullptr; /**< A top of registered AutoConnectAux */ @@ -295,12 +294,12 @@ class AutoConnect { unsigned long _portalAccessPeriod; /** The control indicators */ - bool _rfConnect; /**< URI /connect requested */ - bool _rfDisconnect; /**< URI /disc requested */ - bool _rfReset; /**< URI /reset requested */ + bool _rfConnect = false; /**< URI /connect requested */ + bool _rfDisconnect = false; /**< URI /disc requested */ + bool _rfReset = false; /**< URI /reset requested */ wl_status_t _rsConnect; /**< connection result */ #ifdef ARDUINO_ARCH_ESP32 - WiFiEventId_t _disconnectEventId; /**< STA disconnection event handler registered id */ + WiFiEventId_t _disconnectEventId = -1; /**< STA disconnection event handler registered id */ #endif std::unique_ptr _ticker; /**< */ From 02e98f54f4268c39dcacd8cecf61aa079315665b Mon Sep 17 00:00:00 2001 From: Sven Steckmann Date: Thu, 17 Oct 2019 22:32:27 +0200 Subject: [PATCH 6/7] Remove error prone handling of direct calling destructors. A destructor should never be directly called. But this is a good position to use unique_ptr for memory management. --- src/AutoConnect.cpp | 9 +++------ src/AutoConnect.h | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/AutoConnect.cpp b/src/AutoConnect.cpp index 4de87d3..8611d69 100644 --- a/src/AutoConnect.cpp +++ b/src/AutoConnect.cpp @@ -360,11 +360,8 @@ void AutoConnect::home(const String& uri) { * Stops AutoConnect captive portal service. */ void AutoConnect::end(void) { - if (_responsePage != nullptr) { - _responsePage->~PageBuilder(); - delete _responsePage; - _responsePage = nullptr; - } + _responsePage.reset(); + if (_currentPageElement != nullptr) { _currentPageElement->~PageElement(); _currentPageElement = nullptr; @@ -436,7 +433,7 @@ void AutoConnect::_startWebServer(void) { _webServer->onNotFound(std::bind(&AutoConnect::_handleNotFound, this)); // here, Prepare PageBuilders for captive portal if (!_responsePage) { - _responsePage = new PageBuilder(); + _responsePage.reset( new PageBuilder() ); _responsePage->exitCanHandle(std::bind(&AutoConnect::_classifyHandle, this, std::placeholders::_1, std::placeholders::_2)); _responsePage->onUpload(std::bind(&AutoConnect::_handleUpload, this, std::placeholders::_1, std::placeholders::_2)); _responsePage->insert(*_webServer); diff --git a/src/AutoConnect.h b/src/AutoConnect.h index afd0d9b..5d608fb 100644 --- a/src/AutoConnect.h +++ b/src/AutoConnect.h @@ -274,7 +274,7 @@ class AutoConnect { * Every time a GET/POST HTTP request occurs, an AutoConnect * menu page corresponding to the URI is generated. */ - PageBuilder* _responsePage = nullptr; + std::unique_ptr _responsePage; PageElement* _currentPageElement = nullptr; /** Extended pages made up with AutoConnectAux */ From a4cc82c8083cd7f51331b85b35c29173f314cdb0 Mon Sep 17 00:00:00 2001 From: Sven Steckmann Date: Thu, 17 Oct 2019 22:53:07 +0200 Subject: [PATCH 7/7] Fix memory leak on destruction and make use of unique_ptr. The _currentPageElement was not deleted on destruction. This caused a memory leak. Furthermore there was an explicit destructor call which should never be used. Now the memory handling is delegated to a unique_ptr which makes it easier to track. --- src/AutoConnect.cpp | 24 ++++++++++-------------- src/AutoConnect.h | 2 +- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/AutoConnect.cpp b/src/AutoConnect.cpp index 8611d69..c5c946c 100644 --- a/src/AutoConnect.cpp +++ b/src/AutoConnect.cpp @@ -361,11 +361,7 @@ void AutoConnect::home(const String& uri) { */ void AutoConnect::end(void) { _responsePage.reset(); - - if (_currentPageElement != nullptr) { - _currentPageElement->~PageElement(); - _currentPageElement = nullptr; - } + _currentPageElement.reset(); _stopPortal(); _dnsServer.reset(); @@ -912,12 +908,13 @@ bool AutoConnect::_classifyHandle(HTTPMethod method, String uri) { _purgePages(); // Create the page dynamically - if ((_currentPageElement = _setupPage(uri)) == nullptr) - if (_aux) { - // Requested URL is not a normal page, exploring AUX pages - _currentPageElement = _aux->_setupPage(uri); - } - if (_currentPageElement != nullptr) { + _currentPageElement.reset( _setupPage(uri) ); + if (!_currentPageElement && _aux) { + // Requested URL is not a normal page, exploring AUX pages + _currentPageElement.reset(_aux->_setupPage(uri)); + } + + if (_currentPageElement) { AC_DBG_DUMB(",generated:%s", uri.c_str()); _uri = uri; _responsePage->addElement(*_currentPageElement); @@ -947,9 +944,8 @@ void AutoConnect::_handleUpload(const String& requestUri, const HTTPUpload& uplo */ void AutoConnect::_purgePages(void) { _responsePage->clearElement(); - if (_currentPageElement != nullptr) { - delete _currentPageElement; - _currentPageElement = nullptr; + if (_currentPageElement) { + _currentPageElement.reset(); _uri = String(""); } } diff --git a/src/AutoConnect.h b/src/AutoConnect.h index 5d608fb..f0f8a98 100644 --- a/src/AutoConnect.h +++ b/src/AutoConnect.h @@ -275,7 +275,7 @@ class AutoConnect { * menu page corresponding to the URI is generated. */ std::unique_ptr _responsePage; - PageElement* _currentPageElement = nullptr; + std::unique_ptr _currentPageElement; /** Extended pages made up with AutoConnectAux */ AutoConnectAux* _aux = nullptr; /**< A top of registered AutoConnectAux */