Change Wi-Fi config to POST

This commit is contained in:
2025-07-19 11:18:30 -04:00
parent d3b12890bb
commit d25218898b
5 changed files with 389 additions and 310 deletions
+164 -87
View File
@@ -25,6 +25,7 @@ static bool clientmode = false;
static bool config_loaded = false;
static bool bad_config = false;
static bool reboot = false;
static void *current_connection;
// list of SSI variable names for lwIP SSI handler
const char * __not_in_flash("httpd") ssi_tags[] = {
@@ -49,10 +50,24 @@ const char * __not_in_flash("httpd") ssi_tags[] = {
"dhcp"
};
const char * ip_parts[] = {
"ip0=",
"ip1=",
"ip2=",
"ip3=",
"mask0=",
"mask1=",
"mask2=",
"mask3=",
"gw0=",
"gw1=",
"gw2=",
"gw3="
};
#define NPARTS ( sizeof( ip_parts )/ sizeof(ip_parts[0]) )
static const tCGI cgi_handlers[] = {
{ "/sendkeys.cgi", sendkeys_cgi },
{ "/wifi.cgi", save_wifi },
{ "/reboot.cgi", reboot_cgi },
};
@@ -119,7 +134,7 @@ void run_http_server() {
// start the HTTP web server for keyboard input and config page
httpd_init();
http_set_cgi_handlers(cgi_handlers, 3);
http_set_cgi_handlers(cgi_handlers, 2);
for (size_t i = 0; i < LWIP_ARRAYSIZE(ssi_tags); i++) {
LWIP_ASSERT("tag too long for LWIP_HTTPD_MAX_TAG_NAME_LEN",
strlen(ssi_tags[i]) <= LWIP_HTTPD_MAX_TAG_NAME_LEN);
@@ -184,89 +199,6 @@ const char * sendkeys_cgi (int iIndex, int iNumParams, char *pcParam[], char *pc
return "/success.html";
}
// lwIP cgi handler for form submission of network config to wifi.cgi
const char * save_wifi (int iIndex, int iNumParams, char *pcParam[], char *pcValue[]) {
// clear all values in manual network settings
memset(ip, 0, sizeof(ip));
memset(mask, 0, sizeof(mask));
memset(gw, 0, sizeof(gw));
bad_config = false;
wifi.manual = true;
// read parameter values
for (int i=0; i < iNumParams; i++) {
if (strcmp(pcParam[i], "ssid") == 0){
if (pcValue[i][0] == "\0") {
bad_config = true;
} else {
urldecode(pcValue[i], wifi.ssid);
}
} else if (strcmp(pcParam[i], "pass") == 0) {
urldecode(pcValue[i], wifi.pass);
} else if (strcmp(pcParam[i], "host") == 0) {
urldecode(pcValue[i], wifi.host);
} else if (strcmp(pcParam[i], "dhcp") == 0) {
wifi.manual = false;
} else if (strncmp(pcParam[i], "ip", 2) ==0 ) {
uint8_t part = atoi(&(pcParam[i][2]));
int val = atoi(pcValue[i]);
if (pcValue[i][0] == "\0" || val > 255 || val < 0 || part > 4) {
bad_config = true;
} else {
ip[part] = (uint8_t) val;
}
} else if (strncmp(pcParam[i], "gw", 2) ==0 ) {
uint8_t part = atoi(&(pcParam[i][2]));
int val = atoi(pcValue[i]);
if (pcValue[i][0] == "\0" || val > 255 || val < 0 || part > 4) {
bad_config = true;
} else {
gw[part] = (uint8_t) val;
}
} else if (strncmp(pcParam[i], "mask", 4) ==0 ) {
uint8_t part = atoi(&(pcParam[i][4]));
int val = atoi(pcValue[i]);
if (pcValue[i][0] == "\0" || val > 255 || val < 0 || part > 4) {
bad_config = true;
} else {
mask[part] = (uint8_t) val;
}
}
}
if (bad_config) {
// config is invalid, so don't save and return to config page
return "/wifi.shtml";
} else {
// config is valid, prepare for saving to flash
IP4_ADDR(&(wifi.ip), ip[0], ip[1], ip[2], ip[3]);
if(!wifi.ip.addr) {
wifi.ip.addr = IPADDR_NONE;
}
IP4_ADDR(&(wifi.mask), mask[0], mask[1], mask[2], mask[3]);
if(!wifi.mask.addr) {
wifi.mask.addr = IPADDR_NONE;
}
IP4_ADDR(&(wifi.gw), gw[0], gw[1], gw[2], gw[3]);
if(!wifi.gw.addr) {
wifi.gw.addr = IPADDR_NONE;
}
wifi.header = STARTFILE;
wifi.footer = ENDFILE;
config_loaded = true;
watchdog_update();
// save configuratitons to flash
net_config_write(&wifi);
printf("wifi settings saved\n");
return "/success.html";
}
}
// lwIP cgi handler for reboots initiated from the web
const char * reboot_cgi(int iIndex, int iNumParams, char *pcParam[], char *pcValue[]) {
// turn on reboot flag to prevent watchdog from updating
@@ -275,7 +207,7 @@ const char * reboot_cgi(int iIndex, int iNumParams, char *pcParam[], char *pcVal
return "/success.html";
}
// write configuration data to flash memory
void net_config_write(net_config *config) {
// core 0 must have its TinyUSB interrupts disabled to allow flash writes
multicore_lockout_start_blocking();
@@ -397,12 +329,157 @@ uint16_t __time_critical_func(ssi_handler)(int iIndex, char *pcInsert, int iInse
return (uint16_t)printed;
}
// lwIP handler for POST requests
err_t httpd_post_begin(void *connection, const char *uri,
const char * http_request, u16_t http_request_len, int content_len,
char *response_uri,u16_t response_uri_len, u8_t *post_auto_wnd) {
if (memcmp(uri, "/wifi.cgi", 9) == 0 && current_connection != connection) {
// initiate post request to wifi.cgi
current_connection = connection;
// default page is wifi config page
snprintf(response_uri, response_uri_len, "/wifi.shtml");
*post_auto_wnd = 1;
return ERR_OK;
}
return ERR_VAL;
}
// lwIP handler for receiving POST data
err_t httpd_post_receive_data(void *connection, struct pbuf *p) {
if (current_connection == connection) {
// clear all values in manual network settings
memset(ip, 0, sizeof(ip));
memset(mask, 0, sizeof(mask));
memset(gw, 0, sizeof(gw));
bad_config = false;
wifi.manual = true;
char buf[MAX_POST_PARAM_LEN];
char * value;
// read parameter values
value = find_post_param(p, "ssid=", buf, sizeof(buf));
if (value) {
urldecode(value, wifi.ssid);
} else {
bad_config = true;
}
value = find_post_param(p, "pass=", buf, sizeof(buf));
if (value) {
urldecode(value, wifi.pass);
} else {
wifi.pass[0]=0;
}
value = find_post_param(p, "host=", buf, sizeof(buf));
if (value) {
urldecode(value, wifi.host);
} else {
wifi.host[0]=0;
}
value = find_post_param(p, "dhcp=", buf, sizeof(buf));
if (value) {
wifi.manual = false;
} else {
for (int i=0; i< NPARTS; i++) {
value = find_post_param(p, ip_parts[i], buf, sizeof(buf));
if (value) {
int ip_part = atoi(value);
if (ip_part > 255 || ip_part < 0) {
bad_config = true;
} else {
if (strncmp(ip_parts[i], "ip", 2) == 0) {
uint8_t part = atoi(&ip_parts[i][2]);
ip[part] = (uint8_t) ip_part;
} else if (strncmp(ip_parts[i], "gw", 2) == 0) {
uint8_t part = atoi(&ip_parts[i][2]);
gw[part] = (uint8_t) ip_part;
} else if (strncmp(ip_parts[i], "mask", 4) == 0) {
uint8_t part = atoi(&ip_parts[i][4]);
mask[part] = (uint8_t) ip_part;
}
}
} else {
bad_config = true;
}
}
}
if (!bad_config) {
// config is valid, prepare for saving to flash
IP4_ADDR(&(wifi.ip), ip[0], ip[1], ip[2], ip[3]);
if(!wifi.ip.addr) {
wifi.ip.addr = IPADDR_NONE;
}
IP4_ADDR(&(wifi.mask), mask[0], mask[1], mask[2], mask[3]);
if(!wifi.mask.addr) {
wifi.mask.addr = IPADDR_NONE;
}
IP4_ADDR(&(wifi.gw), gw[0], gw[1], gw[2], gw[3]);
if(!wifi.gw.addr) {
wifi.gw.addr = IPADDR_NONE;
}
wifi.header = STARTFILE;
wifi.footer = ENDFILE;
config_loaded = true;
watchdog_update();
// save configurations to flash
net_config_write(&wifi);
printf("wifi settings saved\n");
pbuf_free(p);
return ERR_OK;
}
}
pbuf_free(p);
current_connection = NULL;
return ERR_VAL;
}
// lwIP handler for end of POST request
void httpd_post_finished(void *connection, char *response_uri, u16_t response_uri_len) {
// return to Wi-Fi config page unless save was successful
snprintf(response_uri, response_uri_len, "/wifi.shtml");
if (current_connection == connection) {
snprintf(response_uri, response_uri_len, "/success.html");
}
current_connection = NULL;
}
// Return a value for a parameter from POST
char *find_post_param(struct pbuf *p, const char *param, char *buf, size_t len) {
size_t param_len = strlen(param);
uint16_t param_pos = pbuf_memfind(p, param, param_len, 0);
if (param_pos != 0xFFFF) {
uint16_t value_pos = param_pos + param_len;
uint16_t value_len = 0;
uint16_t tmp;
tmp = pbuf_memfind(p, "&", 1, value_pos);
if (tmp != 0xFFFF) {
value_len = tmp - value_pos;
} else {
value_len = p->tot_len - value_pos;
}
if (value_len > 0 && value_len < len) {
char *value = (char *) pbuf_get_contiguous(p, buf, len, value_len, value_pos);
if (value) {
value[value_len]=0;
return value;
}
}
}
return NULL;
}
// save keyboard's LED indicator status to memory
void set_indicator(uint8_t const* buffer) {
led_code = *buffer;
}
// turn URL-formatted string from GET request and turn into regular string
// take URL-formatted string from GET request and turn into regular string
void urldecode(char *urlstring, char *decoded) {
uint8_t conv;
while(*urlstring) {