From 2c0207fb405ad1dd99708d2b4dde307d69ee693d Mon Sep 17 00:00:00 2001 From: Hieromon Ikasamo Date: Sat, 30 Mar 2019 23:27:41 +0900 Subject: [PATCH] Improved heap fragmentation in page content generation. Issue#51 --- src/AutoConnect.cpp | 1 - src/AutoConnect.h | 6 +++++ src/AutoConnectDefs.h | 2 +- src/AutoConnectPage.cpp | 51 ++++++++++++++++++++++++++++++++--------- 4 files changed, 47 insertions(+), 13 deletions(-) diff --git a/src/AutoConnect.cpp b/src/AutoConnect.cpp index 8114051..1c4bfc0 100644 --- a/src/AutoConnect.cpp +++ b/src/AutoConnect.cpp @@ -389,7 +389,6 @@ void AutoConnect::_startWebServer(void) { // here, Prepare PageBuilders for captive portal if (!_responsePage) { _responsePage = new PageBuilder(); - _responsePage->reserve(AUTOCONNECT_CONTENTBUFFER_SIZE); _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 315de3d..2c697e6 100644 --- a/src/AutoConnect.h +++ b/src/AutoConnect.h @@ -312,6 +312,12 @@ class AutoConnect { static const char _PAGE_FAIL[] PROGMEM; static const char _PAGE_404[] PROGMEM; + static const struct PageTranserModeST { + const char* uri; + const TransferEncoding_t transMode; + const size_t rSize; + } _pageBuildMode[]; + /** Token handlers for PageBuilder */ String _token_CSS_BASE(PageArgument& args); String _token_CSS_UL(PageArgument& args); diff --git a/src/AutoConnectDefs.h b/src/AutoConnectDefs.h index 57baad2..90b30a1 100644 --- a/src/AutoConnectDefs.h +++ b/src/AutoConnectDefs.h @@ -124,7 +124,7 @@ // Reserved buffer size to build content #ifndef AUTOCONNECT_CONTENTBUFFER_SIZE -#define AUTOCONNECT_CONTENTBUFFER_SIZE 0 +#define AUTOCONNECT_CONTENTBUFFER_SIZE (13 * 1024) #endif // !AUTOCONNECT_CONTENTBUFFER_SIZE // Number of unit lines in the page that lists available SSIDs diff --git a/src/AutoConnectPage.cpp b/src/AutoConnectPage.cpp index d93bfc4..a5e27ad 100644 --- a/src/AutoConnectPage.cpp +++ b/src/AutoConnectPage.cpp @@ -139,7 +139,7 @@ const char AutoConnect::_CSS_ICON_LOCK[] PROGMEM = { /**< INPUT button and submit style */ const char AutoConnect::_CSS_INPUT_BUTTON[] PROGMEM = { "input[type=\"button\"],input[type=\"submit\"],button[type=\"submit\"]{" - "padding:8px 30px;" + "padding:8px 0.5em;" "font-weight:bold;" "letter-spacing:0.8px;" "color:#fff;" @@ -162,6 +162,7 @@ const char AutoConnect::_CSS_INPUT_BUTTON[] PROGMEM = { "width:15em;" "}" "input[type=\"submit\"],button[type=\"submit\"]{" + "padding:8px 30px;" "background-color:#006064;" "border-color:#006064;" "}" @@ -687,6 +688,12 @@ const char AutoConnect::_PAGE_CONFIGNEW[] PROGMEM = { "" "" "" + "" "" }; @@ -847,6 +854,25 @@ const char AutoConnect::_PAGE_DISCONN[] PROGMEM = { "" }; +// Each page of AutoConnect is http transferred by the content transfer +// mode of Page Builder. The default transfer mode is +// AUTOCONNECT_HTTP_TRANSFER defined in AutoConnectDefs.h. The page to +// which default transfer mode is not applied, specifies the enumeration +// value of PageBuilder::TransferEncoding_t. The content construction +// buffer can be reserved with the chunked transfer, and its size is +// macro defined by AUTOCONNECT_CONTENTBUFFER_SIZE. +const AutoConnect::PageTranserModeST AutoConnect::_pageBuildMode[] = { + { AUTOCONNECT_URI, AUTOCONNECT_HTTP_TRANSFER, 0 }, + { AUTOCONNECT_URI_CONFIG, PB_Chunk, AUTOCONNECT_CONTENTBUFFER_SIZE }, + { AUTOCONNECT_URI_CONNECT, AUTOCONNECT_HTTP_TRANSFER, 0 }, + { AUTOCONNECT_URI_RESULT, AUTOCONNECT_HTTP_TRANSFER, 0 }, + { AUTOCONNECT_URI_OPEN, AUTOCONNECT_HTTP_TRANSFER, 0 }, + { AUTOCONNECT_URI_DISCON, AUTOCONNECT_HTTP_TRANSFER, 0 }, + { AUTOCONNECT_URI_RESET, AUTOCONNECT_HTTP_TRANSFER, 0 }, + { AUTOCONNECT_URI_SUCCESS, AUTOCONNECT_HTTP_TRANSFER, 0 }, + { AUTOCONNECT_URI_FAIL, AUTOCONNECT_HTTP_TRANSFER, 0 } +}; + uint32_t AutoConnect::_getChipId() { #if defined(ARDUINO_ARCH_ESP8266) return ESP.getChipId(); @@ -1129,7 +1155,7 @@ String AutoConnect::_token_LIST_SSID(PageArgument& args) { // per page in the available SSID list. if (validCount >= page * AUTOCONNECT_SSIDPAGEUNIT_LINES && validCount <= (page + 1) * AUTOCONNECT_SSIDPAGEUNIT_LINES - 1) { if (++dispCount <= AUTOCONNECT_SSIDPAGEUNIT_LINES) { - ssidList += String(F(""); + ssidList += String(F(""); ssidList += String(F("")); if (WiFi.encryptionType(i) != ENC_TYPE_NONE) ssidList += String(F("")); @@ -1259,7 +1285,6 @@ PageElement* AutoConnect::_setupPage(String uri) { elm->addToken(String(FPSTR("FLASH_SIZE")), std::bind(&AutoConnect::_token_FLASH_SIZE, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CHIP_ID")), std::bind(&AutoConnect::_token_CHIP_ID, this, std::placeholders::_1)); elm->addToken(String(FPSTR("FREE_HEAP")), std::bind(&AutoConnect::_token_FREE_HEAP, this, std::placeholders::_1)); - _responsePage->chunked(AUTOCONNECT_HTTP_TRANSFER); } else if (uri == String(AUTOCONNECT_URI_CONFIG)) { @@ -1278,7 +1303,6 @@ PageElement* AutoConnect::_setupPage(String uri) { elm->addToken(String(FPSTR("LIST_SSID")), std::bind(&AutoConnect::_token_LIST_SSID, this, std::placeholders::_1)); elm->addToken(String(FPSTR("SSID_COUNT")), std::bind(&AutoConnect::_token_SSID_COUNT, this, std::placeholders::_1)); elm->addToken(String(FPSTR("HIDDEN_COUNT")), std::bind(&AutoConnect::_token_HIDDEN_COUNT, this, std::placeholders::_1)); - _responsePage->chunked(PB_Chunk); } else if (uri == String(AUTOCONNECT_URI_CONNECT)) { @@ -1293,7 +1317,6 @@ PageElement* AutoConnect::_setupPage(String uri) { elm->addToken(String(FPSTR("MENU_PRE")), std::bind(&AutoConnect::_token_MENU_PRE, this, std::placeholders::_1)); elm->addToken(String(FPSTR("MENU_POST")), std::bind(&AutoConnect::_token_MENU_POST, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CUR_SSID")), std::bind(&AutoConnect::_token_CURRENT_SSID, this, std::placeholders::_1)); - _responsePage->chunked(AUTOCONNECT_HTTP_TRANSFER); } else if (uri == String(AUTOCONNECT_URI_OPEN)) { @@ -1308,7 +1331,6 @@ PageElement* AutoConnect::_setupPage(String uri) { elm->addToken(String(FPSTR("MENU_AUX")), std::bind(&AutoConnect::_token_MENU_AUX, this, std::placeholders::_1)); elm->addToken(String(FPSTR("MENU_POST")), std::bind(&AutoConnect::_token_MENU_POST, this, std::placeholders::_1)); elm->addToken(String(FPSTR("OPEN_SSID")), std::bind(&AutoConnect::_token_OPEN_SSID, this, std::placeholders::_1)); - _responsePage->chunked(AUTOCONNECT_HTTP_TRANSFER); } else if (uri == String(AUTOCONNECT_URI_DISCON)) { @@ -1321,7 +1343,6 @@ PageElement* AutoConnect::_setupPage(String uri) { elm->addToken(String(FPSTR("CSS_LUXBAR")), std::bind(&AutoConnect::_token_CSS_LUXBAR, this, std::placeholders::_1)); elm->addToken(String(FPSTR("MENU_PRE")), std::bind(&AutoConnect::_token_MENU_PRE, this, std::placeholders::_1)); elm->addToken(String(FPSTR("MENU_POST")), std::bind(&AutoConnect::_token_MENU_POST, this, std::placeholders::_1)); - _responsePage->chunked(AUTOCONNECT_HTTP_TRANSFER); } else if (uri == String(AUTOCONNECT_URI_RESET)) { @@ -1331,14 +1352,12 @@ PageElement* AutoConnect::_setupPage(String uri) { elm->addToken(String(FPSTR("BOOTURI")), std::bind(&AutoConnect::_token_BOOTURI, this, std::placeholders::_1)); elm->addToken(String(FPSTR("UPTIME")), std::bind(&AutoConnect::_token_UPTIME, this, std::placeholders::_1)); elm->addToken(String(FPSTR("RESET")), std::bind(&AutoConnect::_induceReset, this, std::placeholders::_1)); - _responsePage->chunked(AUTOCONNECT_HTTP_TRANSFER); } else if (uri == String(AUTOCONNECT_URI_RESULT)) { // Setup /auto/result elm->setMold("{{RESULT}}"); elm->addToken(String(FPSTR("RESULT")), std::bind(&AutoConnect::_invokeResult, this, std::placeholders::_1)); - _responsePage->chunked(AUTOCONNECT_HTTP_TRANSFER); } else if (uri == String(AUTOCONNECT_URI_SUCCESS)) { @@ -1359,7 +1378,6 @@ PageElement* AutoConnect::_setupPage(String uri) { elm->addToken(String(FPSTR("NETMASK")), std::bind(&AutoConnect::_token_NETMASK, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CHANNEL")), std::bind(&AutoConnect::_token_CHANNEL, this, std::placeholders::_1)); elm->addToken(String(FPSTR("DBM")), std::bind(&AutoConnect::_token_DBM, this, std::placeholders::_1)); - _responsePage->chunked(AUTOCONNECT_HTTP_TRANSFER); } else if (uri == String(AUTOCONNECT_URI_FAIL)) { @@ -1374,12 +1392,23 @@ PageElement* AutoConnect::_setupPage(String uri) { elm->addToken(String(FPSTR("MENU_AUX")), std::bind(&AutoConnect::_token_MENU_AUX, this, std::placeholders::_1)); elm->addToken(String(FPSTR("MENU_POST")), std::bind(&AutoConnect::_token_MENU_POST, this, std::placeholders::_1)); elm->addToken(String(FPSTR("STATION_STATUS")), std::bind(&AutoConnect::_token_STATION_STATUS, this, std::placeholders::_1)); - _responsePage->chunked(AUTOCONNECT_HTTP_TRANSFER); } else { delete elm; elm = nullptr; } + // Restore the page transfer mode and the content build buffer + // reserved size corresponding to each URI defined in structure + // _pageBuildMode. + if (elm) { + for (uint8_t n = 0; n < sizeof(_pageBuildMode) / sizeof(PageTranserModeST); n++) + if (!strcmp(_pageBuildMode[n].uri, uri.c_str())) { + _responsePage->reserve(_pageBuildMode[n].rSize); + _responsePage->chunked(_pageBuildMode[n].transMode); + break; + } + } + return elm; }