Adaptation of the HttpServer by user yueee_yt. This version has improved handling of the HTTP headers (**NOTE**: There are limitations with this implementation and it is not fully functional. Use it only as a starting point.)

Dependents:   DMSupport DMSupport DMSupport DMSupport

Fork of DM_HttpServer by EmbeddedArtists AB

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 #define _DEBUG_HTTP_SERVER_H
00008 #endif
00009 
00010 #include <string>
00011 using std::string;
00012 
00013 #include <map>
00014 using std::map;
00015 
00016 #include "HTTPRequestHandler.h"
00017 #include "rtos.h"
00018 #include "mbed.h"
00019 #include "EthernetInterface.h"
00020 //#include "HTTPRequestDispatcher.h"
00021 
00022 //#include "dbg/dbg.h"
00023 
00024 #define THREAD_MAX 5
00025 Thread *threads[THREAD_MAX];
00026 Thread *xthread;
00027 //#include "HTTPServer2.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) {
00068             break;
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 #ifdef _DEBUG_HTTP_SERVER_H
00083     printf("Parsing request : %s\r\n", req);
00084 #endif
00085     ret = sscanf(req, "%s %s HTTP/%*d.%*d", c_meth, c_path);
00086     if(ret !=2)        return false;
00087     *meth = string(c_meth);
00088     *path = string(c_path);
00089     return true;
00090 }
00091 
00092 void dispatchRequest(TCPSocket* client)
00093 {
00094     string path;
00095     string meth;
00096     HTTP_METH methCode;
00097 #ifdef _DEBUG_HTTP_SERVER_H
00098     printf("Dispatching req\r\n");
00099 #endif
00100     if( !getRequest(client,&path, &meth ) ) {
00101 #ifdef _DEBUG_HTTP_SERVER_H
00102         printf("dispatchRequest Invalid request\r\n");
00103 #endif
00104         //close();
00105         return; //Invalid request
00106     }
00107     if( !meth.compare("GET") ) {
00108 #ifdef _DEBUG_HTTP_SERVER_H
00109         printf("dispatchRequest HTTP_GET\r\n");
00110 #endif
00111         methCode = HTTP_GET;
00112     } else if( !meth.compare("POST") ) {
00113 #ifdef _DEBUG_HTTP_SERVER_H
00114         printf("dispatchRequest HTTP_POST\r\n");
00115 #endif
00116         methCode = HTTP_POST;
00117     } else if( !meth.compare("HEAD") ) {
00118 #ifdef _DEBUG_HTTP_SERVER_H
00119         printf("dispatchRequest HTTP_HEAD\r\n");
00120 #endif
00121         methCode = HTTP_HEAD;
00122     } else {
00123 #ifdef _DEBUG_HTTP_SERVER_H
00124         printf("dispatchRequest() Parse error\r\n");
00125 #endif
00126         //close(); //Parse error
00127         return;
00128     }
00129 #ifdef _DEBUG_HTTP_SERVER_H
00130     printf("Looking for a handler\r\n");
00131 #endif
00132     map< string, HTTPRequestHandler*(*)(const char*, const char*, TCPSocket*) >::iterator it;
00133     int root_len = 0;
00134     for (it = m_lpHandlers.begin(); it != m_lpHandlers.end(); it++) {
00135 #ifdef _DEBUG_HTTP_SERVER_H
00136         printf("Checking %s...\r\n", (*it).first.c_str());
00137 #endif
00138         root_len = (*it).first.length();
00139         if ( root_len &&
00140                 !path.compare( 0, root_len, (*it).first ) &&
00141                 (path[root_len] == '/' || path[root_len] == '\0')) {
00142 #ifdef _DEBUG_HTTP_SERVER_H
00143             printf("Found (%s)\r\n", (*it).first.c_str());
00144 #endif
00145             // Found!
00146             break;  // for
00147         }
00148     }
00149     if((it == m_lpHandlers.end()) && !(m_lpHandlers.empty())) {
00150 #ifdef _DEBUG_HTTP_SERVER_H
00151         printf("Using default handler\r\n");
00152 #endif
00153         it = m_lpHandlers.end();
00154         it--; //Get the last element
00155         if( ! (((*it).first.length() == 0) || !(*it).first.compare("/")) ) //This is not the default handler
00156             it = m_lpHandlers.end();
00157         root_len = 0;
00158     }
00159     if(it == m_lpHandlers.end()) {
00160 #ifdef _DEBUG_HTTP_SERVER_H
00161         printf("No handler found\r\n");
00162 #endif
00163         return;
00164     }
00165 #ifdef _DEBUG_HTTP_SERVER_H
00166     printf("Handler found.\r\n");
00167 #endif
00168     HTTPRequestHandler* pHdlr = (*it).second((*it).first.c_str(), path.c_str() + root_len, client);
00169     //****  client = NULL; //We don't own it anymore
00170     switch(methCode) {
00171         case HTTP_GET:
00172             pHdlr->doGet();
00173             break;
00174         case HTTP_POST:
00175             pHdlr->doPost();
00176             break;
00177         case HTTP_HEAD:
00178             pHdlr->doHead();
00179             break;
00180     }
00181     delete pHdlr;
00182     // delete client;
00183     // delete m_pTCPSocketConnection;
00184 #ifdef _DEBUG_HTTP_SERVER_H
00185     printf("(dispatcherRequest)return\r\n");
00186 #endif
00187     return ;
00188 }
00189 
00190 void HTTPServerChild (void const *arg)
00191 {
00192 #ifdef _DEBUG_HTTP_SERVER_H
00193     SocketAddress remoteAddress;
00194     printf("HTTPServerChiled Start......\r\n");
00195 #endif
00196     TCPSocket* client = (TCPSocket*)arg;
00197 
00198     for (;;) {
00199 #ifdef _DEBUG_HTTP_SERVER_H
00200         client->getpeername(&remoteAddress);
00201         printf("(HTTPServer.h<HTTPServerChild>)Connection from %s\r\n", remoteAddress.get_ip_address());
00202 #endif
00203         dispatchRequest(client);
00204 #ifdef _DEBUG_HTTP_SERVER_H
00205         client->getpeername(&remoteAddress);
00206         printf("(HTTPServer.h<HTTPServerChild>)Close %s\r\n", remoteAddress.get_ip_address());
00207 #endif
00208         client->close();
00209 //        client->reset_address();
00210         //delete client;
00211         ThisThread::flags_wait_any(1);
00212     }
00213 }
00214 
00215 void HTTPServerCloser (void const *arg)
00216 {
00217 #ifdef _DEBUG_HTTP_SERVER_H
00218     SocketAddress remoteAddress;
00219 #endif    
00220     TCPSocket *client = (TCPSocket*)arg;
00221 
00222     for (;;) {
00223 #ifdef _DEBUG_HTTP_SERVER_H
00224         client->getpeername(&remoteAddress);
00225         printf("Close %s, %x\r\n", remoteAddress.get_ip_address(), client);
00226 #endif
00227         client->close();
00228         ThisThread::flags_wait_any(1);
00229     }
00230 }
00231 
00232 void HTTPServerStart(int port = 80)
00233 {
00234     int i, t = 0;
00235     nsapi_error_t ret;
00236     TCPSocket* clients[THREAD_MAX];
00237     TCPSocket* xclient;
00238 
00239     for (i = 0; i < THREAD_MAX; i ++) {
00240         threads[i] = NULL;
00241     }
00242     xthread = NULL;
00243 
00244     TCPSocket server;
00245     
00246     
00247     ret = server.open(NetworkInterface::get_default_instance());
00248     if (ret != NSAPI_ERROR_OK) {
00249         printf("HTTPServer: open failed %d\n", ret);
00250         return;
00251     }    
00252     
00253     ret = server.bind(port);
00254     if (ret != NSAPI_ERROR_OK) {
00255         printf("HTTPServer: bind failed %d\n", ret);
00256         return;
00257     }
00258     server.listen();
00259     // server.set_blocking(false);
00260 #ifdef _DEBUG_HTTP_SERVER_H
00261     printf("Wait for new connection...\r\n");
00262 #endif
00263     for (;;) {
00264 #ifdef _DEBUG_HTTP_SERVER_H
00265         printf("**Start Loop** \r\n");
00266 #endif
00267         if (t >= 0) {
00268             
00269             clients[t] = server.accept();
00270             //if(server.accept(clients[t])==0) {
00271             if (clients[t] != NULL) {
00272                 // fork child process
00273                 if (threads[t]) {
00274                     threads[t]->flags_set(1);
00275                 } else {
00276                     
00277                     threads[t] = new Thread(osPriorityNormal, OS_STACK_SIZE*2);
00278                     if (threads[t] != NULL) {
00279                         
00280                         threads[t]->start(callback(HTTPServerChild, (void*)clients[t]));
00281                     } 
00282                 }
00283 #ifdef _DEBUG_HTTP_SERVER_H
00284                 printf("Forked %d\r\n", t);
00285 #endif
00286             }
00287         } else {
00288             xclient = server.accept();
00289             //if(server.accept(xclient)==0) {
00290             if (xclient != NULL) {
00291                 // closer process
00292                 if (xthread) {
00293                     xthread->flags_set(1);
00294                 } else {
00295                     xthread = new Thread(osPriorityNormal, OS_STACK_SIZE*2);
00296                     if (xthread != NULL) {
00297                         xthread->start(callback(HTTPServerChild, (void*)xclient));
00298                     }                     
00299                 }
00300 #ifdef _DEBUG_HTTP_SERVER_H
00301                 printf("Connection full\r\n");
00302 #endif
00303             }
00304         }
00305 
00306         t = -1;
00307         for (i = 0; i < THREAD_MAX; i ++) {
00308             if (threads[i] == NULL || threads[i]->get_state() == Thread::WaitingThreadFlag) {
00309                 if (t < 0) t = i; // next empty thread
00310             }
00311         }
00312         // Thread::wait(100);
00313     }
00314 }
00315 //#include "Handler/RPCHandler.h"
00316 #include "Handler/FSHandler.h"
00317 #include "Handler/SimpleHandler.h"
00318 
00319 #endif