Henry Leinen / Mbed 2 deprecated MultiThreadingHTTPServer

Dependencies:   WiFlyHTTPServer WiflyInterface mbed-rpc mbed-rtos mbed

Committer:
leihen
Date:
Wed Jun 26 21:13:55 2013 +0000
Revision:
0:9c6ebc97c758
Working Multithreaded HTTP Server

Who changed what in which revision?

UserRevisionLine numberNew contents of line
leihen 0:9c6ebc97c758 1 #ifndef __HTTPSERVER_H__
leihen 0:9c6ebc97c758 2 #define __HTTPSERVER_H__
leihen 0:9c6ebc97c758 3
leihen 0:9c6ebc97c758 4 #include "Wifly.h"
leihen 0:9c6ebc97c758 5 #include "rtos.h"
leihen 0:9c6ebc97c758 6 #include "HTTPConnection.h"
leihen 0:9c6ebc97c758 7 #include "HTTPRequestHandler.h"
leihen 0:9c6ebc97c758 8
leihen 0:9c6ebc97c758 9 #include <string>
leihen 0:9c6ebc97c758 10 #include <map>
leihen 0:9c6ebc97c758 11
leihen 0:9c6ebc97c758 12 typedef enum {
leihen 0:9c6ebc97c758 13 msg_get,
leihen 0:9c6ebc97c758 14 msg_post,
leihen 0:9c6ebc97c758 15 msg_head,
leihen 0:9c6ebc97c758 16 msg_put,
leihen 0:9c6ebc97c758 17 msg_delete,
leihen 0:9c6ebc97c758 18 msg_trace,
leihen 0:9c6ebc97c758 19 msg_options,
leihen 0:9c6ebc97c758 20 msg_connect
leihen 0:9c6ebc97c758 21 } msg_t;
leihen 0:9c6ebc97c758 22
leihen 0:9c6ebc97c758 23
leihen 0:9c6ebc97c758 24 typedef struct {
leihen 0:9c6ebc97c758 25 msg_t requestType;
leihen 0:9c6ebc97c758 26 char requestUri[256];
leihen 0:9c6ebc97c758 27 // map<string, string> messageHeaders;
leihen 0:9c6ebc97c758 28 } request_msg_t;
leihen 0:9c6ebc97c758 29
leihen 0:9c6ebc97c758 30 /** Typedefinition for a handler function
leihen 0:9c6ebc97c758 31 */
leihen 0:9c6ebc97c758 32 typedef void (*HTTPRequestHandlerFunction)(HTTPConnection::HTTPMessage&);
leihen 0:9c6ebc97c758 33
leihen 0:9c6ebc97c758 34
leihen 0:9c6ebc97c758 35 /** This is the non-blocking HTTP Server class. The idea behind this class is as follows:
leihen 0:9c6ebc97c758 36 * the user may instantiate the class and initialize it. Once the server is setup and
leihen 0:9c6ebc97c758 37 * listening, the server will stay in an endless loop and keep on listening for new
leihen 0:9c6ebc97c758 38 * connections and for new HTTP requests. Once a request is received it will be placed
leihen 0:9c6ebc97c758 39 * in a queue. The queue itself will be handled in a separate task.
leihen 0:9c6ebc97c758 40 */
leihen 0:9c6ebc97c758 41 class HttpServer : public Wifly
leihen 0:9c6ebc97c758 42 {
leihen 0:9c6ebc97c758 43 Thread *m_listener;
leihen 0:9c6ebc97c758 44 Thread *m_worker;
leihen 0:9c6ebc97c758 45
leihen 0:9c6ebc97c758 46 request_msg_t* checkMessageReceived(char *);
leihen 0:9c6ebc97c758 47 void processMessageHeader(char* headerLine, char **fieldname, char **fieldvalue);
leihen 0:9c6ebc97c758 48
leihen 0:9c6ebc97c758 49 public:
leihen 0:9c6ebc97c758 50 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);
leihen 0:9c6ebc97c758 51 ~HttpServer();
leihen 0:9c6ebc97c758 52
leihen 0:9c6ebc97c758 53 bool start(int port);
leihen 0:9c6ebc97c758 54
leihen 0:9c6ebc97c758 55 virtual void handler_rx(void);
leihen 0:9c6ebc97c758 56 virtual void attach_rx(bool);
leihen 0:9c6ebc97c758 57
leihen 0:9c6ebc97c758 58 virtual bool join();
leihen 0:9c6ebc97c758 59 virtual int send(const char * str, int len, const char * ACK = NULL, char * res = NULL, int timeout = DEFAULT_WAIT_RESP_TIMEOUT);
leihen 0:9c6ebc97c758 60
leihen 0:9c6ebc97c758 61 public:
leihen 0:9c6ebc97c758 62
leihen 0:9c6ebc97c758 63
leihen 0:9c6ebc97c758 64 /**
leihen 0:9c6ebc97c758 65 * Structure which will allow to order the stored handlers according to their associated path.
leihen 0:9c6ebc97c758 66 */
leihen 0:9c6ebc97c758 67 struct handlersComp //Used to order handlers in the right way
leihen 0:9c6ebc97c758 68 {
leihen 0:9c6ebc97c758 69 bool operator() (const string& handler1, const string& handler2) const
leihen 0:9c6ebc97c758 70 {
leihen 0:9c6ebc97c758 71 //The first handler is longer than the second one
leihen 0:9c6ebc97c758 72 if (handler1.length() > handler2.length())
leihen 0:9c6ebc97c758 73 return true; //Returns true if handler1 is to appear before handler2
leihen 0:9c6ebc97c758 74 else if (handler1.length() < handler2.length())
leihen 0:9c6ebc97c758 75 return false;
leihen 0:9c6ebc97c758 76 else //To avoid the == case, sort now by address
leihen 0:9c6ebc97c758 77 return ((&handler1)>(&handler2));
leihen 0:9c6ebc97c758 78 }
leihen 0:9c6ebc97c758 79 };
leihen 0:9c6ebc97c758 80 /** The standard error handler function.
leihen 0:9c6ebc97c758 81 * @param msg : Request message data.
leihen 0:9c6ebc97c758 82 * @param tcp : Socket to be used for responding.
leihen 0:9c6ebc97c758 83 */
leihen 0:9c6ebc97c758 84 static void StdErrorHandler(HTTPConnection::HTTPMessage& msg);
leihen 0:9c6ebc97c758 85
leihen 0:9c6ebc97c758 86
leihen 0:9c6ebc97c758 87 /** Internal function which processes a request and which will try to find the matching handler function
leihen 0:9c6ebc97c758 88 * for the given request. Please note that the function will search through the list of handlers, iterating
leihen 0:9c6ebc97c758 89 * from longest to shortest \c paths. If the registered \c path is a subset of the request the associated
leihen 0:9c6ebc97c758 90 * handler is considered as being a match.
leihen 0:9c6ebc97c758 91 * @param msg : Request message data. Contains the requested logical \c uri.
leihen 0:9c6ebc97c758 92 * @param tcp : Socket to be used for communication with the client.
leihen 0:9c6ebc97c758 93 */
leihen 0:9c6ebc97c758 94 void HandleRequest(HTTPConnection::HTTPMessage* msg);
leihen 0:9c6ebc97c758 95
leihen 0:9c6ebc97c758 96 /** Map of handler objects. Can be any object derived from \ref HTTPRequestHeader. Use the \ref addHandler function
leihen 0:9c6ebc97c758 97 * to register new handler objects.
leihen 0:9c6ebc97c758 98 */
leihen 0:9c6ebc97c758 99 static map<string, HTTPRequestHandler* (*)(const char*, const char*, HTTPConnection::HTTPMessage&), handlersComp> m_lpHandlers;
leihen 0:9c6ebc97c758 100
leihen 0:9c6ebc97c758 101 /**
leihen 0:9c6ebc97c758 102 * Adds a request handler to the handlers list. You will have to use one of the existing implementations.
leihen 0:9c6ebc97c758 103 * With each handler a \c uri or \c path is associated. Whenever a request is received the server will
leihen 0:9c6ebc97c758 104 * walk through all registered handlers and check which \c path is matching.
leihen 0:9c6ebc97c758 105 * @param T : class which will be instanciated to serve these requests for the associated \b path.
leihen 0:9c6ebc97c758 106 * @param path : request uri starting with this \c path will be served using this handler.
leihen 0:9c6ebc97c758 107 */
leihen 0:9c6ebc97c758 108 template<typename T>
leihen 0:9c6ebc97c758 109 void addHandler(const char* path)
leihen 0:9c6ebc97c758 110 { m_lpHandlers[path] = &T::create; }
leihen 0:9c6ebc97c758 111
leihen 0:9c6ebc97c758 112 /**
leihen 0:9c6ebc97c758 113 * Replaces the standard error Handler. The error Handler will be called everytime a request is not
leihen 0:9c6ebc97c758 114 * matching any of the registered \c paths or \c uris.
leihen 0:9c6ebc97c758 115 * @param hdlFunc: User specified handler function which will be used in error conditions.
leihen 0:9c6ebc97c758 116 */
leihen 0:9c6ebc97c758 117 void addErrorHandler(HTTPRequestHandlerFunction hdlFunc)
leihen 0:9c6ebc97c758 118 { m_pErrorHandler = hdlFunc!=NULL ?hdlFunc : StdErrorHandler; }
leihen 0:9c6ebc97c758 119 HTTPRequestHandlerFunction m_pErrorHandler;
leihen 0:9c6ebc97c758 120
leihen 0:9c6ebc97c758 121 protected:
leihen 0:9c6ebc97c758 122 bool bind(int port);
leihen 0:9c6ebc97c758 123 void listenForRequests();
leihen 0:9c6ebc97c758 124 void serveRequests();
leihen 0:9c6ebc97c758 125
leihen 0:9c6ebc97c758 126 bool parseRequest(char *request);
leihen 0:9c6ebc97c758 127
leihen 0:9c6ebc97c758 128 static void listen_thread(const void * parms);
leihen 0:9c6ebc97c758 129 static void worker_thread(const void * parms);
leihen 0:9c6ebc97c758 130 };
leihen 0:9c6ebc97c758 131
leihen 0:9c6ebc97c758 132 #endif // __HTTPSERVER_H__