HttpServer Library for "mbed-os" which added a snapshot handler.

Dependents:   GR-PEACH-webcam GR-Boards_WebCamera GR-Boards_WebCamera GR-Boards_WebCamera

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