LRSD stephane / Mbed 2 deprecated WEBserverv3

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