These are the examples provided for [[/users/frank26080115/libraries/LPC1700CMSIS_Lib/]] Note, the entire "program" is not compilable!

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers webclient.c Source File

webclient.c

Go to the documentation of this file.
00001 /** @addtogroup EMAC_uIP
00002  * @{
00003  */
00004 /**
00005  * \addtogroup apps
00006  * @{
00007  */
00008 
00009 /**
00010  * \defgroup webclient Web client
00011  * @{
00012  *
00013  * This example shows a HTTP client that is able to download web pages
00014  * and files from web servers. It requires a number of callback
00015  * functions to be implemented by the module that utilizes the code:
00016  * webclient_datahandler(), webclient_connected(),
00017  * webclient_timedout(), webclient_aborted(), webclient_closed().
00018  */
00019 
00020 /**
00021  * \file
00022  * Implementation of the HTTP client.
00023  * \author Adam Dunkels <adam@dunkels.com>
00024  */
00025 
00026 /*
00027  * Copyright (c) 2002, Adam Dunkels.
00028  * All rights reserved.
00029  *
00030  * Redistribution and use in source and binary forms, with or without
00031  * modification, are permitted provided that the following conditions
00032  * are met:
00033  * 1. Redistributions of source code must retain the above copyright
00034  *    notice, this list of conditions and the following disclaimer.
00035  * 2. Redistributions in binary form must reproduce the above
00036  *    copyright notice, this list of conditions and the following
00037  *    disclaimer in the documentation and/or other materials provided
00038  *    with the distribution.
00039  * 3. The name of the author may not be used to endorse or promote
00040  *    products derived from this software without specific prior
00041  *    written permission.
00042  *
00043  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
00044  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00045  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00046  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00047  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00048  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00049  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00050  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00051  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00052  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00053  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00054  *
00055  * This file is part of the uIP TCP/IP stack.
00056  *
00057  * $Id: webclient.c,v 1.2 2006/06/11 21:46:37 adam Exp $
00058  *
00059  */
00060 
00061 #include "uip.h"
00062 #include "uiplib.h"
00063 #include "webclient.h"
00064 #include "resolv.h"
00065 
00066 #include <string.h>
00067 
00068 #define WEBCLIENT_TIMEOUT 100
00069 
00070 #define WEBCLIENT_STATE_STATUSLINE 0
00071 #define WEBCLIENT_STATE_HEADERS    1
00072 #define WEBCLIENT_STATE_DATA       2
00073 #define WEBCLIENT_STATE_CLOSE      3
00074 
00075 #define HTTPFLAG_NONE   0
00076 #define HTTPFLAG_OK     1
00077 #define HTTPFLAG_MOVED  2
00078 #define HTTPFLAG_ERROR  3
00079 
00080 
00081 #define ISO_nl       0x0a
00082 #define ISO_cr       0x0d
00083 #define ISO_space    0x20
00084 
00085 
00086 static struct webclient_state s;
00087 
00088 /*-----------------------------------------------------------------------------------*/
00089 char *
00090 webclient_mimetype(void)
00091 {
00092   return s.mimetype;
00093 }
00094 /*-----------------------------------------------------------------------------------*/
00095 char *
00096 webclient_filename(void)
00097 {
00098   return s.file;
00099 }
00100 /*-----------------------------------------------------------------------------------*/
00101 char *
00102 webclient_hostname(void)
00103 {
00104   return s.host;
00105 }
00106 /*-----------------------------------------------------------------------------------*/
00107 unsigned short
00108 webclient_port(void)
00109 {
00110   return s.port;
00111 }
00112 /*-----------------------------------------------------------------------------------*/
00113 void
00114 webclient_init(void)
00115 {
00116 
00117 }
00118 /*-----------------------------------------------------------------------------------*/
00119 static void
00120 init_connection(void)
00121 {
00122   s.state = WEBCLIENT_STATE_STATUSLINE;
00123 
00124   s.getrequestleft = sizeof(http_get) - 1 + 1 +
00125     sizeof(http_10) - 1 +
00126     sizeof(http_crnl) - 1 +
00127     sizeof(http_host) - 1 +
00128     sizeof(http_crnl) - 1 +
00129     strlen(http_user_agent_fields) +
00130     strlen(s.file) + strlen(s.host);
00131   s.getrequestptr = 0;
00132 
00133   s.httpheaderlineptr = 0;
00134 }
00135 /*-----------------------------------------------------------------------------------*/
00136 void
00137 webclient_close(void)
00138 {
00139   s.state = WEBCLIENT_STATE_CLOSE;
00140 }
00141 /*-----------------------------------------------------------------------------------*/
00142 unsigned char
00143 webclient_get(char *host, u16_t port, char *file)
00144 {
00145   struct uip_conn *conn;
00146   uip_ipaddr_t *ipaddr;
00147   static uip_ipaddr_t addr;
00148 
00149   /* First check if the host is an IP address. */
00150   ipaddr = &addr;
00151   if(uiplib_ipaddrconv(host, (unsigned char *)addr) == 0) {
00152     ipaddr = (uip_ipaddr_t *)resolv_lookup(host);
00153 
00154     if(ipaddr == NULL) {
00155       return 0;
00156     }
00157   }
00158 
00159   conn = uip_connect(ipaddr, htons(port));
00160 
00161   if(conn == NULL) {
00162     return 0;
00163   }
00164 
00165   s.port = port;
00166   strncpy(s.file, file, sizeof(s.file));
00167   strncpy(s.host, host, sizeof(s.host));
00168 
00169   init_connection();
00170   return 1;
00171 }
00172 /*-----------------------------------------------------------------------------------*/
00173 static unsigned char *
00174 copy_string(unsigned char *dest,
00175         const unsigned char *src, unsigned char len)
00176 {
00177   strncpy(dest, src, len);
00178   return dest + len;
00179 }
00180 /*-----------------------------------------------------------------------------------*/
00181 static void
00182 senddata(void)
00183 {
00184   u16_t len;
00185   char *getrequest;
00186   char *cptr;
00187 
00188   if(s.getrequestleft > 0) {
00189     cptr = getrequest = (char *)uip_appdata;
00190 
00191     cptr = copy_string(cptr, http_get, sizeof(http_get) - 1);
00192     cptr = copy_string(cptr, s.file, strlen(s.file));
00193     *cptr++ = ISO_space;
00194     cptr = copy_string(cptr, http_10, sizeof(http_10) - 1);
00195 
00196     cptr = copy_string(cptr, http_crnl, sizeof(http_crnl) - 1);
00197 
00198     cptr = copy_string(cptr, http_host, sizeof(http_host) - 1);
00199     cptr = copy_string(cptr, s.host, strlen(s.host));
00200     cptr = copy_string(cptr, http_crnl, sizeof(http_crnl) - 1);
00201 
00202     cptr = copy_string(cptr, http_user_agent_fields,
00203                strlen(http_user_agent_fields));
00204 
00205     len = s.getrequestleft > uip_mss()?
00206       uip_mss():
00207       s.getrequestleft;
00208     uip_send(&(getrequest[s.getrequestptr]), len);
00209   }
00210 }
00211 /*-----------------------------------------------------------------------------------*/
00212 static void
00213 acked(void)
00214 {
00215   u16_t len;
00216 
00217   if(s.getrequestleft > 0) {
00218     len = s.getrequestleft > uip_mss()?
00219       uip_mss():
00220       s.getrequestleft;
00221     s.getrequestleft -= len;
00222     s.getrequestptr += len;
00223   }
00224 }
00225 /*-----------------------------------------------------------------------------------*/
00226 static u16_t
00227 parse_statusline(u16_t len)
00228 {
00229   char *cptr;
00230 
00231   while(len > 0 && s.httpheaderlineptr < sizeof(s.httpheaderline)) {
00232     s.httpheaderline[s.httpheaderlineptr] = *(char *)uip_appdata;
00233     ++((char *)uip_appdata);
00234     --len;
00235     if(s.httpheaderline[s.httpheaderlineptr] == ISO_nl) {
00236 
00237       if((strncmp(s.httpheaderline, http_10,
00238           sizeof(http_10) - 1) == 0) ||
00239      (strncmp(s.httpheaderline, http_11,
00240           sizeof(http_11) - 1) == 0)) {
00241     cptr = &(s.httpheaderline[9]);
00242     s.httpflag = HTTPFLAG_NONE;
00243     if(strncmp(cptr, http_200, sizeof(http_200) - 1) == 0) {
00244       /* 200 OK */
00245       s.httpflag = HTTPFLAG_OK;
00246     } else if(strncmp(cptr, http_301, sizeof(http_301) - 1) == 0 ||
00247           strncmp(cptr, http_302, sizeof(http_302) - 1) == 0) {
00248       /* 301 Moved permanently or 302 Found. Location: header line
00249          will contain thw new location. */
00250       s.httpflag = HTTPFLAG_MOVED;
00251     } else {
00252       s.httpheaderline[s.httpheaderlineptr - 1] = 0;
00253     }
00254       } else {
00255     uip_abort();
00256     webclient_aborted();
00257     return 0;
00258       }
00259 
00260       /* We're done parsing the status line, so we reset the pointer
00261      and start parsing the HTTP headers.*/
00262       s.httpheaderlineptr = 0;
00263       s.state = WEBCLIENT_STATE_HEADERS;
00264       break;
00265     } else {
00266       ++s.httpheaderlineptr;
00267     }
00268   }
00269   return len;
00270 }
00271 /*-----------------------------------------------------------------------------------*/
00272 static char
00273 casecmp(char *str1, const char *str2, char len)
00274 {
00275   static char c;
00276 
00277   while(len > 0) {
00278     c = *str1;
00279     /* Force lower-case characters. */
00280     if(c & 0x40) {
00281       c |= 0x20;
00282     }
00283     if(*str2 != c) {
00284       return 1;
00285     }
00286     ++str1;
00287     ++str2;
00288     --len;
00289   }
00290   return 0;
00291 }
00292 /*-----------------------------------------------------------------------------------*/
00293 static u16_t
00294 parse_headers(u16_t len)
00295 {
00296   char *cptr;
00297   static unsigned char i;
00298 
00299   while(len > 0 && s.httpheaderlineptr < sizeof(s.httpheaderline)) {
00300     s.httpheaderline[s.httpheaderlineptr] = *(char *)uip_appdata;
00301     ++((char *)uip_appdata);
00302     --len;
00303     if(s.httpheaderline[s.httpheaderlineptr] == ISO_nl) {
00304       /* We have an entire HTTP header line in s.httpheaderline, so
00305      we parse it. */
00306       if(s.httpheaderline[0] == ISO_cr) {
00307     /* This was the last header line (i.e., and empty "\r\n"), so
00308        we are done with the headers and proceed with the actual
00309        data. */
00310     s.state = WEBCLIENT_STATE_DATA;
00311     return len;
00312       }
00313 
00314       s.httpheaderline[s.httpheaderlineptr - 1] = 0;
00315       /* Check for specific HTTP header fields. */
00316       if(casecmp(s.httpheaderline, http_content_type,
00317              sizeof(http_content_type) - 1) == 0) {
00318     /* Found Content-type field. */
00319     cptr = strchr(s.httpheaderline, ';');
00320     if(cptr != NULL) {
00321       *cptr = 0;
00322     }
00323     strncpy(s.mimetype, s.httpheaderline +
00324         sizeof(http_content_type) - 1, sizeof(s.mimetype));
00325       } else if(casecmp(s.httpheaderline, http_location,
00326                 sizeof(http_location) - 1) == 0) {
00327     cptr = s.httpheaderline +
00328       sizeof(http_location) - 1;
00329 
00330     if(strncmp(cptr, http_http, 7) == 0) {
00331       cptr += 7;
00332       for(i = 0; i < s.httpheaderlineptr - 7; ++i) {
00333         if(*cptr == 0 ||
00334            *cptr == '/' ||
00335            *cptr == ' ' ||
00336            *cptr == ':') {
00337           s.host[i] = 0;
00338           break;
00339         }
00340         s.host[i] = *cptr;
00341         ++cptr;
00342       }
00343     }
00344     strncpy(s.file, cptr, sizeof(s.file));
00345     /*  s.file[s.httpheaderlineptr - i] = 0;*/
00346       }
00347 
00348 
00349       /* We're done parsing, so we reset the pointer and start the
00350      next line. */
00351       s.httpheaderlineptr = 0;
00352     } else {
00353       ++s.httpheaderlineptr;
00354     }
00355   }
00356   return len;
00357 }
00358 /*-----------------------------------------------------------------------------------*/
00359 static void
00360 newdata(void)
00361 {
00362   u16_t len;
00363 
00364   len = uip_datalen();
00365 
00366   if(s.state == WEBCLIENT_STATE_STATUSLINE) {
00367     len = parse_statusline(len);
00368   }
00369 
00370   if(s.state == WEBCLIENT_STATE_HEADERS && len > 0) {
00371     len = parse_headers(len);
00372   }
00373 
00374   if(len > 0 && s.state == WEBCLIENT_STATE_DATA &&
00375      s.httpflag != HTTPFLAG_MOVED) {
00376     webclient_datahandler((char *)uip_appdata, len);
00377   }
00378 }
00379 /*-----------------------------------------------------------------------------------*/
00380 void
00381 webclient_appcall(void)
00382 {
00383   if(uip_connected()) {
00384     s.timer = 0;
00385     s.state = WEBCLIENT_STATE_STATUSLINE;
00386     senddata();
00387     webclient_connected();
00388     return;
00389   }
00390 
00391   if(s.state == WEBCLIENT_STATE_CLOSE) {
00392     webclient_closed();
00393     uip_abort();
00394     return;
00395   }
00396 
00397   if(uip_aborted()) {
00398     webclient_aborted();
00399   }
00400   if(uip_timedout()) {
00401     webclient_timedout();
00402   }
00403 
00404 
00405   if(uip_acked()) {
00406     s.timer = 0;
00407     acked();
00408   }
00409   if(uip_newdata()) {
00410     s.timer = 0;
00411     newdata();
00412   }
00413   if(uip_rexmit() ||
00414      uip_newdata() ||
00415      uip_acked()) {
00416     senddata();
00417   } else if(uip_poll()) {
00418     ++s.timer;
00419     if(s.timer == WEBCLIENT_TIMEOUT) {
00420       webclient_timedout();
00421       uip_abort();
00422       return;
00423     }
00424         /*    senddata();*/
00425   }
00426 
00427   if(uip_closed()) {
00428     if(s.httpflag != HTTPFLAG_MOVED) {
00429       /* Send NULL data to signal EOF. */
00430       webclient_datahandler(NULL, 0);
00431     } else {
00432       if(resolv_lookup(s.host) == NULL) {
00433     resolv_query(s.host);
00434       }
00435       webclient_get(s.host, s.port, s.file);
00436     }
00437   }
00438 }
00439 /*-----------------------------------------------------------------------------------*/
00440 
00441 /** @} */
00442 /** @} */
00443 /** @} */