diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2007-11-19 18:17:23 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2007-11-19 18:17:23 +0000 |
commit | befc37ada0b901ad7c315e4089976508396d496b (patch) | |
tree | 44818265dc09577601c19bf81b3576109f31a534 /nuttx/netutils | |
parent | 6f5479c267e1ed09e85461464ae73b4cbfd3d486 (diff) | |
download | px4-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/Makefile | 6 | ||||
-rw-r--r-- | nuttx/netutils/uiplib/Make.defs | 2 | ||||
-rw-r--r-- | nuttx/netutils/uiplib/uip-gethostaddr.c | 2 | ||||
-rw-r--r-- | nuttx/netutils/uiplib/uip-getmacaddr.c | 2 | ||||
-rw-r--r-- | nuttx/netutils/uiplib/uip-server.c | 191 | ||||
-rw-r--r-- | nuttx/netutils/uiplib/uip-setdraddr.c | 2 | ||||
-rw-r--r-- | nuttx/netutils/uiplib/uip-sethostaddr.c | 2 | ||||
-rw-r--r-- | nuttx/netutils/uiplib/uip-setmacaddr.c | 2 | ||||
-rw-r--r-- | nuttx/netutils/uiplib/uip-setnetmask.c | 2 | ||||
-rw-r--r-- | nuttx/netutils/webserver/httpd-cgi.c | 2 | ||||
-rw-r--r-- | nuttx/netutils/webserver/httpd.c | 218 | ||||
-rw-r--r-- | nuttx/netutils/webserver/httpd.h | 53 |
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, ¶m) < 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 */ |