Enhancements to the uIP web server from Kate

git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@5088 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
patacongo 2012-09-04 16:59:24 +00:00
parent 90ef4d1d10
commit d06103b98b
8 changed files with 264 additions and 33 deletions

View File

@ -305,3 +305,6 @@
netutils/webserver/httpd_fsdata.c has been replaced with a dynamically
built configuration located at apps/examples/uip (Contributed by
Max Holtzberg).
* apps/netutils/webserver: Several inenhancements from Kate including the
ability to elide scripting and SERVER headers and the ability to map
files into memory before transferring them.

View File

@ -96,6 +96,9 @@ struct httpd_fs_file
{
char *data;
int len;
#ifdef CONFIG_NETUTILS_HTTPD_MMAP
int fd;
#endif
};
struct httpd_state

View File

@ -7,7 +7,28 @@ config NETUTILS_WEBSERVER
bool "uIP web server"
default n
---help---
Enable support for the uIP web server.
Enable support for the uIP web server. This tiny web server was
from uIP 1.0, but has undergone many changes. It is, however,
still referred to as the "uIP" web server.
if NETUTILS_WEBSERVER
config NETUTILS_HTTPD_SCRIPT_DISABLE
bool "Disable %! scripting"
default n
---help---
This option, if selected, will elide the %! scripting
config NETUTILS_HTTPD_SERVERHEADER_DISABLE, which elides the Server: header
bool "Disabled the SERVER header"
default n
---help---
This option, if selected, will elide the Server: header
config NETUTILS_HTTPD_MMAP
bool "File mmap-ing"
default n
---help---
Replaces standard uIP server file open operations with mmap-ing operations.
endif

View File

@ -1,7 +1,7 @@
############################################################################
# apps/netutils/webserver/Makefile
#
# Copyright (C) 2011 Gregory Nutt. All rights reserved.
# Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@ -43,7 +43,12 @@ ASRCS =
CSRCS =
ifeq ($(CONFIG_NET_TCP),y)
CSRCS = httpd.c httpd_fs.c httpd_cgi.c
CSRCS = httpd.c httpd_cgi.c
ifeq ($(CONFIG_NETUTILS_HTTPD_MMAP),y)
CSRCS += httpd_mmap.c
else
CSRCS += httpd_fs.c
endif
endif
AOBJS = $(ASRCS:.S=$(OBJEXT))

View File

@ -77,6 +77,10 @@
#define ISO_slash 0x2f
#define ISO_colon 0x3a
#ifndef CONFIG_NETUTILS_HTTPD_PATH
# define CONFIG_NETUTILS_HTTPD_PATH "/mnt"
#endif
/****************************************************************************
* Private Data
****************************************************************************/
@ -89,32 +93,60 @@ static const char g_httpcontenttypejpg[] = "Content-type: image/jpeg\r\n\r\n"
static const char g_httpcontenttypeplain[] = "Content-type: text/plain\r\n\r\n";
static const char g_httpcontenttypepng[] = "Content-type: image/png\r\n\r\n";
static const char g_httpextensionhtml[] = ".html";
#ifndef CONFIG_NETUTILS_HTTPD_SCRIPT_DISABLE
static const char g_httpextensionshtml[] = ".shtml";
#endif
static const char g_httpextensionhtml[] = ".html";
static const char g_httpextensioncss[] = ".css";
static const char g_httpextensionpng[] = ".png";
static const char g_httpextensiongif[] = ".gif";
static const char g_httpextensionjpg[] = ".jpg";
static const char g_http404path[] = "/404.html";
#ifndef CONFIG_NETUTILS_HTTPD_SCRIPT_DISABLE
static const char g_httpindexpath[] = "/index.shtml";
#else
static const char g_httpindexpath[] = "/index.html";
#endif
static const char g_httpcmdget[] = "GET ";
static const char g_httpheader200[] =
"HTTP/1.0 200 OK\r\n"
#ifndef CONFIG_NETUTILS_HTTPD_SERVERHEADER_DISABLE
"Server: uIP/1.0 http://www.sics.se/~adam/uip/\r\n"
#endif
"Connection: close\r\n";
static const char g_httpheader404[] =
"HTTP/1.0 404 Not found\r\n"
#ifndef CONFIG_NETUTILS_HTTPD_SERVERHEADER_DISABLE
"Server: uIP/1.0 http://www.sics.se/~adam/uip/\r\n"
#endif
"Connection: close\r\n";
/****************************************************************************
* Private Functions
****************************************************************************/
static int httpd_open(const char *name, struct httpd_fs_file *file)
{
#ifdef CONFIG_NETUTILS_HTTPD_MMAP
return httpd_mmap_open(name, file);
#else
return httpd_fs_open(name, file);
#endif
}
static int httpd_close(struct httpd_fs_file *file)
{
#ifdef CONFIG_NETUTILS_HTTPD_MMAP
return httpd_mmap_close(file);
#else
return OK;
#endif
}
#ifdef CONFIG_NETUTILS_HTTPD_DUMPBUFFER
static void httpd_dumpbuffer(FAR const char *msg, FAR const char *buffer, unsigned int nbytes)
{
@ -145,6 +177,7 @@ static void httpd_dumppstate(struct httpd_state *pstate, const char *msg)
# define httpd_dumppstate(pstate, msg)
#endif
#ifndef CONFIG_NETUTILS_HTTPD_SCRIPT_DISABLE
static void next_scriptstate(struct httpd_state *pstate)
{
char *p;
@ -152,7 +185,9 @@ static void next_scriptstate(struct httpd_state *pstate)
pstate->ht_scriptlen -= (unsigned short)(p - pstate->ht_scriptptr);
pstate->ht_scriptptr = p;
}
#endif
#ifndef CONFIG_NETUTILS_HTTPD_SCRIPT_DISABLE
static int handle_script(struct httpd_state *pstate)
{
int len;
@ -168,8 +203,14 @@ static int handle_script(struct httpd_state *pstate)
pstate->ht_scriptlen = pstate->ht_file.len - 3;
if (*(pstate->ht_scriptptr - 1) == ISO_colon)
{
httpd_fs_open(pstate->ht_scriptptr + 1, &pstate->ht_file);
if (httpd_open(pstate->ht_scriptptr + 1, &pstate->ht_file) != OK)
{
return ERROR;
}
send(pstate->ht_sockfd, pstate->ht_file.data, pstate->ht_file.len, 0);
httpd_close(&pstate->ht_file);
}
else
{
@ -223,6 +264,7 @@ static int handle_script(struct httpd_state *pstate)
}
return OK;
}
#endif
static int httpd_addchunk(struct httpd_state *pstate, const char *buffer, int len)
{
@ -244,6 +286,7 @@ static int httpd_addchunk(struct httpd_state *pstate, const char *buffer, int le
{
chunklen = len;
}
nvdbg("[%d] sndlen=%d len=%d newlen=%d chunklen=%d\n",
pstate->ht_sockfd, pstate->ht_sndlen, len, newlen, chunklen);
@ -270,6 +313,7 @@ static int httpd_addchunk(struct httpd_state *pstate, const char *buffer, int le
buffer += chunklen;
}
while (len > 0);
return OK;
}
@ -282,9 +326,9 @@ static int httpd_flush(struct httpd_state *pstate)
httpd_dumpbuffer("Outgoing buffer", pstate->ht_buffer, pstate->ht_sndlen);
ret = send(pstate->ht_sockfd, pstate->ht_buffer, pstate->ht_sndlen, 0);
if (ret >= 0)
{
pstate->ht_sndlen = 0;
}
{
pstate->ht_sndlen = 0;
}
}
return ret;
}
@ -305,8 +349,11 @@ static int send_headers(struct httpd_state *pstate, const char *statushdr, int l
{
ret = httpd_addchunk(pstate, g_httpcontenttypebinary, strlen(g_httpcontenttypebinary));
}
else if (strncmp(g_httpextensionhtml, ptr, strlen(g_httpextensionhtml)) == 0 ||
strncmp(g_httpextensionshtml, ptr, strlen(g_httpextensionshtml)) == 0)
else if (strncmp(g_httpextensionhtml, ptr, strlen(g_httpextensionhtml)) == 0
#ifndef CONFIG_NETUTILS_HTTPD_SCRIPT_DISABLE
|| strncmp(g_httpextensionshtml, ptr, strlen(g_httpextensionshtml)) == 0
#endif
)
{
ret = httpd_addchunk(pstate, g_httpcontenttypehtml, strlen(g_httpcontenttypehtml));
}
@ -336,17 +383,24 @@ static int send_headers(struct httpd_state *pstate, const char *statushdr, int l
static int httpd_sendfile(struct httpd_state *pstate)
{
#ifndef CONFIG_NETUTILS_HTTPD_SCRIPT_DISABLE
char *ptr;
#endif
int ret = ERROR;
pstate->ht_sndlen = 0;
nvdbg("[%d] sending file '%s'\n", pstate->ht_sockfd, pstate->ht_filename);
if (!httpd_fs_open(pstate->ht_filename, &pstate->ht_file))
if (httpd_open(pstate->ht_filename, &pstate->ht_file) != OK)
{
ndbg("[%d] '%s' not found\n", pstate->ht_sockfd, pstate->ht_filename);
memcpy(pstate->ht_filename, g_http404path, strlen(g_http404path));
httpd_fs_open(g_http404path, &pstate->ht_file);
if (httpd_open(g_http404path, &pstate->ht_file) != OK)
{
return ERROR;
}
if (send_headers(pstate, g_httpheader404, strlen(g_httpheader404)) == OK)
{
ret = httpd_addchunk(pstate, pstate->ht_file.data, pstate->ht_file.len);
@ -356,34 +410,38 @@ static int httpd_sendfile(struct httpd_state *pstate)
{
if (send_headers(pstate, g_httpheader200, strlen(g_httpheader200)) == OK)
{
if (httpd_flush(pstate) < 0)
{
ret = ERROR;
}
else
{
ptr = strchr(pstate->ht_filename, ISO_period);
if (ptr != NULL &&
strncmp(ptr, g_httpextensionshtml, strlen(g_httpextensionshtml)) == 0)
{
ret = handle_script(pstate);
}
else
{
ret = httpd_addchunk(pstate, pstate->ht_file.data, pstate->ht_file.len);
}
}
if (httpd_flush(pstate) < 0)
{
ret = ERROR;
}
else
{
#ifndef CONFIG_NETUTILS_HTTPD_SCRIPT_DISABLE
ptr = strchr(pstate->ht_filename, ISO_period);
if (ptr != NULL &&
strncmp(ptr, g_httpextensionshtml, strlen(g_httpextensionshtml)) == 0)
{
ret = handle_script(pstate);
}
else
#endif
{
ret = httpd_addchunk(pstate, pstate->ht_file.data, pstate->ht_file.len);
}
}
}
}
(void)httpd_close(&pstate->ht_file);
/* Send anything remaining in the buffer */
if (ret == OK && pstate->ht_sndlen > 0)
{
if (httpd_flush(pstate) < 0)
{
ret = ERROR;
}
{
ret = ERROR;
}
}
return ret;
@ -522,5 +580,7 @@ int httpd_listen(void)
void httpd_init(void)
{
#ifndef CONFIG_NETUTILS_HTTPD_MMAP
httpd_fs_init();
#endif
}

View File

@ -56,9 +56,14 @@
* Public Function Prototypes
****************************************************************************/
/* file must be allocated by caller and will be filled in by the function. */
/* 'file' must be allocated by caller and will be filled in by the function. */
int httpd_fs_open(const char *name, struct httpd_fs_file *file);
void httpd_fs_init(void);
#ifdef CONFIG_NETUTILS_HTTPD_MMAP
int httpd_mmap_open(const char *name, struct httpd_fs_file *file);
int httpd_mmap_close(struct httpd_fs_file *file);
#endif
#endif /* _NETUTILS_WEBSERVER_HTTPD_H */

View File

@ -0,0 +1,131 @@
/****************************************************************************
* netutils/webserver/httpd_mmap.c
*
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Header Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <debug.h>
#include <apps/netutils/httpd.h>
#include "httpd.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
int httpd_mmap_open(const char *name, struct httpd_fs_file *file)
{
char path[PATH_MAX];
struct stat st;
if (sizeof path < snprintf(path, sizeof path, "%s%s",
CONFIG_NETUTILS_HTTPD_PATH, name))
{
errno = ENAMETOOLONG;
return ERROR;
}
/* XXX: awaiting fstat to avoid a race */
if (-1 == stat(path, &st))
{
return ERROR;
}
if (st.st_size > INT_MAX)
{
errno = EFBIG;
return ERROR;
}
file->fd = open(path, O_RDONLY);
if (file->fd == -1)
{
return ERROR;
}
file->data = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED | MAP_FILE, file->fd, 0);
if (file->data == MAP_FAILED)
{
(void) close(file->fd);
return ERROR;
}
file->len = (int) st.st_size;
return OK;
}
int httpd_mmap_close(struct httpd_fs_file *file)
{
#ifdef CONFIG_FS_RAMMAP
if (-1 == munmap(file->data, file->len))
{
return ERROR;
}
#endif
if (-1 == close(file->fd))
{
return ERROR;
}
return OK;
}

View File

@ -3256,3 +3256,6 @@
only 16-bits wide and the SDIO DMA must be set up differently.
* arch/arm/src/stm32/stm32_dma.c: Back out the 16-bit DMA change. It
is incorrect.
* configs/: Make use of UART4/5 vs USART4/5 consistent in all places.
* Kconfig: Serial 2STOP setting must be integer 0/1, not a boolean.