diff --git a/user/cgi.c b/user/cgi.c index e0c580f..753ea84 100644 --- a/user/cgi.c +++ b/user/cgi.c @@ -50,9 +50,9 @@ int ICACHE_FLASH_ATTR cgiLed(HttpdConnData *connData) { //Template code for the led page. -void ICACHE_FLASH_ATTR tplLed(HttpdConnData *connData, char *token, void **arg) { +int ICACHE_FLASH_ATTR tplLed(HttpdConnData *connData, char *token, void **arg) { char buff[128]; - if (token==NULL) return; + if (token==NULL) return HTTPD_CGI_DONE; os_strcpy(buff, "Unknown"); if (os_strcmp(token, "ledstate")==0) { @@ -63,20 +63,22 @@ void ICACHE_FLASH_ATTR tplLed(HttpdConnData *connData, char *token, void **arg) } } httpdSend(connData, buff, -1); + return HTTPD_CGI_DONE; } static long hitCounter=0; //Template code for the counter on the index page. -void ICACHE_FLASH_ATTR tplCounter(HttpdConnData *connData, char *token, void **arg) { +int ICACHE_FLASH_ATTR tplCounter(HttpdConnData *connData, char *token, void **arg) { char buff[128]; - if (token==NULL) return; + if (token==NULL) return HTTPD_CGI_DONE; if (os_strcmp(token, "counter")==0) { hitCounter++; os_sprintf(buff, "%ld", hitCounter); } httpdSend(connData, buff, -1); + return HTTPD_CGI_DONE; } @@ -232,7 +234,7 @@ int ICACHE_FLASH_ATTR updateWeb(HttpdConnData *connData) { if (connData->cgiPrivData!=NULL) os_free(connData->cgiPrivData); return HTTPD_CGI_DONE; }else{ - return HTTPD_CGI_NOTDONE; + return HTTPD_CGI_MORE; } } return HTTPD_CGI_DONE; diff --git a/user/cgi.h b/user/cgi.h index 915d332..8b3c8b2 100644 --- a/user/cgi.h +++ b/user/cgi.h @@ -4,9 +4,9 @@ #include "httpd.h" int cgiLed(HttpdConnData *connData); -void tplLed(HttpdConnData *connData, char *token, void **arg); +int tplLed(HttpdConnData *connData, char *token, void **arg); int cgiReadFlash(HttpdConnData *connData); -void tplCounter(HttpdConnData *connData, char *token, void **arg); +int tplCounter(HttpdConnData *connData, char *token, void **arg); int updateWeb(HttpdConnData *connData); #endif \ No newline at end of file diff --git a/user/cgiwifi.c b/user/cgiwifi.c index f67f6c4..fb20347 100644 --- a/user/cgiwifi.c +++ b/user/cgiwifi.c @@ -231,11 +231,11 @@ int ICACHE_FLASH_ATTR cgiWifiSetMode(HttpdConnData *connData) { } //Template code for the WLAN page. -void ICACHE_FLASH_ATTR tplWlan(HttpdConnData *connData, char *token, void **arg) { +int ICACHE_FLASH_ATTR tplWlan(HttpdConnData *connData, char *token, void **arg) { char buff[1024]; int x; static struct station_config stconf; - if (token==NULL) return; + if (token==NULL) return HTTPD_CGI_DONE; wifi_station_get_config(&stconf); os_strcpy(buff, "Unknown"); @@ -257,6 +257,7 @@ void ICACHE_FLASH_ATTR tplWlan(HttpdConnData *connData, char *token, void **arg) } } httpdSend(connData, buff, -1); + return HTTPD_CGI_DONE; } diff --git a/user/cgiwifi.h b/user/cgiwifi.h index 18f4816..5fc179f 100644 --- a/user/cgiwifi.h +++ b/user/cgiwifi.h @@ -4,7 +4,7 @@ #include "httpd.h" int cgiWiFiScan(HttpdConnData *connData); -void tplWlan(HttpdConnData *connData, char *token, void **arg); +int tplWlan(HttpdConnData *connData, char *token, void **arg); int cgiWiFi(HttpdConnData *connData); int cgiWiFiConnect(HttpdConnData *connData); int cgiWifiSetMode(HttpdConnData *connData); diff --git a/user/httpd.c b/user/httpd.c index 79ae2c8..d068f3a 100644 --- a/user/httpd.c +++ b/user/httpd.c @@ -30,7 +30,7 @@ Esp8266 http server - core routines //Max amount of connections #define MAX_CONN 8 //Max post buffer len -#define MAX_POST 1460 +#define MAX_POST 1024 //Max send buffer len #define MAX_SENDBUFF_LEN 2048 @@ -42,7 +42,6 @@ static HttpdBuiltInUrl *builtInUrls; struct HttpdPriv { char head[MAX_HEAD_LEN]; int headPos; - int postPos; char *sendBuff; int sendBuffLen; }; @@ -287,21 +286,20 @@ static const char *httpNotFoundHeader="HTTP/1.0 404 Not Found\r\nServer: esp8266 //This is called when the headers have been received and the connection is ready to send //the result headers and data. -static void ICACHE_FLASH_ATTR httpdSendResp(HttpdConnData *conn) { +static void ICACHE_FLASH_ATTR httpdProcessRequest(HttpdConnData *conn) { int r; r=conn->cgi(conn); if (r!=HTTPD_CGI_NOTFOUND) { - if (r==HTTPD_CGI_DONE){ - conn->cgi=NULL; //If cgi finishes immediately: mark conn for destruction. - xmitSendBuff(conn); - } - return; + if (r==HTTPD_CGI_DONE) conn->cgi=NULL; //If cgi finishes immediately: mark conn for destruction. + xmitSendBuff(conn); + }else{ + //Can't find :/ + os_printf("%s not found. 404!\n", conn->url); + httpdSend(conn, httpNotFoundHeader, -1); + xmitSendBuff(conn); + conn->cgi=NULL; //mark for destruction } - //Can't find :/ - os_printf("%s not found. 404!\n", conn->url); - httpdSend(conn, httpNotFoundHeader, -1); - conn->cgi=NULL; //mark for destruction } //Parse a line of header data and modify the connection data accordingly. @@ -355,7 +353,6 @@ static void ICACHE_FLASH_ATTR httpdParseHeader(char *h, HttpdConnData *conn) { conn->cgiData=NULL; conn->cgi=builtInUrls[i].cgiCb; conn->cgiArg=builtInUrls[i].cgiArg; - conn->stream=builtInUrls[i].stream; return; } i++; @@ -366,16 +363,17 @@ static void ICACHE_FLASH_ATTR httpdParseHeader(char *h, HttpdConnData *conn) { while (h[i]!=' ') i++; //Get POST data length conn->postLen=atoi(h+i+1); - if(conn->stream){ - conn->postBuff=(char*)os_malloc(MAX_POST+1); + + // Allocate the buffer + if(conn->postLen > MAX_POST){ + // we'll stream this in in chunks + conn->postBuffSize = MAX_POST; }else{ - //Clamp if too big. Hmm, maybe we should error out instead? - if (conn->postLen>MAX_POST) conn->postLen=MAX_POST; - os_printf("Mallocced buffer for %d bytes of post data.\n", conn->postLen); - //Alloc the memory. - conn->postBuff=(char*)os_malloc(conn->postLen+1); + conn->postBuffSize = conn->postLen; } - conn->priv->postPos=0; + os_printf("Mallocced buffer for %d + 1 bytes of post data.\n", conn->postBuffSize); + conn->postBuff=(char*)os_malloc(conn->postBuffSize + 1); + conn->postBuffLen=0; } else if (os_strncmp(h, "Content-Type: ", 14)==0) { if(os_strstr(h, "multipart/form-data")){ // It's multipart form data so let's pull out the boundary for future use @@ -394,7 +392,6 @@ static void ICACHE_FLASH_ATTR httpdParseHeader(char *h, HttpdConnData *conn) { //Callback called when there's data available on a socket. static void ICACHE_FLASH_ATTR httpdRecvCb(void *arg, char *data, unsigned short len) { int x; - int r; char *p, *e; char sendBuff[MAX_SENDBUFF_LEN]; HttpdConnData *conn=httpdFindConnData(arg); @@ -424,40 +421,23 @@ static void ICACHE_FLASH_ATTR httpdRecvCb(void *arg, char *data, unsigned short } //If we don't need to receive post data, we can send the response now. if (conn->postLen==0) { - httpdSendResp(conn); + httpdProcessRequest(conn); } } - } else if (conn->priv->postPos!=-1 && conn->postLen!=0 && conn->priv->postPos <= conn->postLen) { + } else if (conn->postLen!=0) { //This byte is a POST byte. - conn->postBuff[conn->priv->postPos++]=data[x]; + conn->postBuff[conn->postBuffLen++]=data[x]; conn->postReceived++; - if (conn->priv->postPos>=conn->postLen) { - //Received post stuff. - conn->postBuff[conn->priv->postPos]=0; //zero-terminate - conn->postBuffLen = conn->priv->postPos; - conn->priv->postPos=-1; - os_printf("Post data: %s\n", conn->postBuff); + if (conn->postBuffLen >= conn->postBuffSize || conn->postReceived == conn->postLen) { + //Received a chunk of post data + conn->postBuff[conn->postBuffLen]=0; //zero-terminate, in case the cgi handler knows it can use strings + //os_printf("Post data: %s\n", conn->postBuff); //Send the response. - httpdSendResp(conn); - break; + httpdProcessRequest(conn); + conn->postBuffLen = 0; } } } - - if(conn->priv->postPos > 0 && conn->stream){ - conn->postBuff[conn->priv->postPos]=0; //zero-terminate - conn->postBuffLen = conn->priv->postPos; - r=conn->cgi(conn); - if (r!=HTTPD_CGI_NOTFOUND) { - if (r==HTTPD_CGI_DONE){ - conn->cgi=NULL; //If cgi finishes mark conn for destruction. - xmitSendBuff(conn); - } - } - conn->priv->postPos = 0; - }else{ - xmitSendBuff(conn); - } } static void ICACHE_FLASH_ATTR httpdReconCb(void *arg, sint8 err) { @@ -510,7 +490,7 @@ static void ICACHE_FLASH_ATTR httpdConnectCb(void *arg) { connData[i].conn=conn; connData[i].priv->headPos=0; connData[i].postBuff=NULL; - connData[i].priv->postPos=0; + connData[i].postBuffLen=0; connData[i].postLen=-1; espconn_regist_recvcb(conn, httpdRecvCb); diff --git a/user/httpd.h b/user/httpd.h index 0829ea3..2dc7e66 100644 --- a/user/httpd.h +++ b/user/httpd.h @@ -8,9 +8,8 @@ #define HTTPD_CGI_MORE 0 #define HTTPD_CGI_DONE 1 -#define HTTPD_CGI_NOTDONE 2 -#define HTTPD_CGI_NOTFOUND 3 -#define HTTPD_CGI_AUTHENTICATED 4 //for now +#define HTTPD_CGI_NOTFOUND 2 +#define HTTPD_CGI_AUTHENTICATED 3 //for now #define GET 1 #define POST 2 @@ -33,10 +32,10 @@ struct HttpdConnData { HttpdPriv *priv; cgiSendCallback cgi; int postLen; - int postBuffLen; - int postReceived; + int postBuffSize; // The maximum length of the post buffer + int postBuffLen; // The amount of bytes in the current post buffer + int postReceived; // The total amount of bytes received so far char *postBuff; - int stream; }; //A struct describing an url. This is the main struct that's used to send different URL requests to @@ -45,7 +44,6 @@ typedef struct { const char *url; cgiSendCallback cgiCb; const void *cgiArg; - int stream; } HttpdBuiltInUrl; int ICACHE_FLASH_ATTR cgiRedirect(HttpdConnData *connData); diff --git a/user/user_main.c b/user/user_main.c index 8fa288f..3ce7d77 100644 --- a/user/user_main.c +++ b/user/user_main.c @@ -50,27 +50,27 @@ general ones. Authorization things (like authBasic) act as a 'barrier' and should be placed above the URLs they protect. */ HttpdBuiltInUrl builtInUrls[]={ - {"/", cgiRedirect, "/index.tpl", FALSE}, - {"/flash.bin", cgiReadFlash, NULL, FALSE}, - {"/led.tpl", cgiEspFsTemplate, tplLed, FALSE}, - {"/index.tpl", cgiEspFsTemplate, tplCounter, FALSE}, - {"/led.cgi", cgiLed, NULL, FALSE}, - {"/updateweb.cgi", updateWeb, NULL, TRUE}, + {"/", cgiRedirect, "/index.tpl"}, + {"/flash.bin", cgiReadFlash, NULL}, + {"/led.tpl", cgiEspFsTemplate, tplLed}, + {"/index.tpl", cgiEspFsTemplate, tplCounter}, + {"/led.cgi", cgiLed, NULL}, + {"/updateweb.cgi", updateWeb, NULL}, //Routines to make the /wifi URL and everything beneath it work. //Enable the line below to protect the WiFi configuration with an username/password combo. -// {"/wifi/*", authBasic, myPassFn, FALSE}, +// {"/wifi/*", authBasic, myPassFn}, - {"/wifi", cgiRedirect, "/wifi/wifi.tpl", FALSE}, - {"/wifi/", cgiRedirect, "/wifi/wifi.tpl", FALSE}, - {"/wifi/wifiscan.cgi", cgiWiFiScan, NULL, FALSE}, - {"/wifi/wifi.tpl", cgiEspFsTemplate, tplWlan, FALSE}, - {"/wifi/connect.cgi", cgiWiFiConnect, NULL, FALSE}, - {"/wifi/setmode.cgi", cgiWifiSetMode, NULL, FALSE}, + {"/wifi", cgiRedirect, "/wifi/wifi.tpl"}, + {"/wifi/", cgiRedirect, "/wifi/wifi.tpl"}, + {"/wifi/wifiscan.cgi", cgiWiFiScan, NULL}, + {"/wifi/wifi.tpl", cgiEspFsTemplate, tplWlan}, + {"/wifi/connect.cgi", cgiWiFiConnect, NULL}, + {"/wifi/setmode.cgi", cgiWifiSetMode, NULL}, - {"*", cgiEspFsHook, NULL, FALSE}, //Catch-all cgi function for the filesystem - {NULL, NULL, NULL, FALSE} + {"*", cgiEspFsHook, NULL}, //Catch-all cgi function for the filesystem + {NULL, NULL, NULL} };