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