diff --git a/httpd/httpd.c b/httpd/httpd.c index a4ff2ac..290f321 100644 --- a/httpd/httpd.c +++ b/httpd/httpd.c @@ -33,10 +33,12 @@ static HttpdBuiltInUrl *builtInUrls; //Private data for http connection struct HttpdPriv { - char head[MAX_HEAD_LEN]; - int headPos; - char *sendBuff; - int sendBuffLen; + char head[MAX_HEAD_LEN]; // buffer to accumulate header + char from[24]; // source ip&port + char *sendBuff; // output buffer + short headPos; // offset into header + short sendBuffLen; // offset into output buffer + short code; // http response code (only for logging) }; //Connection pool @@ -93,56 +95,32 @@ static void debugConn(void *arg, char *what) { os_sprintf(connStr, "%d.%d.%d.%d:%d ", tcp->remote_ip[0], tcp->remote_ip[1], tcp->remote_ip[2], tcp->remote_ip[3], tcp->remote_port); - //os_printf("%s %s\n", connStr, what); + os_printf("%s %s\n", connStr, what); #else connStr[0] = 0; #endif } -//Looks up the connData info for a specific esp connection -static HttpdConnData ICACHE_FLASH_ATTR *httpdFindConnData(void *arg) { - struct espconn *espconn = arg; - for (int i = 0; iproto.tcp->remote_port && - os_memcmp(connData[i].remote_ip, espconn->proto.tcp->remote_ip, 4) == 0) - { -#if 0 -#ifdef HTTPD_DBG - os_printf("FindConn: 0x%p->0x%p", arg, &connData[i]); - if (arg == connData[i].conn) os_printf("\n"); - else os_printf(" *** was 0x%p\n", connData[i].conn); -#endif -#endif - if (arg != connData[i].conn) connData[i].conn = arg; // yes, this happens!? - return &connData[i]; - } - } - //Shouldn't happen. +// Retires a connection for re-use +static void ICACHE_FLASH_ATTR httpdRetireConn(HttpdConnData *conn) { + if (conn->conn && conn->conn->reverse == conn) + conn->conn->reverse = NULL; // break reverse link + #ifdef HTTPD_DBG - os_printf("%s*** Unknown connection 0x%p\n", connStr, arg); + // log information about the request we handled + uint32 dt = conn->startTime; + if (dt > 0) dt = (system_get_time() - dt) / 1000; + if (conn->conn && conn->url) + os_printf("HTTP %s %s from %s -> %d in %ums, heap=%ld\n", + conn->requestType == HTTPD_METHOD_GET ? "GET" : "POST", conn->url, conn->priv->from, + conn->priv->code, dt, (unsigned long)system_get_free_heap_size()); #endif - return NULL; -} -//Retires a connection for re-use -static void ICACHE_FLASH_ATTR httpdRetireConn(HttpdConnData *conn) { conn->conn = NULL; // don't try to send anything, the SDK crashes... if (conn->cgi != NULL) conn->cgi(conn); // free cgi data - if (conn->post->buff != NULL) { - os_free(conn->post->buff); - } + if (conn->post->buff != NULL) os_free(conn->post->buff); conn->cgi = NULL; conn->post->buff = NULL; - conn->remote_port = 0; - conn->remote_ip[0] = 0; - - uint32 dt = conn->startTime; - if (dt > 0) dt = (system_get_time() - dt) / 1000; -#ifdef HTTPD_DBG - os_printf("%sHTTP %s in %ums, heap=%ld\n", connStr, - conn->requestType == HTTPD_METHOD_GET ? "GET" : "POST", dt, - (unsigned long)system_get_free_heap_size()); -#endif } //Stupid li'l helper function that returns the value of a hex char. @@ -242,6 +220,7 @@ int ICACHE_FLASH_ATTR httpdGetHeader(HttpdConnData *conn, char *header, char *re void ICACHE_FLASH_ATTR httpdStartResponse(HttpdConnData *conn, int code) { char buff[128]; int l; + conn->priv->code = code; char *status = code < 400 ? "OK" : "ERROR"; l = os_sprintf(buff, "HTTP/1.0 %d %s\r\nServer: esp-link\r\nConnection: close\r\n", code, status); httpdSend(conn, buff, l); @@ -266,7 +245,9 @@ void ICACHE_FLASH_ATTR httpdEndHeaders(HttpdConnData *conn) { void ICACHE_FLASH_ATTR httpdRedirect(HttpdConnData *conn, char *newUrl) { char buff[1024]; int l; - l = os_sprintf(buff, "HTTP/1.0 302 Found\r\nServer: esp8266-link\r\nConnection: close\r\nLocation: %s\r\n\r\nRedirecting to %s\r\n", newUrl, newUrl); + conn->priv->code = 302; + l = os_sprintf(buff, "HTTP/1.0 302 Found\r\nServer: esp8266-link\r\nConnection: close\r\n" + "Location: %s\r\n\r\nRedirecting to %s\r\n", newUrl, newUrl); httpdSend(conn, buff, l); } @@ -314,11 +295,11 @@ static void ICACHE_FLASH_ATTR xmitSendBuff(HttpdConnData *conn) { //Callback called when the data on a socket has been successfully sent. static void ICACHE_FLASH_ATTR httpdSentCb(void *arg) { debugConn(arg, "httpdSentCb"); - int r; - HttpdConnData *conn = httpdFindConnData(arg); - char sendBuff[MAX_SENDBUFF_LEN]; + struct espconn* pCon = (struct espconn *)arg; + HttpdConnData *conn = (HttpdConnData *)pCon->reverse; + if (conn == NULL) return; // aborted connection - if (conn == NULL) return; + char sendBuff[MAX_SENDBUFF_LEN]; conn->priv->sendBuff = sendBuff; conn->priv->sendBuffLen = 0; @@ -328,7 +309,7 @@ static void ICACHE_FLASH_ATTR httpdSentCb(void *arg) { return; //No need to call xmitSendBuff. } - r = conn->cgi(conn); //Execute cgi fn. + int r = conn->cgi(conn); //Execute cgi fn. if (r == HTTPD_CGI_DONE) { conn->cgi = NULL; //mark for destruction. } @@ -341,7 +322,8 @@ static void ICACHE_FLASH_ATTR httpdSentCb(void *arg) { xmitSendBuff(conn); } -static const char *httpNotFoundHeader = "HTTP/1.0 404 Not Found\r\nConnection: close\r\nContent-Type: text/plain\r\nContent-Length: 12\r\n\r\nNot Found.\r\n"; +static const char *httpNotFoundHeader = "HTTP/1.0 404 Not Found\r\nConnection: close\r\n" + "Content-Type: text/plain\r\nContent-Length: 12\r\n\r\nNot Found.\r\n"; //This is called when the headers have been received and the connection is ready to send //the result headers and data. @@ -438,18 +420,9 @@ static void ICACHE_FLASH_ATTR httpdParseHeader(char *h, HttpdConnData *conn) { // Count number of open connections #ifdef HTTPD_DBG -#if 0 - int open = 0; - for (int j = 0; jrequestType == HTTPD_METHOD_GET ? "GET" : "POST", conn->url, open); -#else - esp_tcp *tcp = conn->conn->proto.tcp; - os_printf("%sHTTP %s %s from %d.%d.%d.%d:%d\n", connStr, - conn->requestType == HTTPD_METHOD_GET ? "GET" : "POST", conn->url, - tcp->remote_ip[0], tcp->remote_ip[1], tcp->remote_ip[2], tcp->remote_ip[3], - tcp->remote_port); -#endif + //esp_tcp *tcp = conn->conn->proto.tcp; + //os_printf("%sHTTP %s %s from %s\n", connStr, + // conn->requestType == HTTPD_METHOD_GET ? "GET" : "POST", conn->url, conn->priv->from); #endif //Parse out the URL part before the GET parameters. conn->getArgs = (char*)os_strstr(conn->url, "?"); @@ -502,11 +475,11 @@ 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) { debugConn(arg, "httpdRecvCb"); - int x; - char *p, *e; + struct espconn* pCon = (struct espconn *)arg; + HttpdConnData *conn = (HttpdConnData *)pCon->reverse; + if (conn == NULL) return; // aborted connection + char sendBuff[MAX_SENDBUFF_LEN]; - HttpdConnData *conn = httpdFindConnData(arg); - if (conn == NULL) return; conn->priv->sendBuff = sendBuff; conn->priv->sendBuffLen = 0; @@ -516,7 +489,7 @@ static void ICACHE_FLASH_ATTR httpdRecvCb(void *arg, char *data, unsigned short //>0: Need to receive post data //ToDo: See if we can use something more elegant for this. - for (x = 0; xpost->len<0) { //This byte is a header byte. if (conn->priv->headPos != MAX_HEAD_LEN) conn->priv->head[conn->priv->headPos++] = data[x]; @@ -528,9 +501,9 @@ static void ICACHE_FLASH_ATTR httpdRecvCb(void *arg, char *data, unsigned short //Reset url data conn->url = NULL; //Iterate over all received headers and parse them. - p = conn->priv->head; + char *p = conn->priv->head; while (p<(&conn->priv->head[conn->priv->headPos - 4])) { - e = (char *)os_strstr(p, "\r\n"); //Find end of header line + char *e = (char *)os_strstr(p, "\r\n"); //Find end of header line if (e == NULL) break; //Shouldn't happen. e[0] = 0; //Zero-terminate header httpdParseHeader(p, conn); //and parse it. @@ -559,8 +532,9 @@ static void ICACHE_FLASH_ATTR httpdRecvCb(void *arg, char *data, unsigned short static void ICACHE_FLASH_ATTR httpdDisconCb(void *arg) { debugConn(arg, "httpdDisconCb"); - HttpdConnData *conn = httpdFindConnData(arg); - if (conn == NULL) return; + struct espconn* pCon = (struct espconn *)arg; + HttpdConnData *conn = (HttpdConnData *)pCon->reverse; + if (conn == NULL) return; // aborted connection httpdRetireConn(conn); } @@ -568,11 +542,13 @@ static void ICACHE_FLASH_ATTR httpdDisconCb(void *arg) { // of "you need to reconnect". Sigh... Note that there is no DisconCb after ReconCb static void ICACHE_FLASH_ATTR httpdReconCb(void *arg, sint8 err) { debugConn(arg, "httpdReconCb"); - HttpdConnData *conn = httpdFindConnData(arg); + struct espconn* pCon = (struct espconn *)arg; + HttpdConnData *conn = (HttpdConnData *)pCon->reverse; + if (conn == NULL) return; // aborted connection + #ifdef HTTPD_DBG os_printf("%s***** reset, err=%d\n", connStr, err); #endif - if (conn == NULL) return; httpdRetireConn(conn); } @@ -580,14 +556,13 @@ static void ICACHE_FLASH_ATTR httpdReconCb(void *arg, sint8 err) { static void ICACHE_FLASH_ATTR httpdConnectCb(void *arg) { debugConn(arg, "httpdConnectCb"); struct espconn *conn = arg; + + // Find empty conndata in pool int i; - //Find empty conndata in pool for (i = 0; iproto.tcp->remote_port; - os_memcpy(connData[i].remote_ip, conn->proto.tcp->remote_ip, 4); + conn->reverse = connData+i; connData[i].priv->headPos = 0; + + esp_tcp *tcp = conn->proto.tcp; + os_sprintf(connData[i].priv->from, "%d.%d.%d.%d:%d", tcp->remote_ip[0], tcp->remote_ip[1], + tcp->remote_ip[2], tcp->remote_ip[3], tcp->remote_port); connData[i].post = &connPostData[i]; connData[i].post->buff = NULL; connData[i].post->buffLen = 0; diff --git a/httpd/httpd.h b/httpd/httpd.h index 5ceb1aa..cca6f32 100644 --- a/httpd/httpd.h +++ b/httpd/httpd.h @@ -21,11 +21,10 @@ typedef int (* cgiSendCallback)(HttpdConnData *connData); //A struct describing a http connection. This gets passed to cgi functions. struct HttpdConnData { struct espconn *conn; - int remote_port; - uint8 remote_ip[4]; - + //int remote_port; + //uint8 remote_ip[4]; uint32 startTime; - char requestType; + char requestType; // HTTP_METHOD_GET | HTTPD_METHOD_POST char *url; char *getArgs; const void *cgiArg;