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