Modify httpd to be able to use streaming post requests.

This also ups the post buffer to 1460 to match the TCP packet size

WIP: The cgi function to update the espfs is not complete
pull/30/head
Ben Pirt 9 years ago
parent 92b27fd615
commit 6f80e55a61
  1. 26
      user/cgi.c
  2. 1
      user/cgi.h
  3. 78
      user/httpd.c
  4. 8
      user/httpd.h
  5. 29
      user/user_main.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; 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, "<html><body><form method=\"POST\" enctype=\"multipart/form-data\"><input type=\"file\" name=\"file\"><input type=\"submit\"></form></body></html>", 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;
}

@ -7,5 +7,6 @@ int cgiLed(HttpdConnData *connData);
void tplLed(HttpdConnData *connData, char *token, void **arg); void tplLed(HttpdConnData *connData, char *token, void **arg);
int cgiReadFlash(HttpdConnData *connData); int cgiReadFlash(HttpdConnData *connData);
void tplCounter(HttpdConnData *connData, char *token, void **arg); void tplCounter(HttpdConnData *connData, char *token, void **arg);
int updateWeb(HttpdConnData *connData);
#endif #endif

@ -30,7 +30,7 @@ Esp8266 http server - core routines
//Max amount of connections //Max amount of connections
#define MAX_CONN 8 #define MAX_CONN 8
//Max post buffer len //Max post buffer len
#define MAX_POST 1024 #define MAX_POST 1460
//Max send buffer len //Max send buffer len
#define MAX_SENDBUFF_LEN 2048 #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 //This is called when the headers have been received and the connection is ready to send
//the result headers and data. //the result headers and data.
static void ICACHE_FLASH_ATTR httpdSendResp(HttpdConnData *conn) { static void ICACHE_FLASH_ATTR httpdSendResp(HttpdConnData *conn) {
int i=0;
int r; int r;
//See if the url is somewhere in our internal url table.
while (builtInUrls[i].url!=NULL && conn->url!=NULL) { r=conn->cgi(conn);
int match=0; if (r!=HTTPD_CGI_NOTFOUND) {
// os_printf("%s == %s?\n", builtInUrls[i].url, conn->url); if (r==HTTPD_CGI_DONE){
if (os_strcmp(builtInUrls[i].url, conn->url)==0) match=1; conn->cgi=NULL; //If cgi finishes immediately: mark conn for destruction.
if (builtInUrls[i].url[os_strlen(builtInUrls[i].url)-1]=='*' && xmitSendBuff(conn);
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;
}
} }
i++; return;
} }
//Can't find :/ //Can't find :/
os_printf("%s not found. 404!\n", conn->url); os_printf("%s not found. 404!\n", conn->url);
@ -353,17 +341,40 @@ static void ICACHE_FLASH_ATTR httpdParseHeader(char *h, HttpdConnData *conn) {
} else { } else {
conn->getArgs=NULL; 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) { } else if (os_strncmp(h, "Content-Length: ", 16)==0) {
i=0; i=0;
//Skip trailing spaces //Skip trailing spaces
while (h[i]!=' ') i++; while (h[i]!=' ') i++;
//Get POST data length //Get POST data length
conn->postLen=atoi(h+i+1); conn->postLen=atoi(h+i+1);
//Clamp if too big. Hmm, maybe we should error out instead? if(conn->stream){
if (conn->postLen>MAX_POST) conn->postLen=MAX_POST; conn->postBuff=(char*)os_malloc(MAX_POST+1);
os_printf("Mallocced buffer for %d bytes of post data.\n", conn->postLen); }else{
//Alloc the memory. //Clamp if too big. Hmm, maybe we should error out instead?
conn->postBuff=(char*)os_malloc(conn->postLen+1); 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; 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. //Callback called when there's data available on a socket.
static void ICACHE_FLASH_ATTR httpdRecvCb(void *arg, char *data, unsigned short len) { static void ICACHE_FLASH_ATTR httpdRecvCb(void *arg, char *data, unsigned short len) {
int x; int x;
int r;
char *p, *e; char *p, *e;
char sendBuff[MAX_SENDBUFF_LEN]; char sendBuff[MAX_SENDBUFF_LEN];
HttpdConnData *conn=httpdFindConnData(arg); 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) { } else if (conn->priv->postPos!=-1 && conn->postLen!=0 && conn->priv->postPos <= conn->postLen) {
//This byte is a POST byte. //This byte is a POST byte.
conn->postBuff[conn->priv->postPos++]=data[x]; conn->postBuff[conn->priv->postPos++]=data[x];
conn->postReceived++;
if (conn->priv->postPos>=conn->postLen) { if (conn->priv->postPos>=conn->postLen) {
//Received post stuff. //Received post stuff.
conn->postBuff[conn->priv->postPos]=0; //zero-terminate 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) { static void ICACHE_FLASH_ATTR httpdReconCb(void *arg, sint8 err) {

@ -8,8 +8,9 @@
#define HTTPD_CGI_MORE 0 #define HTTPD_CGI_MORE 0
#define HTTPD_CGI_DONE 1 #define HTTPD_CGI_DONE 1
#define HTTPD_CGI_NOTFOUND 2 #define HTTPD_CGI_NOTDONE 2
#define HTTPD_CGI_AUTHENTICATED 2 //for now #define HTTPD_CGI_NOTFOUND 3
#define HTTPD_CGI_AUTHENTICATED 4 //for now
#define GET 1 #define GET 1
#define POST 2 #define POST 2
@ -30,7 +31,9 @@ struct HttpdConnData {
HttpdPriv *priv; HttpdPriv *priv;
cgiSendCallback cgi; cgiSendCallback cgi;
int postLen; int postLen;
int postReceived;
char *postBuff; char *postBuff;
int stream;
}; };
//A struct describing an url. This is the main struct that's used to send different URL requests to //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; const char *url;
cgiSendCallback cgiCb; cgiSendCallback cgiCb;
const void *cgiArg; const void *cgiArg;
int stream;
} HttpdBuiltInUrl; } HttpdBuiltInUrl;
int ICACHE_FLASH_ATTR cgiRedirect(HttpdConnData *connData); int ICACHE_FLASH_ATTR cgiRedirect(HttpdConnData *connData);

@ -50,26 +50,27 @@ general ones. Authorization things (like authBasic) act as a 'barrier' and
should be placed above the URLs they protect. should be placed above the URLs they protect.
*/ */
HttpdBuiltInUrl builtInUrls[]={ HttpdBuiltInUrl builtInUrls[]={
{"/", cgiRedirect, "/index.tpl"}, {"/", cgiRedirect, "/index.tpl", FALSE},
{"/flash.bin", cgiReadFlash, NULL}, {"/flash.bin", cgiReadFlash, NULL, FALSE},
{"/led.tpl", cgiEspFsTemplate, tplLed}, {"/led.tpl", cgiEspFsTemplate, tplLed, FALSE},
{"/index.tpl", cgiEspFsTemplate, tplCounter}, {"/index.tpl", cgiEspFsTemplate, tplCounter, FALSE},
{"/led.cgi", cgiLed, NULL}, {"/led.cgi", cgiLed, NULL, FALSE},
{"/updateweb.cgi", updateWeb, NULL, TRUE},
//Routines to make the /wifi URL and everything beneath it work. //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. //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", FALSE},
{"/wifi/", cgiRedirect, "/wifi/wifi.tpl"}, {"/wifi/", cgiRedirect, "/wifi/wifi.tpl", FALSE},
{"/wifi/wifiscan.cgi", cgiWiFiScan, NULL}, {"/wifi/wifiscan.cgi", cgiWiFiScan, NULL, FALSE},
{"/wifi/wifi.tpl", cgiEspFsTemplate, tplWlan}, {"/wifi/wifi.tpl", cgiEspFsTemplate, tplWlan, FALSE},
{"/wifi/connect.cgi", cgiWiFiConnect, NULL}, {"/wifi/connect.cgi", cgiWiFiConnect, NULL, FALSE},
{"/wifi/setmode.cgi", cgiWifiSetMode, NULL}, {"/wifi/setmode.cgi", cgiWifiSetMode, NULL, FALSE},
{"*", cgiEspFsHook, NULL}, //Catch-all cgi function for the filesystem {"*", cgiEspFsHook, NULL, FALSE}, //Catch-all cgi function for the filesystem
{NULL, NULL, NULL} {NULL, NULL, NULL, FALSE}
}; };

Loading…
Cancel
Save