httpd:
- include 'struct fs_file' in 'struct http_state' to prevent file allocation fails when connection allocation succeeded (plus have less allocations/pools); - added (conditional) code to abort the oldest connection when allocating a new connection fails; - fixed some warnings;
This commit is contained in:
parent
98b666de5d
commit
8eb51799aa
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Reference in New Issue