Fork of HttpServer_snapshot_mbed-os library
Fork of HttpServer_snapshot_mbed-os by
Diff: HTTPServer.h
- Revision:
- 0:fdf9c2c5200f
- Child:
- 4:1b6b021ee21d
diff -r 000000000000 -r fdf9c2c5200f HTTPServer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HTTPServer.h Thu Feb 20 05:36:19 2014 +0000 @@ -0,0 +1,244 @@ +#ifndef HTTP_SERVER_H +#define HTTP_SERVER_H + +#include <string> +using std::string; + +#include <map> +using std::map; + +#include "HTTPRequestHandler.h" +#include "rtos.h" +#include "mbed.h" +#include "EthernetInterface.h" +//#include "HTTPRequestDispatcher.h" + +//#include "dbg/dbg.h" + +#define THREAD_MAX 5 +Thread *threads[THREAD_MAX]; +Thread *xthread; +//#include "HTTPServer2.h" + +struct handlersComp { //Used to order handlers in the right way + bool operator() (const string& handler1, const string& handler2) const { + //The first handler is longer than the second one + if (handler1.length() > handler2.length()) + return true; //Returns true if handler1 is to appear before handler2 + else if (handler1.length() < handler2.length()) + return false; + else //To avoid the == case, sort now by address + return ((&handler1)>(&handler2)); + } +}; + +map< string, HTTPRequestHandler*(*)(const char*, const char* , TCPSocketConnection* ), handlersComp > m_lpHandlers; +template<typename T> +void HTTPServerAddHandler(const char* path) //Template decl in header +{ + m_lpHandlers[path] = &T::inst; +} + +void ListenThread(void const *args); +//DigitalOut _led(LED4); +//bool serverIsListened; +//bool clientIsConnected; +enum HTTP_METH { + HTTP_GET, + HTTP_POST, + HTTP_HEAD +}; + +bool getRequest(TCPSocketConnection* client,string* path, string* meth) +{ + char req[128]; + char c_path[128]; + char c_meth[128]; + const int maxLen = 128; + char* p = req; + //Read Line + int ret; + int len = 0; + for(int i = 0; i < maxLen - 1; i++) { + ret = client->receive(p, 1); + if(!ret) { + break; + } + if( (len > 1) && *(p-1)=='\r' && *p=='\n' ) { + p--; + len-=2; + break; + } else if( *p=='\n' ) { + len--; + break; + } + p++; + len++; + } + *p = 0; + + printf("Parsing request : %s\r\n", req); + ret = sscanf(req, "%s %s HTTP/%*d.%*d", c_meth, c_path); + if(ret !=2) return false; + *meth = string(c_meth); + *path = string(c_path); + return true; +} + +void dispatchRequest(TCPSocketConnection* client) +{ + string path; + string meth; + HTTP_METH methCode; + + printf("Dispatching req\r\n"); + + if( !getRequest(client,&path, &meth ) ) { + printf("dispatchRequest Invalid request\r\n"); + //close(); + return; //Invalid request + } + if( !meth.compare("GET") ) { + printf("dispatchRequest HTTP_GET\r\n"); + methCode = HTTP_GET; + } else if( !meth.compare("POST") ) { + printf("dispatchRequest HTTP_POST\r\n"); + methCode = HTTP_POST; + } else if( !meth.compare("HEAD") ) { + printf("dispatchRequest HTTP_HEAD\r\n"); + methCode = HTTP_HEAD; + } else { + printf("dispatchRequest() Parse error\r\n"); + //close(); //Parse error + return; + } + + printf("Looking for a handler\r\n"); + map< string, HTTPRequestHandler*(*)(const char*, const char*, TCPSocketConnection*) >::iterator it; + int root_len = 0; + for (it = m_lpHandlers.begin(); it != m_lpHandlers.end(); it++) { + printf("Checking %s...\r\n", (*it).first.c_str()); + root_len = (*it).first.length(); + if ( root_len && + !path.compare( 0, root_len, (*it).first ) && + (path[root_len] == '/' || path[root_len] == '\0')) { + printf("Found (%s)\r\n", (*it).first.c_str()); + // Found! + break; // for + } + } + if((it == m_lpHandlers.end()) && !(m_lpHandlers.empty())) { + printf("Using default handler\r\n"); + it = m_lpHandlers.end(); + it--; //Get the last element + if( ! (((*it).first.length() == 0) || !(*it).first.compare("/")) ) //This is not the default handler + it = m_lpHandlers.end(); + root_len = 0; + } + if(it == m_lpHandlers.end()) { + printf("No handler found\r\n"); + return; + } + printf("Handler found.\r\n"); + + HTTPRequestHandler* pHdlr = (*it).second((*it).first.c_str(), path.c_str() + root_len, client); + //**** client = NULL; //We don't own it anymore + switch(methCode) { + case HTTP_GET: + pHdlr->doGet(); + break; + case HTTP_POST: + pHdlr->doPost(); + break; + case HTTP_HEAD: + pHdlr->doHead(); + break; + } + delete pHdlr; + // delete client; + // delete m_pTCPSocketConnection; + printf("(dispatcherRequest)return\r\n"); + return ; +} + +void HTTPServerChild (void const *arg) +{ + printf("HTTPServerChiled Start......\r\n"); + TCPSocketConnection* client = (TCPSocketConnection*)arg; + + for (;;) { + printf("(HTTPServer.h<HTTPServerChild>)Connection from %s\r\n", client->get_address()); + dispatchRequest(client); + printf("(HTTPServer.h<HTTPServerChild>)Close %s\r\n", client->get_address()); + client->close(); + client->reset_address(); + //delete client; + Thread::signal_wait(1); + } +} + +void HTTPServerCloser (void const *arg) +{ + TCPSocketConnection *client = (TCPSocketConnection*)arg; + + for (;;) { + client->close(); + printf("Close %s\r\n", client->get_address()); + Thread::signal_wait(1); + } +} + +void HTTPServerStart(int port = 80) +{ + int i, t = 0; + TCPSocketConnection clients[THREAD_MAX]; + TCPSocketConnection xclient; + + for (i = 0; i < THREAD_MAX; i ++) { + threads[i] = NULL; + } + xthread = NULL; + + TCPSocketServer server; + server.bind(port); + server.listen(); + // server.set_blocking(false); + printf("Wait for new connection...\r\n"); + for (;;) { + printf("**Start Loop** \r\n"); + if (t >= 0) { + if(server.accept(clients[t])==0) { + // fork child process + if (threads[t]) { + threads[t]->signal_set(1); + } else { + threads[t] = new Thread(HTTPServerChild, (void*)&clients[t]); + } + printf("Forked %d\r\n", t); + } + } else { + if(server.accept(xclient)==0) { + // closer process + if (xthread) { + xthread->signal_set(1); + } else { + xthread = new Thread(HTTPServerCloser, (void*)&xclient); + } + printf("Connection full\r\n"); + } + } + + t = -1; + for (i = 0; i < THREAD_MAX; i ++) { + if (threads[i] == NULL || threads[i]->get_state() == Thread::WaitingAnd) { + if (t < 0) t = i; // next empty thread + } + } + Thread::wait(100); + } +} +#include "Handler/RPCHandler.h" +#include "Handler/FSHandler.h" +#include "Handler/SimpleHandler.h" + +#endif