Embedded WebSockets Experiment

Dependencies:   mbed MD5

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