A version of LWIP, provided for backwards compatibility.

Dependents:   AA_DemoBoard DemoBoard HelloServerDemo DemoBoard_RangeIndicator ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers HTTPClient.cpp Source File

HTTPClient.cpp

00001 #include "HTTPClient.h"
00002 #include "NetServer.h"
00003 #include "util.h"
00004 
00005 using namespace mbed;
00006 using namespace std;
00007 
00008 #define POST   0x1
00009 #define FDATA  0x2
00010 #define FRES   0x4
00011 #define GET    0x0
00012 #define CDATA  0x0
00013 #define CRES   0x0
00014 
00015 long fleft(FILE *fd) {
00016   long len, cur;
00017   cur = ftell(fd);
00018   fseek(fd, 0, SEEK_END);
00019   len = ftell(fd);
00020   fseek(fd, cur, SEEK_SET);
00021   return len;
00022 }
00023 
00024 void HTTPClient::err(err_t err) {
00025   release_callbacks();
00026 }
00027 
00028 err_t HTTPClient::poll() {
00029   if(_timeout++==30) {
00030     release_callbacks();
00031     close();
00032     _ready = true;
00033   }
00034   return ERR_OK;
00035 }
00036 
00037 void HTTPClient::dnsreply(const char *hostname, struct ip_addr *ipaddr) {
00038   _ready = true;
00039   _ipaddr = *ipaddr;
00040   _state = (ipaddr==NULL)? 99 : 0;
00041 }
00042 
00043 err_t HTTPClient::connected(err_t err) {
00044   TCPConnection::connected(err);
00045   _ready = false;
00046   _state = 0;
00047   _resultoff = 0;
00048   if(_mode&POST) {
00049     write((void *)"POST ", 5,  TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
00050   } else {
00051     write((void *)"GET ", 4, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
00052   }
00053   write((void *)_path, strlen(_path), TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
00054   write((void *)" HTTP/1.1\r\nHost: ", 17, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
00055   write((void *)_host, _hostlen, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
00056   if(_auth&&(*_auth!='\0')) {
00057     write((void *)"\r\nAuthorization: Basic ", 23, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE); 
00058     write((void *)_auth, strlen(_auth), TCP_WRITE_FLAG_COPY |TCP_WRITE_FLAG_MORE); 
00059   }
00060   if(_headerfields&&(*_headerfields!='\0')) {
00061     write((void *)"\r\n", 2, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE); 
00062     write((void *)_headerfields, strlen(_headerfields), TCP_WRITE_FLAG_COPY |TCP_WRITE_FLAG_MORE); 
00063   }
00064   write((void *)"\r\nConnection: Close\r\n", 21, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_COPY); 
00065   if(_data) {
00066     char clen[256];
00067     int len, blen;
00068     if(_mode&FDATA) {
00069       //printf("Send file\n");
00070       len = fleft((FILE *)_data);
00071       sprintf(clen, "Content-Length: %d\r\n\r\n\0", len);
00072       write((void *)clen, strlen(clen), TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_COPY); 
00073       if(len) {
00074         do {
00075           int sb = sndbuf();
00076           blen = fread(clen, sizeof(char), (int)min(sb, 100), (FILE *)_data);
00077           write(clen, blen, (TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE));
00078           len -= blen;
00079         } while(len > 1 && blen);  
00080       }
00081     } else {
00082       len = strlen((const char *)_data);
00083       sprintf(clen, "Content-Length: %d\r\n\r\n\0", len);
00084       write((void *)clen, strlen(clen), TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_COPY); 
00085       write((void *)_data, len, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE); 
00086     }
00087   }
00088   write((void *)"\r\n", 2, TCP_WRITE_FLAG_COPY);
00089   _timeout = 0; 
00090   return ERR_OK; 
00091 }
00092 
00093 err_t HTTPClient::recv(struct pbuf *p, err_t err) {
00094   if(err == ERR_OK && p != NULL&&_state<10) {
00095     _timeout = 0;
00096     struct pbuf *q = p;
00097     char *d = (char *)q->payload;
00098     recved(p->tot_len);
00099     while(q&&_state<10) {
00100       unsigned int end = ((unsigned int)(q->payload)+(unsigned int)(q->len));
00101       switch(_state) {
00102         case 0: {
00103           for(; _state==0 && ((unsigned int)d < end); d++) {
00104             if((*((char *)(d-0))=='\n')&&(*((char *)(d-1))=='\r')&&
00105                (*((char *)(d-2))=='\n')&&(*((char *)(d-3))=='\r')) {
00106               _state = 1;
00107               d += 1;
00108               break;
00109             }
00110           }
00111         } break;
00112         case 1: {
00113           if(_result) {
00114             if(_mode&FRES) {
00115               fwrite(d, sizeof(char), end - (unsigned int)d, (FILE *)_result);
00116               _resultoff  += (end - (unsigned int)d);
00117               d = (char *)end;
00118             } else {
00119               unsigned int len = min(_resultleft, (end-(unsigned int)d));
00120               memcpy((char *)_result + _resultoff, d, len);
00121               _resultleft -= len;
00122               _resultoff  += len;
00123               d += len;
00124   
00125               if(!_resultleft) {
00126                 _state = 10;
00127               }
00128             }
00129           } else {
00130              _state = 10;
00131           }
00132         } break;
00133         default: {
00134           break;
00135         }
00136       }
00137       if(_state<10&&(unsigned int)d==end) {
00138         q = q->next;
00139         if(q) {
00140           d = static_cast<char *>(q->payload);
00141         }
00142       }
00143     }
00144   }
00145   
00146   if(p!=NULL) {
00147     pbuf_free(p);
00148   }
00149   
00150   if(_state>10||p==NULL||err!=ERR_OK) {
00151     release_callbacks();
00152     close();
00153     _ready = true;
00154   }
00155   return ERR_OK;
00156 }
00157 
00158 unsigned int HTTPClient::make(const char *request) {
00159   _request    = request;
00160   _resultoff  = 0;
00161   _ready      = false;
00162   _state      = 0;
00163   _hostlen    = 0;
00164   _port       = 0;
00165   NetServer::ready();
00166 
00167   int hostlen = 0;
00168   if(strlen(_request)<10||strncmp("http://", _request, 7)!=0) {
00169     printf("Only http requests are allowed\n");
00170     return 0;
00171   }
00172   _path = _host = _request + 6;
00173   _host++;
00174   while(!_state == 1) {
00175     switch(*(++_path)) {
00176       case ':':
00177         _port = atoi(_path+1);
00178         break;
00179       case '/':
00180       case '\0':
00181         _port = (_port)?_port:80;
00182         _state  = 1;
00183         break;
00184       default:
00185         break;
00186     }
00187     if(!_port) {
00188       hostlen++;
00189     }
00190     if(!_state == 1) {
00191       _hostlen++;
00192     }
00193   }
00194   _state = 0;
00195   
00196   if(hostlen>256) {
00197     printf("Hostname longer than allowed\n");
00198     return 0;
00199   }
00200   
00201   char host[257];
00202   memcpy(host, _host, hostlen);
00203   host[hostlen] = 0;
00204   struct in_addr in;
00205   if(!inet_aton(host, &in)) {
00206     _ready = false;
00207     if(dnsrequest(host, &_ipaddr)==ERR_INPROGRESS) {
00208       while(!_ready) {
00209         NetServer::poll();
00210         wait(0.01);
00211       }
00212       if(_state==99) {
00213         printf("Server not found\n");
00214         return 0;
00215       }
00216     }
00217   } else {
00218     _ipaddr.addr = in.s_addr;
00219   }
00220 
00221   _ready = false;
00222   connect();
00223   set_poll_interval(10);
00224   tcp_setprio(_pcb, TCP_PRIO_MIN);
00225   while(!_ready) {
00226     NetServer::poll();
00227     wait(0.01);
00228   }
00229   close();
00230   if(_state==99) {
00231     printf("Connection error\n");
00232     return 0;
00233   }  
00234   
00235   if(!_mode&FRES&&_result) {
00236     ((char *)_result)[_resultoff]  = '\0';
00237   }
00238   return ((!_mode&FRES)&&!_result)?1:_resultoff;
00239   
00240 }
00241 
00242 void HTTPClient::auth(const char *user, const char *password) {
00243   if(user) {
00244     char up[256];
00245     sprintf(up, "%s:%s", user, password);
00246     _auth = new char[base64enc_len(up)+1];
00247     base64enc(up, strlen(up), _auth);
00248   } else if(_auth) {
00249     delete _auth;
00250     _auth = NULL;
00251   }
00252 }
00253 
00254 void HTTPClient::headers(const char *fields) {
00255   _headerfields = fields;
00256 }
00257 
00258 unsigned int HTTPClient::get(const char *url, char *result, int rsize) {
00259   _mode = GET | CDATA | CRES;
00260   _data = (void *)NULL;
00261   _result = (void *)result;
00262   _resultleft = rsize -1;
00263 
00264   return make(url);
00265 }
00266 
00267 unsigned int HTTPClient::get(const char *url, FILE *result) {
00268   _mode = GET | CDATA | FRES;
00269   _data = (void *)NULL;
00270   _result = (void *)result;
00271   _resultleft = 0;
00272 
00273   return make(url);
00274 }
00275 
00276 unsigned int HTTPClient::post(const char *url, const char *data, char *result, int rsize) {
00277   _mode = POST | CDATA | CRES;
00278   _data = (void *)data;
00279   _result = (void *)result;
00280   _resultleft = rsize -1;
00281   
00282   return make(url);
00283 }
00284 
00285 unsigned int HTTPClient::post(const char *url, const char *data, FILE *result) {
00286   _mode = POST | CDATA | FRES;
00287   _data = (void *)data;
00288   _result = (void *)result;
00289   _resultleft = 0;
00290   
00291   return make(url);
00292 }
00293 
00294 unsigned int HTTPClient::post(const char *url, FILE *data, FILE *result) {
00295   _mode = POST | FDATA | FRES;
00296   _data = (void *)data;
00297   _result = (void *)result;
00298   _resultleft = 0;
00299   
00300   return make(url);
00301 }
00302 
00303 unsigned int HTTPClient::post(const char *url, FILE *data, char *result, int rsize) {
00304   _mode = POST | FDATA | CRES;
00305   _data = (void *)data;
00306   _result = (void *)result;
00307   _resultleft = rsize -1;
00308   
00309   return make(url);
00310 }
00311 
00312