this will take a image from C328 serial camera and store those images in mbed flash as html and this html page is uploaded into the server at ip:192.168.1.2
Diff: lwip/HTTPServer/HTTPServer.cpp
- Revision:
- 0:e1a0471e5ffb
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lwip/HTTPServer/HTTPServer.cpp Wed Dec 15 15:01:56 2010 +0000 @@ -0,0 +1,394 @@ +#include "HTTPServer.h" +#include "NetServer.h" + +extern int gDebug; // [iva2k] + +using namespace std; +using namespace mbed; + +//unsigned int gconnections = 0; + +unsigned int mbed::hash(unsigned char *str) { + unsigned int hash = 5381; + int c; + while((c = *(str++))!=(unsigned char)'\0') { + hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ + } + return hash; +} + +HTTPConnection::HTTPConnection(HTTPServer *pparent, struct tcp_pcb *pcb) +: TCPConnection(pparent, pcb), request_incomplete(true), data(NULL), +request_handler(NULL), request_status(HTTP_NotFound), parent(pparent), +_request_url(NULL), _request_type(0), _request_headerfields(NULL), +_request_length(0), _request_arg_key(NULL), _request_arg_value(NULL), +_request_arg_state(0), emptypolls(0) { + _timeout_max = pparent->timeout(); +} + +HTTPConnection::~HTTPConnection() { + deleteRequest(); + emptypolls = NetServer::time(); +} + +const char *HTTPConnection::getField(char *key) const { + unsigned int h = hash((unsigned char *)key); + return _request_fields.find(h)->second; +} + +void HTTPConnection::addField(char *key, char *value) { + unsigned int h = hash((unsigned char *)key); + if(parent->isField(h)) { + _request_fields.insert( make_pair(h, value)); + } +} + +void HTTPConnection::send() { + int i = sndbuf(); + if(!request_incomplete&&i) { + switch(request_handler->send(this, i)) { + case HTTP_SuccessEnded: + case HTTP_Failed: { + deleteRequest(); + release_callbacks(); + NetServer::get()->free(this); + close(); + } break; + default: + emptypolls = NetServer::time(); + break; + } + } else { + if(NetServer::time() - emptypolls > _timeout_max) { + release_callbacks(); + NetServer::get()->free(this); + close(); + } + } +} + +void HTTPConnection::store(void *d, struct pbuf *p) { + int len = p->len-(((int)d)-((int)p->payload)); + do { + switch(request_handler->data(this, d, len)) { + case HTTP_SuccessEnded: + case HTTP_Failed: { + deleteRequest(); + release_callbacks(); + NetServer::get()->free(this); + close(); + } break; + default: + break; + } + p = p->next; + if(p) { + len = p->len; + d = static_cast<char *>(p->payload); + } + } while(_request_type&&p); +} + +void HTTPConnection::err(err_t err) { + printf("Error\n"); + release_callbacks(); + NetServer::get()->free(this); +} + +err_t HTTPConnection::poll() { + send(); + return ERR_OK; +} + +err_t HTTPConnection::sent(u16_t len) { + return poll(); +} + +err_t HTTPConnection::recv(struct pbuf *q, err_t err) { + struct pbuf *p = q; + int i; + char *data; +if (gDebug>1) printf("DEBUG: HTTPConnection::recv(%s, %d) :1\r\n", p ? "<some data>" : "NULL", (int)err); + if(err == ERR_OK && p != NULL) { + /* Inform TCP that we have taken the data. */ + recved(p->tot_len); + data = static_cast<char *>(p->payload); + + // :1 + // Looking if it's GET, POST, + // Followup from an incomplete request Header, + // POST data or just crap (DEL, HEAD ...). + if(!_request_type&&(strncmp(data, "GET ", 4) == 0)) { + _request_type = GET; // Need :2 + } else if(!_request_type&&(strncmp(data, "POST ", 5) == 0)) { + _request_type = POST; // Need :2 + } else if(_request_type&&request_incomplete) { + getFields(&p, &data); // Need :3 + } else if(_request_type == POST) { + // Followup (Data) // Exits + data = static_cast<char *>(p->payload); // [iva2k] Redundand + store(data, p); + emptypolls = NetServer::time(); + pbuf_free(q); + data = NULL; // [iva2k] Unnecessary + return ERR_OK; + } else { + pbuf_free(q); // Exits + data = NULL; // [iva2k] Unnecessary + return ERR_OK; + } + +if (gDebug>1) printf(" : HTTPConnection::recv() :2 _request_type=%d, _request_url=%s\r\n", (int)_request_type, _request_url?_request_url:"NULL"); + // :2 + // Processing first POST or GET Packet + // need :3 v--- If its 0 we have followup header data. + if(_request_type&&!_request_url) { + char *pagename = (char *)(data + _request_type); + for(i = _request_type; i < p->len; i++) { + if((data[i] == ' ') || (data[i] == '\r') || (data[i] == '\n')) { + data[i] = 0; + data = &data[i+1]; + break; + } + } + emptypolls = NetServer::time(); + + if((pagename[0] == '/') && (pagename[1] == 0)) { + pagename = "/index.htm"; + } + + i = strlen(pagename); + _request_url = new char[i+1]; + memcpy(_request_url, pagename, i); // [iva2k] memcpy(_request_url, pagename, i+1); would not need next line + _request_url[i] = '\0'; + getFields(&p, &data); + } + +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); + // :3 + // Send or store the first amoungh of data. + // Only when the message is complete. + if(!request_incomplete) { + emptypolls = NetServer::time(); + // Find the right handler + if(!request_handler) { + request_handler = parent->handle(this); + request_status = request_handler->init(this); +if (gDebug>1) printf(" : ... request_status=%d\r\n", (int)request_status); + } + i = strlen(_request_headerfields) + 120; + char *buf = new char[i]; + sprintf(buf, "HTTP/1.1 %d OK\r\nServer:mbed embedded%s%d%s\r\nConnection: Close\r\n\r\n", request_status, + (_request_length?"\r\nContent-Length: ":""),_request_length, + getHeaderFields()); + i = strlen(buf); // [iva2k] sprintf returns just that, use i=sprintf(...) above instead. + if(sndbuf()>i) { + if(request_status==HTTP_NotFound) { + const char *msg = { + "HTTP/1.1 404 Not Found\r\nServer:mbed embedded\r\n" + "Content-Type: text/html\r\n" + "Content-Length: 163\r\n" + "\r\n" + "<html>\r\n" + "<header>\r\n" + "<title>File not found<title>\r\n" + "</header>\r\n" + "<body>\r\n" + "<h1>HTTP 404</h1>\r\n" + "<p>The file you requested was not found on this mbed. </p>\r\n" + "</body>\r\n" + "</html>\r\n" + }; + +if (gDebug) printf("HTTP : %s NOT FOUND\r\n", p ? _request_url : "NULL"); + write((void *)msg, strlen(msg), 0); + deleteRequest(); + } else { +if (gDebug) printf("HTTP : %s \r\n", p ? _request_url : "NULL"); + write(buf, i, (TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE)); + if(_request_type == POST) { + store(data, p); + } else { + send(); + } + } + } + delete buf; + } + + // Exits + pbuf_free(q); + data = NULL; + } else { + release_callbacks(); + NetServer::get()->free(this); + close(); + } + return ERR_OK; +} + +void HTTPConnection::getFields(struct pbuf **q, char **d) { + if(parent->fields.empty()) { + while((*q)&&request_incomplete) { + unsigned int end = ((unsigned int)((*q)->payload)+(unsigned int)((*q)->len)); + for(; request_incomplete && ((unsigned int)(*d) < end); (*d)++) { + if((*((char *)((*d)-0))=='\n')&&(*((char *)((*d)-1))=='\r')&& + (*((char *)((*d)-2))=='\n')&&(*((char *)((*d)-3))=='\r')) { + request_incomplete = false; + (*d) += 1; + break; + } + } + if(request_incomplete) { + (*q) = (*q)->next; + if((*q)) { + (*d) = static_cast<char *>((*q)->payload); + } + } + } + } else { + char *kb = *d, *ke = NULL, *vb = *d, *ve = NULL; + while((*q)&&request_incomplete) { + unsigned int end = ((unsigned int)((*q)->payload)+(unsigned int)((*q)->len)); + for(; request_incomplete && ((unsigned int)(*d) < end); (*d)++) { + switch(**d) { + case ' ': switch(_request_arg_state) { + case 1: case 2: _request_arg_state = 2; break; + case 3: _request_arg_state = 3; break; + default: _request_arg_state = 0; break; + } break; + case ':': switch(_request_arg_state) { + default: _request_arg_state = 2; break; + case 3: _request_arg_state = 3; break; + } break; + case '\r': switch(_request_arg_state) { + default: _request_arg_state = 4; break; + case 5: case 6: _request_arg_state = 6; break; + } break; + case '\n': switch(_request_arg_state) { + default: _request_arg_state = 4; break; + case 4: case 5: _request_arg_state = 5; break; + case 6: _request_arg_state = 7; break; + } break; + default: switch(_request_arg_state) { + default: _request_arg_state = 1; break; + case 2: case 3: _request_arg_state = 3; break; + } break; + } + switch(_request_arg_state) { + case 0: kb = (*d)+1; break; //PreKey + case 1: ke = (*d); break; //Key + case 2: vb = (*d)+1; break; //PreValue + case 3: ve = (*d); break; //Value + default: break; + case 7: request_incomplete = false; break; + case 5: { + int oldkey = (_request_arg_key)?strlen(_request_arg_key):0; + int oldval = (_request_arg_value)?strlen(_request_arg_value):0; + int keylen =(ke&&kb)?ke-kb+1:0; + int vallen = (ve&&vb)?ve-vb+1:0; + char *key = new char[oldkey+keylen]; + char *val = new char[oldval+vallen]; + if(_request_arg_key&&oldkey) { + strncpy(key, _request_arg_key, oldkey); + } + if(_request_arg_value&&oldval) { + strncpy(val, _request_arg_value, oldval); + } + if(kb&&keylen) { + strncpy(&key[oldkey], kb, keylen); + } + if(vb&&vallen) { + strncpy(&val[oldval], vb, vallen); + } + key[oldkey+keylen] = 0; + val[oldval+vallen] = 0; +// printf("'%s':='%s'\n", key, val); + addField(key, val); + kb = vb = (*d)+1; + ke = ve = NULL; + if(_request_arg_key) { + delete _request_arg_key; + _request_arg_key = NULL; + } + if(_request_arg_value) { + delete _request_arg_value; + _request_arg_value = NULL; + } + delete key; + } break; + } + } + } + switch(_request_arg_state) { + case 0: break; // PreKey + case 5: break; // n-rec + case 6: break; // 2r-rec + default: break; + case 1: case 2: { // Key // PreValue + int keylen =(kb)?(*d)-kb+1:0; + _request_arg_key = new char[keylen]; + strncpy(_request_arg_key, kb, keylen+1); + _request_arg_key[keylen] = 0; + } break; + case 3: case 4: { // Value // r-rec + int keylen =(ke&&kb)?ke-kb+1:0; + int vallen = (vb)?(*d)-vb+1:0; + _request_arg_key = new char[keylen]; + _request_arg_value = new char[vallen]; + strncpy(_request_arg_key, kb, keylen+1); + strncpy(_request_arg_value, vb, vallen+1); + _request_arg_key[keylen] = 0; + _request_arg_value[vallen] = 0; + } break; + } + if(request_incomplete) { + (*q) = (*q)->next; + if((*q)) { + (*d) = static_cast<char *>((*q)->payload); + } + } + } +} + +HTTPServer::HTTPServer(unsigned short port) + : TCPListener(port), _timeout_max(60000) { +} + +HTTPServer::HTTPServer(const char *hostname, struct ip_addr ip, struct ip_addr nm, struct ip_addr gw, struct ip_addr dns, unsigned short port) + : TCPListener(port), _timeout_max(60000) { + NetServer *net = NULL; + if(ip.addr != ip_addr_any.addr && nm.addr != ip_addr_any.addr && gw.addr != ip_addr_any.addr) { + net = NetServer::create(ip, nm, gw); + if(dns.addr != ip_addr_any.addr) { + net->setDNS1(dns); + } + } else if(hostname) { + net = NetServer::create(); + } + if(hostname) { + net->setHostname(hostname); + } +} + +void HTTPConnection::deleteRequest() { + for(map<unsigned int, char *>::iterator iter = _request_fields.begin(); + iter!=_request_fields.end();iter++) { + delete iter->second; + } + _request_fields.clear(); + if(data) {delete data; data = NULL; }; + + if(_request_type) { + delete _request_headerfields; + delete _request_arg_key; + delete _request_arg_value; + if(_request_url) { + delete _request_url; + _request_url = NULL; + } + } + _request_type = 0; + request_incomplete = true; +} +