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