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