diff --git a/apps/httpserver_raw/fs.c b/apps/httpserver_raw/fs.c index 5f49ba9..2cb7575 100644 --- a/apps/httpserver_raw/fs.c +++ b/apps/httpserver_raw/fs.c @@ -48,19 +48,6 @@ #endif /* HTTPD_USE_CUSTOM_FSDATA */ /*-----------------------------------------------------------------------------------*/ -/* Define the number of open files that we can support. */ -#ifndef LWIP_MAX_OPEN_FILES -#define LWIP_MAX_OPEN_FILES 10 -#endif - -/* Define the file system memory allocation structure. */ -struct fs_table { - struct fs_file file; - u8_t inuse; -}; - -/* Allocate file system memory */ -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); @@ -72,54 +59,24 @@ u8_t fs_wait_read_custom(struct fs_file *file, fs_wait_cb callback_fn, void *cal #endif /* LWIP_HTTPD_CUSTOM_FILES */ /*-----------------------------------------------------------------------------------*/ -static struct fs_file * -fs_malloc(void) +err_t +fs_open(struct fs_file *file, const char *name) { - int i; - for(i = 0; i < LWIP_MAX_OPEN_FILES; i++) { - if(fs_memory[i].inuse == 0) { - fs_memory[i].inuse = 1; - return(&fs_memory[i].file); - } - } - return(NULL); -} - -/*-----------------------------------------------------------------------------------*/ -static void -fs_free(struct fs_file *file) -{ - int i; - for(i = 0; i < LWIP_MAX_OPEN_FILES; i++) { - if(&fs_memory[i].file == file) { - fs_memory[i].inuse = 0; - break; - } - } - return; -} - -/*-----------------------------------------------------------------------------------*/ -struct fs_file * -fs_open(const char *name) -{ - struct fs_file *file; const struct fsdata_file *f; - file = fs_malloc(); - if(file == NULL) { - return NULL; + if ((file == NULL) || (name == NULL)) { + return ERR_ARG; } #if LWIP_HTTPD_CUSTOM_FILES - if(fs_open_custom(file, name)) { + if (fs_open_custom(file, name)) { file->is_custom_file = 1; - return file; + return ERR_OK; } file->is_custom_file = 0; #endif /* LWIP_HTTPD_CUSTOM_FILES */ - for(f = FS_ROOT; f != NULL; f = f->next) { + for (f = FS_ROOT; f != NULL; f = f->next) { if (!strcmp(name, (char *)f->name)) { file->data = (const char *)f->data; file->len = f->len; @@ -133,11 +90,11 @@ fs_open(const char *name) #if LWIP_HTTPD_FILE_STATE file->state = fs_state_init(file, name); #endif /* #if LWIP_HTTPD_FILE_STATE */ - return file; + return ERR_OK; } } - fs_free(file); - return NULL; + /* file not found */ + return ERR_VAL; } /*-----------------------------------------------------------------------------------*/ @@ -152,7 +109,7 @@ fs_close(struct fs_file *file) #if LWIP_HTTPD_FILE_STATE fs_state_free(file, file->state); #endif /* #if LWIP_HTTPD_FILE_STATE */ - fs_free(file); + LWIP_UNUSED_ARG(file); } /*-----------------------------------------------------------------------------------*/ #if LWIP_HTTPD_DYNAMIC_FILE_READ @@ -169,13 +126,18 @@ fs_read(struct fs_file *file, char *buffer, int count) if(file->index == file->len) { return FS_READ_EOF; } -#if LWIP_HTTPD_FS_ASYNC_READ && LWIP_HTTPD_CUSTOM_FILES +#if LWIP_HTTPD_FS_ASYNC_READ +#if 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 */ +#else /* LWIP_HTTPD_CUSTOM_FILES */ + LWIP_UNUSED_ARG(callback_fn); + LWIP_UNUSED_ARG(callback_arg); +#endif /* LWIP_HTTPD_CUSTOM_FILES */ +#endif /* LWIP_HTTPD_FS_ASYNC_READ */ read = file->len - file->index; if(read > count) { @@ -194,13 +156,18 @@ 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 LWIP_HTTPD_FS_ASYNC_READ +#if 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 */ +#else /* LWIP_HTTPD_CUSTOM_FILES */ + LWIP_UNUSED_ARG(callback_fn); + LWIP_UNUSED_ARG(callback_arg); +#endif /* LWIP_HTTPD_CUSTOM_FILES */ +#endif /* LWIP_HTTPD_FS_ASYNC_READ */ } return 1; } diff --git a/apps/httpserver_raw/fs.h b/apps/httpserver_raw/fs.h index 75e479f..c021e2f 100644 --- a/apps/httpserver_raw/fs.h +++ b/apps/httpserver_raw/fs.h @@ -33,6 +33,7 @@ #define __FS_H__ #include "lwip/opt.h" +#include "lwip/err.h" /** Set this to 1 and provide the functions: * - "int fs_open_custom(struct fs_file *file, const char *name)" @@ -107,7 +108,7 @@ struct fs_file { typedef void (*fs_wait_cb)(void *arg); #endif /* LWIP_HTTPD_FS_ASYNC_READ */ -struct fs_file *fs_open(const char *name); +err_t fs_open(struct fs_file *file, const char *name); void fs_close(struct fs_file *file); #if LWIP_HTTPD_DYNAMIC_FILE_READ #if LWIP_HTTPD_FS_ASYNC_READ diff --git a/apps/httpserver_raw/httpd.c b/apps/httpserver_raw/httpd.c index 3bd97cd..e567a3f 100644 --- a/apps/httpserver_raw/httpd.c +++ b/apps/httpserver_raw/httpd.c @@ -337,6 +337,7 @@ struct http_state { #if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED struct http_state *next; #endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */ + struct fs_file file_handle; struct fs_file *handle; char *file; /* Pointer to first unsent byte in buf. */ @@ -381,8 +382,9 @@ struct http_state { }; static err_t http_close_conn(struct tcp_pcb *pcb, struct http_state *hs); +static err_t http_close_or_abort_conn(struct tcp_pcb *pcb, struct http_state *hs, u8_t abort); static err_t http_find_file(struct http_state *hs, const char *uri, int is_09); -static err_t http_init_file(struct http_state *hs, struct fs_file *file, int is_09, const char *uri); +static err_t http_init_file(struct http_state *hs, struct fs_file *file, int is_09, const char *uri, u8_t tag_check); static err_t http_poll(void *arg, struct tcp_pcb *pcb); #if LWIP_HTTPD_FS_ASYNC_READ static void http_continue(void *connection); @@ -451,7 +453,8 @@ http_kill_oldest_connection(u8_t ssi_required) if (hs_free_next != NULL) { LWIP_ASSERT("hs_free_next->next != NULL", hs_free_next->next != NULL); LWIP_ASSERT("hs_free_next->next->pcb != NULL", hs_free_next->next->pcb != NULL); - http_close_conn(hs_free_next->next->pcb, hs_free_next->next); /* this also unlinks the http_state from the list */ + /* send RST when killing a connection because of memory shortage */ + http_close_or_abort_conn(hs_free_next->next->pcb, hs_free_next->next, 1); /* this also unlinks the http_state from the list */ } } #endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */ @@ -634,14 +637,14 @@ http_write(struct tcp_pcb *pcb, const void* ptr, u16_t *length, u8_t apiflags) } /** - * The connection shall be actively closed. + * The connection shall be actively closed (using RST to close from fault states). * Reset the sent- and recv-callbacks. * * @param pcb the tcp pcb to reset callbacks * @param hs connection state to free */ static err_t -http_close_conn(struct tcp_pcb *pcb, struct http_state *hs) +http_close_or_abort_conn(struct tcp_pcb *pcb, struct http_state *hs, u8_t abort) { err_t err; LWIP_DEBUGF(HTTPD_DEBUG, ("Closing connection %p\n", (void*)pcb)); @@ -666,10 +669,14 @@ http_close_conn(struct tcp_pcb *pcb, struct http_state *hs) tcp_err(pcb, NULL); tcp_poll(pcb, NULL, 0); tcp_sent(pcb, NULL); - if(hs != NULL) { + if (hs != NULL) { http_state_free(hs); } + if (abort) { + tcp_abort(pcb); + return ERR_OK; + } err = tcp_close(pcb); if (err != ERR_OK) { LWIP_DEBUGF(HTTPD_DEBUG, ("Error %d closing %p\n", err, (void*)pcb)); @@ -679,6 +686,19 @@ http_close_conn(struct tcp_pcb *pcb, struct http_state *hs) return err; } +/** + * The connection shall be actively closed. + * Reset the sent- and recv-callbacks. + * + * @param pcb the tcp pcb to reset callbacks + * @param hs connection state to free + */ +static err_t +http_close_conn(struct tcp_pcb *pcb, struct http_state *hs) +{ + return http_close_or_abort_conn(pcb, hs, 0); +} + /** End of file: either close the connection (Connection: close) or * close the file (Connection: keep-alive) */ @@ -1555,7 +1575,7 @@ static err_t http_find_error_file(struct http_state *hs, u16_t error_nr) { const char *uri1, *uri2, *uri3; - struct fs_file *file; + err_t err; if (error_nr == 501) { uri1 = "/501.html"; @@ -1567,19 +1587,19 @@ http_find_error_file(struct http_state *hs, u16_t error_nr) uri2 = "/400.htm"; uri3 = "/400.shtml"; } - file = fs_open(uri1); - if (file == NULL) { - file = fs_open(uri2); - if (file == NULL) { - file = fs_open(uri3); - if (file == NULL) { + err = fs_open(&hs->file_handle, uri1); + if (err != ERR_OK) { + err = fs_open(&hs->file_handle, uri2); + if (err != ERR_OK) { + err = fs_open(&hs->file_handle, uri3); + if (err != ERR_OK) { LWIP_DEBUGF(HTTPD_DEBUG, ("Error page for error %"U16_F" not found\n", error_nr)); return ERR_ARG; } } } - return http_init_file(hs, file, 0, NULL); + return http_init_file(hs, &hs->file_handle, 0, NULL, 0); } #else /* LWIP_HTTPD_SUPPORT_EXTSTATUS */ #define http_find_error_file(hs, error_nr) ERR_ARG @@ -1593,30 +1613,31 @@ http_find_error_file(struct http_state *hs, u16_t error_nr) * @return file struct for the error page or NULL no matching file was found */ static struct fs_file * -http_get_404_file(const char **uri) +http_get_404_file(struct http_state *hs, const char **uri) { - struct fs_file *file; + err_t err; *uri = "/404.html"; - file = fs_open(*uri); - if(file == NULL) { + err = fs_open(&hs->file_handle, *uri); + if (err != ERR_OK) { /* 404.html doesn't exist. Try 404.htm instead. */ *uri = "/404.htm"; - file = fs_open(*uri); - if(file == NULL) { + err = fs_open(&hs->file_handle, *uri); + if (err != ERR_OK) { /* 404.htm doesn't exist either. Try 404.shtml instead. */ *uri = "/404.shtml"; - file = fs_open(*uri); - if(file == NULL) { + err = fs_open(&hs->file_handle, *uri); + if (err != ERR_OK) { /* 404.htm doesn't exist either. Indicate to the caller that it should * send back a default 404 page. */ *uri = NULL; + return NULL; } } } - return file; + return &hs->file_handle; } #if LWIP_HTTPD_SUPPORT_POST @@ -2020,14 +2041,16 @@ http_find_file(struct http_state *hs, const char *uri, int is_09) size_t loop; struct fs_file *file = NULL; char *params; + err_t err; #if LWIP_HTTPD_CGI int i; int count; #endif /* LWIP_HTTPD_CGI */ -#if LWIP_HTTPD_SSI +#if !LWIP_HTTPD_SSI + const +#endif /* !LWIP_HTTPD_SSI */ /* By default, assume we will not be processing server-side-includes tags */ u8_t tag_check = 0; -#endif /* LWIP_HTTPD_SSI */ /* Have we been asked for the default root file? */ if((uri[0] == '/') && (uri[1] == 0)) { @@ -2035,9 +2058,10 @@ http_find_file(struct http_state *hs, const char *uri, int is_09) that exists. */ for (loop = 0; loop < NUM_DEFAULT_FILENAMES; loop++) { LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Looking for %s...\n", g_psDefaultFilenames[loop].name)); - file = fs_open((char *)g_psDefaultFilenames[loop].name); + err = fs_open(&hs->file_handle, (char *)g_psDefaultFilenames[loop].name); uri = (char *)g_psDefaultFilenames[loop].name; - if(file != NULL) { + if(err == ERR_OK) { + file = &hs->file_handle; LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Opened.\n")); #if LWIP_HTTPD_SSI tag_check = g_psDefaultFilenames[loop].shtml; @@ -2047,7 +2071,7 @@ http_find_file(struct http_state *hs, const char *uri, int is_09) } if (file == NULL) { /* None of the default filenames exist so send back a 404 page */ - file = http_get_404_file(&uri); + file = http_get_404_file(hs, &uri); #if LWIP_HTTPD_SSI tag_check = 0; #endif /* LWIP_HTTPD_SSI */ @@ -2082,9 +2106,11 @@ http_find_file(struct http_state *hs, const char *uri, int is_09) LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Opening %s\n", uri)); - file = fs_open(uri); - if (file == NULL) { - file = http_get_404_file(&uri); + err = fs_open(&hs->file_handle, uri); + if (err == ERR_OK) { + file = &hs->file_handle; + } else { + file = http_get_404_file(hs, &uri); } #if LWIP_HTTPD_SSI if (file != NULL) { @@ -2100,21 +2126,7 @@ http_find_file(struct http_state *hs, const char *uri, int is_09) } #endif /* LWIP_HTTPD_SSI */ } -#if LWIP_HTTPD_SSI - if (file && tag_check) { - struct http_ssi_state *ssi = http_ssi_state_alloc(); - if (ssi != NULL) { - ssi->tag_index = 0; - ssi->tag_state = TAG_NONE; - ssi->parsed = file->data; - ssi->parse_left = file->len; - ssi->tag_end = file->data; - hs->ssi = ssi; - } - } -#endif /* LWIP_HTTPD_SSI */ - - return http_init_file(hs, file, is_09, uri); + return http_init_file(hs, file, is_09, uri, tag_check); } /** Initialize a http connection with a file to send (if found). @@ -2124,14 +2136,30 @@ http_find_file(struct http_state *hs, const char *uri, int is_09) * @param file file structure to send (or NULL if not found) * @param is_09 1 if the request is HTTP/0.9 (no HTTP headers in response) * @param uri the HTTP header URI + * @param tag_check enable SSI tag checking * @return ERR_OK if file was found and hs has been initialized correctly * another err_t otherwise */ static err_t -http_init_file(struct http_state *hs, struct fs_file *file, int is_09, const char *uri) +http_init_file(struct http_state *hs, struct fs_file *file, int is_09, const char *uri, u8_t tag_check) { if (file != NULL) { /* file opened, initialise struct http_state */ +#if LWIP_HTTPD_SSI + if (tag_check) { + struct http_ssi_state *ssi = http_ssi_state_alloc(); + if (ssi != NULL) { + ssi->tag_index = 0; + ssi->tag_state = TAG_NONE; + ssi->parsed = file->data; + ssi->parse_left = file->len; + ssi->tag_end = file->data; + hs->ssi = ssi; + } + } +#else /* LWIP_HTTPD_SSI */ + LWIP_UNUSED_ARG(tag_check); +#endif /* LWIP_HTTPD_SSI */ hs->handle = file; hs->file = (char*)file->data; LWIP_ASSERT("File length must be positive!", (file->len >= 0));