improved some comments - use the dbg funcs
This commit is contained in:
+30
-29
@@ -108,7 +108,7 @@ static HttpdConnData ICACHE_FLASH_ATTR *httpdFindConnData(ConnTypePtr conn, cons
|
||||
}
|
||||
}
|
||||
//Shouldn't happen.
|
||||
httpd_printf("*** Unknown connection %d.%d.%d.%d:%d\n", remIp[0]&0xff, remIp[1]&0xff, remIp[2]&0xff, remIp[3]&0xff, remPort);
|
||||
error("*** Unknown connection %d.%d.%d.%d:%d", remIp[0]&0xff, remIp[1]&0xff, remIp[2]&0xff, remIp[3]&0xff, remPort);
|
||||
httpdPlatDisconnect(conn);
|
||||
return NULL;
|
||||
}
|
||||
@@ -190,7 +190,7 @@ int ICACHE_FLASH_ATTR httpdFindArg(char *line, char *arg, char *buff, int buffLe
|
||||
p=(char*)strstr(p, "&");
|
||||
if (p!=NULL) p+=1;
|
||||
}
|
||||
httpd_printf("Finding %s in %s: Not found :/\n", arg, line);
|
||||
warn("Finding %s in %s: Not found :/", arg, line);
|
||||
return -1; //not found
|
||||
}
|
||||
|
||||
@@ -297,7 +297,7 @@ int ICACHE_FLASH_ATTR cgiRedirectToHostname(HttpdConnData *connData) {
|
||||
return HTTPD_CGI_DONE;
|
||||
}
|
||||
if (connData->hostName==NULL) {
|
||||
httpd_printf("Huh? No hostname.\n");
|
||||
warn("Huh? No hostname.\n");
|
||||
return HTTPD_CGI_NOTFOUND;
|
||||
}
|
||||
|
||||
@@ -314,7 +314,7 @@ int ICACHE_FLASH_ATTR cgiRedirectToHostname(HttpdConnData *connData) {
|
||||
//Not the same. Redirect to real hostname.
|
||||
buff=malloc(strlen((char*)connData->cgiArg)+sizeof(hostFmt));
|
||||
sprintf(buff, hostFmt, (char*)connData->cgiArg);
|
||||
httpd_printf("Redirecting to hostname url %s\n", buff);
|
||||
dbg("Redirecting to hostname url %s", buff);
|
||||
httpdRedirect(connData, buff);
|
||||
free(buff);
|
||||
return HTTPD_CGI_DONE;
|
||||
@@ -400,13 +400,13 @@ void ICACHE_FLASH_ATTR httpdFlushSendBuffer(HttpdConnData *conn) {
|
||||
if (!r) {
|
||||
//Can't send this for some reason. Dump packet in backlog, we can send it later.
|
||||
if (conn->priv->sendBacklogSize+conn->priv->sendBuffLen>MAX_BACKLOG_SIZE) {
|
||||
httpd_printf("Httpd: Backlog: Exceeded max backlog size, dropped %d bytes instead of sending them.\n", conn->priv->sendBuffLen);
|
||||
error("Httpd: Backlog: Exceeded max backlog size, dropped %d bytes instead of sending them.", conn->priv->sendBuffLen);
|
||||
conn->priv->sendBuffLen=0;
|
||||
return;
|
||||
}
|
||||
HttpSendBacklogItem *i=malloc(sizeof(HttpSendBacklogItem)+conn->priv->sendBuffLen);
|
||||
if (i==NULL) {
|
||||
httpd_printf("Httpd: Backlog: malloc failed, out of memory!\n");
|
||||
error("Httpd: Backlog: malloc failed, out of memory!");
|
||||
return;
|
||||
}
|
||||
memcpy(i->data, conn->priv->sendBuff, conn->priv->sendBuffLen);
|
||||
@@ -428,7 +428,7 @@ void ICACHE_FLASH_ATTR httpdFlushSendBuffer(HttpdConnData *conn) {
|
||||
void ICACHE_FLASH_ATTR httpdCgiIsDone(HttpdConnData *conn) {
|
||||
conn->cgi=NULL; //no need to call this anymore
|
||||
if (conn->priv->flags&HFL_CHUNKED) {
|
||||
httpd_printf("Pool slot %d is done. Cleaning up for next req\n", conn->slot);
|
||||
dbg("Pool slot %d is done. Cleaning up for next req", conn->slot);
|
||||
httpdFlushSendBuffer(conn);
|
||||
//Note: Do not clean up sendBacklog, it may still contain data at this point.
|
||||
conn->priv->headPos=0;
|
||||
@@ -465,7 +465,7 @@ void ICACHE_FLASH_ATTR httpdSentCb(ConnTypePtr rconn, char *remIp, int remPort)
|
||||
}
|
||||
|
||||
if (conn->priv->flags&HFL_DISCONAFTERSENT) { //Marked for destruction?
|
||||
httpd_printf("Pool slot %d is done. Closing.\n", conn->slot);
|
||||
dbg("Pool slot %d is done. Closing.", conn->slot);
|
||||
httpdPlatDisconnect(conn->conn);
|
||||
return; //No need to call httpdFlushSendBuffer.
|
||||
}
|
||||
@@ -496,7 +496,7 @@ static void ICACHE_FLASH_ATTR httpdProcessRequest(HttpdConnData *conn) {
|
||||
int r;
|
||||
int i=0;
|
||||
if (conn->url==NULL) {
|
||||
httpd_printf("WtF? url = NULL\n");
|
||||
error("WtF? url = NULL");
|
||||
return; //Shouldn't happen
|
||||
}
|
||||
//See if we can find a CGI that's happy to handle the request.
|
||||
@@ -510,7 +510,7 @@ static void ICACHE_FLASH_ATTR httpdProcessRequest(HttpdConnData *conn) {
|
||||
if (builtInUrls[i].url[strlen(builtInUrls[i].url)-1]=='*' &&
|
||||
strncmp(builtInUrls[i].url, conn->url, strlen(builtInUrls[i].url)-1)==0) match=1;
|
||||
if (match) {
|
||||
httpd_printf("Is url index %d\n", i);
|
||||
dbg("Is url index %d", i);
|
||||
conn->cgiData=NULL;
|
||||
conn->cgi=builtInUrls[i].cgiCb;
|
||||
conn->cgiArg=builtInUrls[i].cgiArg;
|
||||
@@ -522,7 +522,7 @@ static void ICACHE_FLASH_ATTR httpdProcessRequest(HttpdConnData *conn) {
|
||||
if (builtInUrls[i].url==NULL) {
|
||||
//Drat, we're at the end of the URL table. This usually shouldn't happen. Well, just
|
||||
//generate a built-in 404 to handle this.
|
||||
httpd_printf("%s not found. 404!\n", conn->url);
|
||||
warn("%s not found. 404!", conn->url);
|
||||
conn->cgi=cgiNotFound;
|
||||
}
|
||||
|
||||
@@ -584,13 +584,13 @@ static void ICACHE_FLASH_ATTR httpdParseHeader(char *h, HttpdConnData *conn) {
|
||||
//If HTTP/1.1, note that and set chunked encoding
|
||||
if (strcasecmp(e, "HTTP/1.1")==0) conn->priv->flags|=HFL_HTTP11|HFL_CHUNKED;
|
||||
|
||||
httpd_printf("URL = %s\n", conn->url);
|
||||
info("Incoming request, URL = %s", conn->url);
|
||||
//Parse out the URL part before the GET parameters.
|
||||
conn->getArgs=(char*)strstr(conn->url, "?");
|
||||
if (conn->getArgs!=0) {
|
||||
*conn->getArgs=0;
|
||||
conn->getArgs++;
|
||||
httpd_printf("GET args = %s\n", conn->getArgs);
|
||||
dbg("GET args = %s", conn->getArgs);
|
||||
} else {
|
||||
conn->getArgs=NULL;
|
||||
}
|
||||
@@ -613,7 +613,7 @@ static void ICACHE_FLASH_ATTR httpdParseHeader(char *h, HttpdConnData *conn) {
|
||||
} else {
|
||||
conn->post->buffSize = conn->post->len;
|
||||
}
|
||||
httpd_printf("Mallocced buffer for %d + 1 bytes of post data.\n", conn->post->buffSize);
|
||||
dbg("Malloc'd buffer for %d + 1 bytes of post data.", conn->post->buffSize);
|
||||
conn->post->buff=(char*)malloc(conn->post->buffSize + 1);
|
||||
conn->post->buffLen=0;
|
||||
} else if (strncmp(h, "Content-Type: ", 14)==0) {
|
||||
@@ -624,7 +624,7 @@ static void ICACHE_FLASH_ATTR httpdParseHeader(char *h, HttpdConnData *conn) {
|
||||
conn->post->multipartBoundary = b + 7; // move the pointer 2 chars before boundary then fill them with dashes
|
||||
conn->post->multipartBoundary[0] = '-';
|
||||
conn->post->multipartBoundary[1] = '-';
|
||||
httpd_printf("boundary = %s\n", conn->post->multipartBoundary);
|
||||
dbg("boundary = %s", conn->post->multipartBoundary);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -705,13 +705,13 @@ void httpdRecvCb(ConnTypePtr rconn, char *remIp, int remPort, char *data, unsign
|
||||
if (conn->recvHdl) {
|
||||
r=conn->recvHdl(conn, data+x, len-x);
|
||||
if (r==HTTPD_CGI_DONE) {
|
||||
httpd_printf("Recvhdl returned DONE\n");
|
||||
dbg("Recvhdl returned DONE");
|
||||
httpdCgiIsDone(conn);
|
||||
//We assume the recvhdlr has sent something; we'll kill the sock in the sent callback.
|
||||
}
|
||||
break; //ignore rest of data, recvhdl has parsed it.
|
||||
} else {
|
||||
httpd_printf("Eh? Got unexpected data from client. %s\n", data);
|
||||
warn("Eh? Got unexpected data from client. %s", data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -724,7 +724,7 @@ void httpdRecvCb(ConnTypePtr rconn, char *remIp, int remPort, char *data, unsign
|
||||
void ICACHE_FLASH_ATTR httpdDisconCb(ConnTypePtr rconn, char *remIp, int remPort) {
|
||||
HttpdConnData *hconn=httpdFindConnData(rconn, remIp, remPort);
|
||||
if (hconn==NULL) return;
|
||||
httpd_printf("Pool slot %d: socket closed.\n", hconn->slot);
|
||||
info("Pool slot %d: socket closed.", hconn->slot);
|
||||
hconn->conn=NULL; //indicate cgi the connection is gone
|
||||
if (hconn->cgi) hconn->cgi(hconn); //Execute cgi fn if needed
|
||||
httpdRetireConn(hconn);
|
||||
@@ -732,26 +732,27 @@ void ICACHE_FLASH_ATTR httpdDisconCb(ConnTypePtr rconn, char *remIp, int remPort
|
||||
|
||||
|
||||
int ICACHE_FLASH_ATTR httpdConnectCb(ConnTypePtr conn, char *remIp, int remPort) {
|
||||
|
||||
static int failed_cnt = 0;
|
||||
|
||||
int i;
|
||||
//Find empty conndata in pool
|
||||
for (i=0; i<HTTPD_MAX_CONNECTIONS; i++) if (connData[i]==NULL) break;
|
||||
httpd_printf("Conn req from %d.%d.%d.%d:%d, using pool slot %d\n", remIp[0]&0xff, remIp[1]&0xff, remIp[2]&0xff, remIp[3]&0xff, remPort, i);
|
||||
info("Conn req from %d.%d.%d.%d:%d, using pool slot %d", remIp[0]&0xff, remIp[1]&0xff, remIp[2]&0xff, remIp[3]&0xff, remPort, i);
|
||||
if (i==HTTPD_MAX_CONNECTIONS) {
|
||||
httpd_printf("Aiee, conn pool overflow!\n");
|
||||
error("Aiee, conn pool overflow!");
|
||||
|
||||
failed_cnt++;
|
||||
|
||||
// added by mightypork
|
||||
if (system_get_free_heap_size() < 29000) {
|
||||
// this probably means we got flooded by someone spamming F5
|
||||
// better restart
|
||||
|
||||
httpd_printf("\x1b[31;1mLow heap & con pool overflow, GOING FOR RESTART.\x1b[0m\n");
|
||||
if (failed_cnt >= 5) {
|
||||
error("5 failed connections, this is bad. GOING FOR RESTART!");
|
||||
system_restart();
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
failed_cnt = 0;
|
||||
|
||||
connData[i]=malloc(sizeof(HttpdConnData));
|
||||
memset(connData[i], 0, sizeof(HttpdConnData));
|
||||
connData[i]->priv=malloc(sizeof(HttpdPriv));
|
||||
@@ -784,5 +785,5 @@ void ICACHE_FLASH_ATTR httpdInit(HttpdBuiltInUrl *fixedUrls, int port) {
|
||||
builtInUrls=fixedUrls;
|
||||
|
||||
httpdPlatInit(port, HTTPD_MAX_CONNECTIONS);
|
||||
httpd_printf("Httpd init\n");
|
||||
info("Httpd started.");
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ int ICACHE_FLASH_ATTR serveStaticFile(HttpdConnData *connData, const char* filep
|
||||
|
||||
// invalid call.
|
||||
if (filepath == NULL) {
|
||||
printf("serveStaticFile called with NULL path!\n");
|
||||
error("serveStaticFile called with NULL path!");
|
||||
return HTTPD_CGI_NOTFOUND;
|
||||
}
|
||||
|
||||
@@ -139,6 +139,8 @@ int ICACHE_FLASH_ATTR serveStaticFile(HttpdConnData *connData, const char* filep
|
||||
if (len != 1024) {
|
||||
//We're done.
|
||||
espFsClose(file);
|
||||
info("Static file done");
|
||||
|
||||
return HTTPD_CGI_DONE;
|
||||
} else {
|
||||
//Ok, till next time.
|
||||
@@ -210,7 +212,7 @@ int ICACHE_FLASH_ATTR cgiEspFsTemplate(HttpdConnData *connData)
|
||||
// check for custom template URL
|
||||
if (connData->cgiArg2 != NULL) {
|
||||
filepath = connData->cgiArg2;
|
||||
printf("Using filepath %s\n", filepath);
|
||||
dbg("Using filepath %s", filepath);
|
||||
}
|
||||
|
||||
tpd->file = espFsOpen(filepath);
|
||||
@@ -226,7 +228,7 @@ int ICACHE_FLASH_ATTR cgiEspFsTemplate(HttpdConnData *connData)
|
||||
tpd->tplArg = NULL;
|
||||
tpd->tokenPos = -1;
|
||||
if (espFsFlags(tpd->file) & FLAG_GZIP) {
|
||||
httpd_printf("cgiEspFsTemplate: Trying to use gzip-compressed file %s as template!\n", connData->url);
|
||||
error("cgiEspFsTemplate: Trying to use gzip-compressed file %s as template!", connData->url);
|
||||
espFsClose(tpd->file);
|
||||
free(tpd);
|
||||
return HTTPD_CGI_NOTFOUND;
|
||||
@@ -244,6 +246,7 @@ int ICACHE_FLASH_ATTR cgiEspFsTemplate(HttpdConnData *connData)
|
||||
// resume the parser state from the last token,
|
||||
// if subst. func wants more data to be sent.
|
||||
if (tpd->chunk_resume) {
|
||||
dbg("Resuming tpl parser for multi-part subst");
|
||||
// resume
|
||||
len = tpd->buff_len;
|
||||
e = tpd->buff_e;
|
||||
@@ -289,6 +292,7 @@ int ICACHE_FLASH_ATTR cgiEspFsTemplate(HttpdConnData *connData)
|
||||
int status = ((TplCallback)(connData->cgiArg))(connData, tpd->token, &tpd->tplArg);
|
||||
|
||||
if (status == HTTPD_CGI_MORE) {
|
||||
dbg("Multi-part tpl subst, saving parser state");
|
||||
// wants to send more in this token's place.....
|
||||
tpd->chunk_resume = true;
|
||||
|
||||
@@ -323,6 +327,8 @@ int ICACHE_FLASH_ATTR cgiEspFsTemplate(HttpdConnData *connData)
|
||||
// let the cgi func clean it's stuff
|
||||
((TplCallback)(connData->cgiArg))(connData, NULL, &tpd->tplArg);
|
||||
|
||||
info("Template sent.");
|
||||
|
||||
espFsClose(tpd->file);
|
||||
free(tpd);
|
||||
return HTTPD_CGI_DONE;
|
||||
|
||||
@@ -111,7 +111,7 @@ void ICACHE_FLASH_ATTR readFlashUnaligned(char *dst, char *src, int len)
|
||||
int ICACHE_FLASH_ATTR espFsFlags(EspFsFile *fh)
|
||||
{
|
||||
if (fh == NULL) {
|
||||
httpd_printf("File handle not ready\n");
|
||||
error("[EspFS] File handle not ready");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -123,10 +123,10 @@ int ICACHE_FLASH_ATTR espFsFlags(EspFsFile *fh)
|
||||
//Open a file and return a pointer to the file desc struct.
|
||||
EspFsFile ICACHE_FLASH_ATTR *espFsOpen(const char *fileName)
|
||||
{
|
||||
printf("Open file %s\n", fileName);
|
||||
dbg("[EspFS] Open file %s", fileName);
|
||||
|
||||
if (espFsData == NULL) {
|
||||
httpd_printf("Call espFsInit first!\n");
|
||||
error("[EspFS] Call espFsInit first!");
|
||||
return NULL;
|
||||
}
|
||||
const char *p = espFsData;
|
||||
@@ -143,11 +143,11 @@ EspFsFile ICACHE_FLASH_ATTR *espFsOpen(const char *fileName)
|
||||
spi_flash_read((uint32)p, (uint32*)&h, sizeof(EspFsHeader));
|
||||
|
||||
if (h.magic != ESPFS_MAGIC) {
|
||||
httpd_printf("Magic mismatch. EspFS image broken.\n");
|
||||
error("[EspFS] Magic mismatch. EspFS image broken.");
|
||||
return NULL;
|
||||
}
|
||||
if (h.flags & FLAG_LASTFILE) {
|
||||
httpd_printf("File %s not found in EspFS.\n", fileName);
|
||||
warn("[EspFS] File %s not found in EspFS.", fileName);
|
||||
return NULL;
|
||||
}
|
||||
//Grab the name of the file.
|
||||
@@ -167,6 +167,7 @@ EspFsFile ICACHE_FLASH_ATTR *espFsOpen(const char *fileName)
|
||||
r->posStart = p;
|
||||
r->posDecomp = 0;
|
||||
if (h.compression == COMPRESS_NONE) {
|
||||
info("[EspFS] File found.");
|
||||
r->decompData = NULL;
|
||||
#ifdef ESPFS_HEATSHRINK
|
||||
} else if (h.compression == COMPRESS_HEATSHRINK) {
|
||||
@@ -176,12 +177,12 @@ EspFsFile ICACHE_FLASH_ATTR *espFsOpen(const char *fileName)
|
||||
//Decoder params are stored in 1st byte.
|
||||
readFlashUnaligned(&parm, (char*)r->posComp, 1);
|
||||
r->posComp++;
|
||||
httpd_printf("Heatshrink compressed file; decode parms = %x\n", parm);
|
||||
info("[EspFS] Heatshrink compressed file found; decode params = %x", parm);
|
||||
dec = heatshrink_decoder_alloc(16, (parm >> 4) & 0xf, parm & 0xf);
|
||||
r->decompData = dec;
|
||||
#endif
|
||||
} else {
|
||||
httpd_printf("Invalid compression: %d\n", h.compression);
|
||||
error("[EspFS] File found, but has invalid compression: %d", h.compression);
|
||||
return NULL;
|
||||
}
|
||||
return r;
|
||||
|
||||
@@ -31,3 +31,4 @@
|
||||
#include "espmissingincludes.h"
|
||||
#include "esp_sdk_ver.h"
|
||||
|
||||
#include "logging.h"
|
||||
|
||||
@@ -110,12 +110,4 @@ void httpdRecvCb(ConnTypePtr conn, char *remIp, int remPort, char *data, unsigne
|
||||
void httpdDisconCb(ConnTypePtr conn, char *remIp, int remPort);
|
||||
int httpdConnectCb(ConnTypePtr conn, char *remIp, int remPort);
|
||||
|
||||
|
||||
// debugging
|
||||
|
||||
#define LOG_EOL "\n"
|
||||
#define dbg(fmt, ...) httpd_printf(fmt LOG_EOL, ##__VA_ARGS__);
|
||||
#define error(fmt, ...) httpd_printf("\x1b[31;1m"fmt"\x1b[0m"LOG_EOL, ##__VA_ARGS__);
|
||||
#define info(fmt, ...) httpd_printf("\x1b[32;1m"fmt"\x1b[0m"LOG_EOL, ##__VA_ARGS__);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef HTTPD_LOGGING_H
|
||||
#define HTTPD_LOGGING_H
|
||||
|
||||
|
||||
#ifndef httpd_printf
|
||||
#define httpd_printf(fmt, ...) os_printf(fmt, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
|
||||
// logging functions
|
||||
#define LOG_EOL "\n"
|
||||
#define dbg(fmt, ...) httpd_printf(fmt LOG_EOL, ##__VA_ARGS__);
|
||||
#define banner(fmt, ...) httpd_printf("\x1b[32;1m"fmt"\x1b[0m"LOG_EOL, ##__VA_ARGS__);
|
||||
#define info(fmt, ...) httpd_printf("\x1b[32m"fmt"\x1b[0m"LOG_EOL, ##__VA_ARGS__);
|
||||
#define error(fmt, ...) httpd_printf("\x1b[31;1m"fmt"\x1b[0m"LOG_EOL, ##__VA_ARGS__);
|
||||
#define warn(fmt, ...) httpd_printf("\x1b[33;1m"fmt"\x1b[0m"LOG_EOL, ##__VA_ARGS__);
|
||||
|
||||
|
||||
#endif // HTTPD_LOGGING_H
|
||||
@@ -199,7 +199,7 @@ static void ICACHE_FLASH_ATTR captdnsRecv(struct sockaddr_in *premote_addr, char
|
||||
if (p==NULL) return;
|
||||
DnsQuestionFooter *qf=(DnsQuestionFooter*)p;
|
||||
p+=sizeof(DnsQuestionFooter);
|
||||
httpd_printf("DNS: Q (type 0x%X class 0x%X) for %s\n", my_ntohs(&qf->type), my_ntohs(&qf->class), buff);
|
||||
info("DNS: Q (type 0x%X class 0x%X) for %s", my_ntohs(&qf->type), my_ntohs(&qf->class), buff);
|
||||
if (my_ntohs(&qf->type)==QTYPE_A) {
|
||||
//They want to know the IPv4 address of something.
|
||||
//Build the response.
|
||||
@@ -319,6 +319,7 @@ void captdnsInit(void) {
|
||||
#else
|
||||
|
||||
void ICACHE_FLASH_ATTR captdnsInit(void) {
|
||||
info("Starting captive portal");
|
||||
static struct espconn conn;
|
||||
static esp_udp udpconn;
|
||||
conn.type=ESPCONN_UDP;
|
||||
|
||||
+20
-18
@@ -5,9 +5,9 @@ Some flash handling cgi routines. Used for reading the existing flash and updati
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
|
||||
* this notice you can do whatever you want with this stuff. If we meet some day,
|
||||
* and you think this stuff is worth it, you can buy me a beer in return.
|
||||
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
|
||||
* this notice you can do whatever you want with this stuff. If we meet some day,
|
||||
* and you think this stuff is worth it, you can buy me a beer in return.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
@@ -88,8 +88,8 @@ int ICACHE_FLASH_ATTR cgiReadFlash(HttpdConnData *connData) {
|
||||
//a direct POST from e.g. Curl or a Javascript AJAX call with either the
|
||||
//firmware given by cgiGetFirmwareNext or an OTA upgrade image.
|
||||
|
||||
//Because we don't have the buffer to allocate an entire sector but will
|
||||
//have to buffer some data because the post buffer may be misaligned, we
|
||||
//Because we don't have the buffer to allocate an entire sector but will
|
||||
//have to buffer some data because the post buffer may be misaligned, we
|
||||
//write SPI data in pages. The page size is a software thing, not
|
||||
//a hardware one.
|
||||
#define PAGELEN 64
|
||||
@@ -137,10 +137,10 @@ int ICACHE_FLASH_ATTR cgiUploadFirmware(HttpdConnData *connData) {
|
||||
|
||||
if (state==NULL) {
|
||||
//First call. Allocate and initialize state variable.
|
||||
httpd_printf("Firmware upload cgi start.\n");
|
||||
info("Firmware upload cgi start.");
|
||||
state=malloc(sizeof(UploadState));
|
||||
if (state==NULL) {
|
||||
httpd_printf("Can't allocate firmware upload struct!\n");
|
||||
error("Can't allocate firmware upload struct!");
|
||||
return HTTPD_CGI_DONE;
|
||||
}
|
||||
memset(state, 0, sizeof(UploadState));
|
||||
@@ -148,10 +148,10 @@ int ICACHE_FLASH_ATTR cgiUploadFirmware(HttpdConnData *connData) {
|
||||
connData->cgiData=state;
|
||||
state->err="Premature end";
|
||||
}
|
||||
|
||||
|
||||
char *data=connData->post->buff;
|
||||
int dataLen=connData->post->buffLen;
|
||||
|
||||
|
||||
while (dataLen!=0) {
|
||||
if (state->state==FLST_START) {
|
||||
//First call. Assume the header of whatever we're uploading already is in the POST buffer.
|
||||
@@ -161,11 +161,11 @@ int ICACHE_FLASH_ATTR cgiUploadFirmware(HttpdConnData *connData) {
|
||||
strncpy(buff, h->tag, 27);
|
||||
buff[27]=0;
|
||||
if (strcmp(buff, def->tagName)!=0) {
|
||||
httpd_printf("OTA tag mismatch! Current=`%s` uploaded=`%s`.\n",
|
||||
def->tagName, buff);
|
||||
warn("OTA tag mismatch! Current=`%s` uploaded=`%s`.", def->tagName, buff);
|
||||
|
||||
len=httpdFindArg(connData->getArgs, "force", buff, sizeof(buff));
|
||||
if (len!=-1 && atoi(buff)) {
|
||||
httpd_printf("Forcing firmware flash.\n");
|
||||
info("Forcing firmware flash.");
|
||||
} else {
|
||||
state->err="Firmware not intended for this device!\n";
|
||||
state->state=FLST_ERROR;
|
||||
@@ -180,13 +180,13 @@ int ICACHE_FLASH_ATTR cgiUploadFirmware(HttpdConnData *connData) {
|
||||
dataLen-=sizeof(OtaHeader); //skip header when parsing data
|
||||
data+=sizeof(OtaHeader);
|
||||
if (system_upgrade_userbin_check()==1) {
|
||||
httpd_printf("Flashing user1.bin from ota image\n");
|
||||
info("Flashing user1.bin from ota image");
|
||||
state->len=h->len1;
|
||||
state->skip=h->len2;
|
||||
state->state=FLST_WRITE;
|
||||
state->address=def->fw1Pos;
|
||||
} else {
|
||||
httpd_printf("Flashing user2.bin from ota image\n");
|
||||
info("Flashing user2.bin from ota image");
|
||||
state->len=h->len2;
|
||||
state->skip=h->len1;
|
||||
state->state=FLST_SKIP;
|
||||
@@ -214,7 +214,7 @@ int ICACHE_FLASH_ATTR cgiUploadFirmware(HttpdConnData *connData) {
|
||||
} else {
|
||||
state->err="Invalid flash image type!";
|
||||
state->state=FLST_ERROR;
|
||||
httpd_printf("Did not recognize flash image type!\n");
|
||||
error("Did not recognize flash image type!");
|
||||
}
|
||||
} else if (state->state==FLST_SKIP) {
|
||||
//Skip bytes without doing anything with them
|
||||
@@ -263,7 +263,7 @@ int ICACHE_FLASH_ATTR cgiUploadFirmware(HttpdConnData *connData) {
|
||||
}
|
||||
}
|
||||
} else if (state->state==FLST_DONE) {
|
||||
httpd_printf("Huh? %d bogus bytes received after data received.\n", dataLen);
|
||||
warn("Huh? %d bogus bytes received after data received.", dataLen);
|
||||
//Ignore those bytes.
|
||||
dataLen=0;
|
||||
} else if (state->state==FLST_ERROR) {
|
||||
@@ -271,14 +271,16 @@ int ICACHE_FLASH_ATTR cgiUploadFirmware(HttpdConnData *connData) {
|
||||
dataLen=0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (connData->post->len==connData->post->received) {
|
||||
//We're done! Format a response.
|
||||
httpd_printf("Upload done. Sending response.\n");
|
||||
info("Upload done. Sending response.");
|
||||
httpdStartResponse(connData, state->state==FLST_ERROR?400:200);
|
||||
httpdHeader(connData, "Content-Type", "text/plain");
|
||||
httpdEndHeaders(connData);
|
||||
if (state->state!=FLST_DONE) {
|
||||
error("Error msg: %s", state->err);
|
||||
|
||||
httpdSend(connData, "Firmware image error:", -1);
|
||||
httpdSend(connData, state->err, -1);
|
||||
httpdSend(connData, "\n", -1);
|
||||
|
||||
@@ -5,9 +5,9 @@ Websocket support for esphttpd. Inspired by https://github.com/dangrie158/ESP-82
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
|
||||
* this notice you can do whatever you want with this stuff. If we meet some day,
|
||||
* and you think this stuff is worth it, you can buy me a beer in return.
|
||||
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
|
||||
* this notice you can do whatever you want with this stuff. If we meet some day,
|
||||
* and you think this stuff is worth it, you can buy me a beer in return.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
@@ -22,24 +22,24 @@ Websocket support for esphttpd. Inspired by https://github.com/dangrie158/ESP-82
|
||||
#define WS_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
|
||||
|
||||
/* from IEEE RFC6455 sec 5.2
|
||||
0 1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-------+-+-------------+-------------------------------+
|
||||
|F|R|R|R| opcode|M| Payload len | Extended payload length |
|
||||
|I|S|S|S| (4) |A| (7) | (16/64) |
|
||||
|N|V|V|V| |S| | (if payload len==126/127) |
|
||||
| |1|2|3| |K| | |
|
||||
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
|
||||
| Extended payload length continued, if payload len == 127 |
|
||||
+ - - - - - - - - - - - - - - - +-------------------------------+
|
||||
| |Masking-key, if MASK set to 1 |
|
||||
+-------------------------------+-------------------------------+
|
||||
| Masking-key (continued) | Payload Data |
|
||||
+-------------------------------- - - - - - - - - - - - - - - - +
|
||||
: Payload Data continued ... :
|
||||
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
|
||||
| Payload Data continued ... |
|
||||
+---------------------------------------------------------------+
|
||||
0 1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-------+-+-------------+-------------------------------+
|
||||
|F|R|R|R| opcode|M| Payload len | Extended payload length |
|
||||
|I|S|S|S| (4) |A| (7) | (16/64) |
|
||||
|N|V|V|V| |S| | (if payload len==126/127) |
|
||||
| |1|2|3| |K| | |
|
||||
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
|
||||
| Extended payload length continued, if payload len == 127 |
|
||||
+ - - - - - - - - - - - - - - - +-------------------------------+
|
||||
| |Masking-key, if MASK set to 1 |
|
||||
+-------------------------------+-------------------------------+
|
||||
| Masking-key (continued) | Payload Data |
|
||||
+-------------------------------- - - - - - - - - - - - - - - - +
|
||||
: Payload Data continued ... :
|
||||
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
|
||||
| Payload Data continued ... |
|
||||
+---------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#define FLAG_FIN (1 << 7)
|
||||
@@ -92,7 +92,7 @@ static int ICACHE_FLASH_ATTR sendFrameHead(Websock *ws, int opcode, int len) {
|
||||
buf[i++]=opcode;
|
||||
if (len>65535) {
|
||||
buf[i++]=127;
|
||||
buf[i++]=0; buf[i++]=0; buf[i++]=0; buf[i++]=0;
|
||||
buf[i++]=0; buf[i++]=0; buf[i++]=0; buf[i++]=0;
|
||||
buf[i++]=len>>24;
|
||||
buf[i++]=len>>16;
|
||||
buf[i++]=len>>8;
|
||||
@@ -104,7 +104,7 @@ static int ICACHE_FLASH_ATTR sendFrameHead(Websock *ws, int opcode, int len) {
|
||||
} else {
|
||||
buf[i++]=len;
|
||||
}
|
||||
httpd_printf("WS: Sent frame head for payload of %d bytes.\n", len);
|
||||
info("[WS] Sent frame head for payload of %d bytes.", len);
|
||||
return httpdSend(ws->conn, buf, i);
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ int ICACHE_FLASH_ATTR cgiWebsocketSend(Websock *ws, char *data, int len, int fla
|
||||
//Broadcast data to all websockets at a specific url. Returns the amount of connections sent to.
|
||||
int ICACHE_FLASH_ATTR cgiWebsockBroadcast(char *resource, char *data, int len, int flags) {
|
||||
//This is majorly broken (and actually, always, it just tended to work because the circumstances
|
||||
//were juuuust right). Because the socket is used outside of the httpd send/receive context, it
|
||||
//were juuuust right). Because the socket is used outside of the httpd send/receive context, it
|
||||
//will not have an associated send buffer. This means httpdSend will write to a dangling pointer!
|
||||
//Disabled for now. If you really need this, open an issue on github or otherwise poke me and I'll
|
||||
//see what I can do.
|
||||
@@ -148,11 +148,13 @@ void ICACHE_FLASH_ATTR cgiWebsocketClose(Websock *ws, int reason) {
|
||||
httpdSend(ws->conn, rs, 2);
|
||||
ws->priv->closedHere=1;
|
||||
httpdFlushSendBuffer(ws->conn);
|
||||
|
||||
info("[WS] WebSocket closed.");
|
||||
}
|
||||
|
||||
|
||||
static void ICACHE_FLASH_ATTR websockFree(Websock *ws) {
|
||||
httpd_printf("Ws: Free\n");
|
||||
dbg("[WS] Free WebSocket struct");
|
||||
if (ws->closeCb) ws->closeCb(ws);
|
||||
//Clean up linked list
|
||||
if (llStart==ws) {
|
||||
@@ -202,7 +204,7 @@ int ICACHE_FLASH_ATTR cgiWebSocketRecv(HttpdConnData *connData, char *data, int
|
||||
//Was a payload byte.
|
||||
wasHeaderByte=0;
|
||||
}
|
||||
|
||||
|
||||
if (ws->priv->wsStatus==ST_PAYLOAD && wasHeaderByte) {
|
||||
//We finished parsing the header, but i still is on the last header byte. Move one forward so
|
||||
//the payload code works as usual.
|
||||
@@ -211,11 +213,11 @@ int ICACHE_FLASH_ATTR cgiWebSocketRecv(HttpdConnData *connData, char *data, int
|
||||
//Also finish parsing frame if we haven't received any payload bytes yet, but the length of the frame
|
||||
//is zero.
|
||||
if (ws->priv->wsStatus==ST_PAYLOAD) {
|
||||
//Okay, header is in; this is a data byte. We're going to process all the data bytes we have
|
||||
//Okay, header is in; this is a data byte. We're going to process all the data bytes we have
|
||||
//received here at the same time; no more byte iterations till the end of this frame.
|
||||
//First, unmask the data
|
||||
sl=len-i;
|
||||
httpd_printf("Ws: Frame payload. wasHeaderByte %d fr.len %d sl %d cmd 0x%x\n", wasHeaderByte, (int)ws->priv->fr.len, (int)sl, ws->priv->fr.flags);
|
||||
dbg("[WS] Frame payload. wasHeaderByte %d fr.len %d sl %d cmd 0x%x\n", wasHeaderByte, (int)ws->priv->fr.len, (int)sl, ws->priv->fr.flags);
|
||||
if (sl > ws->priv->fr.len) sl=ws->priv->fr.len;
|
||||
for (j=0; j<sl; j++) data[i+j]^=(ws->priv->fr.mask[(ws->priv->maskCtr++)&3]);
|
||||
|
||||
@@ -233,7 +235,7 @@ int ICACHE_FLASH_ATTR cgiWebSocketRecv(HttpdConnData *connData, char *data, int
|
||||
if (!ws->priv->frameCont) sendFrameHead(ws, OPCODE_PONG|FLAG_FIN, ws->priv->fr.len);
|
||||
if (sl>0) httpdSend(ws->conn, data+i, sl);
|
||||
}
|
||||
} else if ((ws->priv->fr.flags&OPCODE_MASK)==OPCODE_TEXT ||
|
||||
} else if ((ws->priv->fr.flags&OPCODE_MASK)==OPCODE_TEXT ||
|
||||
(ws->priv->fr.flags&OPCODE_MASK)==OPCODE_BINARY ||
|
||||
(ws->priv->fr.flags&OPCODE_MASK)==OPCODE_CONTINUE) {
|
||||
if (sl>ws->priv->fr.len) sl=ws->priv->fr.len;
|
||||
@@ -249,15 +251,15 @@ int ICACHE_FLASH_ATTR cgiWebSocketRecv(HttpdConnData *connData, char *data, int
|
||||
if (ws->recvCb) ws->recvCb(ws, data+i, sl, flags);
|
||||
}
|
||||
} else if ((ws->priv->fr.flags&OPCODE_MASK)==OPCODE_CLOSE) {
|
||||
httpd_printf("WS: Got close frame\n");
|
||||
dbg("[WS] Got close frame");
|
||||
if (!ws->priv->closedHere) {
|
||||
httpd_printf("WS: Sending response close frame\n");
|
||||
dbg("[WS] Sending response close frame");
|
||||
cgiWebsocketClose(ws, ((data[i]<<8)&0xff00)+(data[i+1]&0xff));
|
||||
}
|
||||
r=HTTPD_CGI_DONE;
|
||||
break;
|
||||
} else {
|
||||
if (!ws->priv->frameCont) httpd_printf("WS: Unknown opcode 0x%X\n", ws->priv->fr.flags&OPCODE_MASK);
|
||||
if (!ws->priv->frameCont) error("[WS] Unknown opcode 0x%X", ws->priv->fr.flags&OPCODE_MASK);
|
||||
}
|
||||
i+=sl-1;
|
||||
ws->priv->fr.len-=sl;
|
||||
@@ -285,7 +287,7 @@ int ICACHE_FLASH_ATTR cgiWebsocket(HttpdConnData *connData) {
|
||||
sha1nfo s;
|
||||
if (connData->conn==NULL) {
|
||||
//Connection aborted. Clean up.
|
||||
httpd_printf("WS: Cleanup\n");
|
||||
dbg("[WS] Cleanup");
|
||||
if (connData->cgiData) {
|
||||
Websock *ws=(Websock*)connData->cgiData;
|
||||
websockFree(ws);
|
||||
@@ -294,12 +296,13 @@ int ICACHE_FLASH_ATTR cgiWebsocket(HttpdConnData *connData) {
|
||||
}
|
||||
return HTTPD_CGI_DONE;
|
||||
}
|
||||
|
||||
|
||||
if (connData->cgiData==NULL) {
|
||||
// httpd_printf("WS: First call\n");
|
||||
//First call here. Check if client headers are OK, send server header.
|
||||
i=httpdGetHeader(connData, "Upgrade", buff, sizeof(buff)-1);
|
||||
httpd_printf("WS: Upgrade: %s\n", buff);
|
||||
info("[WS] Opening websocket, Upgrade: %s\n", buff);
|
||||
|
||||
if (i && strcasecmp(buff, "websocket")==0) {
|
||||
i=httpdGetHeader(connData, "Sec-WebSocket-Key", buff, sizeof(buff)-1);
|
||||
if (i) {
|
||||
@@ -344,7 +347,7 @@ int ICACHE_FLASH_ATTR cgiWebsocket(HttpdConnData *connData) {
|
||||
httpdEndHeaders(connData);
|
||||
return HTTPD_CGI_DONE;
|
||||
}
|
||||
|
||||
|
||||
//Sending is done. Call the sent callback if we have one.
|
||||
Websock *ws=(Websock*)connData->cgiData;
|
||||
if (ws && ws->sentCb) ws->sentCb(ws);
|
||||
|
||||
+16
-16
@@ -5,9 +5,9 @@ Cgi/template routines for the /wifi url.
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
|
||||
* this notice you can do whatever you want with this stuff. If we meet some day,
|
||||
* and you think this stuff is worth it, you can buy me a beer in return.
|
||||
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
|
||||
* this notice you can do whatever you want with this stuff. If we meet some day,
|
||||
* and you think this stuff is worth it, you can buy me a beer in return.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
@@ -50,7 +50,7 @@ static os_timer_t resetTimer;
|
||||
void ICACHE_FLASH_ATTR wifiScanDoneCb(void *arg, STATUS status) {
|
||||
int n;
|
||||
struct bss_info *bss_link = (struct bss_info *)arg;
|
||||
httpd_printf("wifiScanDoneCb %d\n", status);
|
||||
dbg("wifiScanDoneCb %d\n", status);
|
||||
if (status!=OK) {
|
||||
cgiWifiAps.scanInProgress=0;
|
||||
return;
|
||||
@@ -71,7 +71,7 @@ void ICACHE_FLASH_ATTR wifiScanDoneCb(void *arg, STATUS status) {
|
||||
//Allocate memory for access point data
|
||||
cgiWifiAps.apData=(ApData **)malloc(sizeof(ApData *)*n);
|
||||
cgiWifiAps.noAps=n;
|
||||
httpd_printf("Scan done: found %d APs\n", n);
|
||||
info("Scan done: found %d APs\n", n);
|
||||
|
||||
//Copy access point data to the static struct
|
||||
n=0;
|
||||
@@ -80,7 +80,7 @@ void ICACHE_FLASH_ATTR wifiScanDoneCb(void *arg, STATUS status) {
|
||||
if (n>=cgiWifiAps.noAps) {
|
||||
//This means the bss_link changed under our nose. Shouldn't happen!
|
||||
//Break because otherwise we will write in unallocated memory.
|
||||
httpd_printf("Huh? I have more than the allocated %d aps!\n", cgiWifiAps.noAps);
|
||||
warn("Huh? I have more than the allocated %d aps!\n", cgiWifiAps.noAps);
|
||||
break;
|
||||
}
|
||||
//Save the ap data.
|
||||
@@ -164,12 +164,12 @@ static void ICACHE_FLASH_ATTR resetTimerCb(void *arg) {
|
||||
int x=wifi_station_get_connect_status();
|
||||
if (x==STATION_GOT_IP) {
|
||||
//Go to STA mode. This needs a reset, so do that.
|
||||
httpd_printf("Got IP. Going into STA mode..\n");
|
||||
info("Got IP. Going into STA mode..\n");
|
||||
wifi_set_opmode(1);
|
||||
system_restart();
|
||||
} else {
|
||||
connTryStatus=CONNTRY_FAIL;
|
||||
httpd_printf("Connect fail. Not going into STA-only mode.\n");
|
||||
error("Connect fail. Not going into STA-only mode.\n");
|
||||
//Maybe also pass this through on the webpage?
|
||||
}
|
||||
}
|
||||
@@ -181,7 +181,7 @@ static void ICACHE_FLASH_ATTR resetTimerCb(void *arg) {
|
||||
//but I can't be arsed to put the code back :P
|
||||
static void ICACHE_FLASH_ATTR reassTimerCb(void *arg) {
|
||||
int x;
|
||||
httpd_printf("Try to connect to AP....\n");
|
||||
dbg("Try to connect to AP....\n");
|
||||
wifi_station_disconnect();
|
||||
wifi_station_set_config(&stconf);
|
||||
wifi_station_connect();
|
||||
@@ -202,18 +202,18 @@ int ICACHE_FLASH_ATTR cgiWiFiConnect(HttpdConnData *connData) {
|
||||
char essid[128];
|
||||
char passwd[128];
|
||||
static os_timer_t reassTimer;
|
||||
|
||||
|
||||
if (connData->conn==NULL) {
|
||||
//Connection aborted. Clean up.
|
||||
return HTTPD_CGI_DONE;
|
||||
}
|
||||
|
||||
|
||||
httpdFindArg(connData->post->buff, "essid", essid, sizeof(essid));
|
||||
httpdFindArg(connData->post->buff, "passwd", passwd, sizeof(passwd));
|
||||
|
||||
strncpy((char*)stconf.ssid, essid, 32);
|
||||
strncpy((char*)stconf.password, passwd, 64);
|
||||
httpd_printf("Try to connect to AP %s pw %s\n", essid, passwd);
|
||||
info("Try to connect to AP %s pw %s\n", essid, passwd);
|
||||
|
||||
//Schedule disconnect/connect
|
||||
os_timer_disarm(&reassTimer);
|
||||
@@ -233,7 +233,7 @@ int ICACHE_FLASH_ATTR cgiWiFiConnect(HttpdConnData *connData) {
|
||||
int ICACHE_FLASH_ATTR cgiWiFiSetMode(HttpdConnData *connData) {
|
||||
int len;
|
||||
char buff[1024];
|
||||
|
||||
|
||||
if (connData->conn==NULL) {
|
||||
//Connection aborted. Clean up.
|
||||
return HTTPD_CGI_DONE;
|
||||
@@ -241,7 +241,7 @@ int ICACHE_FLASH_ATTR cgiWiFiSetMode(HttpdConnData *connData) {
|
||||
|
||||
len=httpdFindArg(connData->getArgs, "mode", buff, sizeof(buff));
|
||||
if (len!=0) {
|
||||
httpd_printf("cgiWifiSetMode: %s\n", buff);
|
||||
info("cgiWifiSetMode: %s\n", buff);
|
||||
#ifndef DEMO_MODE
|
||||
wifi_set_opmode(atoi(buff));
|
||||
system_restart();
|
||||
@@ -264,8 +264,8 @@ int ICACHE_FLASH_ATTR cgiWiFiConnStatus(HttpdConnData *connData) {
|
||||
} else if (connTryStatus==CONNTRY_WORKING || connTryStatus==CONNTRY_SUCCESS) {
|
||||
if (st==STATION_GOT_IP) {
|
||||
wifi_get_ip_info(0, &info);
|
||||
len=sprintf(buff, "{\n \"status\": \"success\",\n \"ip\": \"%d.%d.%d.%d\" }\n",
|
||||
(info.ip.addr>>0)&0xff, (info.ip.addr>>8)&0xff,
|
||||
len=sprintf(buff, "{\n \"status\": \"success\",\n \"ip\": \"%d.%d.%d.%d\" }\n",
|
||||
(info.ip.addr>>0)&0xff, (info.ip.addr>>8)&0xff,
|
||||
(info.ip.addr>>16)&0xff, (info.ip.addr>>24)&0xff);
|
||||
//Reset into AP-only mode sooner.
|
||||
os_timer_disarm(&resetTimer);
|
||||
|
||||
Reference in New Issue
Block a user