A version of LWIP, provided for backwards compatibility.

Dependents:   AA_DemoBoard DemoBoard HelloServerDemo DemoBoard_RangeIndicator ... more

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 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