Merge pull request #144 from Boldie/improvement_unique_ptr_webserver

Improvement unique ptr webserver
pull/169/head
Hieromon Ikasamo 5 years ago committed by GitHub
commit 56ba89649f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 101
      src/AutoConnect.cpp
  2. 22
      src/AutoConnect.h
  3. 3
      src/AutoConnectAux.cpp
  4. 24
      src/AutoConnectAuxImpl.h
  5. 27
      src/AutoConnectElementJson.h

@ -22,15 +22,17 @@
#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.
*/
AutoConnect::AutoConnect() {
_initialize();
_webServer.reset(nullptr);
_dnsServer.reset(nullptr);
_webServerAlloc = AC_WEBSERVER_HOSTED;
AutoConnect::AutoConnect()
: _scanCount( 0 )
, _connectTimeout( AUTOCONNECT_TIMEOUT )
, _menuTitle( _apConfig.title )
{
memset(&_credential, 0x00, sizeof(station_config_t));
}
/**
@ -38,28 +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();
_webServer.reset(&webServer);
_dnsServer.reset(nullptr);
_webServerAlloc = AC_WEBSERVER_PARASITIC;
}
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("");
AutoConnect::AutoConnect(WebServerClass& webServer)
: AutoConnect()
{
_webServer = WebserverUP(&webServer, [](WebServerClass*){});
}
/**
@ -296,8 +280,9 @@ bool AutoConnect::config(AutoConnectConfig& Config) {
* by Config method.
*/
bool AutoConnect::_config(void) {
if (static_cast<uint32_t>(_apConfig.apip) == 0U || static_cast<uint32_t>(_apConfig.gateway) == 0U || static_cast<uint32_t>(_apConfig.netmask) == 0U)
if (static_cast<uint32_t>(_apConfig.apip) == 0U || static_cast<uint32_t>(_apConfig.gateway) == 0U || static_cast<uint32_t>(_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;
@ -317,8 +302,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
@ -374,32 +360,12 @@ void AutoConnect::home(const String& uri) {
* Stops AutoConnect captive portal service.
*/
void AutoConnect::end(void) {
if (_responsePage != nullptr) {
_responsePage->~PageBuilder();
delete _responsePage;
_responsePage = nullptr;
}
if (_currentPageElement != nullptr) {
_currentPageElement->~PageElement();
_currentPageElement = nullptr;
}
_responsePage.reset();
_currentPageElement.reset();
_stopPortal();
if (_webServer) {
switch (_webServerAlloc) {
case AC_WEBSERVER_HOSTED:
if (_dnsServer) {
_dnsServer->stop();
_dnsServer.reset();
}
_webServer.reset();
break;
case AC_WEBSERVER_PARASITIC:
_webServer.release();
break;
}
}
}
/**
@ -455,8 +421,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<WebServerClass>() );
AC_DBG("WebServer allocated\n");
}
// Discard the original the not found handler to redirect captive portal detection.
@ -464,7 +429,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);
@ -539,17 +504,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<const char*>(_credential.ssid));
else
}
else {
AC_DBG("credential %.*s save failed\n", sizeof(_credential.ssid), reinterpret_cast<const char*>(_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<const char*>(_credential.ssid));
}
// Activate AutoConnectUpdate if it is attached and incorporate
// it into the AutoConnect menu.
@ -686,7 +654,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) {
@ -940,12 +908,13 @@ bool AutoConnect::_classifyHandle(HTTPMethod method, String uri) {
_purgePages();
// Create the page dynamically
if ((_currentPageElement = _setupPage(uri)) == nullptr)
if (_aux) {
_currentPageElement.reset( _setupPage(uri) );
if (!_currentPageElement && _aux) {
// Requested URL is not a normal page, exploring AUX pages
_currentPageElement = _aux->_setupPage(uri);
_currentPageElement.reset(_aux->_setupPage(uri));
}
if (_currentPageElement != nullptr) {
if (_currentPageElement) {
AC_DBG_DUMB(",generated:%s", uri.c_str());
_uri = uri;
_responsePage->addElement(*_currentPageElement);
@ -975,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("");
}
}
@ -1064,8 +1032,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<int>(WiFiEvent_t::SYSTEM_EVENT_AP_STADISCONNECTED));
}

@ -218,16 +218,10 @@ 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
} 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);
@ -271,17 +265,17 @@ class AutoConnect {
size_t _freeHeapSize;
/** Servers which works in concert. */
std::unique_ptr<WebServerClass> _webServer;
typedef std::unique_ptr<WebServerClass, std::function<void(WebServerClass *)> > WebserverUP;
WebserverUP _webServer = WebserverUP(nullptr, std::default_delete<WebServerClass>());
std::unique_ptr<DNSServer> _dnsServer;
AC_WEBSERVER_TYPE _webServerAlloc;
/**
* Dynamically hold one page of AutoConnect menu.
* Every time a GET/POST HTTP request occurs, an AutoConnect
* menu page corresponding to the URI is generated.
*/
PageBuilder* _responsePage;
PageElement* _currentPageElement;
std::unique_ptr<PageBuilder> _responsePage;
std::unique_ptr<PageElement> _currentPageElement;
/** Extended pages made up with AutoConnectAux */
AutoConnectAux* _aux = nullptr; /**< A top of registered AutoConnectAux */
@ -300,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<AutoConnectTicker> _ticker; /**< */

@ -303,10 +303,11 @@ void AutoConnectAux::upload(const String& requestUri, const HTTPUpload& upload)
_upload = _uploadHandler;
AC_DBG_DUMB("enabled\n");
}
else
else {
AC_DBG_DUMB("missing\n");
}
}
}
// Invokes upload handler
if (_upload) {

@ -272,9 +272,10 @@ AutoConnectButtonJson& AutoConnectAux::getElement(const String& name) {
if (elm) {
if (elm->typeOf() == AC_Button)
return *(reinterpret_cast<AutoConnectButtonJson*>(elm));
else
else {
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
}
return reinterpret_cast<AutoConnectButtonJson&>(_nullElement());
}
@ -289,9 +290,10 @@ AutoConnectCheckboxJson& AutoConnectAux::getElement(const String& name) {
if (elm) {
if (elm->typeOf() == AC_Checkbox)
return *(reinterpret_cast<AutoConnectCheckboxJson*>(elm));
else
else {
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
}
return reinterpret_cast<AutoConnectCheckboxJson&>(_nullElement());
}
@ -306,9 +308,10 @@ AutoConnectFileJson& AutoConnectAux::getElement(const String& name) {
if (elm) {
if (elm->typeOf() == AC_File)
return *(reinterpret_cast<AutoConnectFileJson*>(elm));
else
else {
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
}
return reinterpret_cast<AutoConnectFileJson&>(_nullElement());
}
@ -323,9 +326,10 @@ AutoConnectInputJson& AutoConnectAux::getElement(const String& name) {
if (elm) {
if (elm->typeOf() == AC_Input)
return *(reinterpret_cast<AutoConnectInputJson*>(elm));
else
else {
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
}
return reinterpret_cast<AutoConnectInputJson&>(_nullElement());
}
@ -340,9 +344,10 @@ AutoConnectRadioJson& AutoConnectAux::getElement(const String& name) {
if (elm) {
if (elm->typeOf() == AC_Radio)
return *(reinterpret_cast<AutoConnectRadioJson*>(elm));
else
else {
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
}
return reinterpret_cast<AutoConnectRadioJson&>(_nullElement());
}
@ -357,9 +362,10 @@ AutoConnectSelectJson& AutoConnectAux::getElement(const String& name) {
if (elm) {
if (elm->typeOf() == AC_Select)
return *(reinterpret_cast<AutoConnectSelectJson*>(elm));
else
else {
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
}
return reinterpret_cast<AutoConnectSelectJson&>(_nullElement());
}
@ -374,9 +380,10 @@ AutoConnectSubmitJson& AutoConnectAux::getElement(const String& name) {
if (elm) {
if (elm->typeOf() == AC_Submit)
return *(reinterpret_cast<AutoConnectSubmitJson*>(elm));
else
else {
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
}
return reinterpret_cast<AutoConnectSubmitJson&>(_nullElement());
}
@ -391,9 +398,10 @@ AutoConnectTextJson& AutoConnectAux::getElement(const String& name) {
if (elm) {
if (elm->typeOf() == AC_Text)
return *(reinterpret_cast<AutoConnectTextJson*>(elm));
else
else {
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
}
return reinterpret_cast<AutoConnectTextJson&>(_nullElement());
}

@ -309,64 +309,73 @@ class AutoConnectTextJson : public AutoConnectElementJson, public AutoConnectTex
*/
template<>
inline AutoConnectButtonJson& AutoConnectElementJson::as<AutoConnectButtonJson>(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<AutoConnectButtonJson*>(this));
}
template<>
inline AutoConnectCheckboxJson& AutoConnectElementJson::as<AutoConnectCheckboxJson>(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<AutoConnectCheckboxJson*>(this));
}
template<>
inline AutoConnectFileJson& AutoConnectElementJson::as<AutoConnectFileJson>(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<AutoConnectFileJson*>(this));
}
template<>
inline AutoConnectInputJson& AutoConnectElementJson::as<AutoConnectInputJson>(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<AutoConnectInputJson*>(this));
}
template<>
inline AutoConnectRadioJson& AutoConnectElementJson::as<AutoConnectRadioJson>(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<AutoConnectRadioJson*>(this));
}
template<>
inline AutoConnectSelectJson& AutoConnectElementJson::as<AutoConnectSelectJson>(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<AutoConnectSelectJson*>(this));
}
template<>
inline AutoConnectStyleJson& AutoConnectElementJson::as<AutoConnectStyleJson>(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<AutoConnectStyleJson*>(this));
}
template<>
inline AutoConnectSubmitJson& AutoConnectElementJson::as<AutoConnectSubmitJson>(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<AutoConnectSubmitJson*>(this));
}
template<>
inline AutoConnectTextJson& AutoConnectElementJson::as<AutoConnectTextJson>(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<AutoConnectTextJson*>(this));
}

Loading…
Cancel
Save