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
HTTPServer.cpp
00001 #include "HTTPServer.h" 00002 #include "NetServer.h" 00003 00004 using namespace std; 00005 using namespace mbed; 00006 00007 //unsigned int gconnections = 0; 00008 00009 unsigned int mbed::hash(unsigned char *str) { 00010 unsigned int hash = 5381; 00011 int c; 00012 while((c = *(str++))!=(unsigned char)'\0') { 00013 hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ 00014 } 00015 return hash; 00016 } 00017 00018 HTTPConnection::HTTPConnection(HTTPServer *pparent, struct tcp_pcb *pcb) 00019 : TCPConnection(pparent, pcb), request_incomplete(true), data(NULL), 00020 request_handler(NULL), request_status(HTTP_NotFound), parent(pparent), 00021 _request_url(NULL), _request_type(0), _request_headerfields(NULL), 00022 _request_length(0), _request_arg_key(NULL), _request_arg_value(NULL), 00023 _request_arg_state(0), emptypolls(0) { 00024 _timeout_max = pparent->timeout(); 00025 } 00026 00027 HTTPConnection::~HTTPConnection() { 00028 deleteRequest(); 00029 emptypolls = NetServer::time(); 00030 } 00031 00032 const char *HTTPConnection::getField(char *key) const { 00033 unsigned int h = hash((unsigned char *)key); 00034 return _request_fields.find(h)->second; 00035 } 00036 00037 void HTTPConnection::addField(char *key, char *value) { 00038 unsigned int h = hash((unsigned char *)key); 00039 if(parent->isField(h)) { 00040 _request_fields.insert( make_pair(h, value)); 00041 } 00042 } 00043 00044 void HTTPConnection::send() { 00045 int i = sndbuf(); 00046 if(!request_incomplete&&i) { 00047 switch(request_handler->send(this, i)) { 00048 case HTTP_SuccessEnded: 00049 case HTTP_Failed: { 00050 deleteRequest(); 00051 release_callbacks(); 00052 NetServer::get()->free(this); 00053 close(); 00054 } break; 00055 default: 00056 emptypolls = NetServer::time(); 00057 break; 00058 } 00059 } else { 00060 if(NetServer::time() - emptypolls > _timeout_max) { 00061 release_callbacks(); 00062 NetServer::get()->free(this); 00063 close(); 00064 } 00065 } 00066 } 00067 00068 void HTTPConnection::store(void *d, struct pbuf *p) { 00069 int len = p->len-(((int)d)-((int)p->payload)); 00070 do { 00071 switch(request_handler->data(this, d, len)) { 00072 case HTTP_SuccessEnded: 00073 case HTTP_Failed: { 00074 deleteRequest(); 00075 release_callbacks(); 00076 NetServer::get()->free(this); 00077 close(); 00078 } break; 00079 default: 00080 break; 00081 } 00082 p = p->next; 00083 if(p) { 00084 len = p->len; 00085 d = static_cast<char *>(p->payload); 00086 } 00087 } while(_request_type&&p); 00088 } 00089 00090 void HTTPConnection::err(err_t err) { 00091 printf("Error\n"); 00092 release_callbacks(); 00093 NetServer::get()->free(this); 00094 } 00095 00096 err_t HTTPConnection::poll() { 00097 send(); 00098 return ERR_OK; 00099 } 00100 00101 err_t HTTPConnection::sent(u16_t len) { 00102 return poll(); 00103 } 00104 00105 err_t HTTPConnection::recv(struct pbuf *q, err_t err) { 00106 struct pbuf *p = q; 00107 int i; 00108 char *data; 00109 if(err == ERR_OK && p != NULL) { 00110 /* Inform TCP that we have taken the data. */ 00111 recved(p->tot_len); 00112 data = static_cast<char *>(p->payload); 00113 00114 // :1 00115 // Looking if it's GET, POST, 00116 // Followup from an incomplete request Header, 00117 // POST data or just crap (DEL, HEAD ...). 00118 if(!_request_type&&(strncmp(data, "GET ", 4) == 0)) { 00119 _request_type = GET; // Need :2 00120 } else if(!_request_type&&(strncmp(data, "POST ", 5) == 0)) { 00121 _request_type = POST; // Need :2 00122 } else if(_request_type&&request_incomplete) { 00123 getFields(&p, &data); // Need :3 00124 } else if(_request_type == POST) { 00125 // Followup (Data) // Exits 00126 data = static_cast<char *>(p->payload); 00127 store(data, p); 00128 emptypolls = NetServer::time(); 00129 pbuf_free(q); 00130 data = NULL; 00131 return ERR_OK; 00132 } else { 00133 pbuf_free(q); // Exits 00134 data = NULL; 00135 return ERR_OK; 00136 } 00137 00138 // :2 00139 // Processing first POST or GET Packet 00140 // need :3 v--- If its 0 we have followup header data. 00141 if(_request_type&&!_request_url) { 00142 char *pagename = (char *)(data + _request_type); 00143 for(i = _request_type; i < p->len; i++) { 00144 if((data[i] == ' ') || (data[i] == '\r') || (data[i] == '\n')) { 00145 data[i] = 0; 00146 data = &data[i+1]; 00147 break; 00148 } 00149 } 00150 emptypolls = NetServer::time(); 00151 00152 if((pagename[0] == '/') && (pagename[1] == 0)) { 00153 pagename = "/index.htm"; 00154 } 00155 00156 i = strlen(pagename); 00157 _request_url = new char[i+1]; 00158 memcpy(_request_url, pagename, i); 00159 _request_url[i] = '\0'; 00160 getFields(&p, &data); 00161 } 00162 // :3 00163 // Send or store the first amoungh of data. 00164 // Only when the message is complete. 00165 if(!request_incomplete) { 00166 emptypolls = NetServer::time(); 00167 // Find the right handler 00168 if(!request_handler) { 00169 request_handler = parent->handle(this); 00170 request_status = request_handler->init(this); 00171 } 00172 i = strlen(_request_headerfields) + 120; 00173 char *buf = new char[i]; 00174 sprintf(buf, "HTTP/1.1 %d OK\r\nServer:mbed embedded%s%d%s\r\nConnection: Close\r\n\r\n", request_status, 00175 (_request_length?"\r\nContent-Length: ":""),_request_length, 00176 getHeaderFields()); 00177 i = strlen(buf); 00178 if(sndbuf()>i) { 00179 if(request_status==HTTP_NotFound) { 00180 const char *msg = { 00181 "HTTP/1.1 404 Not Found\r\nServer:mbed embedded\r\n" 00182 "Content-Type: text/html\r\n" 00183 "Content-Length: 163\r\n" 00184 "\r\n" 00185 "<html>\r\n" 00186 "<header>\r\n" 00187 "<title>File not found<title>\r\n" 00188 "</header>\r\n" 00189 "<body>\r\n" 00190 "<h1>HTTP 404</h1>\r\n" 00191 "<p>The file you requested was not found on this mbed. </p>\r\n" 00192 "</body>\r\n" 00193 "</html>\r\n" 00194 }; 00195 00196 write((void *)msg, strlen(msg), 0); 00197 deleteRequest(); 00198 } else { 00199 write(buf, i, (TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE)); 00200 if(_request_type == POST) { 00201 store(data, p); 00202 } else { 00203 send(); 00204 } 00205 } 00206 } 00207 delete buf; 00208 } 00209 00210 // Exits 00211 pbuf_free(q); 00212 data = NULL; 00213 } else { 00214 release_callbacks(); 00215 NetServer::get()->free(this); 00216 close(); 00217 } 00218 return ERR_OK; 00219 } 00220 00221 void HTTPConnection::getFields(struct pbuf **q, char **d) { 00222 if(parent->fields.empty()) { 00223 while((*q)&&request_incomplete) { 00224 unsigned int end = ((unsigned int)((*q)->payload)+(unsigned int)((*q)->len)); 00225 for(; request_incomplete && ((unsigned int)(*d) < end); (*d)++) { 00226 if((*((char *)((*d)-0))=='\n')&&(*((char *)((*d)-1))=='\r')&& 00227 (*((char *)((*d)-2))=='\n')&&(*((char *)((*d)-3))=='\r')) { 00228 request_incomplete = false; 00229 (*d) += 1; 00230 break; 00231 } 00232 } 00233 if(request_incomplete) { 00234 (*q) = (*q)->next; 00235 if((*q)) { 00236 (*d) = static_cast<char *>((*q)->payload); 00237 } 00238 } 00239 } 00240 } else { 00241 char *kb = *d, *ke = NULL, *vb = *d, *ve = NULL; 00242 while((*q)&&request_incomplete) { 00243 unsigned int end = ((unsigned int)((*q)->payload)+(unsigned int)((*q)->len)); 00244 for(; request_incomplete && ((unsigned int)(*d) < end); (*d)++) { 00245 switch(**d) { 00246 case ' ': switch(_request_arg_state) { 00247 case 1: case 2: _request_arg_state = 2; break; 00248 case 3: _request_arg_state = 3; break; 00249 default: _request_arg_state = 0; break; 00250 } break; 00251 case ':': switch(_request_arg_state) { 00252 default: _request_arg_state = 2; break; 00253 case 3: _request_arg_state = 3; break; 00254 } break; 00255 case '\r': switch(_request_arg_state) { 00256 default: _request_arg_state = 4; break; 00257 case 5: case 6: _request_arg_state = 6; break; 00258 } break; 00259 case '\n': switch(_request_arg_state) { 00260 default: _request_arg_state = 4; break; 00261 case 4: case 5: _request_arg_state = 5; break; 00262 case 6: _request_arg_state = 7; break; 00263 } break; 00264 default: switch(_request_arg_state) { 00265 default: _request_arg_state = 1; break; 00266 case 2: case 3: _request_arg_state = 3; break; 00267 } break; 00268 } 00269 switch(_request_arg_state) { 00270 case 0: kb = (*d)+1; break; //PreKey 00271 case 1: ke = (*d); break; //Key 00272 case 2: vb = (*d)+1; break; //PreValue 00273 case 3: ve = (*d); break; //Value 00274 default: break; 00275 case 7: request_incomplete = false; break; 00276 case 5: { 00277 int oldkey = (_request_arg_key)?strlen(_request_arg_key):0; 00278 int oldval = (_request_arg_value)?strlen(_request_arg_value):0; 00279 int keylen =(ke&&kb)?ke-kb+1:0; 00280 int vallen = (ve&&vb)?ve-vb+1:0; 00281 char *key = new char[oldkey+keylen]; 00282 char *val = new char[oldval+vallen]; 00283 if(_request_arg_key&&oldkey) { 00284 strncpy(key, _request_arg_key, oldkey); 00285 } 00286 if(_request_arg_value&&oldval) { 00287 strncpy(val, _request_arg_value, oldval); 00288 } 00289 if(kb&&keylen) { 00290 strncpy(&key[oldkey], kb, keylen); 00291 } 00292 if(vb&&vallen) { 00293 strncpy(&val[oldval], vb, vallen); 00294 } 00295 key[oldkey+keylen] = 0; 00296 val[oldval+vallen] = 0; 00297 // printf("'%s':='%s'\n", key, val); 00298 addField(key, val); 00299 kb = vb = (*d)+1; 00300 ke = ve = NULL; 00301 if(_request_arg_key) { 00302 delete _request_arg_key; 00303 _request_arg_key = NULL; 00304 } 00305 if(_request_arg_value) { 00306 delete _request_arg_value; 00307 _request_arg_value = NULL; 00308 } 00309 delete key; 00310 } break; 00311 } 00312 } 00313 } 00314 switch(_request_arg_state) { 00315 case 0: break; // PreKey 00316 case 5: break; // n-rec 00317 case 6: break; // 2r-rec 00318 default: break; 00319 case 1: case 2: { // Key // PreValue 00320 int keylen =(kb)?(*d)-kb+1:0; 00321 _request_arg_key = new char[keylen]; 00322 strncpy(_request_arg_key, kb, keylen+1); 00323 _request_arg_key[keylen] = 0; 00324 } break; 00325 case 3: case 4: { // Value // r-rec 00326 int keylen =(ke&&kb)?ke-kb+1:0; 00327 int vallen = (vb)?(*d)-vb+1:0; 00328 _request_arg_key = new char[keylen]; 00329 _request_arg_value = new char[vallen]; 00330 strncpy(_request_arg_key, kb, keylen+1); 00331 strncpy(_request_arg_value, vb, vallen+1); 00332 _request_arg_key[keylen] = 0; 00333 _request_arg_value[vallen] = 0; 00334 } break; 00335 } 00336 if(request_incomplete) { 00337 (*q) = (*q)->next; 00338 if((*q)) { 00339 (*d) = static_cast<char *>((*q)->payload); 00340 } 00341 } 00342 } 00343 } 00344 00345 HTTPServer::HTTPServer(unsigned short port) 00346 : TCPListener(port), _timeout_max(60000) { 00347 } 00348 00349 HTTPServer::HTTPServer(const char *hostname, struct ip_addr ip, struct ip_addr nm, struct ip_addr gw, struct ip_addr dns, unsigned short port) 00350 : TCPListener(port), _timeout_max(60000) { 00351 NetServer *net = NULL; 00352 if(ip.addr != ip_addr_any.addr && nm.addr != ip_addr_any.addr && gw.addr != ip_addr_any.addr) { 00353 net = NetServer::create(ip, nm, gw); 00354 if(dns.addr != ip_addr_any.addr) { 00355 net->setDNS1(dns); 00356 } 00357 } else if(hostname) { 00358 net = NetServer::create(); 00359 } 00360 if(hostname) { 00361 net->setHostname(hostname); 00362 } 00363 } 00364 00365 void HTTPConnection::deleteRequest() { 00366 for(map<unsigned int, char *>::iterator iter = _request_fields.begin(); 00367 iter!=_request_fields.end();iter++) { 00368 delete iter->second; 00369 } 00370 _request_fields.clear(); 00371 if(data) {delete data; data = NULL; }; 00372 00373 if(_request_type) { 00374 delete _request_headerfields; 00375 delete _request_arg_key; 00376 delete _request_arg_value; 00377 if(_request_url) { 00378 delete _request_url; 00379 _request_url = NULL; 00380 } 00381 } 00382 _request_type = 0; 00383 request_incomplete = true; 00384 } 00385
Generated on Tue Jul 12 2022 16:07:04 by
1.7.2
