mirror of
https://github.com/apache/nuttx.git
synced 2026-05-26 02:36:11 +08:00
Import of uIP 1.0
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@308 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
############################################################################
|
||||
# Make.defs
|
||||
#
|
||||
# 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 NuttX 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.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
WEBCLIENT_ASRCS =
|
||||
WEBCLIENT_CSRCS = webclient-strings.c webclient.c
|
||||
Executable
+40
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
|
||||
sub stringify {
|
||||
my $name = shift(@_);
|
||||
open(OUTPUTC, "> $name.c");
|
||||
open(OUTPUTH, "> $name.h");
|
||||
|
||||
open(FILE, "$name");
|
||||
|
||||
while(<FILE>) {
|
||||
if(/(.+) "(.+)"/) {
|
||||
$var = $1;
|
||||
$data = $2;
|
||||
|
||||
$datan = $data;
|
||||
$datan =~ s/\\r/\r/g;
|
||||
$datan =~ s/\\n/\n/g;
|
||||
$datan =~ s/\\01/\01/g;
|
||||
$datan =~ s/\\0/\0/g;
|
||||
|
||||
printf(OUTPUTC "const char $var\[%d] = \n", length($datan) + 1);
|
||||
printf(OUTPUTC "/* \"$data\" */\n");
|
||||
printf(OUTPUTC "{");
|
||||
for($j = 0; $j < length($datan); $j++) {
|
||||
printf(OUTPUTC "%#02x, ", unpack("C", substr($datan, $j, 1)));
|
||||
}
|
||||
printf(OUTPUTC "0 };\n");
|
||||
|
||||
printf(OUTPUTH "extern const char $var\[%d];\n", length($datan) + 1);
|
||||
|
||||
}
|
||||
}
|
||||
close(OUTPUTC);
|
||||
close(OUTPUTH);
|
||||
}
|
||||
stringify("webclient-strings");
|
||||
|
||||
exit 0;
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
http_http "http://"
|
||||
http_200 "200 "
|
||||
http_301 "301 "
|
||||
http_302 "302 "
|
||||
http_get "GET "
|
||||
http_10 "HTTP/1.0"
|
||||
http_11 "HTTP/1.1"
|
||||
http_content_type "content-type: "
|
||||
http_texthtml "text/html"
|
||||
http_location "location: "
|
||||
http_host "host: "
|
||||
http_crnl "\r\n"
|
||||
http_index_html "/index.html"
|
||||
http_404_html "/404.html"
|
||||
http_content_type_html "Content-type: text/html\r\n\r\n"
|
||||
http_content_type_css "Content-type: text/css\r\n\r\n"
|
||||
http_content_type_text "Content-type: text/text\r\n\r\n"
|
||||
http_content_type_png "Content-type: image/png\r\n\r\n"
|
||||
http_content_type_gif "Content-type: image/gif\r\n\r\n"
|
||||
http_content_type_jpg "Content-type: image/jpeg\r\n\r\n"
|
||||
http_content_type_binary "Content-type: application/octet-stream\r\n\r\n"
|
||||
http_html ".html"
|
||||
http_shtml ".shtml"
|
||||
http_htm ".htm"
|
||||
http_css ".css"
|
||||
http_png ".png"
|
||||
http_gif ".gif"
|
||||
http_jpg ".jpg"
|
||||
http_text ".text"
|
||||
http_txt ".txt"
|
||||
http_user_agent_fields "Connection: close\r\nUser-Agent: uIP/1.0 (; http://www.sics.se/~adam/uip/)\r\n\r\n"
|
||||
@@ -0,0 +1,93 @@
|
||||
const char http_http[8] =
|
||||
/* "http://" */
|
||||
{0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0 };
|
||||
const char http_200[5] =
|
||||
/* "200 " */
|
||||
{0x32, 0x30, 0x30, 0x20, 0 };
|
||||
const char http_301[5] =
|
||||
/* "301 " */
|
||||
{0x33, 0x30, 0x31, 0x20, 0 };
|
||||
const char http_302[5] =
|
||||
/* "302 " */
|
||||
{0x33, 0x30, 0x32, 0x20, 0 };
|
||||
const char http_get[5] =
|
||||
/* "GET " */
|
||||
{0x47, 0x45, 0x54, 0x20, 0 };
|
||||
const char http_10[9] =
|
||||
/* "HTTP/1.0" */
|
||||
{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0 };
|
||||
const char http_11[9] =
|
||||
/* "HTTP/1.1" */
|
||||
{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0 };
|
||||
const char http_content_type[15] =
|
||||
/* "content-type: " */
|
||||
{0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0 };
|
||||
const char http_texthtml[10] =
|
||||
/* "text/html" */
|
||||
{0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0 };
|
||||
const char http_location[11] =
|
||||
/* "location: " */
|
||||
{0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0 };
|
||||
const char http_host[7] =
|
||||
/* "host: " */
|
||||
{0x68, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0 };
|
||||
const char http_crnl[3] =
|
||||
/* "\r\n" */
|
||||
{0xd, 0xa, 0 };
|
||||
const char http_index_html[12] =
|
||||
/* "/index.html" */
|
||||
{0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0 };
|
||||
const char http_404_html[10] =
|
||||
/* "/404.html" */
|
||||
{0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0 };
|
||||
const char http_content_type_html[28] =
|
||||
/* "Content-type: text/html\r\n\r\n" */
|
||||
{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, 0xd, 0xa, 0 };
|
||||
const char http_content_type_css [27] =
|
||||
/* "Content-type: text/css\r\n\r\n" */
|
||||
{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x63, 0x73, 0x73, 0xd, 0xa, 0xd, 0xa, 0 };
|
||||
const char http_content_type_text[28] =
|
||||
/* "Content-type: text/text\r\n\r\n" */
|
||||
{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x74, 0x65, 0x78, 0x74, 0xd, 0xa, 0xd, 0xa, 0 };
|
||||
const char http_content_type_png [28] =
|
||||
/* "Content-type: image/png\r\n\r\n" */
|
||||
{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0xd, 0xa, 0xd, 0xa, 0 };
|
||||
const char http_content_type_gif [28] =
|
||||
/* "Content-type: image/gif\r\n\r\n" */
|
||||
{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, 0x69, 0x66, 0xd, 0xa, 0xd, 0xa, 0 };
|
||||
const char http_content_type_jpg [29] =
|
||||
/* "Content-type: image/jpeg\r\n\r\n" */
|
||||
{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x65, 0x67, 0xd, 0xa, 0xd, 0xa, 0 };
|
||||
const char http_content_type_binary[43] =
|
||||
/* "Content-type: application/octet-stream\r\n\r\n" */
|
||||
{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6f, 0x63, 0x74, 0x65, 0x74, 0x2d, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0xd, 0xa, 0xd, 0xa, 0 };
|
||||
const char http_html[6] =
|
||||
/* ".html" */
|
||||
{0x2e, 0x68, 0x74, 0x6d, 0x6c, 0 };
|
||||
const char http_shtml[7] =
|
||||
/* ".shtml" */
|
||||
{0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0 };
|
||||
const char http_htm[5] =
|
||||
/* ".htm" */
|
||||
{0x2e, 0x68, 0x74, 0x6d, 0 };
|
||||
const char http_css[5] =
|
||||
/* ".css" */
|
||||
{0x2e, 0x63, 0x73, 0x73, 0 };
|
||||
const char http_png[5] =
|
||||
/* ".png" */
|
||||
{0x2e, 0x70, 0x6e, 0x67, 0 };
|
||||
const char http_gif[5] =
|
||||
/* ".gif" */
|
||||
{0x2e, 0x67, 0x69, 0x66, 0 };
|
||||
const char http_jpg[5] =
|
||||
/* ".jpg" */
|
||||
{0x2e, 0x6a, 0x70, 0x67, 0 };
|
||||
const char http_text[6] =
|
||||
/* ".text" */
|
||||
{0x2e, 0x74, 0x65, 0x78, 0x74, 0 };
|
||||
const char http_txt[5] =
|
||||
/* ".txt" */
|
||||
{0x2e, 0x74, 0x78, 0x74, 0 };
|
||||
const char http_user_agent_fields[77] =
|
||||
/* "Connection: close\r\nUser-Agent: uIP/1.0 (; http://www.sics.se/~adam/uip/)\r\n\r\n" */
|
||||
{0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0xd, 0xa, 0x55, 0x73, 0x65, 0x72, 0x2d, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x28, 0x3b, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x73, 0x69, 0x63, 0x73, 0x2e, 0x73, 0x65, 0x2f, 0x7e, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, 0x70, 0x2f, 0x29, 0xd, 0xa, 0xd, 0xa, 0 };
|
||||
@@ -0,0 +1,31 @@
|
||||
extern const char http_http[8];
|
||||
extern const char http_200[5];
|
||||
extern const char http_301[5];
|
||||
extern const char http_302[5];
|
||||
extern const char http_get[5];
|
||||
extern const char http_10[9];
|
||||
extern const char http_11[9];
|
||||
extern const char http_content_type[15];
|
||||
extern const char http_texthtml[10];
|
||||
extern const char http_location[11];
|
||||
extern const char http_host[7];
|
||||
extern const char http_crnl[3];
|
||||
extern const char http_index_html[12];
|
||||
extern const char http_404_html[10];
|
||||
extern const char http_content_type_html[28];
|
||||
extern const char http_content_type_css [27];
|
||||
extern const char http_content_type_text[28];
|
||||
extern const char http_content_type_png [28];
|
||||
extern const char http_content_type_gif [28];
|
||||
extern const char http_content_type_jpg [29];
|
||||
extern const char http_content_type_binary[43];
|
||||
extern const char http_html[6];
|
||||
extern const char http_shtml[7];
|
||||
extern const char http_htm[5];
|
||||
extern const char http_css[5];
|
||||
extern const char http_png[5];
|
||||
extern const char http_gif[5];
|
||||
extern const char http_jpg[5];
|
||||
extern const char http_text[6];
|
||||
extern const char http_txt[5];
|
||||
extern const char http_user_agent_fields[77];
|
||||
@@ -0,0 +1,450 @@
|
||||
/* webclient.c
|
||||
* Implementation of the HTTP client.
|
||||
* Author: Adam Dunkels <adam@dunkels.com>
|
||||
*
|
||||
* 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().
|
||||
*
|
||||
* 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 file is part of the uIP TCP/IP stack.
|
||||
*
|
||||
* $Id: webclient.c,v 1.1.1.1 2007-08-26 23:07:05 patacongo Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <net/uip/uip.h>
|
||||
#include <net/uip/resolv.h>
|
||||
|
||||
#include "uiplib/uiplib.h"
|
||||
#include "webclient.h"
|
||||
|
||||
#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 HTTPFLAG_NONE 0
|
||||
#define HTTPFLAG_OK 1
|
||||
#define HTTPFLAG_MOVED 2
|
||||
#define HTTPFLAG_ERROR 3
|
||||
|
||||
|
||||
#define ISO_nl 0x0a
|
||||
#define ISO_cr 0x0d
|
||||
#define ISO_space 0x20
|
||||
|
||||
|
||||
static struct webclient_state s;
|
||||
|
||||
char *webclient_mimetype(void)
|
||||
{
|
||||
return s.mimetype;
|
||||
}
|
||||
|
||||
char *webclient_filename(void)
|
||||
{
|
||||
return s.file;
|
||||
}
|
||||
|
||||
char *webclient_hostname(void)
|
||||
{
|
||||
return s.host;
|
||||
}
|
||||
|
||||
unsigned shortwebclient_port(void)
|
||||
{
|
||||
return s.port;
|
||||
}
|
||||
|
||||
void webclient_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void init_connection(void)
|
||||
{
|
||||
s.state = WEBCLIENT_STATE_STATUSLINE;
|
||||
|
||||
s.getrequestleft = sizeof(http_get) - 1 + 1 +
|
||||
sizeof(http_10) - 1 +
|
||||
sizeof(http_crnl) - 1 +
|
||||
sizeof(http_host) - 1 +
|
||||
sizeof(http_crnl) - 1 +
|
||||
strlen(http_user_agent_fields) +
|
||||
strlen(s.file) + strlen(s.host);
|
||||
s.getrequestptr = 0;
|
||||
|
||||
s.httpheaderlineptr = 0;
|
||||
}
|
||||
|
||||
void webclient_close(void)
|
||||
{
|
||||
s.state = WEBCLIENT_STATE_CLOSE;
|
||||
}
|
||||
|
||||
unsigned char webclient_get(char *host, uint16 port, char *file)
|
||||
{
|
||||
struct uip_conn *conn;
|
||||
uip_ipaddr_t *ipaddr;
|
||||
static uip_ipaddr_t addr;
|
||||
|
||||
/* First check if the host is an IP address. */
|
||||
ipaddr = &addr;
|
||||
if (uiplib_ipaddrconv(host, (unsigned char *)addr) == 0) {
|
||||
ipaddr = (uip_ipaddr_t *)resolv_lookup(host);
|
||||
|
||||
if (ipaddr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
conn = uip_connect(ipaddr, htons(port));
|
||||
|
||||
if (conn == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
s.port = port;
|
||||
strncpy(s.file, file, sizeof(s.file));
|
||||
strncpy(s.host, host, sizeof(s.host));
|
||||
|
||||
init_connection();
|
||||
return 1;
|
||||
}
|
||||
|
||||
static char *copy_string(char *dest, const char *src, int len)
|
||||
{
|
||||
strncpy(dest, src, len);
|
||||
return dest + len;
|
||||
}
|
||||
|
||||
static void senddata(void)
|
||||
{
|
||||
uint16 len;
|
||||
char *getrequest;
|
||||
char *cptr;
|
||||
|
||||
if (s.getrequestleft > 0) {
|
||||
cptr = getrequest = (char *)uip_appdata;
|
||||
|
||||
cptr = copy_string(cptr, http_get, sizeof(http_get) - 1);
|
||||
cptr = copy_string(cptr, s.file, strlen(s.file));
|
||||
*cptr++ = ISO_space;
|
||||
cptr = copy_string(cptr, http_10, sizeof(http_10) - 1);
|
||||
|
||||
cptr = copy_string(cptr, http_crnl, sizeof(http_crnl) - 1);
|
||||
|
||||
cptr = copy_string(cptr, http_host, sizeof(http_host) - 1);
|
||||
cptr = copy_string(cptr, s.host, strlen(s.host));
|
||||
cptr = copy_string(cptr, http_crnl, sizeof(http_crnl) - 1);
|
||||
|
||||
cptr = copy_string(cptr, http_user_agent_fields,
|
||||
strlen(http_user_agent_fields));
|
||||
|
||||
len = s.getrequestleft > uip_mss()?
|
||||
uip_mss():
|
||||
s.getrequestleft;
|
||||
uip_send(&(getrequest[s.getrequestptr]), len);
|
||||
}
|
||||
}
|
||||
|
||||
static void acked(void)
|
||||
{
|
||||
uint16 len;
|
||||
|
||||
if (s.getrequestleft > 0) {
|
||||
len = s.getrequestleft > uip_mss()?
|
||||
uip_mss():
|
||||
s.getrequestleft;
|
||||
s.getrequestleft -= len;
|
||||
s.getrequestptr += len;
|
||||
}
|
||||
}
|
||||
|
||||
static uint16 parse_statusline(uint16 len)
|
||||
{
|
||||
char *cptr;
|
||||
|
||||
while(len > 0 && s.httpheaderlineptr < sizeof(s.httpheaderline))
|
||||
{
|
||||
char *pappdata = (char*)uip_appdata;
|
||||
s.httpheaderline[s.httpheaderlineptr] = *pappdata++;
|
||||
uip_appdata = (void*)pappdata;
|
||||
len--;
|
||||
|
||||
if (s.httpheaderline[s.httpheaderlineptr] == ISO_nl)
|
||||
{
|
||||
if ((strncmp(s.httpheaderline, http_10, sizeof(http_10) - 1) == 0) ||
|
||||
(strncmp(s.httpheaderline, http_11, sizeof(http_11) - 1) == 0))
|
||||
{
|
||||
cptr = &(s.httpheaderline[9]);
|
||||
s.httpflag = HTTPFLAG_NONE;
|
||||
if (strncmp(cptr, http_200, sizeof(http_200) - 1) == 0)
|
||||
{
|
||||
/* 200 OK */
|
||||
s.httpflag = HTTPFLAG_OK;
|
||||
}
|
||||
else if (strncmp(cptr, http_301, sizeof(http_301) - 1) == 0 ||
|
||||
strncmp(cptr, http_302, sizeof(http_302) - 1) == 0)
|
||||
{
|
||||
/* 301 Moved permanently or 302 Found. Location: header line
|
||||
* will contain thw new location.
|
||||
*/
|
||||
|
||||
s.httpflag = HTTPFLAG_MOVED;
|
||||
}
|
||||
else
|
||||
{
|
||||
s.httpheaderline[s.httpheaderlineptr - 1] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uip_abort();
|
||||
webclient_aborted();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We're done parsing the status line, so we reset the pointer
|
||||
* and start parsing the HTTP headers.
|
||||
*/
|
||||
|
||||
s.httpheaderlineptr = 0;
|
||||
s.state = WEBCLIENT_STATE_HEADERS;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
++s.httpheaderlineptr;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
static uint16 parse_headers(uint16 len)
|
||||
{
|
||||
char *cptr;
|
||||
static unsigned char i;
|
||||
|
||||
while(len > 0 && s.httpheaderlineptr < sizeof(s.httpheaderline))
|
||||
{
|
||||
char *pappdata = (char*)uip_appdata;
|
||||
s.httpheaderline[s.httpheaderlineptr] = *pappdata++;
|
||||
uip_appdata = (void*)pappdata;
|
||||
len--;
|
||||
|
||||
if (s.httpheaderline[s.httpheaderlineptr] == ISO_nl)
|
||||
{
|
||||
/* We have an entire HTTP header line in s.httpheaderline, so
|
||||
* we parse it.
|
||||
*/
|
||||
|
||||
if (s.httpheaderline[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;
|
||||
}
|
||||
|
||||
s.httpheaderline[s.httpheaderlineptr - 1] = 0;
|
||||
|
||||
/* Check for specific HTTP header fields. */
|
||||
if (casecmp(s.httpheaderline, http_content_type, sizeof(http_content_type) - 1) == 0)
|
||||
{
|
||||
/* Found Content-type field. */
|
||||
cptr = strchr(s.httpheaderline, ';');
|
||||
if (cptr != NULL)
|
||||
{
|
||||
*cptr = 0;
|
||||
}
|
||||
strncpy(s.mimetype, s.httpheaderline + sizeof(http_content_type) - 1, sizeof(s.mimetype));
|
||||
}
|
||||
else if (casecmp(s.httpheaderline, http_location, sizeof(http_location) - 1) == 0)
|
||||
{
|
||||
cptr = s.httpheaderline + sizeof(http_location) - 1;
|
||||
|
||||
if (strncmp(cptr, http_http, 7) == 0)
|
||||
{
|
||||
cptr += 7;
|
||||
for(i = 0; i < s.httpheaderlineptr - 7; ++i)
|
||||
{
|
||||
if (*cptr == 0 || *cptr == '/' || *cptr == ' ' || *cptr == ':')
|
||||
{
|
||||
s.host[i] = 0;
|
||||
break;
|
||||
}
|
||||
s.host[i] = *cptr;
|
||||
++cptr;
|
||||
}
|
||||
}
|
||||
strncpy(s.file, cptr, sizeof(s.file));
|
||||
}
|
||||
|
||||
/* We're done parsing, so we reset the pointer and start the
|
||||
* next line.
|
||||
*/
|
||||
|
||||
s.httpheaderlineptr = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
++s.httpheaderlineptr;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static void newdata(void)
|
||||
{
|
||||
uint16 len;
|
||||
|
||||
len = uip_datalen();
|
||||
|
||||
if (s.state == WEBCLIENT_STATE_STATUSLINE) {
|
||||
len = parse_statusline(len);
|
||||
}
|
||||
|
||||
if (s.state == WEBCLIENT_STATE_HEADERS && len > 0) {
|
||||
len = parse_headers(len);
|
||||
}
|
||||
|
||||
if (len > 0 && s.state == WEBCLIENT_STATE_DATA &&
|
||||
s.httpflag != HTTPFLAG_MOVED) {
|
||||
webclient_datahandler((char *)uip_appdata, len);
|
||||
}
|
||||
}
|
||||
|
||||
/* This function is called by the UIP interrupt handling logic whenevent an
|
||||
* event of interest occurs.
|
||||
*/
|
||||
|
||||
void uip_interrupt_event(void)
|
||||
{
|
||||
if (uip_connected())
|
||||
{
|
||||
s.timer = 0;
|
||||
s.state = WEBCLIENT_STATE_STATUSLINE;
|
||||
senddata();
|
||||
webclient_connected();
|
||||
return;
|
||||
}
|
||||
|
||||
if (s.state == WEBCLIENT_STATE_CLOSE)
|
||||
{
|
||||
webclient_closed();
|
||||
uip_abort();
|
||||
return;
|
||||
}
|
||||
|
||||
if (uip_aborted())
|
||||
{
|
||||
webclient_aborted();
|
||||
}
|
||||
|
||||
if (uip_timedout())
|
||||
{
|
||||
webclient_timedout();
|
||||
}
|
||||
|
||||
if (uip_acked())
|
||||
{
|
||||
s.timer = 0;
|
||||
acked();
|
||||
}
|
||||
|
||||
if (uip_newdata())
|
||||
{
|
||||
s.timer = 0;
|
||||
newdata();
|
||||
}
|
||||
|
||||
if (uip_rexmit() || uip_newdata() || uip_acked())
|
||||
{
|
||||
senddata();
|
||||
}
|
||||
else if (uip_poll())
|
||||
{
|
||||
++s.timer;
|
||||
if (s.timer == WEBCLIENT_TIMEOUT)
|
||||
{
|
||||
webclient_timedout();
|
||||
uip_abort();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (uip_closed())
|
||||
{
|
||||
if (s.httpflag != HTTPFLAG_MOVED)
|
||||
{
|
||||
/* Send NULL data to signal EOF. */
|
||||
webclient_datahandler(NULL, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (resolv_lookup(s.host) == NULL)
|
||||
{
|
||||
resolv_query(s.host);
|
||||
}
|
||||
webclient_get(s.host, s.port, s.file);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* This file is part of the uIP TCP/IP stack.
|
||||
*
|
||||
* $Id: webclient.h,v 1.1.1.1 2007-08-26 23:07:04 patacongo Exp $
|
||||
*
|
||||
*/
|
||||
#ifndef __WEBCLIENT_H__
|
||||
#define __WEBCLIENT_H__
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <net/uip/uipopt.h>
|
||||
|
||||
#include "webclient-strings.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.
|
||||
*
|
||||
* \param data A pointer to the data that has been received.
|
||||
* \param 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.
|
||||
*
|
||||
* \param 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).
|
||||
*
|
||||
* \param port The port number to which to connect, in host byte order.
|
||||
*
|
||||
* \param file A pointer to the name of the file to get.
|
||||
*
|
||||
* \retval 0 if the host name could not be found in the cache, or
|
||||
* if a TCP connection could not be created.
|
||||
*
|
||||
* \retval 1 if the connection was initiated.
|
||||
*/
|
||||
unsigned char webclient_get(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__ */
|
||||
|
||||
/** @} */
|
||||
Reference in New Issue
Block a user