Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ espfs/espfstest/*.o
espfs/espfstest/espfstest
*.DS_Store
html_compressed/
libwebpages-espfs.a
libwebpages-espfs.a
*~
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ XTENSA_TOOLS_ROOT ?=

# base directory of the ESP8266 SDK package, absolute
# Only used for the non-FreeRTOS build
SDK_BASE ?= /opt/Espressif/ESP8266_SDK
#SDK_BASE ?= /opt/Espressif/ESP8266_SDK
SDK_BASE ?= $(abspath ../esp_iot_sdk_v2.0.0.p1)

# Base directory of the ESP8266 FreeRTOS SDK package, absolute
# Only used for the FreeRTOS build
Expand Down
2 changes: 1 addition & 1 deletion core/httpd-freertos.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ struct RtosConnType{

static RtosConnType rconn[HTTPD_MAX_CONNECTIONS];

int ICACHE_FLASH_ATTR httpdPlatSendData(ConnTypePtr conn, char *buff, int len) {
int ICACHE_FLASH_ATTR httpdPlatSendData(ConnTypePtr conn, const char *buff, int len) {
conn->needWriteDoneNotif=1;
return (write(conn->fd, buff, len)>=0);
}
Expand Down
7 changes: 4 additions & 3 deletions core/httpd-nonos.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ static esp_tcp httpdTcp;


static void ICACHE_FLASH_ATTR platReconCb(void *arg, sint8 err) {
//Yeah, this is pretty useless...
ConnTypePtr conn=arg;
httpdReconCb(conn, (char*)conn->proto.tcp->remote_ip, conn->proto.tcp->remote_port, err);
}

static void ICACHE_FLASH_ATTR platDisconCb(void *arg) {
Expand Down Expand Up @@ -46,7 +47,7 @@ static void ICACHE_FLASH_ATTR platConnCb(void *arg) {
}


int ICACHE_FLASH_ATTR httpdPlatSendData(ConnTypePtr conn, char *buff, int len) {
int ICACHE_FLASH_ATTR httpdPlatSendData(ConnTypePtr conn, const char *buff, int len) {
int r;
r=espconn_sent(conn, (uint8_t*)buff, len);
return (r>=0);
Expand All @@ -73,4 +74,4 @@ void ICACHE_FLASH_ATTR httpdPlatInit(int port, int maxConnCt) {
}


#endif
#endif
2 changes: 1 addition & 1 deletion core/httpd-platform.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#ifndef HTTPD_PLATFORM_H
#define HTTPD_PLATFORM_H

int httpdPlatSendData(ConnTypePtr conn, char *buff, int len);
int httpdPlatSendData(ConnTypePtr conn, const char *buff, int len);
void httpdPlatDisconnect(ConnTypePtr conn);
void httpdPlatDisableTimeout(ConnTypePtr conn);
void httpdPlatInit(int port, int maxConnCt);
Expand Down
128 changes: 79 additions & 49 deletions core/httpd.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ struct HttpdPriv {
int headPos;
char *sendBuff;
int sendBuffLen;
int sendBuffMax;
char *chunkHdr;
HttpSendBacklogItem *sendBacklog;
int sendBacklogSize;
Expand Down Expand Up @@ -98,23 +99,11 @@ const char ICACHE_FLASH_ATTR *httpdGetMimetype(char *url) {
return mimeTypes[i].mimetype;
}

//Looks up the connData info for a specific connection
static HttpdConnData ICACHE_FLASH_ATTR *httpdFindConnData(ConnTypePtr conn, char *remIp, int remPort) {
for (int i=0; i<HTTPD_MAX_CONNECTIONS; i++) {
if (connData[i] && connData[i]->remote_port == remPort &&
memcmp(connData[i]->remote_ip, remIp, 4) == 0) {
connData[i]->conn=conn;
return connData[i];
}
}
//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);
httpdPlatDisconnect(conn);
return NULL;
}

//Retires a connection for re-use
static void ICACHE_FLASH_ATTR httpdRetireConn(HttpdConnData *conn) {
if (conn==NULL) return;
if (conn->conn && conn->conn->reverse == conn)
conn->conn->reverse = NULL; // break reverse link
if (conn->priv->sendBacklog!=NULL) {
HttpSendBacklogItem *i, *j;
i=conn->priv->sendBacklog;
Expand All @@ -124,13 +113,15 @@ static void ICACHE_FLASH_ATTR httpdRetireConn(HttpdConnData *conn) {
free(j);
} while (i!=NULL);
}
if (conn->post->buff!=NULL) free(conn->post->buff);
if (conn->post!=NULL) free(conn->post);
if (conn->post!=NULL) {
if (conn->post->buff!=NULL) free(conn->post->buff);
free(conn->post);
}
if (conn->priv!=NULL) free(conn->priv);
if (conn) free(conn);
for (int i=0; i<HTTPD_MAX_CONNECTIONS; i++) {
if (connData[i]==conn) connData[i]=NULL;
}
free(conn);
}

//Stupid li'l helper function that returns the value of a hex char.
Expand Down Expand Up @@ -190,7 +181,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);
// httpd_printf("Finding %s in %s: Not found :/\n", arg, line);
return -1; //not found
}

Expand Down Expand Up @@ -229,15 +220,27 @@ void ICACHE_FLASH_ATTR httpdDisableTransferEncoding(HttpdConnData *conn) {
conn->priv->flags&=~HFL_CHUNKED;
}

//Setup a send buffer
void ICACHE_FLASH_ATTR httpdSetSendBuffer(HttpdConnData *conn, char *buff, short max)
{
conn->priv->sendBuff = buff;
conn->priv->sendBuffLen = 0;
conn->priv->sendBuffMax = max;
}

//Start the response headers.
void ICACHE_FLASH_ATTR httpdStartResponse(HttpdConnData *conn, int code) {
char buff[256];
int l;
l=sprintf(buff, "HTTP/1.%d %d OK\r\nServer: esp8266-httpd/"HTTPDVER"\r\n%s\r\n",
l=sprintf(buff, "HTTP/1.%d %d OK\r\nServer: esp8266-httpd/"HTTPDVER"\r\n",
(conn->priv->flags&HFL_HTTP11)?1:0,
code,
(conn->priv->flags&HFL_CHUNKED)?"Transfer-Encoding: chunked":"Connection: close");
code);
httpdSend(conn, buff, l);
if (code != 101) {
l=sprintf(buff, "%s\r\n",
(conn->priv->flags&HFL_CHUNKED)?"Transfer-Encoding: chunked":"Connection: close");
httpdSend(conn, buff, l);
}
}

//Send a http header.
Expand Down Expand Up @@ -350,15 +353,15 @@ int ICACHE_FLASH_ATTR cgiRedirectApClientToHostname(HttpdConnData *connData) {
int ICACHE_FLASH_ATTR httpdSend(HttpdConnData *conn, const char *data, int len) {
if (conn->conn==NULL) return 0;
if (len<0) len=strlen(data);
if (len==0) return 0;
if (len==0) return 1;
if (conn->priv->flags&HFL_CHUNKED && conn->priv->flags&HFL_SENDINGBODY && conn->priv->chunkHdr==NULL) {
if (conn->priv->sendBuffLen+len+6>MAX_SENDBUFF_LEN) return 0;
if (conn->priv->sendBuffLen+len+6>conn->priv->sendBuffMax) return 0;
//Establish start of chunk
conn->priv->chunkHdr=&conn->priv->sendBuff[conn->priv->sendBuffLen];
strcpy(conn->priv->chunkHdr, "0000\r\n");
conn->priv->sendBuffLen+=6;
}
if (conn->priv->sendBuffLen+len>MAX_SENDBUFF_LEN) return 0;
if (conn->priv->sendBuffLen+len>conn->priv->sendBuffMax) return 0;
memcpy(conn->priv->sendBuff+conn->priv->sendBuffLen, data, len);
conn->priv->sendBuffLen+=len;
return 1;
Expand All @@ -374,7 +377,7 @@ static char ICACHE_FLASH_ATTR httpdHexNibble(int val) {
//are doing! Also, if you do set conn->cgi to NULL to indicate the connection is closed, do it BEFORE
//calling this.
void ICACHE_FLASH_ATTR httpdFlushSendBuffer(HttpdConnData *conn) {
int r, len;
int len;
if (conn->conn==NULL) return;
if (conn->priv->chunkHdr!=NULL) {
//We're sending chunked data, and the chunk needs fixing up.
Expand All @@ -395,22 +398,28 @@ void ICACHE_FLASH_ATTR httpdFlushSendBuffer(HttpdConnData *conn) {
strcpy(&conn->priv->sendBuff[conn->priv->sendBuffLen], "0\r\n\r\n");
conn->priv->sendBuffLen+=5;
}
if (conn->priv->sendBuffLen!=0) {
r=httpdPlatSendData(conn->conn, conn->priv->sendBuff, conn->priv->sendBuffLen);
if (!r) {
if (!httpdUnbufferedSend(conn, conn->priv->sendBuff, conn->priv->sendBuffLen)) {
httpd_printf("Httpd: UnbufferedSend failed!\n");
}
conn->priv->sendBuffLen=0;
}

int ICACHE_FLASH_ATTR httpdUnbufferedSend(HttpdConnData *conn, const char *data, int len) {
if (len!=0) {
if (!httpdPlatSendData(conn->conn, data, len)) {
httpd_printf("Httpd: queuing %d byte buffer\n", len);
//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);
conn->priv->sendBuffLen=0;
return;
if (conn->priv->sendBacklogSize+len>MAX_BACKLOG_SIZE) {
httpd_printf("Httpd: Backlog: Exceeded max backlog size, dropped %d bytes instead of sending them.\n", len);
return 0;
}
HttpSendBacklogItem *i=malloc(sizeof(HttpSendBacklogItem)+conn->priv->sendBuffLen);
HttpSendBacklogItem *i=malloc(sizeof(HttpSendBacklogItem)+len);
if (i==NULL) {
httpd_printf("Httpd: Backlog: malloc failed, out of memory!\n");
return;
return 0;
}
memcpy(i->data, conn->priv->sendBuff, conn->priv->sendBuffLen);
i->len=conn->priv->sendBuffLen;
memcpy(i->data, data, len);
i->len=len;
i->next=NULL;
if (conn->priv->sendBacklog==NULL) {
conn->priv->sendBacklog=i;
Expand All @@ -419,10 +428,10 @@ void ICACHE_FLASH_ATTR httpdFlushSendBuffer(HttpdConnData *conn) {
while (e->next!=NULL) e=e->next;
e->next=i;
}
conn->priv->sendBacklogSize+=conn->priv->sendBuffLen;
conn->priv->sendBacklogSize+=len;
}
conn->priv->sendBuffLen=0;
}
return 1;
}

void ICACHE_FLASH_ATTR httpdCgiIsDone(HttpdConnData *conn) {
Expand All @@ -445,16 +454,24 @@ void ICACHE_FLASH_ATTR httpdCgiIsDone(HttpdConnData *conn) {
}
}

// store the cgi callback reason and call the user's function
static int ICACHE_FLASH_ATTR callCGI(HttpdConnData *connData, int reason, int value) {
connData->cgiReason = reason;
connData->cgiValue = value;
return connData->cgi(connData);
}

//Callback called when the data on a socket has been successfully
//sent.
void ICACHE_FLASH_ATTR httpdSentCb(ConnTypePtr rconn, char *remIp, int remPort) {
int r;
HttpdConnData *conn=httpdFindConnData(rconn, remIp, remPort);
HttpdConnData *conn=rconn->reverse;
char *sendBuff;

if (conn==NULL) return;

if (conn->priv->sendBacklog!=NULL) {
httpd_printf("Httpd: sending %d byte queued buffer\n", conn->priv->sendBacklog->len);
//We have some backlog to send first.
HttpSendBacklogItem *next=conn->priv->sendBacklog->next;
httpdPlatSendData(conn->conn, conn->priv->sendBacklog->data, conn->priv->sendBacklog->len);
Expand All @@ -476,7 +493,9 @@ void ICACHE_FLASH_ATTR httpdSentCb(ConnTypePtr rconn, char *remIp, int remPort)
sendBuff=malloc(MAX_SENDBUFF_LEN);
conn->priv->sendBuff=sendBuff;
conn->priv->sendBuffLen=0;
r=conn->cgi(conn); //Execute cgi fn.
conn->priv->sendBuffMax = MAX_SENDBUFF_LEN;

r=callCGI(conn, CGI_CB_SENT, 0); //Execute cgi fn.
if (r==HTTPD_CGI_DONE) {
httpdCgiIsDone(conn);
}
Expand Down Expand Up @@ -510,7 +529,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);
// httpd_printf("Is url index %d\n", i);
conn->cgiData=NULL;
conn->cgi=builtInUrls[i].cgiCb;
conn->cgiArg=builtInUrls[i].cgiArg;
Expand All @@ -527,7 +546,7 @@ static void ICACHE_FLASH_ATTR httpdProcessRequest(HttpdConnData *conn) {

//Okay, we have a CGI function that matches the URL. See if it wants to handle the
//particular URL we're supposed to handle.
r=conn->cgi(conn);
r=callCGI(conn, CGI_CB_RECV, 0);
if (r==HTTPD_CGI_MORE) {
//Yep, it's happy to do so and has more data to send.
if (conn->recvHdl) {
Expand Down Expand Up @@ -581,7 +600,7 @@ static void ICACHE_FLASH_ATTR httpdParseHeader(char *h, HttpdConnData *conn) {
e++; //Skip to protocol indicator
while (*e==' ') e++; //Skip spaces.
//If HTTP/1.1, note that and set chunked encoding
if (strcasecmp(e, "HTTP/1.1")==0) conn->priv->flags|=HFL_HTTP11|HFL_CHUNKED;
if (strcasecmp(e, "HTTP/1.1")==0) conn->priv->flags|=HFL_HTTP11; // BUG -- dbetz |HFL_CHUNKED;

httpd_printf("URL = %s\n", conn->url);
//Parse out the URL part before the GET parameters.
Expand Down Expand Up @@ -631,14 +650,15 @@ static void ICACHE_FLASH_ATTR httpdParseHeader(char *h, HttpdConnData *conn) {


//Callback called when there's data available on a socket.
void httpdRecvCb(ConnTypePtr rconn, char *remIp, int remPort, char *data, unsigned short len) {
void ICACHE_FLASH_ATTR httpdRecvCb(ConnTypePtr rconn, char *remIp, int remPort, char *data, unsigned short len) {
int x, r;
char *p, *e;
char *sendBuff=malloc(MAX_SENDBUFF_LEN);
HttpdConnData *conn=httpdFindConnData(rconn, remIp, remPort);
HttpdConnData *conn=rconn->reverse;
if (conn==NULL) return;
conn->priv->sendBuff=sendBuff;
conn->priv->sendBuffLen=0;
conn->priv->sendBuffMax = MAX_SENDBUFF_LEN;

//This is slightly evil/dirty: we abuse conn->post->len as a state variable for where in the http communications we are:
//<0 (-1): Post len unknown because we're still receiving headers
Expand Down Expand Up @@ -688,7 +708,7 @@ void httpdRecvCb(ConnTypePtr rconn, char *remIp, int remPort, char *data, unsign
conn->post->buff[conn->post->buffLen]=0; //zero-terminate, in case the cgi handler knows it can use strings
//Process the data
if (conn->cgi) {
r=conn->cgi(conn);
r=callCGI(conn, CGI_CB_RECV, 0);
if (r==HTTPD_CGI_DONE) {
httpdCgiIsDone(conn);
}
Expand Down Expand Up @@ -721,14 +741,23 @@ void httpdRecvCb(ConnTypePtr rconn, char *remIp, int remPort, char *data, unsign
//The platform layer should ALWAYS call this function, regardless if the connection is closed by the server
//or by the client.
void ICACHE_FLASH_ATTR httpdDisconCb(ConnTypePtr rconn, char *remIp, int remPort) {
HttpdConnData *hconn=httpdFindConnData(rconn, remIp, remPort);
HttpdConnData *hconn=rconn->reverse;
if (hconn==NULL) return;
httpd_printf("Pool slot %d: socket closed.\n", hconn->slot);
hconn->conn=NULL; //indicate cgi the connection is gone
if (hconn->cgi) hconn->cgi(hconn); //Execute cgi fn if needed
if (hconn->cgi) callCGI(hconn, CGI_CB_DISCONNECT, 0); //Execute cgi fn if needed
httpdRetireConn(hconn);
}

//This seems to be called on connection failure
void ICACHE_FLASH_ATTR httpdReconCb(ConnTypePtr rconn, char *remIp, int remPort, int err) {
HttpdConnData *hconn=rconn->reverse;
if (hconn==NULL) return;
httpd_printf("Pool slot %d: socket closed.\n", hconn->slot);
hconn->conn=NULL; //indicate cgi the connection is gone
if (hconn->cgi) callCGI(hconn, CGI_CB_RECONNECT, err); //Execute cgi fn if needed
httpdRetireConn(hconn);
}

int ICACHE_FLASH_ATTR httpdConnectCb(ConnTypePtr conn, char *remIp, int remPort) {
int i;
Expand All @@ -744,6 +773,7 @@ int ICACHE_FLASH_ATTR httpdConnectCb(ConnTypePtr conn, char *remIp, int remPort)
connData[i]->priv=malloc(sizeof(HttpdPriv));
memset(connData[i]->priv, 0, sizeof(HttpdPriv));
connData[i]->conn=conn;
conn->reverse = connData[i];
connData[i]->slot=i;
connData[i]->priv->headPos=0;
connData[i]->post=malloc(sizeof(HttpdPostData));
Expand Down
2 changes: 1 addition & 1 deletion espfs/espfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ EspFsFile ICACHE_FLASH_ATTR *espFsOpen(char *fileName) {
return NULL;
}
if (h.flags&FLAG_LASTFILE) {
httpd_printf("End of image.\n");
// httpd_printf("End of image.\n");
return NULL;
}
//Grab the name of the file.
Expand Down
Loading