Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of lwip by
HTTPClient.cpp
00001 #include "HTTPClient.h" 00002 #include "NetServer.h" 00003 #include "iputil.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 00025 HTTPClient::HTTPClient(const char *hostname, struct ip_addr ip, struct ip_addr nm, struct ip_addr gw, struct ip_addr dns) 00026 : TCPConnection(), _auth(NULL), _timeout(0), _data(NULL), _headerfields(NULL), _timeout_max(60000) { 00027 NetServer *net = NULL; 00028 if(ip.addr != ip_addr_any.addr && nm.addr != ip_addr_any.addr && gw.addr != ip_addr_any.addr) { 00029 net = NetServer::create(ip, nm, gw); 00030 if(dns.addr != ip_addr_any.addr) { 00031 net->setDNS1(dns); 00032 } 00033 } else if(hostname) { 00034 net = NetServer::create(); 00035 } 00036 if(hostname) { 00037 net->setHostname(hostname); 00038 } 00039 } 00040 00041 void HTTPClient::timeout(int value) { 00042 _timeout_max = value; 00043 } 00044 00045 void HTTPClient::err(err_t err) { 00046 release_callbacks(); 00047 } 00048 00049 err_t HTTPClient::poll() { 00050 if(NetServer::time() - _timeout > _timeout_max) { 00051 release_callbacks(); 00052 close(); 00053 printf("TIMEOUT\n"); 00054 _ready = true; 00055 _state = 99; 00056 } 00057 return ERR_OK; 00058 } 00059 00060 void HTTPClient::dnsreply(const char *hostname, struct ip_addr *ipaddr) { 00061 _ready = true; 00062 _ipaddr = *ipaddr; 00063 _state = (ipaddr==NULL)? 99 : 0; 00064 _timeout = NetServer::time(); 00065 } 00066 00067 err_t HTTPClient::connected(err_t err) { 00068 TCPConnection::connected(err); 00069 _ready = false; 00070 _state = 0; 00071 _resultoff = 0; 00072 if(_mode&POST) { 00073 write((void *)"POST ", 5, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE); 00074 } else { 00075 write((void *)"GET ", 4, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE); 00076 } 00077 if(strlen(_path) == 0) { 00078 write((void *)"/", 1, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE); 00079 } else { 00080 write((void *)_path, strlen(_path), TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE); 00081 } 00082 write((void *)" HTTP/1.1\r\nHost: ", 17, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE); 00083 write((void *)_host, _hostlen, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE); 00084 if(_auth&&(*_auth!='\0')) { 00085 write((void *)"\r\nAuthorization: Basic ", 23, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE); 00086 write((void *)_auth, strlen(_auth), TCP_WRITE_FLAG_COPY |TCP_WRITE_FLAG_MORE); 00087 } 00088 if(_headerfields&&(*_headerfields!='\0')) { 00089 write((void *)"\r\n", 2, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE); 00090 write((void *)_headerfields, strlen(_headerfields), TCP_WRITE_FLAG_COPY |TCP_WRITE_FLAG_MORE); 00091 } 00092 write((void *)"\r\nConnection: Close\r\n", 21, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_COPY); 00093 if(_data) { 00094 char clen[256]; 00095 int len, blen; 00096 if(_mode&FDATA) { 00097 //printf("Send file\n"); 00098 len = fleft((FILE *)_data); 00099 sprintf(clen, "Content-Length: %d\r\n\r\n\0", len); 00100 write((void *)clen, strlen(clen), TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_COPY); 00101 if(len) { 00102 do { 00103 int sb = sndbuf(); 00104 blen = fread(clen, sizeof(char), (int)min(sb, 100), (FILE *)_data); 00105 write(clen, blen, (TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE)); 00106 len -= blen; 00107 } while(len > 1 && blen); 00108 } 00109 } else { 00110 len = strlen((const char *)_data); 00111 sprintf(clen, "Content-Length: %d\r\n\r\n\0", len); 00112 write((void *)clen, strlen(clen), TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_COPY); 00113 write((void *)_data, len, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE); 00114 } 00115 } 00116 write((void *)"\r\n", 2, TCP_WRITE_FLAG_COPY); 00117 _timeout = NetServer::time(); 00118 return ERR_OK; 00119 } 00120 00121 #define _min(x, y) (((x)<(y))?(x):(y)) 00122 err_t HTTPClient::recv(struct pbuf *p, err_t err) { 00123 if(err == ERR_OK && p != NULL&&_state<10) { 00124 _timeout = NetServer::time(); 00125 struct pbuf *q = p; 00126 char *d = (char *)q->payload; 00127 recved(p->tot_len); 00128 00129 while(q&&_state<10) { 00130 unsigned int end = ((unsigned int)(q->payload)+(unsigned int)(q->len)); 00131 switch(_state) { 00132 case 0: { 00133 for(; _state==0 && ((unsigned int)d < end); d++) { 00134 if((*((char *)(d-0))=='\n')&&(*((char *)(d-1))=='\r')&& 00135 (*((char *)(d-2))=='\n')&&(*((char *)(d-3))=='\r')) { 00136 _state = 1; 00137 d += 1; 00138 break; 00139 } 00140 } 00141 } break; 00142 case 1: { 00143 if(_result) { 00144 if(_mode&FRES) { 00145 fwrite(d, sizeof(char), end - (unsigned int)d, (FILE *)_result); 00146 _resultoff += (end - (unsigned int)d); 00147 d = (char *)end; 00148 } else { 00149 unsigned int len = _min(_resultleft, (end-(unsigned int)d)); 00150 memcpy((char *)_result + _resultoff, d, len); 00151 _resultleft -= len; 00152 _resultoff += len; 00153 d += len; 00154 00155 if(!_resultleft) { 00156 _state = 10; 00157 } 00158 } 00159 } else { 00160 _state = 10; 00161 } 00162 } break; 00163 default: { 00164 break; 00165 } 00166 } 00167 if(_state<10&&(unsigned int)d==end) { 00168 q = q->next; 00169 if(q) { 00170 d = static_cast<char *>(q->payload); 00171 } 00172 } 00173 } 00174 } 00175 00176 if(p!=NULL) { 00177 pbuf_free(p); 00178 } 00179 00180 if(_state>10||p==NULL||err!=ERR_OK) { 00181 release_callbacks(); 00182 close(); 00183 _ready = true; 00184 } 00185 return ERR_OK; 00186 } 00187 00188 unsigned int HTTPClient::make(const char *request) { 00189 _request = request; 00190 _resultoff = 0; 00191 _ready = false; 00192 _state = 0; 00193 _hostlen = 0; 00194 _port = 0; 00195 _timeout = NetServer::time(); 00196 NetServer::ready(); 00197 00198 int hostlen = 0; 00199 if(strlen(_request)<10||strncmp("http://", _request, 7)!=0) { 00200 printf("Only http requests are allowed\n"); 00201 return 0; 00202 } 00203 _path = _host = _request + 6; 00204 _host++; 00205 while(!_state == 1) { 00206 switch(*(++_path)) { 00207 case ':': 00208 _port = atoi(_path+1); 00209 break; 00210 case '/': 00211 case '\0': 00212 _port = (_port)?_port:80; 00213 _state = 1; 00214 break; 00215 default: 00216 break; 00217 } 00218 if(!_port) { 00219 hostlen++; 00220 } 00221 if(!_state == 1) { 00222 _hostlen++; 00223 } 00224 } 00225 _state = 0; 00226 00227 if(hostlen>256) { 00228 printf("Hostname longer than allowed\n"); 00229 return 0; 00230 } 00231 00232 char host[257]; 00233 memcpy(host, _host, hostlen); 00234 host[hostlen] = 0; 00235 _timeout = NetServer::time(); 00236 struct in_addr in; 00237 if(!inet_aton(host, &in)) { 00238 _ready = false; 00239 if(dnsrequest(host, &_ipaddr)==ERR_INPROGRESS) { 00240 while(!_ready) { 00241 NetServer::poll(); 00242 wait_ms(10); 00243 } 00244 if(_state==99) { 00245 printf("Server not found\n"); 00246 return 0; 00247 } 00248 } 00249 } else { 00250 _ipaddr.addr = in.s_addr; 00251 } 00252 00253 _ready = false; 00254 _timeout = NetServer::time(); 00255 connect(); 00256 set_poll_interval(10); 00257 tcp_setprio(_pcb, TCP_PRIO_MIN); 00258 while(!_ready) { 00259 NetServer::poll(); 00260 wait_ms(10); 00261 } 00262 //release_callbacks(); 00263 close(); 00264 if(_state==99) { 00265 printf("Connection error\n"); 00266 return 0; 00267 } 00268 00269 if(!_mode&FRES&&_result) { 00270 ((char *)_result)[_resultoff+1] = '\0'; 00271 } 00272 return ((!_mode&FRES)&&!_result)?1:_resultoff; 00273 00274 } 00275 00276 void HTTPClient::auth(const char *user, const char *password) { 00277 if(user) { 00278 char up[256]; 00279 sprintf(up, "%s:%s", user, password); 00280 _auth = new char[base64enc_len(up)+1]; 00281 base64enc(up, strlen(up), _auth); 00282 } else if(_auth) { 00283 delete _auth; 00284 _auth = NULL; 00285 } 00286 } 00287 00288 void HTTPClient::headers(const char *fields) { 00289 _headerfields = fields; 00290 } 00291 00292 unsigned int HTTPClient::get(const char *url, char *result, int rsize) { 00293 _mode = GET | CDATA | CRES; 00294 _data = (void *)NULL; 00295 _result = (void *)result; 00296 _resultleft = rsize -1; 00297 00298 return make(url); 00299 } 00300 00301 unsigned int HTTPClient::get(const char *url, FILE *result) { 00302 _mode = GET | CDATA | FRES; 00303 _data = (void *)NULL; 00304 _result = (void *)result; 00305 _resultleft = 0; 00306 00307 return make(url); 00308 } 00309 00310 unsigned int HTTPClient::post(const char *url, const char *data, char *result, int rsize) { 00311 _mode = POST | CDATA | CRES; 00312 _data = (void *)data; 00313 _result = (void *)result; 00314 _resultleft = rsize -1; 00315 00316 return make(url); 00317 } 00318 00319 unsigned int HTTPClient::post(const char *url, const char *data, FILE *result) { 00320 _mode = POST | CDATA | FRES; 00321 _data = (void *)data; 00322 _result = (void *)result; 00323 _resultleft = 0; 00324 00325 return make(url); 00326 } 00327 00328 unsigned int HTTPClient::post(const char *url, FILE *data, FILE *result) { 00329 _mode = POST | FDATA | FRES; 00330 _data = (void *)data; 00331 _result = (void *)result; 00332 _resultleft = 0; 00333 00334 return make(url); 00335 } 00336 00337 unsigned int HTTPClient::post(const char *url, FILE *data, char *result, int rsize) { 00338 _mode = POST | FDATA | CRES; 00339 _data = (void *)data; 00340 _result = (void *)result; 00341 _resultleft = rsize -1; 00342 00343 return make(url); 00344 } 00345
Generated on Tue Jul 12 2022 16:07:04 by
1.7.2
