Henry Leinen / Mbed 2 deprecated MultiThreadingHTTPServer

Dependencies:   WiFlyHTTPServer WiflyInterface mbed-rpc mbed-rtos mbed

HttpServer.h

Committer:
leihen
Date:
2013-06-26
Revision:
0:9c6ebc97c758

File content as of revision 0:9c6ebc97c758:

#ifndef __HTTPSERVER_H__
#define __HTTPSERVER_H__

#include "Wifly.h"
#include "rtos.h"
#include "HTTPConnection.h"
#include "HTTPRequestHandler.h"

#include <string>
#include <map>

typedef enum {
    msg_get,
    msg_post,
    msg_head,
    msg_put,
    msg_delete,
    msg_trace,
    msg_options,
    msg_connect
} msg_t;


typedef struct {
    msg_t                       requestType;
    char                        requestUri[256];
//    map<string, string>         messageHeaders;
} request_msg_t;

/** Typedefinition for a handler function
*/
typedef void (*HTTPRequestHandlerFunction)(HTTPConnection::HTTPMessage&);


/** This is the non-blocking HTTP Server class. The idea behind this class is as follows:
  * the user may instantiate the class and initialize it. Once the server is setup and 
  * listening, the server will stay in an endless loop and keep on listening for new 
  * connections and for new HTTP requests. Once a request is received it will be placed 
  * in a queue. The queue itself will be handled in a separate task.
  */
class HttpServer : public Wifly
{
        Thread      *m_listener;
        Thread      *m_worker;

        request_msg_t*  checkMessageReceived(char *);
        void            processMessageHeader(char* headerLine, char **fieldname, char **fieldvalue);        
        
    public:
        HttpServer(PinName tx, PinName rx, PinName reset, PinName tcp_status, const char * ssid, const char * phrase, Security sec, Wifly::WiflyBaudrate_t baud = Wifly::Wifly_115200);
        ~HttpServer();
        
        bool start(int port);
        
        virtual void handler_rx(void);
        virtual void attach_rx(bool);
        
        virtual bool join();
        virtual int send(const char * str, int len, const char * ACK = NULL, char * res = NULL, int timeout = DEFAULT_WAIT_RESP_TIMEOUT);
        
    public:
        
        
        /**
        * Structure which will allow to order the stored handlers according to their associated path.
        */
        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));
            }
        };
        /** The standard error handler function.
        * @param msg : Request message data.
        * @param tcp : Socket to be used for responding.
        */
        static void StdErrorHandler(HTTPConnection::HTTPMessage& msg);


        /** Internal function which processes a request and which will try to find the matching handler function
        * for the given request. Please note that the function will search through the list of handlers, iterating
        * from longest to shortest \c paths. If the registered \c path is a subset of the request the associated
        * handler is considered as being a match.
        * @param msg : Request message data. Contains the requested logical \c uri. 
        * @param tcp : Socket to be used for communication with the client.
        */
        void HandleRequest(HTTPConnection::HTTPMessage* msg);
    
        /** Map of handler objects. Can be any object derived from \ref HTTPRequestHeader. Use the \ref addHandler function
        * to register new handler objects.
        */
        static map<string, HTTPRequestHandler* (*)(const char*, const char*, HTTPConnection::HTTPMessage&), handlersComp>   m_lpHandlers;

        /**
        * Adds a request handler to the handlers list. You will have to use one of the existing implementations.
        * With each handler a \c uri or \c path is associated. Whenever a request is received the server will
        * walk through all registered handlers and check which \c path is matching.
        * @param T : class which will be instanciated to serve these requests for the associated \b path.
        * @param path : request uri starting with this \c path will be served using this handler.
        */
        template<typename T>
        void addHandler(const char* path)
        { m_lpHandlers[path] = &T::create; }
    
        /**
        * Replaces the standard error Handler. The error Handler will be called everytime a request is not
        * matching any of the registered \c paths or \c uris.
        * @param hdlFunc: User specified handler function which will be used in error conditions.
        */
        void addErrorHandler(HTTPRequestHandlerFunction hdlFunc)
        { m_pErrorHandler = hdlFunc!=NULL ?hdlFunc : StdErrorHandler; }    
        HTTPRequestHandlerFunction m_pErrorHandler;

    protected:
        bool bind(int port);
        void listenForRequests();
        void serveRequests();
        
        bool parseRequest(char *request);
        
        static void listen_thread(const void * parms);
        static void worker_thread(const void * parms);
};

#endif //   __HTTPSERVER_H__