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