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

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers HTTPServer.cpp Source File

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