Fork of HttpServer_snapshot_mbed-os library

Fork of HttpServer_snapshot_mbed-os by Renesas

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers HTTPServer.h Source File

HTTPServer.h

00001 //#define _DEBUG_ALL
00002 
00003 #ifndef HTTP_SERVER_H
00004 #define HTTP_SERVER_H
00005 
00006 #ifdef _DEBUG_ALL
00007 #include <stdio.h>
00008 #include <stdarg.h>
00009 Serial pc(USBTX, USBRX);
00010 static inline void http_server_debug_print(const char *format, ...) {
00011     va_list args;
00012     va_start(args, format);
00013     vfprintf(stderr, format, args);
00014     va_end(args);
00015 }
00016 #else
00017 static inline void http_server_debug_print(const char *format, ...) {}
00018 #endif
00019 
00020 #include <string>
00021 using std::string;
00022 
00023 #include <map>
00024 using std::map;
00025 
00026 #include "HTTPRequestHandler.h"
00027 #include "rtos.h"
00028 #include "mbed.h"
00029 
00030 struct handlersComp { //Used to order handlers in the right way
00031     bool operator() (const string& handler1, const string& handler2) const {
00032         //The first handler is longer than the second one
00033         if (handler1.length() > handler2.length())
00034             return true; //Returns true if handler1 is to appear before handler2
00035         else if (handler1.length() < handler2.length())
00036             return false;
00037         else //To avoid the == case, sort now by address
00038             return ((&handler1)>(&handler2));
00039     }
00040 };
00041 
00042 map< string, HTTPRequestHandler*(*)(const char*, const char* , TCPSocket* ), handlersComp > m_lpHandlers;
00043 template<typename T>
00044 void HTTPServerAddHandler(const char* path)  //Template decl in header
00045 {
00046     m_lpHandlers[path] = &T::inst;
00047 }
00048 
00049 void ListenThread(void const *args);
00050 enum HTTP_METH {
00051     HTTP_GET,
00052     HTTP_POST,
00053     HTTP_HEAD
00054 };
00055 
00056 bool getRequest(TCPSocket* client, string* path, string* meth)
00057 {
00058     char req[128];
00059     char c_path[128];
00060     char c_meth[128];
00061     const int maxLen = 128;
00062     char* p = req;
00063     //Read Line
00064     int ret;
00065     int len = 0;
00066     for(int i = 0; i < maxLen - 1; i++) {
00067         ret = client->recv(p, 1);
00068         if(!ret) {
00069             break;
00070         }
00071         if( (len > 1) && *(p-1)=='\r' && *p=='\n' ) {
00072             p--;
00073             len-=2;
00074             break;
00075         } else if( *p=='\n' ) {
00076             len--;
00077             break;
00078         }
00079         p++;
00080         len++;
00081     }
00082     *p = 0;
00083     http_server_debug_print("Parsing request : %s\r\n", req);
00084     ret = sscanf(req, "%s %s HTTP/%*d.%*d", c_meth, c_path);
00085     if(ret !=2)        return false;
00086     *meth = string(c_meth);
00087     *path = string(c_path);
00088     return true;
00089 }
00090 
00091 void dispatchRequest(TCPSocket* client)
00092 {
00093     string path;
00094     string meth;
00095     HTTP_METH methCode;
00096     http_server_debug_print("Dispatching req\r\n");
00097     if( !getRequest(client,&path, &meth ) ) {
00098         http_server_debug_print("dispatchRequest Invalid request\r\n");
00099         return; //Invalid request
00100     }
00101     if( !meth.compare("GET") ) {
00102         http_server_debug_print("dispatchRequest HTTP_GET\r\n");
00103         methCode = HTTP_GET;
00104     } else if( !meth.compare("POST") ) {
00105         http_server_debug_print("dispatchRequest HTTP_POST\r\n");
00106         methCode = HTTP_POST;
00107     } else if( !meth.compare("HEAD") ) {
00108         http_server_debug_print("dispatchRequest HTTP_HEAD\r\n");
00109         methCode = HTTP_HEAD;
00110     } else {
00111         http_server_debug_print("dispatchRequest() Parse error\r\n");
00112         return;
00113     }
00114     http_server_debug_print("Looking for a handler\r\n");
00115     map< string, HTTPRequestHandler*(*)(const char*, const char*, TCPSocket*), handlersComp >::iterator it;
00116     int root_len = 0;
00117     for (it = m_lpHandlers.begin(); it != m_lpHandlers.end(); it++) {
00118         http_server_debug_print("Checking %s...\r\n", (*it).first.c_str());
00119         root_len = (*it).first.length();
00120         if ( root_len &&
00121                 !path.compare( 0, root_len, (*it).first ) &&
00122                 (path[root_len] == '/' || path[root_len] == '\0')) {
00123             http_server_debug_print("Found (%s)\r\n", (*it).first.c_str());
00124             // Found!
00125             break;  // for
00126         }
00127     }
00128     if((it == m_lpHandlers.end()) && !(m_lpHandlers.empty())) {
00129         http_server_debug_print("Using default handler\r\n");
00130         it = m_lpHandlers.end();
00131         it--; //Get the last element
00132         if( ! (((*it).first.length() == 0) || !(*it).first.compare("/")) ) //This is not the default handler
00133             it = m_lpHandlers.end();
00134         root_len = 0;
00135     }
00136     if(it == m_lpHandlers.end()) {
00137         http_server_debug_print("No handler found\r\n");
00138         return;
00139     }
00140     http_server_debug_print("Handler found.\r\n");
00141     HTTPRequestHandler* pHdlr = (*it).second((*it).first.c_str(), path.c_str() + root_len, client);
00142     //****  client = NULL; //We don't own it anymore
00143     switch(methCode) {
00144         case HTTP_GET:
00145             pHdlr->doGet();
00146             break;
00147         case HTTP_POST:
00148             pHdlr->doPost();
00149             break;
00150         case HTTP_HEAD:
00151             pHdlr->doHead();
00152             break;
00153     }
00154     delete pHdlr;
00155     http_server_debug_print("(dispatcherRequest)return\r\n");
00156     return ;
00157 }
00158 
00159 #define THREAD_MAX 1
00160 
00161 #if (THREAD_MAX > 1) 
00162 static Thread *threads[THREAD_MAX];
00163 static Thread *xthread;
00164 
00165 static void HTTPServerChild (TCPSocket* client)
00166 {
00167     http_server_debug_print("HTTPServerChiled Start......\r\n");
00168 
00169     for (;;) {
00170         http_server_debug_print("(HTTPServer.h<HTTPServerChild>)Connection\r\n");
00171         dispatchRequest(client);
00172         http_server_debug_print("(HTTPServer.h<HTTPServerChild>)Close\r\n");
00173         client->close();
00174         Thread::signal_wait(1);
00175     }
00176 }
00177 
00178 static void HTTPServerCloser (TCPSocket *client)
00179 {
00180     for (;;) {
00181         client->close();
00182         http_server_debug_print("Close\r\n");
00183         Thread::signal_wait(1);
00184     }
00185 }
00186 
00187 void HTTPServerStart(NetworkInterface *net, int port = 80, osPriority priority = osPriorityNormal)
00188 {
00189     int i, t = 0;
00190     TCPSocket clients[THREAD_MAX];
00191     TCPSocket xclient;
00192 
00193     for (i = 0; i < THREAD_MAX; i ++) {
00194         threads[i] = NULL;
00195     }
00196     xthread = NULL;
00197 
00198     TCPServer server(net);
00199     server.bind(port);
00200     server.listen();
00201     http_server_debug_print("Wait for new connection...\r\n");
00202 
00203     for (;;) {
00204         http_server_debug_print("**Start Loop** \r\n");
00205         pc.printf("Sta\n");
00206         if (t >= 0) {
00207             if(server.accept(&clients[t])==0) {
00208                 // fork child process
00209                 if (threads[t]) {
00210                     threads[t]->signal_set(1);
00211                 } else {
00212                     threads[t] = new Thread(priority, 1024 * 3);
00213                     threads[t]->start(callback(HTTPServerChild, &clients[t]));
00214                 }
00215                 http_server_debug_print("Forked %d\r\n", t);
00216             } else {
00217                 Thread::wait(10);
00218             }
00219         } else {
00220             if(server.accept(&xclient)==0) {
00221                 // closer process
00222                 if (xthread) {
00223                     xthread->signal_set(1);
00224                 } else {
00225                     xthread = new Thread(priority);
00226                     xthread->start(callback(HTTPServerCloser, &xclient));
00227                 }
00228                 http_server_debug_print("Connection full\r\n");
00229             } else {
00230                 Thread::wait(10);
00231             }
00232             pc.printf("end\n");
00233         }
00234 
00235         t = -1;
00236         for (i = 0; i < THREAD_MAX; i ++) {
00237             if ((threads[i] == NULL)
00238              || ((threads[i]->get_state() == Thread::WaitingAnd))) {
00239                 if (t < 0) t = i; // next empty thread
00240             }
00241         }
00242     }
00243 }
00244 
00245 #else  // THREAD_MAX == 1
00246 
00247 void HTTPServerStart(NetworkInterface *net, int port = 80, osPriority priority = osPriorityNormal)
00248 {
00249     TCPSocket client;
00250 
00251     (void)priority;
00252 
00253     TCPServer server(net);
00254     server.bind(port);
00255     server.listen();
00256     http_server_debug_print("Wait for new connection...\r\n");
00257 
00258     while (1) {
00259         http_server_debug_print("**Start Loop** \r\n");
00260         if (server.accept(&client) == 0) {
00261             dispatchRequest(&client);
00262             client.close();
00263         }
00264     }
00265 }
00266 
00267 #endif
00268 
00269 #include "Handler/RPCHandler.h"
00270 #include "Handler/FSHandler.h"
00271 #include "Handler/SimpleHandler.h"
00272 #include "SnapshotHandler.h"
00273 
00274 #endif