summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2009-03-26 01:31:43 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2009-03-26 01:31:43 +0000
commitefbea7b4e1f74be2777711afbe419c8883bcbb0e (patch)
tree5db3bc523f7252b814002e989f2b782bd0770cad
parentbbfe36496772f36bb56a620ac10e953fab99c11c (diff)
downloadnuttx-efbea7b4e1f74be2777711afbe419c8883bcbb0e.tar.gz
nuttx-efbea7b4e1f74be2777711afbe419c8883bcbb0e.tar.bz2
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.txt4
-rw-r--r--nuttx/examples/uip/main.c38
-rw-r--r--nuttx/include/net/uip/webclient.h147
-rw-r--r--nuttx/netutils/webclient/webclient.c535
-rw-r--r--nuttx/netutils/webclient/webclient.h205
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__ */