diff --git a/user/cgi.c b/user/cgi.c index 3587cc7..d0ce1d3 100644 --- a/user/cgi.c +++ b/user/cgi.c @@ -102,3 +102,29 @@ int ICACHE_FLASH_ATTR cgiReadFlash(HttpdConnData *connData) { if (*pos>=0x40200000+(512*1024)) return HTTPD_CGI_DONE; else return HTTPD_CGI_MORE; } + +//Cgi to allow user to upload a new espfs image +int ICACHE_FLASH_ATTR updateWeb(HttpdConnData *connData) { + if (connData->conn==NULL) { + //Connection aborted. Clean up. + return HTTPD_CGI_DONE; + } + if(connData->requestType == GET){ + httpdStartResponse(connData, 200); + httpdHeader(connData, "Content-Length", "135"); + httpdEndHeaders(connData); + httpdSend(connData, "
", 135); + }else if(connData->requestType == POST){ + os_printf("postReceived: %d\r\n", connData->postReceived); + os_printf("postLen : %d\r\n", connData->postLen); + os_printf("data size : %d\r\n", strlen(connData->postBuff)); + if(connData->postReceived >= connData->postLen){ + httpdStartResponse(connData, 204); + return HTTPD_CGI_DONE; + }else{ + return HTTPD_CGI_NOTDONE; + } + } + return HTTPD_CGI_DONE; +} + diff --git a/user/cgi.h b/user/cgi.h index 6dbf923..915d332 100644 --- a/user/cgi.h +++ b/user/cgi.h @@ -7,5 +7,6 @@ int cgiLed(HttpdConnData *connData); void tplLed(HttpdConnData *connData, char *token, void **arg); int cgiReadFlash(HttpdConnData *connData); void tplCounter(HttpdConnData *connData, char *token, void **arg); +int updateWeb(HttpdConnData *connData); #endif \ No newline at end of file diff --git a/user/httpd.c b/user/httpd.c index b0a741c..b047881 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 1024 +#define MAX_POST 1460 //Max send buffer len #define MAX_SENDBUFF_LEN 2048 @@ -288,27 +288,15 @@ 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) { - int i=0; int r; - //See if the url is somewhere in our internal url table. - while (builtInUrls[i].url!=NULL && conn->url!=NULL) { - int match=0; -// os_printf("%s == %s?\n", builtInUrls[i].url, conn->url); - if (os_strcmp(builtInUrls[i].url, conn->url)==0) match=1; - if (builtInUrls[i].url[os_strlen(builtInUrls[i].url)-1]=='*' && - os_strncmp(builtInUrls[i].url, conn->url, os_strlen(builtInUrls[i].url)-1)==0) match=1; - if (match) { - os_printf("Is url index %d\n", i); - conn->cgiData=NULL; - conn->cgi=builtInUrls[i].cgiCb; - conn->cgiArg=builtInUrls[i].cgiArg; - 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. - return; - } + + 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); } - i++; + return; } //Can't find :/ os_printf("%s not found. 404!\n", conn->url); @@ -353,17 +341,40 @@ static void ICACHE_FLASH_ATTR httpdParseHeader(char *h, HttpdConnData *conn) { } else { conn->getArgs=NULL; } + + i=0; + //See if the url is somewhere in our internal url table. + while (builtInUrls[i].url!=NULL && conn->url!=NULL) { + int match=0; + // os_printf("%s == %s?\n", builtInUrls[i].url, conn->url); + if (os_strcmp(builtInUrls[i].url, conn->url)==0) match=1; + if (builtInUrls[i].url[os_strlen(builtInUrls[i].url)-1]=='*' && + os_strncmp(builtInUrls[i].url, conn->url, os_strlen(builtInUrls[i].url)-1)==0) match=1; + if (match) { + os_printf("Is url index %d\n", i); + conn->cgiData=NULL; + conn->cgi=builtInUrls[i].cgiCb; + conn->cgiArg=builtInUrls[i].cgiArg; + conn->stream=builtInUrls[i].stream; + return; + } + i++; + } } else if (os_strncmp(h, "Content-Length: ", 16)==0) { i=0; //Skip trailing spaces while (h[i]!=' ') i++; //Get POST data length conn->postLen=atoi(h+i+1); - //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); + if(conn->stream){ + conn->postBuff=(char*)os_malloc(MAX_POST+1); + }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->priv->postPos=0; } } @@ -372,6 +383,7 @@ 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); @@ -407,6 +419,7 @@ static void ICACHE_FLASH_ATTR httpdRecvCb(void *arg, char *data, unsigned short } else if (conn->priv->postPos!=-1 && conn->postLen!=0 && conn->priv->postPos <= conn->postLen) { //This byte is a POST byte. conn->postBuff[conn->priv->postPos++]=data[x]; + conn->postReceived++; if (conn->priv->postPos>=conn->postLen) { //Received post stuff. conn->postBuff[conn->priv->postPos]=0; //zero-terminate @@ -418,7 +431,20 @@ static void ICACHE_FLASH_ATTR httpdRecvCb(void *arg, char *data, unsigned short } } } - xmitSendBuff(conn); + + if(conn->priv->postPos > 0 && conn->stream){ + conn->postBuff[conn->priv->postPos]=0; //zero-terminate + 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) { diff --git a/user/httpd.h b/user/httpd.h index 8efd9b3..91e8e48 100644 --- a/user/httpd.h +++ b/user/httpd.h @@ -8,8 +8,9 @@ #define HTTPD_CGI_MORE 0 #define HTTPD_CGI_DONE 1 -#define HTTPD_CGI_NOTFOUND 2 -#define HTTPD_CGI_AUTHENTICATED 2 //for now +#define HTTPD_CGI_NOTDONE 2 +#define HTTPD_CGI_NOTFOUND 3 +#define HTTPD_CGI_AUTHENTICATED 4 //for now #define GET 1 #define POST 2 @@ -30,7 +31,9 @@ struct HttpdConnData { HttpdPriv *priv; cgiSendCallback cgi; int postLen; + int postReceived; char *postBuff; + int stream; }; //A struct describing an url. This is the main struct that's used to send different URL requests to @@ -39,6 +42,7 @@ 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 7e03871..8fa288f 100644 --- a/user/user_main.c +++ b/user/user_main.c @@ -50,26 +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"}, - {"/flash.bin", cgiReadFlash, NULL}, - {"/led.tpl", cgiEspFsTemplate, tplLed}, - {"/index.tpl", cgiEspFsTemplate, tplCounter}, - {"/led.cgi", cgiLed, NULL}, + {"/", 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}, //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}, +// {"/wifi/*", authBasic, myPassFn, 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}, + {"/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}, - {"*", cgiEspFsHook, NULL}, //Catch-all cgi function for the filesystem - {NULL, NULL, NULL} + {"*", cgiEspFsHook, NULL, FALSE}, //Catch-all cgi function for the filesystem + {NULL, NULL, NULL, FALSE} };