My fork of the HTTPServer (working)

Dependents:   DGWWebServer LAN2

Committer:
screamer
Date:
Tue Nov 20 12:18:53 2012 +0000
Revision:
1:284f2df30cf9
Parent:
0:7a64fbb4069d
local changes

Who changed what in which revision?

UserRevisionLine numberNew contents of line
screamer 0:7a64fbb4069d 1 #include "HTTPClient.h"
screamer 0:7a64fbb4069d 2 #include "NetServer.h"
screamer 0:7a64fbb4069d 3 #include "iputil.h"
screamer 0:7a64fbb4069d 4
screamer 0:7a64fbb4069d 5 using namespace mbed;
screamer 0:7a64fbb4069d 6 using namespace std;
screamer 0:7a64fbb4069d 7
screamer 0:7a64fbb4069d 8 #define POST 0x1
screamer 0:7a64fbb4069d 9 #define FDATA 0x2
screamer 0:7a64fbb4069d 10 #define FRES 0x4
screamer 0:7a64fbb4069d 11 #define GET 0x0
screamer 0:7a64fbb4069d 12 #define CDATA 0x0
screamer 0:7a64fbb4069d 13 #define CRES 0x0
screamer 0:7a64fbb4069d 14
screamer 0:7a64fbb4069d 15 long fleft(FILE *fd) {
screamer 0:7a64fbb4069d 16 long len, cur;
screamer 0:7a64fbb4069d 17 cur = ftell(fd);
screamer 0:7a64fbb4069d 18 fseek(fd, 0, SEEK_END);
screamer 0:7a64fbb4069d 19 len = ftell(fd);
screamer 0:7a64fbb4069d 20 fseek(fd, cur, SEEK_SET);
screamer 0:7a64fbb4069d 21 return len;
screamer 0:7a64fbb4069d 22 }
screamer 0:7a64fbb4069d 23
screamer 0:7a64fbb4069d 24 void HTTPClient::err(err_t err) {
screamer 0:7a64fbb4069d 25 release_callbacks();
screamer 0:7a64fbb4069d 26 }
screamer 0:7a64fbb4069d 27
screamer 0:7a64fbb4069d 28 err_t HTTPClient::poll() {
screamer 0:7a64fbb4069d 29 if(_timeout++==300) {
screamer 0:7a64fbb4069d 30 release_callbacks();
screamer 0:7a64fbb4069d 31 close();
screamer 0:7a64fbb4069d 32 _ready = true;
screamer 0:7a64fbb4069d 33 }
screamer 0:7a64fbb4069d 34 return ERR_OK;
screamer 0:7a64fbb4069d 35 }
screamer 0:7a64fbb4069d 36
screamer 0:7a64fbb4069d 37 void HTTPClient::dnsreply(const char *hostname, struct ip_addr *ipaddr) {
screamer 0:7a64fbb4069d 38 _ready = true;
screamer 0:7a64fbb4069d 39 _ipaddr = *ipaddr;
screamer 0:7a64fbb4069d 40 _state = (ipaddr==NULL)? 99 : 0;
screamer 0:7a64fbb4069d 41 }
screamer 0:7a64fbb4069d 42
screamer 0:7a64fbb4069d 43 err_t HTTPClient::connected(err_t err) {
screamer 0:7a64fbb4069d 44 TCPConnection::connected(err);
screamer 0:7a64fbb4069d 45 _ready = false;
screamer 0:7a64fbb4069d 46 _state = 0;
screamer 0:7a64fbb4069d 47 _resultoff = 0;
screamer 0:7a64fbb4069d 48 if(_mode&POST) {
screamer 0:7a64fbb4069d 49 write((void *)"POST ", 5, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
screamer 0:7a64fbb4069d 50 } else {
screamer 0:7a64fbb4069d 51 write((void *)"GET ", 4, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
screamer 0:7a64fbb4069d 52 }
screamer 0:7a64fbb4069d 53 write((void *)_path, strlen(_path), TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
screamer 0:7a64fbb4069d 54 write((void *)" HTTP/1.1\r\nHost: ", 17, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
screamer 0:7a64fbb4069d 55 write((void *)_host, _hostlen, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
screamer 0:7a64fbb4069d 56 if(_auth&&(*_auth!='\0')) {
screamer 0:7a64fbb4069d 57 write((void *)"\r\nAuthorization: Basic ", 23, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
screamer 0:7a64fbb4069d 58 write((void *)_auth, strlen(_auth), TCP_WRITE_FLAG_COPY |TCP_WRITE_FLAG_MORE);
screamer 0:7a64fbb4069d 59 }
screamer 0:7a64fbb4069d 60 if(_headerfields&&(*_headerfields!='\0')) {
screamer 0:7a64fbb4069d 61 write((void *)"\r\n", 2, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
screamer 0:7a64fbb4069d 62 write((void *)_headerfields, strlen(_headerfields), TCP_WRITE_FLAG_COPY |TCP_WRITE_FLAG_MORE);
screamer 0:7a64fbb4069d 63 }
screamer 0:7a64fbb4069d 64 write((void *)"\r\nConnection: Close\r\n", 21, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_COPY);
screamer 0:7a64fbb4069d 65 if(_data) {
screamer 0:7a64fbb4069d 66 char clen[256];
screamer 0:7a64fbb4069d 67 int len, blen;
screamer 0:7a64fbb4069d 68 if(_mode&FDATA) {
screamer 0:7a64fbb4069d 69 //printf("Send file\n");
screamer 0:7a64fbb4069d 70 len = fleft((FILE *)_data);
screamer 0:7a64fbb4069d 71 sprintf(clen, "Content-Length: %d\r\n\r\n\0", len);
screamer 0:7a64fbb4069d 72 write((void *)clen, strlen(clen), TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_COPY);
screamer 0:7a64fbb4069d 73 if(len) {
screamer 0:7a64fbb4069d 74 do {
screamer 0:7a64fbb4069d 75 int sb = sndbuf();
screamer 0:7a64fbb4069d 76 blen = fread(clen, sizeof(char), (int)min(sb, 100), (FILE *)_data);
screamer 0:7a64fbb4069d 77 write(clen, blen, (TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE));
screamer 0:7a64fbb4069d 78 len -= blen;
screamer 0:7a64fbb4069d 79 } while(len > 1 && blen);
screamer 0:7a64fbb4069d 80 }
screamer 0:7a64fbb4069d 81 } else {
screamer 0:7a64fbb4069d 82 len = strlen((const char *)_data);
screamer 0:7a64fbb4069d 83 sprintf(clen, "Content-Length: %d\r\n\r\n\0", len);
screamer 0:7a64fbb4069d 84 write((void *)clen, strlen(clen), TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_COPY);
screamer 0:7a64fbb4069d 85 write((void *)_data, len, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
screamer 0:7a64fbb4069d 86 }
screamer 0:7a64fbb4069d 87 }
screamer 0:7a64fbb4069d 88 write((void *)"\r\n", 2, TCP_WRITE_FLAG_COPY);
screamer 0:7a64fbb4069d 89 _timeout = 0;
screamer 0:7a64fbb4069d 90 return ERR_OK;
screamer 0:7a64fbb4069d 91 }
screamer 0:7a64fbb4069d 92
screamer 0:7a64fbb4069d 93 err_t HTTPClient::recv(struct pbuf *p, err_t err) {
screamer 0:7a64fbb4069d 94 if(err == ERR_OK && p != NULL&&_state<10) {
screamer 0:7a64fbb4069d 95 _timeout = 0;
screamer 0:7a64fbb4069d 96 struct pbuf *q = p;
screamer 0:7a64fbb4069d 97 char *d = (char *)q->payload;
screamer 0:7a64fbb4069d 98 recved(p->tot_len);
screamer 0:7a64fbb4069d 99 while(q&&_state<10) {
screamer 0:7a64fbb4069d 100 unsigned int end = ((unsigned int)(q->payload)+(unsigned int)(q->len));
screamer 0:7a64fbb4069d 101 switch(_state) {
screamer 0:7a64fbb4069d 102 case 0: {
screamer 0:7a64fbb4069d 103 for(; _state==0 && ((unsigned int)d < end); d++) {
screamer 0:7a64fbb4069d 104 if((*((char *)(d-0))=='\n')&&(*((char *)(d-1))=='\r')&&
screamer 0:7a64fbb4069d 105 (*((char *)(d-2))=='\n')&&(*((char *)(d-3))=='\r')) {
screamer 0:7a64fbb4069d 106 _state = 1;
screamer 0:7a64fbb4069d 107 d += 1;
screamer 0:7a64fbb4069d 108 break;
screamer 0:7a64fbb4069d 109 }
screamer 0:7a64fbb4069d 110 }
screamer 0:7a64fbb4069d 111 } break;
screamer 0:7a64fbb4069d 112 case 1: {
screamer 0:7a64fbb4069d 113 if(_result) {
screamer 0:7a64fbb4069d 114 if(_mode&FRES) {
screamer 0:7a64fbb4069d 115 fwrite(d, sizeof(char), end - (unsigned int)d, (FILE *)_result);
screamer 0:7a64fbb4069d 116 _resultoff += (end - (unsigned int)d);
screamer 0:7a64fbb4069d 117 d = (char *)end;
screamer 0:7a64fbb4069d 118 } else {
screamer 0:7a64fbb4069d 119 unsigned int len = min(_resultleft, (end-(unsigned int)d));
screamer 0:7a64fbb4069d 120 memcpy((char *)_result + _resultoff, d, len);
screamer 0:7a64fbb4069d 121 _resultleft -= len;
screamer 0:7a64fbb4069d 122 _resultoff += len;
screamer 0:7a64fbb4069d 123 d += len;
screamer 0:7a64fbb4069d 124
screamer 0:7a64fbb4069d 125 if(!_resultleft) {
screamer 0:7a64fbb4069d 126 _state = 10;
screamer 0:7a64fbb4069d 127 }
screamer 0:7a64fbb4069d 128 }
screamer 0:7a64fbb4069d 129 } else {
screamer 0:7a64fbb4069d 130 _state = 10;
screamer 0:7a64fbb4069d 131 }
screamer 0:7a64fbb4069d 132 } break;
screamer 0:7a64fbb4069d 133 default: {
screamer 0:7a64fbb4069d 134 break;
screamer 0:7a64fbb4069d 135 }
screamer 0:7a64fbb4069d 136 }
screamer 0:7a64fbb4069d 137 if(_state<10&&(unsigned int)d==end) {
screamer 0:7a64fbb4069d 138 q = q->next;
screamer 0:7a64fbb4069d 139 if(q) {
screamer 0:7a64fbb4069d 140 d = static_cast<char *>(q->payload);
screamer 0:7a64fbb4069d 141 }
screamer 0:7a64fbb4069d 142 }
screamer 0:7a64fbb4069d 143 }
screamer 0:7a64fbb4069d 144 }
screamer 0:7a64fbb4069d 145
screamer 0:7a64fbb4069d 146 if(p!=NULL) {
screamer 0:7a64fbb4069d 147 pbuf_free(p);
screamer 0:7a64fbb4069d 148 }
screamer 0:7a64fbb4069d 149
screamer 0:7a64fbb4069d 150 if(_state>10||p==NULL||err!=ERR_OK) {
screamer 0:7a64fbb4069d 151 release_callbacks();
screamer 0:7a64fbb4069d 152 close();
screamer 0:7a64fbb4069d 153 _ready = true;
screamer 0:7a64fbb4069d 154 }
screamer 0:7a64fbb4069d 155 return ERR_OK;
screamer 0:7a64fbb4069d 156 }
screamer 0:7a64fbb4069d 157
screamer 0:7a64fbb4069d 158 unsigned int HTTPClient::make(const char *request) {
screamer 0:7a64fbb4069d 159 _request = request;
screamer 0:7a64fbb4069d 160 _resultoff = 0;
screamer 0:7a64fbb4069d 161 _ready = false;
screamer 0:7a64fbb4069d 162 _state = 0;
screamer 0:7a64fbb4069d 163 _hostlen = 0;
screamer 0:7a64fbb4069d 164 _port = 0;
screamer 0:7a64fbb4069d 165 NetServer::ready();
screamer 0:7a64fbb4069d 166
screamer 0:7a64fbb4069d 167 int hostlen = 0;
screamer 0:7a64fbb4069d 168 if(strlen(_request)<10||strncmp("http://", _request, 7)!=0) {
screamer 0:7a64fbb4069d 169 printf("Only http requests are allowed\n");
screamer 0:7a64fbb4069d 170 return 0;
screamer 0:7a64fbb4069d 171 }
screamer 0:7a64fbb4069d 172 _path = _host = _request + 6;
screamer 0:7a64fbb4069d 173 _host++;
screamer 0:7a64fbb4069d 174 while(!_state == 1) {
screamer 0:7a64fbb4069d 175 switch(*(++_path)) {
screamer 0:7a64fbb4069d 176 case ':':
screamer 0:7a64fbb4069d 177 _port = atoi(_path+1);
screamer 0:7a64fbb4069d 178 break;
screamer 0:7a64fbb4069d 179 case '/':
screamer 0:7a64fbb4069d 180 case '\0':
screamer 0:7a64fbb4069d 181 _port = (_port)?_port:80;
screamer 0:7a64fbb4069d 182 _state = 1;
screamer 0:7a64fbb4069d 183 break;
screamer 0:7a64fbb4069d 184 default:
screamer 0:7a64fbb4069d 185 break;
screamer 0:7a64fbb4069d 186 }
screamer 0:7a64fbb4069d 187 if(!_port) {
screamer 0:7a64fbb4069d 188 hostlen++;
screamer 0:7a64fbb4069d 189 }
screamer 0:7a64fbb4069d 190 if(!_state == 1) {
screamer 0:7a64fbb4069d 191 _hostlen++;
screamer 0:7a64fbb4069d 192 }
screamer 0:7a64fbb4069d 193 }
screamer 0:7a64fbb4069d 194 _state = 0;
screamer 0:7a64fbb4069d 195
screamer 0:7a64fbb4069d 196 if(hostlen>256) {
screamer 0:7a64fbb4069d 197 printf("Hostname longer than allowed\n");
screamer 0:7a64fbb4069d 198 return 0;
screamer 0:7a64fbb4069d 199 }
screamer 0:7a64fbb4069d 200
screamer 0:7a64fbb4069d 201 char host[257];
screamer 0:7a64fbb4069d 202 memcpy(host, _host, hostlen);
screamer 0:7a64fbb4069d 203 host[hostlen] = 0;
screamer 0:7a64fbb4069d 204 struct in_addr in;
screamer 0:7a64fbb4069d 205 if(!inet_aton(host, &in)) {
screamer 0:7a64fbb4069d 206 _ready = false;
screamer 0:7a64fbb4069d 207 if(dnsrequest(host, &_ipaddr)==ERR_INPROGRESS) {
screamer 0:7a64fbb4069d 208 while(!_ready) {
screamer 0:7a64fbb4069d 209 NetServer::poll();
screamer 0:7a64fbb4069d 210 wait_ms(10);
screamer 0:7a64fbb4069d 211 }
screamer 0:7a64fbb4069d 212 if(_state==99) {
screamer 0:7a64fbb4069d 213 printf("Server not found\n");
screamer 0:7a64fbb4069d 214 return 0;
screamer 0:7a64fbb4069d 215 }
screamer 0:7a64fbb4069d 216 }
screamer 0:7a64fbb4069d 217 } else {
screamer 0:7a64fbb4069d 218 _ipaddr.addr = in.s_addr;
screamer 0:7a64fbb4069d 219 }
screamer 0:7a64fbb4069d 220
screamer 0:7a64fbb4069d 221 _ready = false;
screamer 0:7a64fbb4069d 222 connect();
screamer 0:7a64fbb4069d 223 set_poll_interval(10);
screamer 0:7a64fbb4069d 224 tcp_setprio(_pcb, TCP_PRIO_MIN);
screamer 0:7a64fbb4069d 225 while(!_ready) {
screamer 0:7a64fbb4069d 226 NetServer::poll();
screamer 0:7a64fbb4069d 227 wait_ms(10);
screamer 0:7a64fbb4069d 228 }
screamer 0:7a64fbb4069d 229 close();
screamer 0:7a64fbb4069d 230 if(_state==99) {
screamer 0:7a64fbb4069d 231 printf("Connection error\n");
screamer 0:7a64fbb4069d 232 return 0;
screamer 0:7a64fbb4069d 233 }
screamer 0:7a64fbb4069d 234
screamer 0:7a64fbb4069d 235 if(!_mode&FRES&&_result) {
screamer 0:7a64fbb4069d 236 ((char *)_result)[_resultoff] = '\0';
screamer 0:7a64fbb4069d 237 }
screamer 0:7a64fbb4069d 238 return ((!_mode&FRES)&&!_result)?1:_resultoff;
screamer 0:7a64fbb4069d 239
screamer 0:7a64fbb4069d 240 }
screamer 0:7a64fbb4069d 241
screamer 0:7a64fbb4069d 242 void HTTPClient::auth(const char *user, const char *password) {
screamer 0:7a64fbb4069d 243 if(user) {
screamer 0:7a64fbb4069d 244 char up[256];
screamer 0:7a64fbb4069d 245 sprintf(up, "%s:%s", user, password);
screamer 0:7a64fbb4069d 246 _auth = new char[base64enc_len(up)+1];
screamer 0:7a64fbb4069d 247 base64enc(up, strlen(up), _auth);
screamer 0:7a64fbb4069d 248 } else if(_auth) {
screamer 0:7a64fbb4069d 249 delete _auth;
screamer 0:7a64fbb4069d 250 _auth = NULL;
screamer 0:7a64fbb4069d 251 }
screamer 0:7a64fbb4069d 252 }
screamer 0:7a64fbb4069d 253
screamer 0:7a64fbb4069d 254 void HTTPClient::headers(const char *fields) {
screamer 0:7a64fbb4069d 255 _headerfields = fields;
screamer 0:7a64fbb4069d 256 }
screamer 0:7a64fbb4069d 257
screamer 0:7a64fbb4069d 258 unsigned int HTTPClient::get(const char *url, char *result, int rsize) {
screamer 0:7a64fbb4069d 259 _mode = GET | CDATA | CRES;
screamer 0:7a64fbb4069d 260 _data = (void *)NULL;
screamer 0:7a64fbb4069d 261 _result = (void *)result;
screamer 0:7a64fbb4069d 262 _resultleft = rsize -1;
screamer 0:7a64fbb4069d 263
screamer 0:7a64fbb4069d 264 return make(url);
screamer 0:7a64fbb4069d 265 }
screamer 0:7a64fbb4069d 266
screamer 0:7a64fbb4069d 267 unsigned int HTTPClient::get(const char *url, FILE *result) {
screamer 0:7a64fbb4069d 268 _mode = GET | CDATA | FRES;
screamer 0:7a64fbb4069d 269 _data = (void *)NULL;
screamer 0:7a64fbb4069d 270 _result = (void *)result;
screamer 0:7a64fbb4069d 271 _resultleft = 0;
screamer 0:7a64fbb4069d 272
screamer 0:7a64fbb4069d 273 return make(url);
screamer 0:7a64fbb4069d 274 }
screamer 0:7a64fbb4069d 275
screamer 0:7a64fbb4069d 276 unsigned int HTTPClient::post(const char *url, const char *data, char *result, int rsize) {
screamer 0:7a64fbb4069d 277 _mode = POST | CDATA | CRES;
screamer 0:7a64fbb4069d 278 _data = (void *)data;
screamer 0:7a64fbb4069d 279 _result = (void *)result;
screamer 0:7a64fbb4069d 280 _resultleft = rsize -1;
screamer 0:7a64fbb4069d 281
screamer 0:7a64fbb4069d 282 return make(url);
screamer 0:7a64fbb4069d 283 }
screamer 0:7a64fbb4069d 284
screamer 0:7a64fbb4069d 285 unsigned int HTTPClient::post(const char *url, const char *data, FILE *result) {
screamer 0:7a64fbb4069d 286 _mode = POST | CDATA | FRES;
screamer 0:7a64fbb4069d 287 _data = (void *)data;
screamer 0:7a64fbb4069d 288 _result = (void *)result;
screamer 0:7a64fbb4069d 289 _resultleft = 0;
screamer 0:7a64fbb4069d 290
screamer 0:7a64fbb4069d 291 return make(url);
screamer 0:7a64fbb4069d 292 }
screamer 0:7a64fbb4069d 293
screamer 0:7a64fbb4069d 294 unsigned int HTTPClient::post(const char *url, FILE *data, FILE *result) {
screamer 0:7a64fbb4069d 295 _mode = POST | FDATA | FRES;
screamer 0:7a64fbb4069d 296 _data = (void *)data;
screamer 0:7a64fbb4069d 297 _result = (void *)result;
screamer 0:7a64fbb4069d 298 _resultleft = 0;
screamer 0:7a64fbb4069d 299
screamer 0:7a64fbb4069d 300 return make(url);
screamer 0:7a64fbb4069d 301 }
screamer 0:7a64fbb4069d 302
screamer 0:7a64fbb4069d 303 unsigned int HTTPClient::post(const char *url, FILE *data, char *result, int rsize) {
screamer 0:7a64fbb4069d 304 _mode = POST | FDATA | CRES;
screamer 0:7a64fbb4069d 305 _data = (void *)data;
screamer 0:7a64fbb4069d 306 _result = (void *)result;
screamer 0:7a64fbb4069d 307 _resultleft = rsize -1;
screamer 0:7a64fbb4069d 308
screamer 0:7a64fbb4069d 309 return make(url);
screamer 0:7a64fbb4069d 310 }
screamer 0:7a64fbb4069d 311