parser timeout, better checksum checking and struct stuffing, shaved some bytes off RAM

This commit is contained in:
2017-08-06 11:22:45 +02:00
parent 4eaee9389d
commit f8c60b0668
19 changed files with 178 additions and 123 deletions
+44 -26
View File
@@ -2,10 +2,11 @@
/* #line 1 "user/ansi_parser.rl" */
#include <esp8266.h>
#include "ansi_parser.h"
#include "screen.h"
/* Ragel constants block */
/* #line 9 "user/ansi_parser.c" */
/* #line 10 "user/ansi_parser.c" */
static const char _ansi_actions[] = {
0, 1, 0, 1, 1, 1, 2, 1,
3, 1, 4, 1, 5, 1, 6, 1,
@@ -30,9 +31,21 @@ static const int ansi_en_OSC_body = 5;
static const int ansi_en_main = 1;
/* #line 8 "user/ansi_parser.rl" */
/* #line 9 "user/ansi_parser.rl" */
static volatile int cs = -1;
static ETSTimer resetTim;
static void ICACHE_FLASH_ATTR
resetParserCb(void *arg) {
if (cs != ansi_start) {
cs = ansi_start;
warn("Parser timeout, state reset");
}
}
/**
* \brief Linear ANSI chars stream parser
*
@@ -49,8 +62,6 @@ static const int ansi_en_main = 1;
void ICACHE_FLASH_ATTR
ansi_parser(const char *newdata, size_t len)
{
static int cs = -1;
// The CSI code is built here
static char csi_leading; //!< Leading char, 0 if none
static int csi_ni; //!< Number of the active digit
@@ -69,17 +80,24 @@ ansi_parser(const char *newdata, size_t len)
// Init Ragel on the first run
if (cs == -1) {
/* #line 73 "user/ansi_parser.c" */
/* #line 84 "user/ansi_parser.c" */
{
cs = ansi_start;
}
/* #line 46 "user/ansi_parser.rl" */
/* #line 57 "user/ansi_parser.rl" */
}
// schedule state reset
if (termconf->parser_tout_ms > 0) {
os_timer_disarm(&resetTim);
os_timer_setfn(&resetTim, resetParserCb, NULL);
os_timer_arm(&resetTim, termconf->parser_tout_ms, 0);
}
// The parser
/* #line 83 "user/ansi_parser.c" */
/* #line 101 "user/ansi_parser.c" */
{
const char *_acts;
unsigned int _nacts;
@@ -315,13 +333,13 @@ execFuncs:
while ( _nacts-- > 0 ) {
switch ( *_acts++ ) {
case 0:
/* #line 58 "user/ansi_parser.rl" */
/* #line 76 "user/ansi_parser.rl" */
{
apars_handle_plainchar((*p));
}
break;
case 1:
/* #line 65 "user/ansi_parser.rl" */
/* #line 83 "user/ansi_parser.rl" */
{
// Reset the CSI builder
csi_leading = csi_char = 0;
@@ -336,13 +354,13 @@ execFuncs:
}
break;
case 2:
/* #line 78 "user/ansi_parser.rl" */
/* #line 96 "user/ansi_parser.rl" */
{
csi_leading = (*p);
}
break;
case 3:
/* #line 82 "user/ansi_parser.rl" */
/* #line 100 "user/ansi_parser.rl" */
{
// x10 + digit
if (csi_ni < CSI_N_MAX) {
@@ -351,13 +369,13 @@ execFuncs:
}
break;
case 4:
/* #line 89 "user/ansi_parser.rl" */
/* #line 107 "user/ansi_parser.rl" */
{
csi_ni++;
}
break;
case 5:
/* #line 93 "user/ansi_parser.rl" */
/* #line 111 "user/ansi_parser.rl" */
{
csi_char = (*p);
@@ -367,14 +385,14 @@ execFuncs:
}
break;
case 6:
/* #line 101 "user/ansi_parser.rl" */
/* #line 119 "user/ansi_parser.rl" */
{
apars_handle_badseq();
{cs = 1;goto _again;}
}
break;
case 7:
/* #line 118 "user/ansi_parser.rl" */
/* #line 136 "user/ansi_parser.rl" */
{
csi_ni = 0;
@@ -390,20 +408,20 @@ execFuncs:
}
break;
case 8:
/* #line 132 "user/ansi_parser.rl" */
/* #line 150 "user/ansi_parser.rl" */
{
apars_handle_OSC_SetScreenSize(csi_n[0], csi_n[1]);
{cs = 1;goto _again;}
}
break;
case 9:
/* #line 137 "user/ansi_parser.rl" */
/* #line 155 "user/ansi_parser.rl" */
{
osc_buffer[osc_bi++] = (*p);
}
break;
case 10:
/* #line 141 "user/ansi_parser.rl" */
/* #line 159 "user/ansi_parser.rl" */
{
osc_buffer[osc_bi++] = '\0';
apars_handle_OSC_SetTitle(osc_buffer);
@@ -411,7 +429,7 @@ execFuncs:
}
break;
case 11:
/* #line 147 "user/ansi_parser.rl" */
/* #line 165 "user/ansi_parser.rl" */
{
osc_buffer[osc_bi++] = '\0';
apars_handle_OSC_SetButton(csi_n[0], osc_buffer);
@@ -419,7 +437,7 @@ execFuncs:
}
break;
case 12:
/* #line 159 "user/ansi_parser.rl" */
/* #line 177 "user/ansi_parser.rl" */
{
// Reset screen
apars_handle_RESET_cmd();
@@ -427,20 +445,20 @@ execFuncs:
}
break;
case 13:
/* #line 165 "user/ansi_parser.rl" */
/* #line 183 "user/ansi_parser.rl" */
{
apars_handle_saveCursorAttrs();
{cs = 1;goto _again;}
}
break;
case 14:
/* #line 170 "user/ansi_parser.rl" */
/* #line 188 "user/ansi_parser.rl" */
{
apars_handle_restoreCursorAttrs();
{cs = 1;goto _again;}
}
break;
/* #line 444 "user/ansi_parser.c" */
/* #line 462 "user/ansi_parser.c" */
}
}
goto _again;
@@ -458,7 +476,7 @@ _again:
while ( __nacts-- > 0 ) {
switch ( *__acts++ ) {
case 6:
/* #line 101 "user/ansi_parser.rl" */
/* #line 119 "user/ansi_parser.rl" */
{
apars_handle_badseq();
{cs = 1; if ( p == pe )
@@ -466,7 +484,7 @@ _again:
goto _again;}
}
break;
/* #line 470 "user/ansi_parser.c" */
/* #line 488 "user/ansi_parser.c" */
}
}
}
@@ -474,6 +492,6 @@ goto _again;}
_out: {}
}
/* #line 190 "user/ansi_parser.rl" */
/* #line 208 "user/ansi_parser.rl" */
}
+20 -2
View File
@@ -1,5 +1,6 @@
#include <esp8266.h>
#include "ansi_parser.h"
#include "screen.h"
/* Ragel constants block */
%%{
@@ -7,6 +8,18 @@
write data;
}%%
static volatile int cs = -1;
static ETSTimer resetTim;
static void ICACHE_FLASH_ATTR
resetParserCb(void *arg) {
if (cs != ansi_start) {
cs = ansi_start;
warn("Parser timeout, state reset");
}
}
/**
* \brief Linear ANSI chars stream parser
*
@@ -23,8 +36,6 @@
void ICACHE_FLASH_ATTR
ansi_parser(const char *newdata, size_t len)
{
static int cs = -1;
// The CSI code is built here
static char csi_leading; //!< Leading char, 0 if none
static int csi_ni; //!< Number of the active digit
@@ -45,6 +56,13 @@ ansi_parser(const char *newdata, size_t len)
%% write init;
}
// schedule state reset
if (termconf->parser_tout_ms > 0) {
os_timer_disarm(&resetTim);
os_timer_setfn(&resetTim, resetParserCb, NULL);
os_timer_arm(&resetTim, termconf->parser_tout_ms, 0);
}
// The parser
%%{
#/*
+3 -3
View File
@@ -28,9 +28,9 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiNetworkSetParams(HttpdConnData *connData)
{
static ETSTimer timer;
char buff[50];
char buff[20];
char redir_url_buf[100];
char redir_url_buf[300];
char *redir_url = redir_url_buf;
redir_url += sprintf(redir_url, SET_REDIR_ERR);
// we'll test if anything was printed by looking for \0 in failed_keys_buf
@@ -201,7 +201,7 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiNetworkSetParams(HttpdConnData *connData)
//Template code for the WLAN page.
httpd_cgi_state ICACHE_FLASH_ATTR tplNetwork(HttpdConnData *connData, char *token, void **arg)
{
char buff[100];
char buff[20];
u8 mac[6];
if (token == NULL) {
+1 -1
View File
@@ -20,7 +20,7 @@ verify_admin_pw(const char *pw)
httpd_cgi_state ICACHE_FLASH_ATTR
cgiPersistWriteDefaults(HttpdConnData *connData)
{
char buff[50];
char buff[PASSWORD_LEN];
if (connData->conn == NULL) {
//Connection aborted. Clean up.
+1 -1
View File
@@ -6,7 +6,7 @@
#include "uart_driver.h"
#include "screen.h"
#define SOCK_BUF_LEN 2048
#define SOCK_BUF_LEN 1024
static char sock_buff[SOCK_BUF_LEN];
volatile bool notify_available = true;
+1 -1
View File
@@ -61,8 +61,8 @@ httpd_cgi_state ICACHE_FLASH_ATTR
cgiSystemCfgSetParams(HttpdConnData *connData)
{
char buff[50];
char redir_url_buf[100];
char redir_url_buf[300];
char *redir_url = redir_url_buf;
redir_url += sprintf(redir_url, SET_REDIR_ERR);
// we'll test if anything was printed by looking for \0 in failed_keys_buf
+28 -13
View File
@@ -19,8 +19,9 @@ httpd_cgi_state ICACHE_FLASH_ATTR
cgiTermCfgSetParams(HttpdConnData *connData)
{
char buff[50];
char redir_url_buf[100];
int n, w, h;
char redir_url_buf[300];
char *redir_url = redir_url_buf;
redir_url += sprintf(redir_url, SET_REDIR_ERR);
// we'll test if anything was printed by looking for \0 in failed_keys_buf
@@ -33,11 +34,11 @@ cgiTermCfgSetParams(HttpdConnData *connData)
// width and height must always go together so we can do max size validation
if (GET_ARG("term_width")) {
dbg("Default screen width: %s", buff);
int w = atoi(buff);
w = atoi(buff);
if (w > 1) {
if (GET_ARG("term_height")) {
dbg("Default screen height: %s", buff);
int h = atoi(buff);
h = atoi(buff);
if (h > 1) {
if (w * h <= MAX_SCREEN_SIZE) {
termconf->width = w;
@@ -63,20 +64,31 @@ cgiTermCfgSetParams(HttpdConnData *connData)
if (GET_ARG("default_bg")) {
dbg("Screen default BG: %s", buff);
int color = atoi(buff);
if (color >= 0 && color < 16) {
termconf->default_bg = (u8) color;
n = atoi(buff);
if (n >= 0 && n < 16) {
termconf->default_bg = (u8) n;
} else {
warn("Bad color %s", buff);
redir_url += sprintf(redir_url, "default_bg,");
}
}
if (GET_ARG("parser_tout_ms")) {
dbg("Parser timeout: %s ms", buff);
n = atoi(buff);
if (n >= 0) {
termconf->parser_tout_ms = (u8) n;
} else {
warn("Bad timeout %s", buff);
redir_url += sprintf(redir_url, "parser_tout_ms,");
}
}
if (GET_ARG("default_fg")) {
dbg("Screen default FG: %s", buff);
int color = atoi(buff);
if (color >= 0 && color < 16) {
termconf->default_fg = (u8) color;
n = atoi(buff);
if (n >= 0 && n < 16) {
termconf->default_fg = (u8) n;
} else {
warn("Bad color %s", buff);
redir_url += sprintf(redir_url, "default_fg,");
@@ -85,9 +97,9 @@ cgiTermCfgSetParams(HttpdConnData *connData)
if (GET_ARG("theme")) {
dbg("Screen color theme: %s", buff);
int theme = atoi(buff);
if (theme >= 0 && theme <= 5) { // ALWAYS ADJUST WHEN ADDING NEW THEME!
termconf->theme = (u8) theme;
n = atoi(buff);
if (n >= 0 && n <= 5) { // ALWAYS ADJUST WHEN ADDING NEW THEME!
termconf->theme = (u8) n;
} else {
warn("Bad theme num: %s", buff);
redir_url += sprintf(redir_url, "theme,");
@@ -127,7 +139,7 @@ cgiTermCfgSetParams(HttpdConnData *connData)
httpd_cgi_state ICACHE_FLASH_ATTR
tplTermCfg(HttpdConnData *connData, char *token, void **arg)
{
#define BUFLEN 100
#define BUFLEN TERM_TITLE_LEN
char buff[BUFLEN];
char buff2[10];
@@ -144,6 +156,9 @@ tplTermCfg(HttpdConnData *connData, char *token, void **arg)
else if (streq(token, "term_height")) {
sprintf(buff, "%d", termconf->height);
}
else if (streq(token, "parser_tout_ms")) {
sprintf(buff, "%d", termconf->parser_tout_ms);
}
else if (streq(token, "theme")) {
sprintf(buff, "%d", termconf->theme);
}
+2 -2
View File
@@ -325,8 +325,8 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiWiFiSetParams(HttpdConnData *connData)
static ETSTimer timer;
char buff[50];
char redir_url_buf[100]; // this is just barely enough - but it's split into two forms, so we never have error in all fields
char redir_url_buf[300];
char *redir_url = redir_url_buf;
redir_url += sprintf(redir_url, SET_REDIR_ERR);
// we'll test if anything was printed by looking for \0 in failed_keys_buf
@@ -507,7 +507,7 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiWiFiSetParams(HttpdConnData *connData)
//Template code for the WLAN page.
httpd_cgi_state ICACHE_FLASH_ATTR tplWlan(HttpdConnData *connData, char *token, void **arg)
{
char buff[100];
char buff[PASSWORD_LEN];
int x;
int connectStatus;
+35 -12
View File
@@ -17,23 +17,45 @@ static void ICACHE_FLASH_ATTR
apply_live_settings(void)
{
dbg("[Persist] Applying live settings...");
terminal_apply_settings();
wifimgr_apply_settings();
dbg("[Persist] > system");
sysconf_apply_settings();
dbg("[Persist] > wifi");
wifimgr_apply_settings();
dbg("[Persist] > terminal");
terminal_apply_settings();
dbg("[Persist] Live settings applied.");
// ...
}
static void ICACHE_FLASH_ATTR
restore_live_settings_to_hard_defaults(void)
{
wifimgr_restore_defaults();
terminal_restore_defaults();
dbg("[Persist] Restore to hard defaults...");
dbg("[Persist] > system");
sysconf_restore_defaults();
dbg("[Persist] > wifi");
wifimgr_restore_defaults();
dbg("[Persist] > terminal");
terminal_restore_defaults();
dbg("[Persist] Restored to hard defaults.");
// ...
}
//endregion
const u32 wconf_at = (u32)&persist.defaults.wificonf - (u32)&persist.defaults;
const u32 tconf_at = (u32)&persist.defaults.termconf - (u32)&persist.defaults;
const u32 sconf_at = (u32)&persist.defaults.sysconf - (u32)&persist.defaults;
const u32 cksum_at = (u32)&persist.defaults.checksum - (u32)&persist.defaults;
/**
* Compute CRC32. Adapted from https://github.com/esp8266/Arduino
* @param data
@@ -43,7 +65,9 @@ restore_live_settings_to_hard_defaults(void)
static uint32_t ICACHE_FLASH_ATTR
calculateCRC32(const uint8_t *data, size_t length)
{
uint32_t crc = 0xffffffff + CHECKSUM_SALT;
// the salt here should ensure settings are wiped when the structure changes
// CHECKSUM_SALT can be adjusted manually to force a reset.
uint32_t crc = 0xffffffff + CHECKSUM_SALT + ((wconf_at << 16) ^ (tconf_at << 10) ^ (sconf_at << 5));
while (length--) {
uint8_t c = *data++;
for (uint32_t i = 0x80; i > 0; i >>= 1) {
@@ -81,13 +105,12 @@ persist_load(void)
{
info("[Persist] Loading stored settings from FLASH...");
dbg("sizeof(AppConfigBundle) = %d bytes", sizeof(AppConfigBundle));
dbg("> sizeof(WiFiConfigBundle) = %d bytes", sizeof(WiFiConfigBundle));
dbg("> sizeof(TerminalConfigBundle) = %d bytes", sizeof(TerminalConfigBundle));
dbg("> sizeof(SystemConfigBundle) = %d bytes", sizeof(SystemConfigBundle));
dbg("> sizeof(checksum) = %d bytes", sizeof(uint32_t));
dbg("> filler = %d bytes",
sizeof(AppConfigBundle) - (sizeof(WiFiConfigBundle) + sizeof(TerminalConfigBundle) + sizeof(SystemConfigBundle)));
dbg("AppConfigBundle memory map:");
dbg("> WiFiConfigBundle at %4d (error %2d)", wconf_at, wconf_at - 0);
dbg("> SystemConfigBundle at %4d (error %2d)", sconf_at, sconf_at - WIFICONF_SIZE);
dbg("> TerminalConfigBundle at %4d (error %2d)", tconf_at, tconf_at - WIFICONF_SIZE - SYSCONF_SIZE);
dbg("> Checksum at %4d (error %2d)", cksum_at, cksum_at - (APPCONF_SIZE - 4));
dbg("> Total size = %d bytes (error %d)", sizeof(AppConfigBundle), APPCONF_SIZE - sizeof(AppConfigBundle));
bool hard_reset = false;
+11 -6
View File
@@ -16,15 +16,20 @@
// Changing this could be used to force-erase the config area
// after a firmware upgrade
#define CHECKSUM_SALT 2
#define CHECKSUM_SALT 3
#define APPCONF_SIZE 2048
/** Struct for current or default settings */
typedef struct { // the entire block should be 1024 bytes long (for compatibility across upgrades)
WiFiConfigBundle wificonf;
TerminalConfigBundle termconf;
uint8_t _filler1[WIFICONF_SIZE - sizeof(WiFiConfigBundle)];
SystemConfigBundle sysconf;
uint8_t _filler3[SYSCONF_SIZE - sizeof(SystemConfigBundle)];
TerminalConfigBundle termconf;
uint8_t _filler2[TERMCONF_SIZE - sizeof(TerminalConfigBundle)];
// --- Space for future settings ---
// The size must be appropriately reduced each time something is added,
@@ -34,12 +39,12 @@ typedef struct { // the entire block should be 1024 bytes long (for compatibilit
// This ensures user settings are not lost each time they upgrade the firmware,
// which would lead to a checksum mismatch if the structure was changed and
// it grew to a different memory area.
uint8_t filler[
uint8_t _filler_end[
APPCONF_SIZE
- sizeof(uint32_t) // checksum
- sizeof(WiFiConfigBundle)
- sizeof(TerminalConfigBundle)
- sizeof(SystemConfigBundle)
- WIFICONF_SIZE
- SYSCONF_SIZE
- TERMCONF_SIZE
];
uint32_t checksum; // computed before write and tested on load. If it doesn't match, values are reset to hard defaults.
+12 -3
View File
@@ -8,6 +8,9 @@
TerminalConfigBundle * const termconf = &persist.current.termconf;
TerminalConfigBundle termconf_scratch;
#define W termconf_scratch.width
#define H termconf_scratch.height
/**
* Restore hard defaults
*/
@@ -17,6 +20,7 @@ void terminal_restore_defaults(void)
termconf->default_fg = 7;
termconf->width = 26;
termconf->height = 10;
termconf->parser_tout_ms = 10;
sprintf(termconf->title, "ESPTerm");
for(int i=1; i <= 5; i++) {
sprintf(termconf->btn[i-1], "%d", i);
@@ -29,12 +33,16 @@ void terminal_restore_defaults(void)
void terminal_apply_settings(void)
{
memcpy(&termconf_scratch, termconf, sizeof(TerminalConfigBundle));
if (W*H >= MAX_SCREEN_SIZE) {
error("BAD SCREEN SIZE: %d rows x %d cols", H, W);
error("reverting terminal settings to default");
terminal_restore_defaults();
persist_store();
memcpy(&termconf_scratch, termconf, sizeof(TerminalConfigBundle));
}
screen_init();
}
#define W termconf_scratch.width
#define H termconf_scratch.height
/**
* Highest permissible value of the color attribute
*/
@@ -105,6 +113,7 @@ static volatile int notifyLock = 0;
static inline void
clear_range(unsigned int from, unsigned int to)
{
if (to >= W*H) to = W*H-1;
Color fg = cursor.inverse ? cursor.bg : cursor.fg;
Color bg = cursor.inverse ? cursor.fg : cursor.bg;
for (unsigned int i = from; i <= to; i++) {
+1 -12
View File
@@ -56,18 +56,7 @@ typedef struct {
char title[TERM_TITLE_LEN];
char btn[5][TERM_BTN_LEN];
u8 theme;
u8 _filler[
TERMCONF_SIZE
- 4
- 4
- 1
- 1
- 1
- TERM_TITLE_LEN
- TERM_BTN_LEN * 5
];
u32 parser_tout_ms;
} TerminalConfigBundle;
// Live config
-7
View File
@@ -15,13 +15,6 @@ typedef struct {
u32 uart_baudrate;
u8 uart_parity;
u8 uart_stopbits;
u8 _filler[
SYSCONF_SIZE
- 4
- 1
- 1
];
} SystemConfigBundle;
extern SystemConfigBundle * const sysconf;
+3 -24
View File
@@ -27,42 +27,21 @@ typedef struct {
WIFI_MODE opmode : 8;
u8 tpw;
// --- AP config ---
// AP config
u8 ap_channel;
u8 ap_ssid[SSID_LEN];
u8 ap_password[PASSWORD_LEN];
bool ap_hidden;
//
u16 ap_dhcp_time; // in minutes
struct dhcps_lease ap_dhcp_range;
struct ip_info ap_addr;
// --- Client config ---
// Client config
u8 sta_ssid[SSID_LEN];
u8 sta_password[PASSWORD_LEN];
bool sta_dhcp_enable;
struct ip_info sta_addr;
u8 _filler[
WIFICONF_SIZE
- 1
- 1
- 1
- SSID_LEN
- PASSWORD_LEN
- 1
- 2
- sizeof(struct dhcps_lease)
- sizeof(struct ip_info)
- SSID_LEN
- PASSWORD_LEN
- 1
- sizeof(struct ip_info)
- 8 // padding?
];
} WiFiConfigBundle;
typedef struct {