00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 #include "uip.h"
00059 #include "uiplib.h"
00060 #include "webclient.h"
00061 #include "resolv.h"
00062 
00063 #include <string.h>
00064 
00065 #define WEBCLIENT_TIMEOUT 100
00066 
00067 #define WEBCLIENT_STATE_STATUSLINE 0
00068 #define WEBCLIENT_STATE_HEADERS    1
00069 #define WEBCLIENT_STATE_DATA       2
00070 #define WEBCLIENT_STATE_CLOSE      3
00071 
00072 #define HTTPFLAG_NONE   0
00073 #define HTTPFLAG_OK     1
00074 #define HTTPFLAG_MOVED  2
00075 #define HTTPFLAG_ERROR  3
00076 
00077 
00078 #define ISO_nl       0x0a
00079 #define ISO_cr       0x0d
00080 #define ISO_space    0x20
00081 
00082 
00083 static struct webclient_state s;
00084 
00085 
00086 char *
00087 webclient_mimetype(void)
00088 {
00089   return s.mimetype;
00090 }
00091 
00092 char *
00093 webclient_filename(void)
00094 {
00095   return s.file;
00096 }
00097 
00098 char *
00099 webclient_hostname(void)
00100 {
00101   return s.host;
00102 }
00103 
00104 unsigned short
00105 webclient_port(void)
00106 {
00107   return s.port;
00108 }
00109 
00110 void
00111 webclient_init(void)
00112 {
00113 
00114 }
00115 
00116 static void
00117 init_connection(void)
00118 {
00119   s.state = WEBCLIENT_STATE_STATUSLINE;
00120 
00121   s.getrequestleft = sizeof(http_get) - 1 + 1 +
00122     sizeof(http_10) - 1 +
00123     sizeof(http_crnl) - 1 +
00124     sizeof(http_host) - 1 +
00125     sizeof(http_crnl) - 1 +
00126     strlen(http_user_agent_fields) +
00127     strlen(s.file) + strlen(s.host);
00128   s.getrequestptr = 0;
00129 
00130   s.httpheaderlineptr = 0;
00131 }
00132 
00133 void
00134 webclient_close(void)
00135 {
00136   s.state = WEBCLIENT_STATE_CLOSE;
00137 }
00138 
00139 unsigned char
00140 webclient_get(char *host, u16_t port, char *file)
00141 {
00142   struct uip_conn *conn;
00143   uip_ipaddr_t *ipaddr;
00144   static uip_ipaddr_t addr;
00145   
00146   
00147   ipaddr = &addr;
00148   if(uiplib_ipaddrconv(host, (unsigned char *)addr) == 0) {
00149     ipaddr = (uip_ipaddr_t *)resolv_lookup(host);
00150     
00151     if(ipaddr == NULL) {
00152       return 0;
00153     }
00154   }
00155   
00156   conn = uip_connect(ipaddr, htons(port));
00157   
00158   if(conn == NULL) {
00159     return 0;
00160   }
00161   
00162   s.port = port;
00163   strncpy(s.file, file, sizeof(s.file));
00164   strncpy(s.host, host, sizeof(s.host));
00165   
00166   init_connection();
00167   return 1;
00168 }
00169 
00170 static unsigned char *
00171 copy_string(unsigned char *dest,
00172             const unsigned char *src, unsigned char len)
00173 {
00174   strncpy(dest, src, len);
00175   return dest + len;
00176 }
00177 
00178 static void
00179 senddata(void)
00180 {
00181   u16_t len;
00182   char *getrequest;
00183   char *cptr;
00184   
00185   if(s.getrequestleft > 0) {
00186     cptr = getrequest = (char *)uip_appdata;
00187 
00188     cptr = copy_string(cptr, http_get, sizeof(http_get) - 1);
00189     cptr = copy_string(cptr, s.file, strlen(s.file));
00190     *cptr++ = ISO_space;
00191     cptr = copy_string(cptr, http_10, sizeof(http_10) - 1);
00192 
00193     cptr = copy_string(cptr, http_crnl, sizeof(http_crnl) - 1);
00194     
00195     cptr = copy_string(cptr, http_host, sizeof(http_host) - 1);
00196     cptr = copy_string(cptr, s.host, strlen(s.host));
00197     cptr = copy_string(cptr, http_crnl, sizeof(http_crnl) - 1);
00198 
00199     cptr = copy_string(cptr, http_user_agent_fields,
00200                        strlen(http_user_agent_fields));
00201     
00202     len = s.getrequestleft > uip_mss()?
00203       uip_mss():
00204       s.getrequestleft;
00205     uip_send(&(getrequest[s.getrequestptr]), len);
00206   }
00207 }
00208 
00209 static void
00210 acked(void)
00211 {
00212   u16_t len;
00213   
00214   if(s.getrequestleft > 0) {
00215     len = s.getrequestleft > uip_mss()?
00216       uip_mss():
00217       s.getrequestleft;
00218     s.getrequestleft -= len;
00219     s.getrequestptr += len;
00220   }
00221 }
00222 
00223 static u16_t
00224 parse_statusline(u16_t len)
00225 {
00226   char *cptr;
00227   
00228   while(len > 0 && s.httpheaderlineptr < sizeof(s.httpheaderline)) {
00229     s.httpheaderline[s.httpheaderlineptr] = *(char *)uip_appdata;
00230     ++((char *)uip_appdata);
00231     --len;
00232     if(s.httpheaderline[s.httpheaderlineptr] == ISO_nl) {
00233 
00234       if((strncmp(s.httpheaderline, http_10,
00235                   sizeof(http_10) - 1) == 0) ||
00236          (strncmp(s.httpheaderline, http_11,
00237                   sizeof(http_11) - 1) == 0)) {
00238         cptr = &(s.httpheaderline[9]);
00239         s.httpflag = HTTPFLAG_NONE;
00240         if(strncmp(cptr, http_200, sizeof(http_200) - 1) == 0) {
00241           
00242           s.httpflag = HTTPFLAG_OK;
00243         } else if(strncmp(cptr, http_301, sizeof(http_301) - 1) == 0 ||
00244                   strncmp(cptr, http_302, sizeof(http_302) - 1) == 0) {
00245           
00246 
00247           s.httpflag = HTTPFLAG_MOVED;
00248         } else {
00249           s.httpheaderline[s.httpheaderlineptr - 1] = 0;
00250         }
00251       } else {
00252         uip_abort();
00253         webclient_aborted();
00254         return 0;
00255       }
00256       
00257       
00258 
00259       s.httpheaderlineptr = 0;
00260       s.state = WEBCLIENT_STATE_HEADERS;
00261       break;
00262     } else {
00263       ++s.httpheaderlineptr;
00264     }
00265   }
00266   return len;
00267 }
00268 
00269 static char
00270 casecmp(char *str1, const char *str2, char len)
00271 {
00272   static char c;
00273   
00274   while(len > 0) {
00275     c = *str1;
00276     
00277     if(c & 0x40) {
00278       c |= 0x20;
00279     }
00280     if(*str2 != c) {
00281       return 1;
00282     }
00283     ++str1;
00284     ++str2;
00285     --len;
00286   }
00287   return 0;
00288 }
00289 
00290 static u16_t
00291 parse_headers(u16_t len)
00292 {
00293   char *cptr;
00294   static unsigned char i;
00295   
00296   while(len > 0 && s.httpheaderlineptr < sizeof(s.httpheaderline)) {
00297     s.httpheaderline[s.httpheaderlineptr] = *(char *)uip_appdata;
00298     ++((char *)uip_appdata);
00299     --len;
00300     if(s.httpheaderline[s.httpheaderlineptr] == ISO_nl) {
00301       
00302 
00303       if(s.httpheaderline[0] == ISO_cr) {
00304         
00305 
00306 
00307         s.state = WEBCLIENT_STATE_DATA;
00308         return len;
00309       }
00310 
00311       s.httpheaderline[s.httpheaderlineptr - 1] = 0;
00312       
00313       if(casecmp(s.httpheaderline, http_content_type,
00314                      sizeof(http_content_type) - 1) == 0) {
00315         
00316         cptr = strchr(s.httpheaderline, ';');
00317         if(cptr != NULL) {
00318           *cptr = 0;
00319         }
00320         strncpy(s.mimetype, s.httpheaderline +
00321                 sizeof(http_content_type) - 1, sizeof(s.mimetype));
00322       } else if(casecmp(s.httpheaderline, http_location,
00323                             sizeof(http_location) - 1) == 0) {
00324         cptr = s.httpheaderline +
00325           sizeof(http_location) - 1;
00326         
00327         if(strncmp(cptr, http_http, 7) == 0) {
00328           cptr += 7;
00329           for(i = 0; i < s.httpheaderlineptr - 7; ++i) {
00330             if(*cptr == 0 ||
00331                *cptr == '/' ||
00332                *cptr == ' ' ||
00333                *cptr == ':') {
00334               s.host[i] = 0;
00335               break;
00336             }
00337             s.host[i] = *cptr;
00338             ++cptr;
00339           }
00340         }
00341         strncpy(s.file, cptr, sizeof(s.file));
00342         
00343       }
00344 
00345 
00346       
00347 
00348       s.httpheaderlineptr = 0;
00349     } else {
00350       ++s.httpheaderlineptr;
00351     }
00352   }
00353   return len;
00354 }
00355 
00356 static void
00357 newdata(void)
00358 {
00359   u16_t len;
00360 
00361   len = uip_datalen();
00362 
00363   if(s.state == WEBCLIENT_STATE_STATUSLINE) {
00364     len = parse_statusline(len);
00365   }
00366   
00367   if(s.state == WEBCLIENT_STATE_HEADERS && len > 0) {
00368     len = parse_headers(len);
00369   }
00370 
00371   if(len > 0 && s.state == WEBCLIENT_STATE_DATA &&
00372      s.httpflag != HTTPFLAG_MOVED) {
00373     webclient_datahandler((char *)uip_appdata, len);
00374   }
00375 }
00376 
00377 void
00378 webclient_appcall(void)
00379 {
00380   if(uip_connected()) {
00381     s.timer = 0;
00382     s.state = WEBCLIENT_STATE_STATUSLINE;
00383     senddata();
00384     webclient_connected();
00385     return;
00386   }
00387 
00388   if(s.state == WEBCLIENT_STATE_CLOSE) {
00389     webclient_closed();
00390     uip_abort();
00391     return;
00392   }
00393 
00394   if(uip_aborted()) {
00395     webclient_aborted();
00396   }
00397   if(uip_timedout()) {
00398     webclient_timedout();
00399   }
00400 
00401   
00402   if(uip_acked()) {
00403     s.timer = 0;
00404     acked();
00405   }
00406   if(uip_newdata()) {
00407     s.timer = 0;
00408     newdata();
00409   }
00410   if(uip_rexmit() ||
00411      uip_newdata() ||
00412      uip_acked()) {
00413     senddata();
00414   } else if(uip_poll()) {
00415     ++s.timer;
00416     if(s.timer == WEBCLIENT_TIMEOUT) {
00417       webclient_timedout();
00418       uip_abort();
00419       return;
00420     }
00421         
00422   }
00423 
00424   if(uip_closed()) {
00425     if(s.httpflag != HTTPFLAG_MOVED) {
00426       
00427       webclient_datahandler(NULL, 0);
00428     } else {
00429       if(resolv_lookup(s.host) == NULL) {
00430         resolv_query(s.host);
00431       }
00432       webclient_get(s.host, s.port, s.file);
00433     }
00434   }
00435 }
00436 
00437 
00438 
00439