Serve HTML from SPIFFS
Posted: Sun Feb 25, 2018 5:29 pm
Hi All, i've integrated the standard AP webserver code in with this example for using SPIFFS filesystem https://github.com/espressif/esp-idf/tr ... age/spiffs
Normally once i detect a "GET" from the connected socket, i return a HTML header, then body, written as a char string. I.E.
"netconn_write(conn, http_html_hdr, sizeof(http_html_hdr)-1, NETCONN_NOCOPY);"
and
"netconn_write(conn, http_index_hml, sizeof(http_index_hml)-1, NETCONN_NOCOPY);"
Where http_html_hdr is a standard http 200 response and http_index_hml is my actual html file.
This works great and i have no issues for the most part. I integrated in the SPIFFS filesystem and was able to read a flashed HTML file out as a char string (to serial) using the following code (copied/modified from the above SPIFFS example)
char readFile(char *fname)
{
printf("==== Reading from file \"%s\" ====\r\n", fname);
int res;
char *buf;
buf = calloc(1024, 1);
if (buf == NULL) {
printf(" Error allocating read buffer\"\r\n");
return NULL;
}
FILE *fd = fopen(fname, "rb");
if (fd == NULL) {
printf(" Error opening file\r\n");
free(buf);
return NULL;
}
res = 999;
res = fread(buf, 1, 1023, fd);
if (res <= 0) {
printf(" Error reading from file\r\n");
}
else {
printf(" %d bytes read [\r\n", res);
buf[res] = '\0';
printf("%s\r\n]\r\n", buf);
}
return(buf);
//free(buf);
res = fclose(fd);
if (res) {
printf(" Error closing file\r\n");
}
printf("\r\n");
}
When i use readFile, it prints to serial no problem (not the printf near the return of buf). But when i try to run readFile while in the middle of my HTTP GET response script, i get stack overflows or assertion failures.
I.E.
SERIAL OUT:
DNS: Q (type 0x1 class 0x1) for connectivitycheck.gstatic.com
buffer = GET /generate_204 HTTP/1.1
User-Agent: Dalvik/2.1.0 (Linux; U; Android 6.0.1; XT1254 Build/MCG24.251-5-5)
Host: connectivitycheck.gstatic.com
Connection: Keep-Alive
Accept-Encoding: gzip
Sc5+?l?
buf[5] = g
==== Reading from file "/spiffs/images/HtmlExample.txt" ====
***ERROR*** A stack overflow in task http_server has been detected.
abort() was called at PC 0x40088340 on core 1
0x40088340: vApplicationStackOverflowHook at C:/msys32/home/esp/esp-idf/components/esp32/panic.c:572
If i free up the buffer of the client before reading in new data, i get this
SERIAL OUT:
DNS: Q (type 0x1 claass 0x1) for connectivitycheck.gstatic.com
buffer = GET /generate_204 HTTP/1.1
User-Agent: Dalvik/2.1.0 (Linux; U; Android 6.0.1; XT1254 Build/MCG24.251-5-5)
Host: connectivitycheck.gstatic.com
Connection: Keep-Alive
Accept-Encoding: gzip
buf[5] = g
assertion "next > (intptr_t)block" failedd: file "C:/msys32/home/esp/esp-idf/components/heap/multi_heap.c", line 116, function: get_next_block
abort() was called at PC 0x401085c3 on core 1
0x401085c3: __assert_func at /Users/ivan/e/newlib_xtensa-2.2.0-bin/newlib_xtensa-2.2.0/xtensa-esp32-elf/newlib/libc/stdlib/../../../.././newlib/li
bc/stdlib/assert.c:63 (discriminator 8)
any thoughts?
Below is my http request read & response code
static void http_server_netconn_serve(struct netconn *conn)
{
struct netbuf *inbuf;
char *buf;
u16_t buflen;
err_t err;
/* Read the data from the port, blocking if nothing yet there.
We assume the request (the part we care about) is in one netbuf */
err = netconn_recv(conn, &inbuf);
if (err == ERR_OK) {
netbuf_data(inbuf, (void**)&buf, &buflen);
// strncpy(_mBuffer, buf, buflen);
/* Is this an HTTP GET command? (only check the first 5 chars, since
there are other formats for GET, and we're keeping it very simple )*/
printf("buffer = %s \n", buf);
if (buflen>=5 &&
buf[0]=='G' &&
buf[1]=='E' &&
buf[2]=='T' &&
buf[3]==' ' &&
buf[4]=='/' ) {
printf("buf[5] = %c\n", buf[5]);
/* Send the HTML header
* subtract 1 from the size, since we dont send the \0 in the string
* NETCONN_NOCOPY: our data is const static, so no need to copy it
*/
netconn_write(conn, http_html_hdr, sizeof(http_html_hdr)-1, NETCONN_NOCOPY);
if(buf[5]=='h' || buf[5]=='g') {
/* Send our HTML page */
//free(buf);
//heap_caps_check_integrity(MALLOC_CAP_8BIT,true);
char filebuf= readFile("/spiffs/images/HtmlExample.txt"); // <----------------- fails here
netconn_write(conn, phork, sizeof(filebuf)-1, NETCONN_NOCOPY);
}
else if(buf[5]=='l') {
/* Send our HTML page */
netconn_write(conn, http_index_hml, sizeof(http_index_hml)-1, NETCONN_NOCOPY);
}
else if(buf[5]=='j') {
netconn_write(conn, json_unformatted, strlen(json_unformatted), NETCONN_NOCOPY);
}
else {
netconn_write(conn, http_index_hml, sizeof(http_index_hml)-1, NETCONN_NOCOPY);
}
}
}
/* Close the connection (server closes in HTTP) */
netconn_close(conn);
/* Delete the buffer (netconn_recv gives us ownership,
so we have to make sure to deallocate the buffer) */
netbuf_delete(inbuf);
}
Normally once i detect a "GET" from the connected socket, i return a HTML header, then body, written as a char string. I.E.
"netconn_write(conn, http_html_hdr, sizeof(http_html_hdr)-1, NETCONN_NOCOPY);"
and
"netconn_write(conn, http_index_hml, sizeof(http_index_hml)-1, NETCONN_NOCOPY);"
Where http_html_hdr is a standard http 200 response and http_index_hml is my actual html file.
This works great and i have no issues for the most part. I integrated in the SPIFFS filesystem and was able to read a flashed HTML file out as a char string (to serial) using the following code (copied/modified from the above SPIFFS example)
char readFile(char *fname)
{
printf("==== Reading from file \"%s\" ====\r\n", fname);
int res;
char *buf;
buf = calloc(1024, 1);
if (buf == NULL) {
printf(" Error allocating read buffer\"\r\n");
return NULL;
}
FILE *fd = fopen(fname, "rb");
if (fd == NULL) {
printf(" Error opening file\r\n");
free(buf);
return NULL;
}
res = 999;
res = fread(buf, 1, 1023, fd);
if (res <= 0) {
printf(" Error reading from file\r\n");
}
else {
printf(" %d bytes read [\r\n", res);
buf[res] = '\0';
printf("%s\r\n]\r\n", buf);
}
return(buf);
//free(buf);
res = fclose(fd);
if (res) {
printf(" Error closing file\r\n");
}
printf("\r\n");
}
When i use readFile, it prints to serial no problem (not the printf near the return of buf). But when i try to run readFile while in the middle of my HTTP GET response script, i get stack overflows or assertion failures.
I.E.
SERIAL OUT:
DNS: Q (type 0x1 class 0x1) for connectivitycheck.gstatic.com
buffer = GET /generate_204 HTTP/1.1
User-Agent: Dalvik/2.1.0 (Linux; U; Android 6.0.1; XT1254 Build/MCG24.251-5-5)
Host: connectivitycheck.gstatic.com
Connection: Keep-Alive
Accept-Encoding: gzip
Sc5+?l?
buf[5] = g
==== Reading from file "/spiffs/images/HtmlExample.txt" ====
***ERROR*** A stack overflow in task http_server has been detected.
abort() was called at PC 0x40088340 on core 1
0x40088340: vApplicationStackOverflowHook at C:/msys32/home/esp/esp-idf/components/esp32/panic.c:572
If i free up the buffer of the client before reading in new data, i get this
SERIAL OUT:
DNS: Q (type 0x1 claass 0x1) for connectivitycheck.gstatic.com
buffer = GET /generate_204 HTTP/1.1
User-Agent: Dalvik/2.1.0 (Linux; U; Android 6.0.1; XT1254 Build/MCG24.251-5-5)
Host: connectivitycheck.gstatic.com
Connection: Keep-Alive
Accept-Encoding: gzip
buf[5] = g
assertion "next > (intptr_t)block" failedd: file "C:/msys32/home/esp/esp-idf/components/heap/multi_heap.c", line 116, function: get_next_block
abort() was called at PC 0x401085c3 on core 1
0x401085c3: __assert_func at /Users/ivan/e/newlib_xtensa-2.2.0-bin/newlib_xtensa-2.2.0/xtensa-esp32-elf/newlib/libc/stdlib/../../../.././newlib/li
bc/stdlib/assert.c:63 (discriminator 8)
any thoughts?
Below is my http request read & response code
static void http_server_netconn_serve(struct netconn *conn)
{
struct netbuf *inbuf;
char *buf;
u16_t buflen;
err_t err;
/* Read the data from the port, blocking if nothing yet there.
We assume the request (the part we care about) is in one netbuf */
err = netconn_recv(conn, &inbuf);
if (err == ERR_OK) {
netbuf_data(inbuf, (void**)&buf, &buflen);
// strncpy(_mBuffer, buf, buflen);
/* Is this an HTTP GET command? (only check the first 5 chars, since
there are other formats for GET, and we're keeping it very simple )*/
printf("buffer = %s \n", buf);
if (buflen>=5 &&
buf[0]=='G' &&
buf[1]=='E' &&
buf[2]=='T' &&
buf[3]==' ' &&
buf[4]=='/' ) {
printf("buf[5] = %c\n", buf[5]);
/* Send the HTML header
* subtract 1 from the size, since we dont send the \0 in the string
* NETCONN_NOCOPY: our data is const static, so no need to copy it
*/
netconn_write(conn, http_html_hdr, sizeof(http_html_hdr)-1, NETCONN_NOCOPY);
if(buf[5]=='h' || buf[5]=='g') {
/* Send our HTML page */
//free(buf);
//heap_caps_check_integrity(MALLOC_CAP_8BIT,true);
char filebuf= readFile("/spiffs/images/HtmlExample.txt"); // <----------------- fails here
netconn_write(conn, phork, sizeof(filebuf)-1, NETCONN_NOCOPY);
}
else if(buf[5]=='l') {
/* Send our HTML page */
netconn_write(conn, http_index_hml, sizeof(http_index_hml)-1, NETCONN_NOCOPY);
}
else if(buf[5]=='j') {
netconn_write(conn, json_unformatted, strlen(json_unformatted), NETCONN_NOCOPY);
}
else {
netconn_write(conn, http_index_hml, sizeof(http_index_hml)-1, NETCONN_NOCOPY);
}
}
}
/* Close the connection (server closes in HTTP) */
netconn_close(conn);
/* Delete the buffer (netconn_recv gives us ownership,
so we have to make sure to deallocate the buffer) */
netbuf_delete(inbuf);
}