summaryrefslogtreecommitdiff
path: root/nuttx/netutils
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-11-19 18:17:23 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-11-19 18:17:23 +0000
commitbefc37ada0b901ad7c315e4089976508396d496b (patch)
tree44818265dc09577601c19bf81b3576109f31a534 /nuttx/netutils
parent6f5479c267e1ed09e85461464ae73b4cbfd3d486 (diff)
downloadpx4-nuttx-befc37ada0b901ad7c315e4089976508396d496b.tar.gz
px4-nuttx-befc37ada0b901ad7c315e4089976508396d496b.tar.bz2
px4-nuttx-befc37ada0b901ad7c315e4089976508396d496b.zip
uIP webserver now uses listen/accept
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@386 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/netutils')
-rw-r--r--nuttx/netutils/Makefile6
-rw-r--r--nuttx/netutils/uiplib/Make.defs2
-rw-r--r--nuttx/netutils/uiplib/uip-gethostaddr.c2
-rw-r--r--nuttx/netutils/uiplib/uip-getmacaddr.c2
-rw-r--r--nuttx/netutils/uiplib/uip-server.c191
-rw-r--r--nuttx/netutils/uiplib/uip-setdraddr.c2
-rw-r--r--nuttx/netutils/uiplib/uip-sethostaddr.c2
-rw-r--r--nuttx/netutils/uiplib/uip-setmacaddr.c2
-rw-r--r--nuttx/netutils/uiplib/uip-setnetmask.c2
-rw-r--r--nuttx/netutils/webserver/httpd-cgi.c2
-rw-r--r--nuttx/netutils/webserver/httpd.c218
-rw-r--r--nuttx/netutils/webserver/httpd.h53
12 files changed, 385 insertions, 99 deletions
diff --git a/nuttx/netutils/Makefile b/nuttx/netutils/Makefile
index 6d8132f77..4e355ab7f 100644
--- a/nuttx/netutils/Makefile
+++ b/nuttx/netutils/Makefile
@@ -39,12 +39,14 @@ MKDEP = $(TOPDIR)/tools/mkdeps.sh
ifeq ($(CONFIG_NET),y)
include uiplib/Make.defs
-include dhcpc/Make.defs
-include resolv/Make.defs
include smtp/Make.defs
include telnetd/Make.defs
include webclient/Make.defs
include webserver/Make.defs
+ifeq ($(CONFIG_NET_UDP),y)
+include dhcpc/Make.defs
+include resolv/Make.defs
+endif
include Make.str
endif
diff --git a/nuttx/netutils/uiplib/Make.defs b/nuttx/netutils/uiplib/Make.defs
index d8b8ac600..8acb0218d 100644
--- a/nuttx/netutils/uiplib/Make.defs
+++ b/nuttx/netutils/uiplib/Make.defs
@@ -35,4 +35,4 @@
UIPLIB_ASRCS =
UIPLIB_CSRCS = uiplib.c uip-setmacaddr.c uip-getmacaddr.c uip-sethostaddr.c \
- uip-gethostaddr.c uip-setdraddr.c uip-setnetmask.c
+ uip-gethostaddr.c uip-setdraddr.c uip-setnetmask.c uip-server.c
diff --git a/nuttx/netutils/uiplib/uip-gethostaddr.c b/nuttx/netutils/uiplib/uip-gethostaddr.c
index a8d36efac..732721b10 100644
--- a/nuttx/netutils/uiplib/uip-gethostaddr.c
+++ b/nuttx/netutils/uiplib/uip-gethostaddr.c
@@ -81,7 +81,7 @@ int uip_gethostaddr(const char *ifname, struct in_addr *addr)
int ret = ERROR;
if (ifname && addr)
{
- int sockfd = socket(PF_INET, SOCK_DGRAM, 0);
+ int sockfd = socket(PF_INET, UIPLIB_SOCK_IOCTL, 0);
if (sockfd >= 0)
{
struct ifreq req;
diff --git a/nuttx/netutils/uiplib/uip-getmacaddr.c b/nuttx/netutils/uiplib/uip-getmacaddr.c
index a8f936113..9e7a368ab 100644
--- a/nuttx/netutils/uiplib/uip-getmacaddr.c
+++ b/nuttx/netutils/uiplib/uip-getmacaddr.c
@@ -75,7 +75,7 @@ int uip_getmacaddr(const char *ifname, uint8 *macaddr)
{
/* Get a socket (only so that we get access to the INET subsystem) */
- int sockfd = socket(PF_INET, SOCK_DGRAM, 0);
+ int sockfd = socket(PF_INET, UIPLIB_SOCK_IOCTL, 0);
if (sockfd >= 0)
{
struct ifreq req;
diff --git a/nuttx/netutils/uiplib/uip-server.c b/nuttx/netutils/uiplib/uip-server.c
new file mode 100644
index 000000000..aa0ea5b11
--- /dev/null
+++ b/nuttx/netutils/uiplib/uip-server.c
@@ -0,0 +1,191 @@
+/****************************************************************************
+ * netutils/uiplib/uip-server.c
+ *
+ * Copyright (C) 2007 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 Gregory Nutt 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 Files
+ ****************************************************************************/
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <unistd.h>
+#include <sched.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <net/uip/uip-lib.h>
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+#define errno *get_errno_ptr()
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: uip_server
+ *
+ * Description:
+ * Implement basic server logic
+ *
+ * Parameters:
+ * portno The port to listen on (in network byte order)
+ * handler The entrypoint of the task to spawn when a new connection is
+ * accepted.
+ * stacksize The stack size needed by the spawned task
+ *
+ * Return:
+ * Does not return unless an error occurs.
+ *
+ ****************************************************************************/
+
+void uip_server(uint16 portno, main_t handler, int stacksize)
+{
+ struct sockaddr_in myaddr;
+#ifdef CONFIG_NET_HAVE_SOLINGER
+ struct linger ling;
+#endif
+ struct sched_param param;
+ socklen_t addrlen;
+ const char *argv[2];
+ int listensd;
+ int acceptsd;
+#ifdef CONFIG_NET_HAVE_REUSEADDR
+ int optval;
+#endif
+
+ /* Create a new TCP socket to use to listen for connections */
+
+ listensd = socket(PF_INET, SOCK_STREAM, 0);
+ if (listensd < 0)
+ {
+ dbg("socket failure: %d\n", errno);
+ return;
+ }
+
+ /* Set socket to reuse address */
+
+#ifdef CONFIG_NET_HAVE_REUSEADDR
+ optval = 1;
+ if (setsockopt(listensd, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, sizeof(int)) < 0)
+ {
+ dbg("setsockopt SO_REUSEADDR failure: %d\n", errno);
+ goto errout_with_socket;
+ }
+#endif
+
+ /* Bind the socket to a local address */
+
+ myaddr.sin_family = AF_INET;
+ myaddr.sin_port = portno;
+ myaddr.sin_addr.s_addr = INADDR_ANY;
+
+ if (bind(listensd, (struct sockaddr*)&myaddr, sizeof(struct sockaddr_in)) < 0)
+ {
+ dbg("bind failure: %d\n", errno);
+ goto errout_with_socket;
+ }
+
+ /* Listen for connections on the bound TCP socket */
+
+ if (listen(listensd, 5) < 0)
+ {
+ dbg("listen failure %d\n", errno);
+ goto errout_with_socket;
+ }
+
+ /* Begin accepting connections */
+
+ dbg("Accepting connections on port %d\n", ntohs(portno));
+ for (;;)
+ {
+ addrlen = sizeof(struct sockaddr_in);
+ acceptsd = accept(listensd, (struct sockaddr*)&myaddr, &addrlen);
+ if (acceptsd < 0)
+ {
+ dbg("accept failure: %d\n", errno);
+ break;;
+ }
+ dbg("Connection accepted -- spawning\n");
+
+ /* Configure to "linger" until all data is sent when the socket is closed */
+
+#ifdef CONFIG_NET_HAVE_SOLINGER
+ ling.l_onoff = 1;
+ ling.l_linger = 30; /* timeout is seconds */
+ if (setsockopt(acceptsd, SOL_SOCKET, SO_LINGER, &ling, sizeof(struct linger)) < 0)
+ {
+ close(acceptsd);
+ dbg("setsockopt SO_LINGER failure: %d\n", errno);
+ break;;
+ }
+#endif
+
+ /* Spawn a thread to handle the connection. The socket descriptor +1 is
+ * provided in as the single argument to the new thread. (The +1 is intended
+ * to handle the valid, zero file descriptor).
+ */
+
+ if (sched_getparam(0, &param) < 0)
+ {
+ close(acceptsd);
+ dbg("sched_getparam failed: %d\n", errno);
+ break;;
+ }
+
+ argv[0] = (char*)(acceptsd + 1);
+ argv[1] = NULL;
+
+ if (task_create("", param.sched_priority, stacksize, handler, argv) < 0)
+ {
+ close(acceptsd);
+ dbg("task_create failed: %d\n", errno);
+ break;;
+ }
+
+ /* We can close our copy of acceptsd now. This file descriptor was dup'ed
+ * by task_create and we no longer need to retain the reference.
+ */
+
+ close(acceptsd);
+ }
+
+errout_with_socket:
+ close(listensd);
+}
diff --git a/nuttx/netutils/uiplib/uip-setdraddr.c b/nuttx/netutils/uiplib/uip-setdraddr.c
index 3b15a9ca9..e8ab142ec 100644
--- a/nuttx/netutils/uiplib/uip-setdraddr.c
+++ b/nuttx/netutils/uiplib/uip-setdraddr.c
@@ -78,7 +78,7 @@ int uip_setdraddr(const char *ifname, const struct in_addr *addr)
int ret = ERROR;
if (ifname && addr)
{
- int sockfd = socket(PF_INET, SOCK_DGRAM, 0);
+ int sockfd = socket(PF_INET, UIPLIB_SOCK_IOCTL, 0);
if (sockfd >= 0)
{
struct ifreq req;
diff --git a/nuttx/netutils/uiplib/uip-sethostaddr.c b/nuttx/netutils/uiplib/uip-sethostaddr.c
index 4a0b979bc..6247184ba 100644
--- a/nuttx/netutils/uiplib/uip-sethostaddr.c
+++ b/nuttx/netutils/uiplib/uip-sethostaddr.c
@@ -78,7 +78,7 @@ int uip_sethostaddr(const char *ifname, const struct in_addr *addr)
int ret = ERROR;
if (ifname && addr)
{
- int sockfd = socket(PF_INET, SOCK_DGRAM, 0);
+ int sockfd = socket(PF_INET, UIPLIB_SOCK_IOCTL, 0);
if (sockfd >= 0)
{
struct ifreq req;
diff --git a/nuttx/netutils/uiplib/uip-setmacaddr.c b/nuttx/netutils/uiplib/uip-setmacaddr.c
index b02e204ce..4b1e67530 100644
--- a/nuttx/netutils/uiplib/uip-setmacaddr.c
+++ b/nuttx/netutils/uiplib/uip-setmacaddr.c
@@ -86,7 +86,7 @@ int uip_setmacaddr(const char *ifname, const uint8 *macaddr)
{
/* Get a socket (only so that we get access to the INET subsystem) */
- int sockfd = socket(PF_INET, SOCK_DGRAM, 0);
+ int sockfd = socket(PF_INET, UIPLIB_SOCK_IOCTL, 0);
if (sockfd >= 0)
{
struct ifreq req;
diff --git a/nuttx/netutils/uiplib/uip-setnetmask.c b/nuttx/netutils/uiplib/uip-setnetmask.c
index 56e579ef3..ff70e5a37 100644
--- a/nuttx/netutils/uiplib/uip-setnetmask.c
+++ b/nuttx/netutils/uiplib/uip-setnetmask.c
@@ -78,7 +78,7 @@ int uip_setnetmask(const char *ifname, const struct in_addr *addr)
int ret = ERROR;
if (ifname && addr)
{
- int sockfd = socket(PF_INET, SOCK_DGRAM, 0);
+ int sockfd = socket(PF_INET, UIPLIB_SOCK_IOCTL, 0);
if (sockfd >= 0)
{
struct ifreq req;
diff --git a/nuttx/netutils/webserver/httpd-cgi.c b/nuttx/netutils/webserver/httpd-cgi.c
index 1c7965374..e93aff1be 100644
--- a/nuttx/netutils/webserver/httpd-cgi.c
+++ b/nuttx/netutils/webserver/httpd-cgi.c
@@ -125,7 +125,7 @@ static void file_stats(struct httpd_state *pstate, char *ptr)
char buffer[16];
char *pcount = strchr(ptr, ' ') + 1;
snprintf(buffer, 16, "%5u", httpd_fs_count(pcount));
- (void)send(pstate->sockout, buffer, strlen(buffer), 0);
+ (void)send(pstate->sockfd, buffer, strlen(buffer), 0);
}
#endif
diff --git a/nuttx/netutils/webserver/httpd.c b/nuttx/netutils/webserver/httpd.c
index 57e60f872..2db3436d7 100644
--- a/nuttx/netutils/webserver/httpd.c
+++ b/nuttx/netutils/webserver/httpd.c
@@ -45,11 +45,17 @@
* Included Files
****************************************************************************/
-#include <stdlib.h>
+#include <nuttx/config.h>
+
#include <sys/socket.h>
+
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
+#include <debug.h>
#include <net/uip/uip.h>
+#include <net/uip/uip-lib.h>
#include <net/uip/httpd.h>
#include "httpd.h"
@@ -60,9 +66,6 @@
* Definitions
****************************************************************************/
-#define STATE_WAITING 0
-#define STATE_OUTPUT 1
-
#define ISO_nl 0x0a
#define ISO_space 0x20
#define ISO_bang 0x21
@@ -71,21 +74,50 @@
#define ISO_slash 0x2f
#define ISO_colon 0x3a
-#define SEND_STR(psock, str) psock_send(psock, str, strlen(str))
+#define CONFIG_NETUTILS_HTTPD_DUMPBUFFER 1
/****************************************************************************
* Private Functions
****************************************************************************/
-static inline int send_file(struct httpd_state *pstate)
+#ifdef CONFIG_NETUTILS_HTTPD_DUMPBUFFER
+static void httpd_dumpbuffer(struct httpd_state *pstate, ssize_t nbytes)
{
- return send(pstate->sockout, pstate->file.data, pstate->file.len, 0);
-}
+#ifdef CONFIG_DEBUG
+ char line[128];
+ int ch;
+ int i;
+ int j;
-static inline int send_part_of_file(struct httpd_state *pstate)
-{
- return send(pstate->sockout, pstate->file.data, pstate->len, 0);
+ for (i = 0; i < nbytes; i += 16)
+ {
+ sprintf(line, "%04x: ", i);
+ for ( j = 0; j < 16; j++)
+ {
+ if (i + j < nbytes)
+ {
+ sprintf(&line[strlen(line)], "%02x ", pstate->ht_buffer[i+j] );
+ }
+ else
+ {
+ strcpy(&line[strlen(line)], " ");
+ }
+ }
+ for ( j = 0; j < 16; j++)
+ {
+ if (i + j < nbytes)
+ {
+ ch = pstate->ht_buffer[i+j];
+ sprintf(&line[strlen(line)], "%c", ch >= 0x20 && ch <= 0x7e ? ch : '.');
+ }
+ }
+ dbg("%s", line);
+ }
+#endif
}
+#else
+# define httpd_dumpbuffer(pstate,nbytes)
+#endif
static void next_scriptstate(struct httpd_state *pstate)
{
@@ -95,35 +127,40 @@ static void next_scriptstate(struct httpd_state *pstate)
pstate->scriptptr = p;
}
-static void handle_script(struct httpd_state *pstate, struct uip_conn *conn)
+static void handle_script(struct httpd_state *pstate)
{
char *ptr;
while(pstate->file.len > 0) {
- /* Check if we should start executing a script. */
+ /* Check if we should start executing a script */
+
if (*pstate->file.data == ISO_percent &&
*(pstate->file.data + 1) == ISO_bang) {
pstate->scriptptr = pstate->file.data + 3;
pstate->scriptlen = pstate->file.len - 3;
- if (*(pstate->scriptptr - 1) == ISO_colon) {
- httpd_fs_open(pstate->scriptptr + 1, &pstate->file);
- send_file(pstate);
- } else {
- httpd_cgi(pstate->scriptptr)(pstate, pstate->scriptptr);
- }
+ if (*(pstate->scriptptr - 1) == ISO_colon)
+ {
+ httpd_fs_open(pstate->scriptptr + 1, &pstate->file);
+ send(pstate->sockfd, pstate->file.data, pstate->file.len, 0);
+ }
+ else
+ {
+ httpd_cgi(pstate->scriptptr)(pstate, pstate->scriptptr);
+ }
next_scriptstate(pstate);
/* The script is over, so we reset the pointers and continue
- sending the rest of the file. */
+ sending the rest of the file */
pstate->file.data = pstate->scriptptr;
pstate->file.len = pstate->scriptlen;
+
} else {
/* See if we find the start of script marker in the block of HTML
- to be sent. */
+ to be sent */
- if (pstate->file.len > uip_mss(conn)) {
- pstate->len = uip_mss(conn);
+ if (pstate->file.len > HTTPD_IOBUFFER_SIZE) {
+ pstate->len = HTTPD_IOBUFFER_SIZE;
} else {
pstate->len = pstate->file.len;
}
@@ -136,11 +173,11 @@ static void handle_script(struct httpd_state *pstate, struct uip_conn *conn)
if (ptr != NULL &&
ptr != pstate->file.data) {
pstate->len = (int)(ptr - pstate->file.data);
- if (pstate->len >= uip_mss(conn)) {
- pstate->len = uip_mss(conn);
+ if (pstate->len >= HTTPD_IOBUFFER_SIZE) {
+ pstate->len = HTTPD_IOBUFFER_SIZE;
}
}
- send_part_of_file(pstate);
+ send(pstate->sockfd, pstate->file.data, pstate->len, 0);
pstate->file.data += pstate->len;
pstate->file.len -= pstate->len;
}
@@ -152,41 +189,41 @@ static int send_headers(struct httpd_state *pstate, const char *statushdr)
char *ptr;
int ret;
- ret = send(pstate->sockout, statushdr, strlen(statushdr), 0);
+ ret = send(pstate->sockfd, statushdr, strlen(statushdr), 0);
ptr = strrchr(pstate->filename, ISO_period);
if (ptr == NULL)
{
- ret = send(pstate->sockout, http_content_type_binary, strlen(http_content_type_binary), 0);
+ ret = send(pstate->sockfd, http_content_type_binary, strlen(http_content_type_binary), 0);
}
else if (strncmp(http_html, ptr, 5) == 0 || strncmp(http_shtml, ptr, 6) == 0)
{
- ret = send(pstate->sockout, http_content_type_html, strlen(http_content_type_html), 0);
+ ret = send(pstate->sockfd, http_content_type_html, strlen(http_content_type_html), 0);
}
else if (strncmp(http_css, ptr, 4) == 0)
{
- ret = send(pstate->sockout, http_content_type_css, strlen(http_content_type_css), 0);
+ ret = send(pstate->sockfd, http_content_type_css, strlen(http_content_type_css), 0);
}
else if (strncmp(http_png, ptr, 4) == 0)
{
- ret = send(pstate->sockout, http_content_type_png, strlen(http_content_type_png), 0);
+ ret = send(pstate->sockfd, http_content_type_png, strlen(http_content_type_png), 0);
}
else if (strncmp(http_gif, ptr, 4) == 0)
{
- ret = send(pstate->sockout, http_content_type_gif, strlen(http_content_type_gif), 0);
+ ret = send(pstate->sockfd, http_content_type_gif, strlen(http_content_type_gif), 0);
}
else if (strncmp(http_jpg, ptr, 4) == 0)
{
- ret = send(pstate->sockout, http_content_type_jpg, strlen(http_content_type_jpg), 0);
+ ret = send(pstate->sockfd, http_content_type_jpg, strlen(http_content_type_jpg), 0);
}
else
{
- ret = send(pstate->sockout, http_content_type_plain, strlen(http_content_type_plain), 0);
+ ret = send(pstate->sockfd, http_content_type_plain, strlen(http_content_type_plain), 0);
}
return ret;
}
-static void handle_output(struct httpd_state *pstate, struct uip_conn *conn)
+static void httpd_sendfile(struct httpd_state *pstate)
{
char *ptr;
@@ -195,7 +232,7 @@ static void handle_output(struct httpd_state *pstate, struct uip_conn *conn)
httpd_fs_open(http_404_html, &pstate->file);
strcpy(pstate->filename, http_404_html);
send_headers(pstate, http_header_404);
- send_file(pstate);
+ send(pstate->sockfd, pstate->file.data, pstate->file.len, 0);
}
else
{
@@ -203,75 +240,102 @@ static void handle_output(struct httpd_state *pstate, struct uip_conn *conn)
ptr = strchr(pstate->filename, ISO_period);
if (ptr != NULL && strncmp(ptr, http_shtml, 6) == 0)
{
- handle_script(pstate, conn);
+ handle_script(pstate);
}
else
{
- send_file(pstate);
+ send(pstate->sockfd, pstate->file.data, pstate->file.len, 0);
}
}
}
-static int handle_input(struct httpd_state *pstate)
+static inline int httpd_cmd(struct httpd_state *pstate)
{
ssize_t recvlen;
+ int i;
+
+ /* Get the next HTTP command. We will handle only GET */
- if (recv(pstate->sockin, pstate->inputbuf, HTTPD_INBUFFER_SIZE, 0) < 0)
+ recvlen = recv(pstate->sockfd, pstate->ht_buffer, HTTPD_IOBUFFER_SIZE, 0);
+ if (recvlen < 0)
{
return ERROR;
}
+ httpd_dumpbuffer(pstate, recvlen);
- if (strncmp(pstate->inputbuf, http_get, 4) != 0)
- {
- return ERROR;
- }
+ /* We will handle only GET */
- recvlen = recv(pstate->sockin, pstate->inputbuf, HTTPD_INBUFFER_SIZE, 0);
- if (recvlen < 0)
+ if (strncmp(pstate->ht_buffer, http_get, 4) != 0)
{
return ERROR;
}
- if (pstate->inputbuf[0] != ISO_slash)
- {
- return ERROR;
- }
+ /* Get the name of the file to provide */
- if (pstate->inputbuf[1] == ISO_space)
+ if (pstate->ht_buffer[4] != ISO_slash)
+ {
+ return ERROR;
+ }
+ else if (pstate->ht_buffer[5] == ISO_space)
{
strncpy(pstate->filename, http_index_html, sizeof(pstate->filename));
}
else
{
- pstate->inputbuf[recvlen - 1] = 0;
- strncpy(pstate->filename, &pstate->inputbuf[0], sizeof(pstate->filename));
+ for (i = 5; i < sizeof(pstate->filename) + 5 && pstate->ht_buffer[5] != ISO_space; i++)
+ {
+ pstate->filename[i] = pstate->ht_buffer[i+5];
+ }
}
- pstate->state = STATE_OUTPUT;
+ /* Then send the file */
+
+ httpd_sendfile(pstate);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: httpd_handler
+ *
+ * Description:
+ * Each time a new connection to port 80 is made, a new thread is created
+ * that begins at this entry point. There should be exactly one argument
+ * and it should be the socket descriptor (+1).
+ *
+ ****************************************************************************/
+
+static int httpd_handler(int argc, char *argv[])
+{
+ struct httpd_state *pstate = (struct httpd_state *)malloc(sizeof(struct httpd_state));
+ int sockfd = (int)argv[1] - 1;
+ int ret = ERROR;
+
+ /* Verify that the state structure was successfully allocated */
- while(1)
+ if (pstate)
{
- recvlen = recv(pstate->sockin, pstate->inputbuf, HTTPD_INBUFFER_SIZE, 0);
- if (recvlen < 0)
+ /* Loop processing each HTTP command */
+ do
{
- return ERROR;
- }
+ /* Re-initialize the thread state structure */
- if (strncmp(pstate->inputbuf, http_referer, 8) == 0)
- {
- pstate->inputbuf[recvlen - 2] = 0;
+ memset(pstate, 0, sizeof(struct httpd_state));
+ pstate->sockfd = sockfd;
+
+ /* Then handle the next httpd command */
+
+ ret = httpd_cmd(pstate);
}
- }
+ while (ret == OK);
- return OK;
-}
+ /* End of command processing -- Clean up and exit */
-static void handle_connection(struct httpd_state *pstate, struct uip_conn *conn)
-{
- handle_input(pstate);
- if (pstate->state == STATE_OUTPUT) {
- handle_output(pstate, conn);
+ free(pstate);
}
+
+ /* Exit the task */
+
+ return 0;
}
/****************************************************************************
@@ -288,20 +352,24 @@ static void handle_connection(struct httpd_state *pstate, struct uip_conn *conn)
int httpd_listen(void)
{
-#warning "this is all very broken at the moment"
- return OK;
+ /* Execute httpd_handler on each connection to port 80 */
+
+ uip_server(HTONS(80), httpd_handler, CONFIG_EXAMPLES_UIP_HTTPDSTACKSIZE);
+
+ /* uip_server only returns on errors */
+
+ return ERROR;
}
/****************************************************************************
* Name: httpd_init
*
* Description:
- * This function initializes the web server and should be called at system
- * boot-up.
+ * This function initializes the web server and should be called at system
+ * boot-up.
*
****************************************************************************/
void httpd_init(void)
{
- uip_listen(HTONS(80));
}
diff --git a/nuttx/netutils/webserver/httpd.h b/nuttx/netutils/webserver/httpd.h
index b256c1dd1..cf067f807 100644
--- a/nuttx/netutils/webserver/httpd.h
+++ b/nuttx/netutils/webserver/httpd.h
@@ -1,11 +1,19 @@
-/* httpd.h
+/****************************************************************************
+ * netutils/webserver/httpd.h
*
- * Copyright (c) 2001-2005, Adam Dunkels.
- * All rights reserved.
+ * Copyright (C) 2007 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Based on uIP which also has a BSD style license:
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ * Copyright (c) 2001-2005, Adam Dunkels.
+ * All rights reserved.
*
* 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
@@ -26,15 +34,33 @@
* 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.
- */
+ *
+ ****************************************************************************/
#ifndef _NETUTILS_WEBSERVER_HTTPD_H
#define _NETUTILS_WEBSERVER_HTTPD_H
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
#include <sys/types.h>
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
#define HTTPD_FS_STATISTICS 1
-#define HTTPD_INBUFFER_SIZE 50
+#define HTTPD_IOBUFFER_SIZE 512
+
+#ifndef CONFIG_EXAMPLES_UIP_HTTPDSTACKSIZE
+# define CONFIG_EXAMPLES_UIP_HTTPDSTACKSIZE 4096
+#endif
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
struct httpd_fs_file
{
@@ -44,13 +70,10 @@ struct httpd_fs_file
struct httpd_state
{
- unsigned char timer;
- int sockin;
- int sockout;
- char inputbuf[HTTPD_INBUFFER_SIZE];
+ char ht_buffer[HTTPD_IOBUFFER_SIZE];
char filename[20];
- char state;
struct httpd_fs_file file;
+ int sockfd; /* The socket descriptor from accept() */
int len;
char *scriptptr;
int scriptlen;
@@ -58,17 +81,19 @@ struct httpd_state
unsigned short count;
};
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
#ifdef HTTPD_FS_STATISTICS
#if HTTPD_FS_STATISTICS == 1
extern uint16 httpd_fs_count(char *name);
#endif /* HTTPD_FS_STATISTICS */
#endif /* HTTPD_FS_STATISTICS */
-/* 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);
+int httpd_fs_open(const char *name, struct httpd_fs_file *file);
void httpd_fs_init(void);
#endif /* _NETUTILS_WEBSERVER_HTTPD_H */