httpd + makefsdata:

- added delayed open/read functionality (so that SSI code can delay sending of a file until internal data is available);
- clean up fs-handling: additional read is not required with our current fs implementation;
- kill oldest connection when running out of http_state memory;
- splitted SSI state into its own struct so that non-SSI pages don't consume too much memory (SSI buffer can get quit big);
- added support for HTTP/1.1 persistent connections (use the '-11' switch of makefsdata; not available for SSI files since we cannot calculate the file length in advance);
- splitted the unreadably-long function http_send_data into multiple smaller functions;
This commit is contained in:
Simon Goldschmidt 2011-09-04 19:26:46 +02:00
parent 227475a45e
commit d1bf1ee0da
5 changed files with 982 additions and 605 deletions

View File

@ -65,6 +65,10 @@ struct fs_table fs_memory[LWIP_MAX_OPEN_FILES];
#if LWIP_HTTPD_CUSTOM_FILES
int fs_open_custom(struct fs_file *file, const char *name);
void fs_close_custom(struct fs_file *file);
#if LWIP_HTTPD_FS_ASYNC_READ
u8_t fs_canread_custom(struct fs_file *file);
u8_t fs_wait_read_custom(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg);
#endif /* LWIP_HTTPD_FS_ASYNC_READ */
#endif /* LWIP_HTTPD_CUSTOM_FILES */
/*-----------------------------------------------------------------------------------*/
@ -151,14 +155,27 @@ fs_close(struct fs_file *file)
fs_free(file);
}
/*-----------------------------------------------------------------------------------*/
#if LWIP_HTTPD_DYNAMIC_FILE_READ
#if LWIP_HTTPD_FS_ASYNC_READ
int
fs_read_async(struct fs_file *file, char *buffer, int count, fs_wait_cb callback_fn, void *callback_arg)
#else /* LWIP_HTTPD_FS_ASYNC_READ */
int
fs_read(struct fs_file *file, char *buffer, int count)
#endif /* LWIP_HTTPD_FS_ASYNC_READ */
{
int read;
if(file->index == file->len) {
return -1;
return FS_READ_EOF;
}
#if LWIP_HTTPD_FS_ASYNC_READ && LWIP_HTTPD_CUSTOM_FILES
if (!fs_canread_custom(file)) {
if (fs_wait_read_custom(file, callback_fn, callback_arg)) {
return FS_READ_DELAYED;
}
}
#endif /* LWIP_HTTPD_FS_ASYNC_READ && LWIP_HTTPD_CUSTOM_FILES */
read = file->len - file->index;
if(read > count) {
@ -170,8 +187,27 @@ fs_read(struct fs_file *file, char *buffer, int count)
return(read);
}
#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */
/*-----------------------------------------------------------------------------------*/
int fs_bytes_left(struct fs_file *file)
#if LWIP_HTTPD_FS_ASYNC_READ
int
fs_is_file_ready(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg)
{
if (file != NULL) {
#if LWIP_HTTPD_FS_ASYNC_READ && LWIP_HTTPD_CUSTOM_FILES
if (!fs_canread_custom(file)) {
if (fs_wait_read_custom(file, callback_fn, callback_arg)) {
return 0;
}
}
#endif /* LWIP_HTTPD_FS_ASYNC_READ && LWIP_HTTPD_CUSTOM_FILES */
}
return 1;
}
#endif /* LWIP_HTTPD_FS_ASYNC_READ */
/*-----------------------------------------------------------------------------------*/
int
fs_bytes_left(struct fs_file *file)
{
return file->len - file->index;
}

View File

@ -45,6 +45,14 @@
#define LWIP_HTTPD_CUSTOM_FILES 0
#endif
/** Set this to 1 to support fs_read() to dynamically read file data.
* Without this (default=off), only one-block files are supported,
* and the contents must be ready after fs_open().
*/
#ifndef LWIP_HTTPD_DYNAMIC_FILE_READ
#define LWIP_HTTPD_DYNAMIC_FILE_READ 0
#endif
/** Set this to 1 to include an application state argument per file
* that is opened. This allows to keep a state per connection/file.
*/
@ -59,6 +67,16 @@
#define HTTPD_PRECALCULATED_CHECKSUM 0
#endif
/** LWIP_HTTPD_FS_ASYNC_READ==1: support asynchronous read operations
* (fs_read_async returns FS_READ_DELAYED and calls a callback when finished).
*/
#ifndef LWIP_HTTPD_FS_ASYNC_READ
#define LWIP_HTTPD_FS_ASYNC_READ 0
#endif
#define FS_READ_EOF -1
#define FS_READ_DELAYED -2
#if HTTPD_PRECALCULATED_CHECKSUM
struct fsdata_chksum {
u32_t offset;
@ -85,9 +103,22 @@ struct fs_file {
#endif /* LWIP_HTTPD_FILE_STATE */
};
#if LWIP_HTTPD_FS_ASYNC_READ
typedef void (*fs_wait_cb)(void *arg);
#endif /* LWIP_HTTPD_FS_ASYNC_READ */
struct fs_file *fs_open(const char *name);
void fs_close(struct fs_file *file);
#if LWIP_HTTPD_DYNAMIC_FILE_READ
#if LWIP_HTTPD_FS_ASYNC_READ
int fs_read_async(struct fs_file *file, char *buffer, int count, fs_wait_cb callback_fn, void *callback_arg);
#else /* LWIP_HTTPD_FS_ASYNC_READ */
int fs_read(struct fs_file *file, char *buffer, int count);
#endif /* LWIP_HTTPD_FS_ASYNC_READ */
#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */
#if LWIP_HTTPD_FS_ASYNC_READ
int fs_is_file_ready(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg);
#endif /* LWIP_HTTPD_FS_ASYNC_READ */
int fs_bytes_left(struct fs_file *file);
#if LWIP_HTTPD_FILE_STATE

File diff suppressed because it is too large Load Diff

View File

@ -54,6 +54,7 @@ static const char * const g_psHTTPHeaderStrings[] =
"HTTP/1.1 501 Not Implemented\r\n",
"Content-Length: ",
"Connection: Close\r\n",
"Connection: keep-alive\r\n",
"Server: "HTTPD_SERVER_AGENT"\r\n",
"\r\n<html><body><h2>404: The requested file cannot be found.</h2></body></html>\r\n"
};
@ -83,8 +84,9 @@ static const char * const g_psHTTPHeaderStrings[] =
#define HTTP_HDR_NOT_IMPL_11 21 /* 501 Not Implemented */
#define HTTP_HDR_CONTENT_LENGTH 22 /* Content-Length: (HTTP 1.1)*/
#define HTTP_HDR_CONN_CLOSE 23 /* Connection: Close (HTTP 1.1) */
#define HTTP_HDR_SERVER 24 /* Server: HTTPD_SERVER_AGENT */
#define DEFAULT_404_HTML 25 /* default 404 body */
#define HTTP_HDR_CONN_KEEPALIVE 24 /* Connection: keep-alive (HTTP 1.1) */
#define HTTP_HDR_SERVER 25 /* Server: HTTPD_SERVER_AGENT */
#define DEFAULT_404_HTML 26 /* default 404 body */
/** A list of extension-to-HTTP header strings */
const static tHTTPHeader g_psHTTPHeaders[] =
@ -105,11 +107,19 @@ const static tHTTPHeader g_psHTTPHeaders[] =
{ "ram", HTTP_HDR_RA},
{ "css", HTTP_HDR_CSS},
{ "swf", HTTP_HDR_SWF},
{ "xml", HTTP_HDR_XML}
{ "xml", HTTP_HDR_XML},
{ "xsl", HTTP_HDR_XML}
};
#define NUM_HTTP_HEADERS (sizeof(g_psHTTPHeaders) / sizeof(tHTTPHeader))
#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */
#if LWIP_HTTPD_SSI
static const char * const g_pcSSIExtensions[] = {
".shtml", ".shtm", ".ssi", ".xml"
};
#define NUM_SHTML_EXTENSIONS (sizeof(g_pcSSIExtensions) / sizeof(const char *))
#endif /* LWIP_HTTPD_SSI */
#endif /* __HTTPD_STRUCTS_H__ */

View File

@ -62,6 +62,7 @@
/* define this to get the header variables we use to build HTTP headers */
#define LWIP_HTTPD_DYNAMIC_HEADERS 1
#define LWIP_HTTPD_SSI 1
#include "../httpd_structs.h"
#include "../../../../lwip/src/core/inet_chksum.c"
@ -103,6 +104,7 @@ char hdr_buf[4096];
unsigned char processSubs = 1;
unsigned char includeHttpHeader = 1;
unsigned char useHttp11 = 0;
unsigned char supportSsi = 1;
unsigned char precalcChksum = 0;
int main(int argc, char *argv[])
@ -134,6 +136,8 @@ int main(int argc, char *argv[])
includeHttpHeader = 0;
} else if (strstr(argv[i], "-11")) {
useHttp11 = 1;
} else if (strstr(argv[i], "-nossi")) {
supportSsi = 0;
} else if (strstr(argv[i], "-c")) {
precalcChksum = 1;
} else if((argv[i][1] == 'f') && (argv[i][2] == ':')) {
@ -155,6 +159,7 @@ int main(int argc, char *argv[])
printf(" switch -s: toggle processing of subdirectories (default is on)" NEWLINE);
printf(" switch -e: exclude HTTP header from file (header is created at runtime, default is off)" NEWLINE);
printf(" switch -11: include HTTP 1.1 header (1.0 is default)" NEWLINE);
printf(" switch -nossi: no support for SSI (cannot calculate Content-Length for SSI)" NEWLINE);
printf(" switch -c: precalculate checksums for all pages (default is off)" NEWLINE);
printf(" switch -f: target filename (default is \"fsdata.c\")" NEWLINE);
printf(" if targetdir not specified, htmlgen will attempt to" NEWLINE);
@ -463,6 +468,17 @@ int file_write_http_header(FILE *data_file, const char *filename, int file_size,
u16_t acc;
const char *file_ext;
int j;
u8_t keepalive = useHttp11;
if (keepalive) {
size_t loop;
for (loop = 0; loop < NUM_SHTML_EXTENSIONS; loop++) {
if (strstr(filename, g_pcSSIExtensions[loop])) {
/* no keepalive connection for SSI files */
keepalive = 0;
}
}
}
memset(hdr_buf, 0, sizeof(hdr_buf));
@ -529,28 +545,38 @@ int file_write_http_header(FILE *data_file, const char *filename, int file_size,
if (useHttp11) {
char intbuf[MAX_PATH_LEN];
int content_len = file_size;
memset(intbuf, 0, sizeof(intbuf));
cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONTENT_LENGTH];
cur_len = strlen(cur_string);
fprintf(data_file, NEWLINE "/* \"%s%d\r\n\" (%d+ bytes) */" NEWLINE, cur_string, file_size, cur_len+2);
written += file_put_ascii(data_file, cur_string, cur_len, &i);
if (precalcChksum) {
memcpy(&hdr_buf[hdr_len], cur_string, cur_len);
hdr_len += cur_len;
if (!keepalive) {
content_len *= 2;
}
{
cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONTENT_LENGTH];
cur_len = strlen(cur_string);
fprintf(data_file, NEWLINE "/* \"%s%d\r\n\" (%d+ bytes) */" NEWLINE, cur_string, content_len, cur_len+2);
written += file_put_ascii(data_file, cur_string, cur_len, &i);
if (precalcChksum) {
memcpy(&hdr_buf[hdr_len], cur_string, cur_len);
hdr_len += cur_len;
}
_itoa(content_len, intbuf, 10);
strcat(intbuf, "\r\n");
cur_len = strlen(intbuf);
written += file_put_ascii(data_file, intbuf, cur_len, &i);
i = 0;
if (precalcChksum) {
memcpy(&hdr_buf[hdr_len], intbuf, cur_len);
hdr_len += cur_len;
}
}
_itoa(file_size, intbuf, 10);
strcat(intbuf, "\r\n");
cur_len = strlen(intbuf);
written += file_put_ascii(data_file, intbuf, cur_len, &i);
i = 0;
if (precalcChksum) {
memcpy(&hdr_buf[hdr_len], intbuf, cur_len);
hdr_len += cur_len;
if (keepalive) {
cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONN_KEEPALIVE];
} else {
cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONN_CLOSE];
}
cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONN_CLOSE];
cur_len = strlen(cur_string);
fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len);
written += file_put_ascii(data_file, cur_string, cur_len, &i);