diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-03-19 21:04:13 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-03-19 21:04:13 +0000 |
commit | 7cc856ea2f1808e98387ea66537ecbc6c3de2f88 (patch) | |
tree | 673b6eef191373f0607e5b9a9f79ad390e9bb970 /nuttx/netutils/webclient/webclient.c | |
parent | 7267882ebd0a6aa79cf88b7f42675804eaff1bcf (diff) | |
download | px4-nuttx-7cc856ea2f1808e98387ea66537ecbc6c3de2f88.tar.gz px4-nuttx-7cc856ea2f1808e98387ea66537ecbc6c3de2f88.tar.bz2 px4-nuttx-7cc856ea2f1808e98387ea66537ecbc6c3de2f88.zip |
Move nuttx/netutils to apps/netutils
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3401 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/netutils/webclient/webclient.c')
-rw-r--r-- | nuttx/netutils/webclient/webclient.c | 583 |
1 files changed, 0 insertions, 583 deletions
diff --git a/nuttx/netutils/webclient/webclient.c b/nuttx/netutils/webclient/webclient.c deleted file mode 100644 index 2c5108a4a..000000000 --- a/nuttx/netutils/webclient/webclient.c +++ /dev/null @@ -1,583 +0,0 @@ -/**************************************************************************** - * netutils/webclient/webclient.c - * Implementation of the HTTP client. - * - * Copyright (C) 2007, 2009, 2011 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@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. - * - ****************************************************************************/ - -/* 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(). - */ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#ifndef CONFIG_WEBCLIENT_HOST -# include <nuttx/config.h> -# include <nuttx/compiler.h> -# include <debug.h> -#endif - -#include <sys/socket.h> -#include <stdint.h> -#include <stdbool.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> - -#ifdef CONFIG_HAVE_GETHOSTBYNAME -# include <netdb.h> -#else -# include <apps/netutils/resolv.h> -#endif - -#include <arpa/inet.h> -#include <netinet/in.h> -#include <apps/netutils/uiplib.h> -#include <apps/netutils/webclient.h> - -/**************************************************************************** - * Definitions - ****************************************************************************/ - -#define WEBCLIENT_TIMEOUT 100 - -#define WEBCLIENT_STATE_STATUSLINE 0 -#define WEBCLIENT_STATE_HEADERS 1 -#define WEBCLIENT_STATE_DATA 2 -#define WEBCLIENT_STATE_CLOSE 3 - -#define HTTPSTATUS_NONE 0 -#define HTTPSTATUS_OK 1 -#define HTTPSTATUS_MOVED 2 -#define HTTPSTATUS_ERROR 3 - -#define ISO_nl 0x0a -#define ISO_cr 0x0d -#define ISO_space 0x20 - -/**************************************************************************** - * Private Types - ****************************************************************************/ - -struct wget_s -{ - /* Internal status */ - - uint8_t state; - uint8_t httpstatus; - - uint16_t port; /* The port number to use in the connection */ - - /* 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_WEBCLIENT_MAXHTTPLINE]; - int ndx; - -#ifdef CONFIG_WEBCLIENT_GETMIMETYPE - char mimetype[CONFIG_WEBCLIENT_MAXMIMESIZE]; -#endif - char hostname[CONFIG_WEBCLIENT_MAXHOSTNAME]; - char filename[CONFIG_WEBCLIENT_MAXFILENAME]; -}; - -/**************************************************************************** - * 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: "; -static const char g_httplocation[] = "location: "; -static const char g_httpget[] = "GET "; - -static const char g_httpuseragentfields[] = - "Connection: close\r\n" - "User-Agent: NuttX/0.4.x (; http://www.nuttx.org/)\r\n\r\n"; - -static const char g_http200[] = "200 "; -static const char g_http301[] = "301 "; -static const char g_http302[] = "302 "; - -static const char g_httpcrnl[] = "\r\n"; - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: wget_strcpy - ****************************************************************************/ - -static char *wget_strcpy(char *dest, const char *src) -{ - int len = strlen(src); - memcpy(dest, src, len); - dest[len] = '\0'; - return dest + len; -} - -/**************************************************************************** - * Name: wget_resolvehost - ****************************************************************************/ - -static inline int wget_resolvehost(const char *hostname, in_addr_t *ipaddr) -{ -#ifdef CONFIG_HAVE_GETHOSTBYNAME - - struct hostent *he; - - nvdbg("Getting address of %s\n", hostname); - he = gethostbyname(hostname); - if (!he) - { - ndbg("gethostbyname failed: %d\n", h_errno); - return ERROR; - } - - nvdbg("Using IP address %04x%04x\n", (uint16_t)he->h_addr[1], (uint16_t)he->h_addr[0]); - memcpy(ipaddr, he->h_addr, sizeof(in_addr_t)); - return OK; - -#else - -# ifdef CONFIG_NET_IPv6 - struct sockaddr_in6 addr; -# else - struct sockaddr_in addr; -# endif - - /* First check if the host is an IP address. */ - - if (!uiplib_ipaddrconv(hostname, (uint8_t*)ipaddr)) - { - /* 'host' does not point to a valid address string. Try to resolve - * the host name to an IP address. - */ - - if (resolv_query(hostname, &addr) < 0) - { - /* Needs to set the errno here */ - - return ERROR; - } - - /* Save the host address -- Needs fixed for IPv6 */ - - *ipaddr = addr.sin_addr.s_addr; - } - return OK; - -#endif -} - -/**************************************************************************** - * Name: wget_parsestatus - ****************************************************************************/ - -static inline int wget_parsestatus(struct wget_s *ws) -{ - int offset; - int ndx; - char *dest; - - offset = ws->offset; - ndx = ws->ndx; - - while (offset < ws->datend) - { - ws->line[ndx] = ws->buffer[offset]; - if (ws->line[ndx] == ISO_nl) - { - ws->line[ndx] = '\0'; - if ((strncmp(ws->line, g_http10, strlen(g_http10)) == 0) || - (strncmp(ws->line, g_http11, strlen(g_http11)) == 0)) - { - dest = &(ws->line[9]); - ws->httpstatus = HTTPSTATUS_NONE; - - /* Check for 200 OK */ - - if (strncmp(dest, g_http200, strlen(g_http200)) == 0) - { - ws->httpstatus = HTTPSTATUS_OK; - } - - /* 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) - { - - ws->httpstatus = HTTPSTATUS_MOVED; - } - } - else - { - return - ECONNABORTED; - } - - /* We're done parsing the status line, so start parsing the HTTP headers. */ - - ws->state = WEBCLIENT_STATE_HEADERS; - break; - } - else - { - offset++; - ndx++; - } - } - - ws->offset = offset; - ws->ndx = ndx; - return OK; -} - -/**************************************************************************** - * Name: wget_parsestatus - ****************************************************************************/ - -static inline int wget_parseheaders(struct wget_s *ws) -{ - int offset; - int ndx; - - offset = ws->offset; - ndx = ws->ndx; - - 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.line, so - * we parse it. - */ - - if (ndx > 0) /* Should always be true */ - { - 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. - */ - - ws->state = WEBCLIENT_STATE_DATA; - goto exit; - } - - /* Truncate the trailing \r\n */ - - ws->line[ndx-1] = '\0'; - - /* Check for specific HTTP header fields. */ - -#ifdef CONFIG_WEBCLIENT_GETMIMETYPE - if (strncasecmp(ws->line, g_httpcontenttype, strlen(g_httpcontenttype)) == 0) - { - /* Found Content-type field. */ - - char *dest = strchr(ws->line, ';'); - if (dest != NULL) - { - *dest = 0; - } - strncpy(ws->mimetype, ws->line + strlen(g_httpcontenttype), sizeof(ws->mimetype)); - } - else -#endif - if (strncasecmp(ws->line, g_httplocation, strlen(g_httplocation)) == 0) - { - /* Parse the new HTTP host and filename from the URL. Note that - * the return value is ignored. In the event of failure, we - * retain the current location. - */ - - (void)uip_parsehttpurl(ws->line + strlen(g_httplocation), &ws->port, - ws->hostname, CONFIG_WEBCLIENT_MAXHOSTNAME, - ws->filename, CONFIG_WEBCLIENT_MAXFILENAME); - nvdbg("New hostname='%s' filename='%s'\n", ws->hostname, ws->filename); - } - } - - /* We're done parsing this line, so we reset the index to the start - * of the next line. - */ - - ndx = 0; - } - else - { - ndx++; - } - offset++; - } - -exit: - ws->offset = offset; - ws->ndx = ndx; - return OK; -} - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * 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 - * url - A pointer to a string containing either the full URL to - * the file to get (e.g., http://www.nutt.org/index.html, or - * http://192.168.23.1:80/index.html). - * 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 - * - ****************************************************************************/ - -int wget(FAR const char *url, FAR char *buffer, int buflen, - wget_callback_t callback, FAR void *arg) -{ - struct sockaddr_in server; - struct wget_s ws; - bool redirected; - char *dest; - int sockfd; - int len; - int ret = OK; - - /* Initialize the state structure */ - - memset(&ws, 0, sizeof(struct wget_s)); - ws.buffer = buffer; - ws.buflen = buflen; - ws.port = 80; - - /* Parse the hostname (with optional port number) and filename from the URL */ - - ret = uip_parsehttpurl(url, &ws.port, - ws.hostname, CONFIG_WEBCLIENT_MAXHOSTNAME, - ws.filename, CONFIG_WEBCLIENT_MAXFILENAME); - if (ret != 0) - { - ndbg("Malformed HTTP URL: %s\n", url); - errno = -ret; - return ERROR; - } - nvdbg("hostname='%s' filename='%s'\n", ws.hostname, ws.filename); - - /* The following sequence may repeat indefinitely if we are redirected */ - - do - { - /* Re-initialize portions of the state structure that could have - * been left from the previous time through the loop and should not - * persist with the new connection. - */ - - ws.httpstatus = HTTPSTATUS_NONE; - ws.offset = 0; - ws.datend = 0; - ws.ndx = 0; - - /* Create a socket */ - - 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; - } - - /* Get the server adddress from the host name */ - - server.sin_family = AF_INET; - server.sin_port = htons(ws.port); - ret = wget_resolvehost(ws.hostname, &server.sin_addr.s_addr); - if (ret < 0) - { - /* Could not resolve host (or malformed IP address) */ - - ndbg("Failed to resolve hostname\n"); - ret = -EHOSTUNREACH; - goto errout_with_errno; - } - - /* Connect to server. First we have to set some fields in the - * 'server' address structure. The system will assign me an arbitrary - * local port that is not in use. - */ - - ret = connect(sockfd, (struct sockaddr *)&server, sizeof(struct sockaddr_in)); - if (ret < 0) - { - ndbg("connect failed: %d\n", errno); - goto errout; - } - - /* Send the GET request */ - - dest = ws.buffer; - dest = wget_strcpy(dest, g_httpget); - dest = wget_strcpy(dest, ws.filename); - *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, ws.hostname); - 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; - } - - /* Now loop to get the file sent in response to the GET. This - * loop continues until either we read the end of file (nbytes == 0) - * or until we detect that we have been redirected. - */ - - ws.state = WEBCLIENT_STATE_STATUSLINE; - redirected = false; - 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_with_errno; - } - else if (ret == 0) - { - close(sockfd); - break; - } - - /* Handle initial parsing of the status line */ - - ws.offset = 0; - if (ws.state == WEBCLIENT_STATE_STATUSLINE) - { - ret = wget_parsestatus(&ws); - if (ret < 0) - { - goto errout_with_errno; - } - } - - /* Parse the HTTP data */ - - if (ws.state == WEBCLIENT_STATE_HEADERS) - { - ret = wget_parseheaders(&ws); - if (ret < 0) - { - goto errout_with_errno; - } - } - - /* Dispose of the data payload */ - - if (ws.state == WEBCLIENT_STATE_DATA) - { - if (ws.httpstatus != HTTPSTATUS_MOVED) - { - /* Let the client decide what to do with the received file */ - - callback(&ws.buffer, ws.offset, ws.datend, &buflen, arg); - } - else - { - redirected = true; - close(sockfd); - break; - } - } - } - } - while (redirected); - return OK; - -errout_with_errno: - errno = -ret; -errout: - close(sockfd); - return ERROR; -} |