diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2009-03-26 01:31:43 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2009-03-26 01:31:43 +0000 |
commit | efbea7b4e1f74be2777711afbe419c8883bcbb0e (patch) | |
tree | 5db3bc523f7252b814002e989f2b782bd0770cad | |
parent | bbfe36496772f36bb56a620ac10e953fab99c11c (diff) | |
download | px4-nuttx-efbea7b4e1f74be2777711afbe419c8883bcbb0e.tar.gz px4-nuttx-efbea7b4e1f74be2777711afbe419c8883bcbb0e.tar.bz2 px4-nuttx-efbea7b4e1f74be2777711afbe419c8883bcbb0e.zip |
1st cut as BSD-izing uIP web client logic
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1642 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r-- | nuttx/examples/README.txt | 4 | ||||
-rw-r--r-- | nuttx/examples/uip/main.c | 38 | ||||
-rw-r--r-- | nuttx/include/net/uip/webclient.h | 147 | ||||
-rw-r--r-- | nuttx/netutils/webclient/webclient.c | 535 | ||||
-rw-r--r-- | nuttx/netutils/webclient/webclient.h | 205 |
5 files changed, 381 insertions, 548 deletions
diff --git a/nuttx/examples/README.txt b/nuttx/examples/README.txt index 83c072da4..2c83dcd4f 100644 --- a/nuttx/examples/README.txt +++ b/nuttx/examples/README.txt @@ -250,8 +250,8 @@ examples/uip ^^^^^^^^^^^^ This is a port of uIP example application. It includes conditionally - compiled logic to exercise the uIP webserver, webclient, telnet, smtp, - dncpc, and resolver. + compiled logic to exercise the uIP webserver, telnet, smtp, dhcpc, + and resolver. Other configuratin items apply also to the selected network utility. For example, the additional relevant settings for the uIP webserver diff --git a/nuttx/examples/uip/main.c b/nuttx/examples/uip/main.c index d5091ae51..2719f5bf7 100644 --- a/nuttx/examples/uip/main.c +++ b/nuttx/examples/uip/main.c @@ -75,9 +75,6 @@ # include <net/uip/telnetd.h> #elif defined(CONFIG_EXAMPLE_UIP_WEBSERVER) # include <net/uip/httpd.h> -#elif defined(CONFIG_EXAMPLE_UIP_WEBCLIENT) -# include <net/uip/resolv.h> -# include <net/uip/webclient.h> #elif !defined(CONFIG_EXAMPLE_UIP_DHCPC) # error "No network application specified" #endif @@ -174,7 +171,7 @@ int user_start(int argc, char *argv[]) addr.s_addr = HTONL(CONFIG_EXAMPLE_UIP_NETMASK); uip_setnetmask("eth0", &addr); -#if defined(CONFIG_EXAMPLE_UIP_DHCPC) || defined(CONFIG_EXAMPLE_UIP_WEBCLIENT) +#if defined(CONFIG_EXAMPLE_UIP_DHCPC) /* Set up the resolver */ resolv_init(); @@ -231,12 +228,6 @@ int user_start(int argc, char *argv[]) g_msg_body, strlen(g_msg_body)); smtp_close(handle); } -#elif defined(CONFIG_EXAMPLE_UIP_WEBCLIENT) - printf("Getting webpage\n"); - webclient_init(); - addr.s_addr = HTONL(CONFIG_EXAMPLE_UIP_DNSADDR); - resolv_conf(&addr); - resolv_query(CONFIG_EXAMPLE_UIP_SERVERURL); #endif while(1) @@ -249,30 +240,3 @@ int user_start(int argc, char *argv[]) } return 0; } - -#if defined(CONFIG_EXAMPLE_UIP_WEBCLIENT) -void webclient_closed(void) -{ - printf("Webclient: connection closed\n"); -} - -void webclient_aborted(void) -{ - printf("Webclient: connection aborted\n"); -} - -void webclient_timedout(void) -{ - printf("Webclient: connection timed out\n"); -} - -void webclient_connected(void) -{ - printf("Webclient: connected, waiting for data...\n"); -} - -void webclient_datahandler(char *data, uint16 len) -{ - printf("Webclient: got %d bytes of data.\n", len); -} -#endif diff --git a/nuttx/include/net/uip/webclient.h b/nuttx/include/net/uip/webclient.h new file mode 100644 index 000000000..554ec3adf --- /dev/null +++ b/nuttx/include/net/uip/webclient.h @@ -0,0 +1,147 @@ +/**************************************************************************** + * include/net/uip/webclient.h + * Header file for the HTTP client + * + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * Based remotely on the uIP webclient which also has a BSD style license: + * + * Author: Adam Dunkels <adam@dunkels.com> + * Copyright (c) 2002, 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 notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + ****************************************************************************/ + +#ifndef __NET_UIP_WEBCLIENT_H +#define __NET_UIP_WEBCLIENT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> +#include <sys/types.h> + +/**************************************************************************** + * Pre-processor definitions + ****************************************************************************/ + +#ifndef CONFIG_NETUTILS_WEBCLIENT_MAXURLLEN +# define CONFIG_NETUTILS_WEBCLIENT_MAXURLLEN 100 +#endif + +#ifndef CONFIG_NETUTILS_WEBCLIENT_MAXHTTPLINE +# define CONFIG_NETUTILS_WEBCLIENT_MAXHTTPLINE 200 +#endif + +#ifndef CONFIG_NETUTILS_WEBCLIENT_MAXMIMESIZE +# define CONFIG_NETUTILS_WEBCLIENT_MAXMIMESIZE 32 +#endif + +#ifndef CONFIG_NETUTILS_WEBCLIENT_MAXHOSTNAME +# define CONFIG_NETUTILS_WEBCLIENT_MAXHOSTNAME 40 +#endif + +/**************************************************************************** + * Public types + ****************************************************************************/ + +/* wget calls a user provided function of the follwoing type to process + * each received chuck of the incoming file data. If the system has a file + * system, then it may just write the data to a file. Or it may buffer the + * file in memory. To facilitate this latter case, the caller may modify + * the buffer address in this callback by writing to buffer and buflen. This + * may be used, for example, to implement double buffering. + * + * Input Parameters: + * buffer - A pointer to a pointer to a buffer. If the callee wishes to + * change the buffer address, it may do so in the callback by writing + * to buffer. + * offset - Offset to the beginning of valid data in the buffer. Offset + * is used to skip over any HTTP header info that may be at the + * beginning of the buffer. + * datend - The end+1 offset of valid data in the buffer. The total number + * of valid bytes is datend - offset. + * buflen - A pointer to the length of the buffer. If the callee wishes + * to change the size of the buffer, it may write to buflen. + */ + +typedef void (*wget_callback_t)(FAR char **buffer, int offset, + int datend, FAR int *buflen); + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: wget + * + * Description: + * Obtain the requested file from an HTTP server using the GET method. + * + * Note: If the function is passed a host name, it must already be in + * the resolver cache in order for the function to connect to the web + * server. It is therefore up to the calling module to implement the + * resolver calls and the signal handler used for reporting a resolv + * query answer. + * + * Input Parameters + * host - A pointer to a string containing either a host name or + * a numerical IP address in dotted decimal notation (e.g., 192.168.23.1). + * port - The port number to which to connect, in host byte order. + * file - A pointer to the name of the file to get. + * buffer - A user provided buffer to receive the file data (also + * used for the outgoing GET request + * buflen - The size of the user provided buffer + * callback - As data is obtained from the host, this function is + * to dispose of each block of file data as it is received. + * + * Returned Value: + * 0: if the GET operation completed successfully; + * -1: On a failure with errno set appropriately + * + ****************************************************************************/ + +EXTERN int wget(FAR const char *host, uint16 port, FAR const char *file, + FAR char *buffer, int buflen, wget_callback_t callback); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __NET_UIP_WEBCLIENT_H */ diff --git a/nuttx/netutils/webclient/webclient.c b/nuttx/netutils/webclient/webclient.c index 3703aed9b..d00fd29b7 100644 --- a/nuttx/netutils/webclient/webclient.c +++ b/nuttx/netutils/webclient/webclient.c @@ -2,7 +2,7 @@ * netutils/webclient/webclient.c * Implementation of the HTTP client. * - * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> * * Based on uIP which also has a BSD style license: @@ -41,27 +41,29 @@ /* This example shows a HTTP client that is able to download web pages * and files from web servers. It requires a number of callback * functions to be implemented by the module that utilizes the code: - * webclient_datahandler(), webclient_connected(), - * webclient_timedout(), webclient_aborted(), webclient_closed(). + * webclient_datahandler(). */ /**************************************************************************** * Included Files ****************************************************************************/ +#include <nuttx/config.h> +#include <nuttx/compiler.h> + #include <sys/types.h> -#include <string.h> #include <sys/socket.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <debug.h> -#include <nuttx/compiler.h> +#include <netinet/in.h> #include <net/uip/uip.h> -#include <net/uip/resolv.h> - -#include <net/uip/uip-arch.h> #include <net/uip/uip-lib.h> - -#include "webclient.h" +#include <net/uip/resolv.h> +#include <net/uip/webclient.h> /**************************************************************************** * Definitions @@ -79,26 +81,58 @@ #define HTTPFLAG_MOVED 2 #define HTTPFLAG_ERROR 3 - #define ISO_nl 0x0a #define ISO_cr 0x0d #define ISO_space 0x20 /**************************************************************************** - * Private Data + * Private Types ****************************************************************************/ -static uint8 g_return; /* Kludge for now */ -static struct webclient_state s; +struct wget_s +{ + ubyte state; + ubyte httpflag; + + /* These describe the just-received buffer of data */ + + FAR char *buffer; /* user-provided buffer */ + int buflen; /* Length of the user provided buffer */ + int offset; /* Offset to the beginning of interesting data */ + int datend; /* Offset+1 to the last valid byte of data in the buffer */ + + /* Buffer HTTP header data and parse line at a time */ + + char line[CONFIG_NETUTILS_WEBCLIENT_MAXHTTPLINE]; + int ndx; + +#ifdef CONFIG_WEBCLIENT_GETMIMETYPE + char mimetype[CONFIG_NETUTILS_WEBCLIENT_MAXMIMESIZE]; +#endif +#ifdef CONFIG_WEBCLIENT_GETHOST + char host[CONFIG_NETUTILS_WEBCLIENT_MAXHOSTNAME]; +#endif +}; + + +/**************************************************************************** + * Private Data + ****************************************************************************/ static const char g_http10[] = "HTTP/1.0"; static const char g_http11[] = "HTTP/1.1"; +#ifdef CONFIG_WEBCLIENT_GETMIMETYPE static const char g_httpcontenttype[] = "content-type: "; +#endif static const char g_httphost[] = "host: "; +#ifdef CONFIG_WEBCLIENT_GETHOST static const char g_httplocation[] = "location: "; +#endif static const char g_httpget[] = "GET "; +#ifdef CONFIG_WEBCLIENT_GETHOST static const char g_httphttp[] = "http://"; +#endif static const char g_httpuseragentfields[] = "Connection: close\r\n" @@ -114,332 +148,177 @@ static const char g_httpcrnl[] = "\r\n"; * Private Functions ****************************************************************************/ -static void init_connection(void) -{ - s.state = WEBCLIENT_STATE_STATUSLINE; - - s.getrequestleft = strlen(g_httpget) - 1 + 1 + - strlen(g_http10) - 1 + - strlen(g_httpcrnl) - 1 + - strlen(g_httphost) - 1 + - strlen(g_httpcrnl) - 1 + - strlen(g_httpuseragentfields) + - strlen(s.file) + strlen(s.host); - s.getrequestptr = 0; - - s.httpheaderlineptr = 0; -} +/**************************************************************************** + * Private Functions + ****************************************************************************/ -static char *copy_string(char *dest, const char *src, int len) +/**************************************************************************** + * Name: wget_strcpy + ****************************************************************************/ + +static char *wget_strcpy(char *dest, const char *src) { - strncpy(dest, src, len); + int len = strlen(src); + memcpy(dest, src, len); return dest + len; } -static void senddata(struct uip_driver_s *dev, struct uip_conn *conn) -{ - uint16 len; - char *getrequest; - char *cptr; - - if (s.getrequestleft > 0) { - cptr = getrequest = (char *)dev->d_appdata; - - cptr = copy_string(cptr, g_httpget, strlen(g_httpget) - 1); - cptr = copy_string(cptr, s.file, strlen(s.file)); - *cptr++ = ISO_space; - cptr = copy_string(cptr, g_http10, strlen(g_http10) - 1); - - cptr = copy_string(cptr, g_httpcrnl, strlen(g_httpcrnl) - 1); - - cptr = copy_string(cptr, g_httphost, strlen(g_httphost) - 1); - cptr = copy_string(cptr, s.host, strlen(s.host)); - cptr = copy_string(cptr, g_httpcrnl, strlen(g_httpcrnl) - 1); - - cptr = copy_string(cptr, g_httpuseragentfields, - strlen(g_httpuseragentfields)); - - len = s.getrequestleft > uip_mss(conn)? - uip_mss(conn): - s.getrequestleft; - uip_send(dev, &(getrequest[s.getrequestptr]), len); - } -} +/**************************************************************************** + * Name: wget_parsestatus + ****************************************************************************/ -static void acked(struct uip_conn *conn) +static inline int wget_parsestatus(struct wget_s *ws) { - uint16 len; - - if (s.getrequestleft > 0) { - len = s.getrequestleft > uip_mss(conn)? - uip_mss(conn): - s.getrequestleft; - s.getrequestleft -= len; - s.getrequestptr += len; - } -} + int offset; + int ndx; + char *dest; -static uint16 parse_statusline(struct uip_driver_s *dev, uint16 len) -{ - char *cptr; + offset = ws->offset; + ndx = ws->ndx; - while(len > 0 && s.httpheaderlineptr < sizeof(s.httpheaderline)) + while (offset < ws->datend) { - char *pappdata = (char*)dev->d_appdata; - s.httpheaderline[s.httpheaderlineptr] = *pappdata++; - dev->d_appdata = (void*)pappdata; - len--; - - if (s.httpheaderline[s.httpheaderlineptr] == ISO_nl) + ws->line[ndx] = ws->buffer[offset]; + if (ws->line[ndx] == ISO_nl) { - if ((strncmp(s.httpheaderline, g_http10, strlen(g_http10) - 1) == 0) || - (strncmp(s.httpheaderline, g_http11, strlen(g_http11) - 1) == 0)) + ws->line[ndx] = '\0'; + if ((strncmp(ws->line, g_http10, strlen(g_http10)) == 0) || + (strncmp(ws->line, g_http11, strlen(g_http11)) == 0)) { - cptr = &(s.httpheaderline[9]); - s.httpflag = HTTPFLAG_NONE; - if (strncmp(cptr, g_http200, strlen(g_http200) - 1) == 0) + dest = &(ws->line[9]); + ws->httpflag = HTTPFLAG_NONE; + + /* Check for 200 OK */ + + if (strncmp(dest, g_http200, strlen(g_http200)) == 0) { - /* 200 OK */ - s.httpflag = HTTPFLAG_OK; + ws->httpflag = HTTPFLAG_OK; } - else if (strncmp(cptr, g_http301, strlen(g_http301) - 1) == 0 || - strncmp(cptr, g_http302, strlen(g_http302) - 1) == 0) - { - /* 301 Moved permanently or 302 Found. Location: header line - * will contain thw new location. - */ - s.httpflag = HTTPFLAG_MOVED; - } - else + /* Check for 301 Moved permanently or 302 Found. Location: header line + * will contain the new location. + */ + + else if (strncmp(dest, g_http301, strlen(g_http301)) == 0 || + strncmp(dest, g_http302, strlen(g_http302)) == 0) { - s.httpheaderline[s.httpheaderlineptr - 1] = 0; + + ws->httpflag = HTTPFLAG_MOVED; } } else { - g_return |= UIP_ABORT; - webclient_aborted(); - return 0; + return - ECONNABORTED; } - /* We're done parsing the status line, so we reset the pointer - * and start parsing the HTTP headers. - */ + /* We're done parsing the status line, so start parsing the HTTP headers. */ - s.httpheaderlineptr = 0; - s.state = WEBCLIENT_STATE_HEADERS; + ws->state = WEBCLIENT_STATE_HEADERS; break; } else { - ++s.httpheaderlineptr; + offset++; + ndx++; } } - return len; -} - -static char casecmp(char *str1, const char *str2, char len) -{ - static char c; - while(len > 0) { - c = *str1; - /* Force lower-case characters. */ - if (c & 0x40) { - c |= 0x20; - } - if (*str2 != c) { - return 1; - } - ++str1; - ++str2; - --len; - } - return 0; + ws->offset = offset; + ws->ndx = ndx; + return OK; } -static uint16 parse_headers(struct uip_driver_s *dev, uint16 len) +/**************************************************************************** + * Name: wget_parsestatus + ****************************************************************************/ + +static inline int wget_parseheaders(struct wget_s *ws) { - char *cptr; - static unsigned char i; + int offset; + int ndx; + char *dest; - while(len > 0 && s.httpheaderlineptr < sizeof(s.httpheaderline)) - { - char *pappdata = (char*)dev->d_appdata; - s.httpheaderline[s.httpheaderlineptr] = *pappdata++; - dev->d_appdata = (void*)pappdata; - len--; + offset = ws->offset; + ndx = ws->ndx; - if (s.httpheaderline[s.httpheaderlineptr] == ISO_nl) + while (offset < ws->datend) + { + ws->line[ndx] = ws->buffer[offset]; + if (ws->line[ndx] == ISO_nl) { - /* We have an entire HTTP header line in s.httpheaderline, so + /* We have an entire HTTP header line in s.line, so * we parse it. */ - if (s.httpheaderline[0] == ISO_cr) + if (ws->line[0] == ISO_cr) { /* This was the last header line (i.e., and empty "\r\n"), so * we are done with the headers and proceed with the actual * data. */ - s.state = WEBCLIENT_STATE_DATA; - return len; + ws->state = WEBCLIENT_STATE_DATA; + return OK; } - s.httpheaderline[s.httpheaderlineptr - 1] = 0; + ws->line[ndx] = '\0'; /* Check for specific HTTP header fields. */ - if (casecmp(s.httpheaderline, g_httpcontenttype, strlen(g_httpcontenttype) - 1) == 0) + +#ifdef CONFIG_WEBCLIENT_GETMIMETYPE + if (strncasecmp(ws->line, g_httpcontenttype, strlen(g_httpcontenttype)) == 0) { /* Found Content-type field. */ - cptr = strchr(s.httpheaderline, ';'); - if (cptr != NULL) + dest = strchr(ws->line, ';'); + if (dest != NULL) { - *cptr = 0; + *dest = 0; } - strncpy(s.mimetype, s.httpheaderline + strlen(g_httpcontenttype) - 1, sizeof(s.mimetype)); + strncpy(ws->mimetype, ws->line + strlen(g_httpcontenttype) - 1, sizeof(ws->mimetype)); } - else if (casecmp(s.httpheaderline, g_httplocation, strlen(g_httplocation) - 1) == 0) +# ifdef CONFIG_WEBCLIENT_GETHOST + else +# endif +#endif +#ifdef CONFIG_WEBCLIENT_GETHOST + if (strncasecmp(ws->line, g_httplocation, strlen(g_httplocation)) == 0) { - cptr = s.httpheaderline + strlen(g_httplocation) - 1; + dest = ws->line + strlen(g_httplocation) - 1; - if (strncmp(cptr, g_httphttp, strlen(g_httphttp)) == 0) + if (strncmp(dest, g_httphttp, strlen(g_httphttp)) == 0) { - cptr += 7; - for(i = 0; i < s.httpheaderlineptr - 7; ++i) + dest += 7; + for(i = 0; i < ws->ndx - 7; ++i) { - if (*cptr == 0 || *cptr == '/' || *cptr == ' ' || *cptr == ':') + if (*dest == 0 || *dest == '/' || *dest == ' ' || *dest == ':') { - s.host[i] = 0; + ws->host[i] = 0; break; } - s.host[i] = *cptr; - ++cptr; + ws->host[i] = *dest; + ++dest; } } - strncpy(s.file, cptr, sizeof(s.file)); + strncpy(ws->file, dest, sizeof(ws->file)); } +#endif /* We're done parsing, so we reset the pointer and start the * next line. */ - s.httpheaderlineptr = 0; + ndx = 0; } else { - ++s.httpheaderlineptr; + ndx++; + offset++; } } - return len; -} - -static void newdata(struct uip_driver_s *dev) -{ - uint16 len; - - len = dev->d_len; - - if (s.state == WEBCLIENT_STATE_STATUSLINE) { - len = parse_statusline(dev, len); - } - - if (s.state == WEBCLIENT_STATE_HEADERS && len > 0) { - len = parse_headers(dev, len); - } - if (len > 0 && s.state == WEBCLIENT_STATE_DATA && - s.httpflag != HTTPFLAG_MOVED) { - webclient_datahandler((char *)dev->d_appdata, len); - } -} - -/* This function is called by the UIP interrupt handling logic whenevent an - * event of interest occurs. - */ - -uint8 uip_interrupt_event(struct uip_driver_s *dev, struct uip_conn *conn, uint8 flags) -{ -#ifdef CONFIG_CPP_HAVE_WARNING -# warning OBSOLETE -- needs to be redesigned -#endif - g_return = flags; - - if ((flags & UIP_CONNECTED) != 0) - { - s.timer = 0; - s.state = WEBCLIENT_STATE_STATUSLINE; - senddata(dev, conn); - webclient_connected(); - return g_return; - } - - if (s.state == WEBCLIENT_STATE_CLOSE) - { - webclient_closed(); - return UIP_ABORT; - } - - if ((flags & UIP_ABORT) != 0) - { - webclient_aborted(); - } - - if ((flags & UIP_TIMEDOUT) != 0) - { - webclient_timedout(); - } - - if ((flags & UIP_ACKDATA) != 0) - { - s.timer = 0; - acked(conn); - } - - if ((flags & UIP_NEWDATA) != 0) - { - s.timer = 0; - newdata(dev); - } - - if ((flags & UIP_REXMIT) != 0 || (flags & UIP_NEWDATA) != 0 || (flags & UIP_ACKDATA) != 0) - { - senddata(dev, conn); - } - else if ((flags & UIP_POLL) != 0) - { - ++s.timer; - if (s.timer == WEBCLIENT_TIMEOUT) - { - webclient_timedout(); - return UIP_ABORT; - } - } - - if ((flags & UIP_CLOSE) != 0) - { - if (s.httpflag != HTTPFLAG_MOVED) - { - /* Send NULL data to signal EOF. */ - webclient_datahandler(NULL, 0); - } - else - { -#ifdef CONFIG_NET_IPv6 - struct sockaddr_in6 addr; -#else - struct sockaddr_in addr; -#endif - if (resolv_query(s.host, &addr) < 0) - { - return g_return; - } - webclient_get(s.host, s.port, s.file); - } - } - return g_return; + ws->offset = offset; + ws->ndx = ndx; + return OK; } /**************************************************************************** @@ -447,22 +326,19 @@ uint8 uip_interrupt_event(struct uip_driver_s *dev, struct uip_conn *conn, uint8 ****************************************************************************/ /**************************************************************************** - * Name: webclient_init + * Name: wget ****************************************************************************/ -void webclient_init(void) -{ -} - -/**************************************************************************** - * Name: webclient_get - ****************************************************************************/ - -unsigned char webclient_get(FAR const char *host, uint16 port, FAR char *file) +int wget(FAR const char *host, uint16 port, FAR const char *file, + FAR char *buffer, int buflen, wget_callback_t callback) { static uip_ipaddr_t addr; struct sockaddr_in server; + struct wget_s ws; + char *dest; int sockfd; + int len; + int ret = OK; /* First check if the host is an IP address. */ @@ -487,6 +363,9 @@ unsigned char webclient_get(FAR const char *host, uint16 port, FAR char *file) sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { + /* socket failed. It will set the errno appropriately */ + + ndbg("socket failed: %d\n", errno); return ERROR; } @@ -497,43 +376,91 @@ unsigned char webclient_get(FAR const char *host, uint16 port, FAR char *file) server.sin_family = AF_INET; memcpy(&server.sin_addr.s_addr, &host, sizeof(in_addr_t)); - server.sin_port = htons(port); + server.sin_port = htons(port); - if (connect(sockfd, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) < 0) + ret = connect(sockfd, (struct sockaddr *)&server, sizeof(struct sockaddr_in)); + if (ret < 0) { - return ERROR; + ndbg("connect failed: %d\n", errno); + goto errout; } - s.port = port; - strncpy(s.file, file, sizeof(s.file)); - strncpy(s.host, host, sizeof(s.host)); + /* Send the GET request */ + + dest = (char *)buffer; + dest = wget_strcpy(dest, g_httpget); + dest = wget_strcpy(dest, file); + *dest++ = ISO_space; + dest = wget_strcpy(dest, g_http10); + dest = wget_strcpy(dest, g_httpcrnl); + dest = wget_strcpy(dest, g_httphost); + dest = wget_strcpy(dest, host); + dest = wget_strcpy(dest, g_httpcrnl); + dest = wget_strcpy(dest, g_httpuseragentfields); + len = dest - buffer; + + ret = send(sockfd, buffer, len, 0); + if (ret < 0) + { + ndbg("send failed: %d\n", errno); + goto errout; + } - init_connection(); - return OK; -} + /* Now get the response */ -void webclient_close(void) -{ - s.state = WEBCLIENT_STATE_CLOSE; -} + memset(&ws, 0, sizeof(struct wget_s)); + ws.state = WEBCLIENT_STATE_STATUSLINE; + ws.buffer = buffer; + ws.buflen = buflen; + + for (;;) + { + ws.datend = recv(sockfd, ws.buffer, ws.buflen, 0); + if (ws.datend < 0) + { + ndbg("recv failed: %d\n", errno); + ret = ws.datend; + goto errout; + } + else if (ret == 0) + { + break; + } + + ws.offset = 0; + if (ws.state == WEBCLIENT_STATE_STATUSLINE) + { + ret = wget_parsestatus(&ws); + if (ret < 0) + { + goto errout_with_errno; + } + } -char *webclient_mimetype(void) -{ - return s.mimetype; -} + if (ws.state == WEBCLIENT_STATE_HEADERS) + { + ret = wget_parseheaders(&ws); + if (ret < 0) + { + goto errout_with_errno; + } + } -char *webclient_filename(void) -{ - return s.file; -} + /* Let the client decide what to do with the received file */ -char *webclient_hostname(void) -{ - return s.host; -} + if (ws.state == WEBCLIENT_STATE_DATA && ws.httpflag != HTTPFLAG_MOVED) + { + callback(&ws.buffer, ws.offset, ws.datend, &buflen); + } + } -unsigned shortwebclient_port(void) -{ - return s.port; -} +okout: + close(sockfd); + return OK; +errout_with_errno: + errno = -ret; +errout: + close(sockfd); + return ERROR; +} diff --git a/nuttx/netutils/webclient/webclient.h b/nuttx/netutils/webclient/webclient.h deleted file mode 100644 index 80a571377..000000000 --- a/nuttx/netutils/webclient/webclient.h +++ /dev/null @@ -1,205 +0,0 @@ -/** - * webclient.h - * Header file for the HTTP client. - * Author: Adam Dunkels <adam@dunkels.com> - * - * Copyright (c) 2002, 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 notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - */ - -#ifndef __WEBCLIENT_H__ -#define __WEBCLIENT_H__ - -#include <sys/types.h> -#include <net/uip/uipopt.h> - -#define WEBCLIENT_CONF_MAX_URLLEN 100 - -struct webclient_state -{ - uint8 timer; - uint8 state; - uint8 httpflag; - - uint16 port; - char host[40]; - char file[WEBCLIENT_CONF_MAX_URLLEN]; - uint16 getrequestptr; - uint16 getrequestleft; - - char httpheaderline[200]; - uint16 httpheaderlineptr; - - char mimetype[32]; -}; - -/* Callback function that is called from the webclient code when HTTP - * data has been received. - * - * This function must be implemented by the module that uses the - * webclient code. The function is called from the webclient module - * when HTTP data has been received. The function is not called when - * HTTP headers are received, only for the actual data. - * - * Note: This function is called many times, repetedly, when data is - * being received, and not once when all data has been received. - * - * data A pointer to the data that has been received. - * len The length of the data that has been received. - */ - -void webclient_datahandler(char *data, uint16 len); - -/* Callback function that is called from the webclient code when the - * HTTP connection has been connected to the web server. - * - * This function must be implemented by the module that uses the - * webclient code. - */ - -void webclient_connected(void); - -/* Callback function that is called from the webclient code if the - * HTTP connection to the web server has timed out. - * - * This function must be implemented by the module that uses the - * webclient code. - */ - -void webclient_timedout(void); - -/* Callback function that is called from the webclient code if the - * HTTP connection to the web server has been aborted by the web - * server. - * - * This function must be implemented by the module that uses the - * webclient code. - */ - -void webclient_aborted(void); - -/* Callback function that is called from the webclient code when the - * HTTP connection to the web server has been closed. - * - * This function must be implemented by the module that uses the - * webclient code. - */ - -void webclient_closed(void); - -/* Initialize the webclient module. */ - -void webclient_init(void); - -/* Open an HTTP connection to a web server and ask for a file using - * the GET method. - * - * This function opens an HTTP connection to the specified web server - * and requests the specified file using the GET method. When the HTTP - * connection has been connected, the webclient_connected() callback - * function is called and when the HTTP data arrives the - * webclient_datahandler() callback function is called. - * - * The callback function webclient_timedout() is called if the web - * server could not be contacted, and the webclient_aborted() callback - * function is called if the HTTP connection is aborted by the web - * server. - * - * When the HTTP request has been completed and the HTTP connection is - * closed, the webclient_closed() callback function will be called. - * - * Note: If the function is passed a host name, it must already be in - * the resolver cache in order for the function to connect to the web - * server. It is therefore up to the calling module to implement the - * resolver calls and the signal handler used for reporting a resolv - * query answer. - * - * host A pointer to a string containing either a host name or - * a numerical IP address in dotted decimal notation (e.g., 192.168.23.1). - * - * port The port number to which to connect, in host byte order. - * - * file A pointer to the name of the file to get. - * - * Return: 0 if the host name could not be found in the cache, or - * if a TCP connection could not be created. - * - * Return: 1 if the connection was initiated. - */ - -unsigned char webclient_get(const char *host, uint16 port, char *file); - -/* Close the currently open HTTP connection. */ - -void webclient_close(void); - -/* Obtain the MIME type of the current HTTP data stream. - * - * Return: A pointer to a string contaning the MIME type. The string - * may be empty if no MIME type was reported by the web server. - */ - -char *webclient_mimetype(void); - -/* Obtain the filename of the current HTTP data stream. - * - * The filename of an HTTP request may be changed by the web server, - * and may therefore not be the same as when the original GET request - * was made with webclient_get(). This function is used for obtaining - * the current filename. - * - * Return: A pointer to the current filename. - */ - -char *webclient_filename(void); - -/* Obtain the hostname of the current HTTP data stream. - * - * The hostname of the web server of an HTTP request may be changed - * by the web server, and may therefore not be the same as when the - * original GET request was made with webclient_get(). This function - * is used for obtaining the current hostname. - * - * Return: A pointer to the current hostname. - */ - -char *webclient_hostname(void); - -/* Obtain the port number of the current HTTP data stream. - * - * The port number of an HTTP request may be changed by the web - * server, and may therefore not be the same as when the original GET - * request was made with webclient_get(). This function is used for - * obtaining the current port number. - * - * Return: The port number of the current HTTP data stream, in host byte order. - */ - -unsigned short webclient_port(void); - -#endif /* __WEBCLIENT_H__ */ |