Embedded WebSockets Experiment

Dependencies:   mbed MD5

Committer:
nandgate
Date:
Tue Jul 26 05:30:53 2011 +0000
Revision:
0:6dee052a3fa4

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
nandgate 0:6dee052a3fa4 1 #ifndef HTTPSERVER_H
nandgate 0:6dee052a3fa4 2 #define HTTPSERVER_H
nandgate 0:6dee052a3fa4 3
nandgate 0:6dee052a3fa4 4 #include "TCPConnection.h"
nandgate 0:6dee052a3fa4 5 #include "TCPListener.h"
nandgate 0:6dee052a3fa4 6 #include "NetServer.h"
nandgate 0:6dee052a3fa4 7
nandgate 0:6dee052a3fa4 8 #include <map>
nandgate 0:6dee052a3fa4 9 #include <set>
nandgate 0:6dee052a3fa4 10 #include <list>
nandgate 0:6dee052a3fa4 11
nandgate 0:6dee052a3fa4 12 #define HTTP_MAX_EMPTYPOLLS 100
nandgate 0:6dee052a3fa4 13 #define GET 4
nandgate 0:6dee052a3fa4 14 #define POST 5
nandgate 0:6dee052a3fa4 15
nandgate 0:6dee052a3fa4 16 //extern unsigned int gconnections;
nandgate 0:6dee052a3fa4 17
nandgate 0:6dee052a3fa4 18 using namespace std;
nandgate 0:6dee052a3fa4 19
nandgate 0:6dee052a3fa4 20 namespace mbed {
nandgate 0:6dee052a3fa4 21
nandgate 0:6dee052a3fa4 22 class HTTPServer;
nandgate 0:6dee052a3fa4 23 class HTTPHandler;
nandgate 0:6dee052a3fa4 24 class HTTPConnection;
nandgate 0:6dee052a3fa4 25
nandgate 0:6dee052a3fa4 26 /**
nandgate 0:6dee052a3fa4 27 * A simple HASH function to reduce the size of stored Header Fields
nandgate 0:6dee052a3fa4 28 * TODO: Make the Hash case insensetive.
nandgate 0:6dee052a3fa4 29 */
nandgate 0:6dee052a3fa4 30 unsigned int hash(unsigned char *str);
nandgate 0:6dee052a3fa4 31
nandgate 0:6dee052a3fa4 32 /**
nandgate 0:6dee052a3fa4 33 * The Status of an HTTP Request
nandgate 0:6dee052a3fa4 34 * Nedded for HTTPHandler subclasses to define there reults in the HTTPHandler:init Method.
nandgate 0:6dee052a3fa4 35 */
nandgate 0:6dee052a3fa4 36 enum HTTPStatus {
nandgate 0:6dee052a3fa4 37 HTTP_SwitchProtocols = 101,
nandgate 0:6dee052a3fa4 38 HTTP_OK = 200,
nandgate 0:6dee052a3fa4 39 HTTP_BadRequest = 400,
nandgate 0:6dee052a3fa4 40 HTTP_Unauthorized = 401,
nandgate 0:6dee052a3fa4 41 HTTP_Forbidden = 403,
nandgate 0:6dee052a3fa4 42 HTTP_NotFound = 404,
nandgate 0:6dee052a3fa4 43 HTTP_MethodNotAllowed = 405,
nandgate 0:6dee052a3fa4 44 HTTP_InternalServerError = 500,
nandgate 0:6dee052a3fa4 45 HTTP_NotImplemented = 501,
nandgate 0:6dee052a3fa4 46 };
nandgate 0:6dee052a3fa4 47
nandgate 0:6dee052a3fa4 48 /**
nandgate 0:6dee052a3fa4 49 * The result of a chunk of data used for the HTTPHandler Methodes data and send
nandgate 0:6dee052a3fa4 50 */
nandgate 0:6dee052a3fa4 51 enum HTTPHandle {
nandgate 0:6dee052a3fa4 52 /** Execution Succeeded but more data expected. */
nandgate 0:6dee052a3fa4 53 HTTP_Success = 600,
nandgate 0:6dee052a3fa4 54
nandgate 0:6dee052a3fa4 55 /** Running out of memory waiting for memory */
nandgate 0:6dee052a3fa4 56 HTTP_SenderMemory = 601,
nandgate 0:6dee052a3fa4 57
nandgate 0:6dee052a3fa4 58
nandgate 0:6dee052a3fa4 59 /** Execution Succeeded and no more data expected. */
nandgate 0:6dee052a3fa4 60 HTTP_SuccessEnded = 700,
nandgate 0:6dee052a3fa4 61
nandgate 0:6dee052a3fa4 62 /** Execution failed. Close conection*/
nandgate 0:6dee052a3fa4 63 HTTP_Failed = 701,
nandgate 0:6dee052a3fa4 64
nandgate 0:6dee052a3fa4 65 /** This module will deliver the data. */
nandgate 0:6dee052a3fa4 66 HTTP_Deliver = 800,
nandgate 0:6dee052a3fa4 67
nandgate 0:6dee052a3fa4 68 /** This module has add header fields to the request. */
nandgate 0:6dee052a3fa4 69 HTTP_AddFields = 801,
nandgate 0:6dee052a3fa4 70 };
nandgate 0:6dee052a3fa4 71
nandgate 0:6dee052a3fa4 72 /**
nandgate 0:6dee052a3fa4 73 * A parent object for a data storage container for all HTTPHandler objects.
nandgate 0:6dee052a3fa4 74 */
nandgate 0:6dee052a3fa4 75 class HTTPData {
nandgate 0:6dee052a3fa4 76 public:
nandgate 0:6dee052a3fa4 77 HTTPData() {}
nandgate 0:6dee052a3fa4 78 virtual ~HTTPData() {}
nandgate 0:6dee052a3fa4 79 };
nandgate 0:6dee052a3fa4 80
nandgate 0:6dee052a3fa4 81 /**
nandgate 0:6dee052a3fa4 82 * A HTTPHandler will serve the requested data if there is an object of a
nandgate 0:6dee052a3fa4 83 * child class from HTTPHandler which is registert to an matching prefix.
nandgate 0:6dee052a3fa4 84 * To see how to implement your own HTTPHandler classes have a look at
nandgate 0:6dee052a3fa4 85 * HTTPRPC HTTPStaticPage and HTTPFileSystemHandler.
nandgate 0:6dee052a3fa4 86 */
nandgate 0:6dee052a3fa4 87 class HTTPHandler {
nandgate 0:6dee052a3fa4 88 public:
nandgate 0:6dee052a3fa4 89 HTTPHandler(const char *prefix) : _prefix(prefix) {};
nandgate 0:6dee052a3fa4 90 virtual ~HTTPHandler() {
nandgate 0:6dee052a3fa4 91 delete _prefix;
nandgate 0:6dee052a3fa4 92 };
nandgate 0:6dee052a3fa4 93
nandgate 0:6dee052a3fa4 94 protected:
nandgate 0:6dee052a3fa4 95 /**
nandgate 0:6dee052a3fa4 96 * Register needed header fields by the HTTPServer.
nandgate 0:6dee052a3fa4 97 * Because of memory size the server will throw away all request header fields which are not registert.
nandgate 0:6dee052a3fa4 98 * Register the fields you need in your implementation of this method.
nandgate 0:6dee052a3fa4 99 */
nandgate 0:6dee052a3fa4 100 virtual void reg(HTTPServer *) {};
nandgate 0:6dee052a3fa4 101
nandgate 0:6dee052a3fa4 102 /**
nandgate 0:6dee052a3fa4 103 * This Method returns if you will deliver the requested page or not.
nandgate 0:6dee052a3fa4 104 * It will only executed if the prefix is matched by the URL.
nandgate 0:6dee052a3fa4 105 * If you want to add something to the headerfiles use this method and return HTTP_AddFields. See HTTPFields
nandgate 0:6dee052a3fa4 106 * This would be the right method to implement an Auth Handler.
nandgate 0:6dee052a3fa4 107 */
nandgate 0:6dee052a3fa4 108 virtual HTTPHandle action(HTTPConnection *) const {return HTTP_Deliver;}
nandgate 0:6dee052a3fa4 109
nandgate 0:6dee052a3fa4 110 /**
nandgate 0:6dee052a3fa4 111 * If action returned HTTP_Deliver.
nandgate 0:6dee052a3fa4 112 * This function will be executed and it means your handler will be deliver the requested data.
nandgate 0:6dee052a3fa4 113 * In this method is the right place to allocate the needed space for your request data and to prepare the sended Header.
nandgate 0:6dee052a3fa4 114 */
nandgate 0:6dee052a3fa4 115 virtual HTTPStatus init(HTTPConnection *) const {return HTTP_NotFound;}
nandgate 0:6dee052a3fa4 116
nandgate 0:6dee052a3fa4 117 /**
nandgate 0:6dee052a3fa4 118 * If data from a post request is arrived for an request you accepted this function will be executed with the data.
nandgate 0:6dee052a3fa4 119 * @param data A pointer to the received data.
nandgate 0:6dee052a3fa4 120 * @param len The length of the received data.
nandgate 0:6dee052a3fa4 121 * @return Return an HTTPHandle. For example HTTP_SuccessEnded if you received all your needed data and want to close the conection (normally not the case).
nandgate 0:6dee052a3fa4 122 */
nandgate 0:6dee052a3fa4 123 virtual HTTPHandle data(HTTPConnection *, void *data, int len) const {return HTTP_SuccessEnded;}
nandgate 0:6dee052a3fa4 124
nandgate 0:6dee052a3fa4 125 /**
nandgate 0:6dee052a3fa4 126 * If tere is new space in the sendbuffer this function is executed. You can send maximal Bytes of data.
nandgate 0:6dee052a3fa4 127 * @return Return an HTTPHandle. For example HTTP_SuccessEnded if you send out all your data and you want to close the connection.
nandgate 0:6dee052a3fa4 128 */
nandgate 0:6dee052a3fa4 129 virtual HTTPHandle send(HTTPConnection *, int) const {return HTTP_SuccessEnded;}
nandgate 0:6dee052a3fa4 130
nandgate 0:6dee052a3fa4 131 /**
nandgate 0:6dee052a3fa4 132 * returns the Prefix from the HTTPHandler
nandgate 0:6dee052a3fa4 133 */
nandgate 0:6dee052a3fa4 134 const char *getPrefix() const {return _prefix;}
nandgate 0:6dee052a3fa4 135
nandgate 0:6dee052a3fa4 136 const char *_prefix;
nandgate 0:6dee052a3fa4 137
nandgate 0:6dee052a3fa4 138 friend HTTPServer;
nandgate 0:6dee052a3fa4 139 friend HTTPConnection;
nandgate 0:6dee052a3fa4 140 };
nandgate 0:6dee052a3fa4 141
nandgate 0:6dee052a3fa4 142 /**
nandgate 0:6dee052a3fa4 143 * For every incomming connection we have a HTTPConnection object which will handle the requests of this connection.
nandgate 0:6dee052a3fa4 144 */
nandgate 0:6dee052a3fa4 145 class HTTPConnection : public TCPConnection {
nandgate 0:6dee052a3fa4 146 public:
nandgate 0:6dee052a3fa4 147 /**
nandgate 0:6dee052a3fa4 148 * Constructs a new connection object from a server.
nandgate 0:6dee052a3fa4 149 * It just need the server object to contact the handlers
nandgate 0:6dee052a3fa4 150 * and the tcp connection pcb.
nandgate 0:6dee052a3fa4 151 * @param parent The server which created the connection.
nandgate 0:6dee052a3fa4 152 * @param pcb The pcb object NetServers internal representation of an TCP Connection
nandgate 0:6dee052a3fa4 153 */
nandgate 0:6dee052a3fa4 154 HTTPConnection(HTTPServer *parent, struct tcp_pcb *pcb);
nandgate 0:6dee052a3fa4 155 /**
nandgate 0:6dee052a3fa4 156 * Default destructor. Simple cleanup.
nandgate 0:6dee052a3fa4 157 */
nandgate 0:6dee052a3fa4 158 virtual ~HTTPConnection();
nandgate 0:6dee052a3fa4 159
nandgate 0:6dee052a3fa4 160 /**
nandgate 0:6dee052a3fa4 161 * Get the requested url.
nandgate 0:6dee052a3fa4 162 * Only set if a request ist received.
nandgate 0:6dee052a3fa4 163 */
nandgate 0:6dee052a3fa4 164 char *getURL() const { return _request_url; }
nandgate 0:6dee052a3fa4 165
nandgate 0:6dee052a3fa4 166 /**
nandgate 0:6dee052a3fa4 167 * Gets a string of set fields to send with the answere header.
nandgate 0:6dee052a3fa4 168 */
nandgate 0:6dee052a3fa4 169 const char *getHeaderFields() const { return (_request_headerfields)?_request_headerfields:""; }
nandgate 0:6dee052a3fa4 170
nandgate 0:6dee052a3fa4 171 /**
nandgate 0:6dee052a3fa4 172 * Gets the length of the anwere in bytes. This is requiered for the HTTP Header.
nandgate 0:6dee052a3fa4 173 * It should be set over setLength by an HTTPHandler in the init() method.
nandgate 0:6dee052a3fa4 174 */
nandgate 0:6dee052a3fa4 175 const int &getLength() const { return _request_length; }
nandgate 0:6dee052a3fa4 176
nandgate 0:6dee052a3fa4 177 /**
nandgate 0:6dee052a3fa4 178 * Gets POST or GET or 0 depends on wether ther is a request and what type is requested.
nandgate 0:6dee052a3fa4 179 */
nandgate 0:6dee052a3fa4 180 const char &getType() const { return _request_type; }
nandgate 0:6dee052a3fa4 181
nandgate 0:6dee052a3fa4 182 /**
nandgate 0:6dee052a3fa4 183 * Gets a value from a header field of the request header.
nandgate 0:6dee052a3fa4 184 * But you must have registerd this headerfield by the HTTPServer before.
nandgate 0:6dee052a3fa4 185 * Use the HTTPHandler::reg() method for the registration of important header fields for your Handler.
nandgate 0:6dee052a3fa4 186 */
nandgate 0:6dee052a3fa4 187 const char *getField(char *key) const;
nandgate 0:6dee052a3fa4 188
nandgate 0:6dee052a3fa4 189 /**
nandgate 0:6dee052a3fa4 190 * For internal usage. Adds an header field value to its hash.
nandgate 0:6dee052a3fa4 191 * If it was registered You can see the Value with the getField method
nandgate 0:6dee052a3fa4 192 */
nandgate 0:6dee052a3fa4 193 void addField(char *key, char *value);
nandgate 0:6dee052a3fa4 194
nandgate 0:6dee052a3fa4 195 /**
nandgate 0:6dee052a3fa4 196 * Sets the result length for an request shoud be set in an HTTPHandler.init() call.
nandgate 0:6dee052a3fa4 197 * This Value will be send with the response header before the first chunk of data is send.
nandgate 0:6dee052a3fa4 198 */
nandgate 0:6dee052a3fa4 199 void setLength(const int &value) { _request_length = value; }
nandgate 0:6dee052a3fa4 200
nandgate 0:6dee052a3fa4 201 /**
nandgate 0:6dee052a3fa4 202 * Set the response header field to a value.
nandgate 0:6dee052a3fa4 203 * Should be used in the HTTPHandler::init() method.
nandgate 0:6dee052a3fa4 204 * For example if you want to set caching methods.
nandgate 0:6dee052a3fa4 205 */
nandgate 0:6dee052a3fa4 206 void setHeaderFields(char *value) { _request_headerfields = value; }
nandgate 0:6dee052a3fa4 207
nandgate 0:6dee052a3fa4 208 /** Indicates that if a request is received the header is incomplete until now. */
nandgate 0:6dee052a3fa4 209 bool request_incomplete;
nandgate 0:6dee052a3fa4 210
nandgate 0:6dee052a3fa4 211 /** If an request is complete HTTPHandler:init will be called and can store here its connection data. */
nandgate 0:6dee052a3fa4 212 HTTPData *data;
nandgate 0:6dee052a3fa4 213
nandgate 0:6dee052a3fa4 214 /** The handler which handles the current request. Depends on the prefix of the URL. */
nandgate 0:6dee052a3fa4 215 HTTPHandler *request_handler;
nandgate 0:6dee052a3fa4 216
nandgate 0:6dee052a3fa4 217 /** The status of the request. Will be set as result of HTTPHandler::init. */
nandgate 0:6dee052a3fa4 218 HTTPStatus request_status;
nandgate 0:6dee052a3fa4 219
nandgate 0:6dee052a3fa4 220 /** The HTTTPServer which created this connection. */
nandgate 0:6dee052a3fa4 221 HTTPServer *parent;
nandgate 0:6dee052a3fa4 222 private:
nandgate 0:6dee052a3fa4 223 virtual void err(err_t err);
nandgate 0:6dee052a3fa4 224 virtual err_t poll();
nandgate 0:6dee052a3fa4 225 virtual err_t sent(u16_t len);
nandgate 0:6dee052a3fa4 226 virtual err_t recv(struct pbuf *q, err_t err);
nandgate 0:6dee052a3fa4 227
nandgate 0:6dee052a3fa4 228 /** We will not make any DNS requests. */
nandgate 0:6dee052a3fa4 229 virtual void dnsreply(const char *, struct ip_addr *) {}
nandgate 0:6dee052a3fa4 230
nandgate 0:6dee052a3fa4 231 /** If a request is finished it will be deleted with this method. Simple cleanup. */
nandgate 0:6dee052a3fa4 232 void deleteRequest();
nandgate 0:6dee052a3fa4 233
nandgate 0:6dee052a3fa4 234 /** Call the handler to send the next chunk of data. */
nandgate 0:6dee052a3fa4 235 void send();
nandgate 0:6dee052a3fa4 236
nandgate 0:6dee052a3fa4 237 /** Call the handler if we received new data. */
nandgate 0:6dee052a3fa4 238 void store(void *d, struct pbuf *p);
nandgate 0:6dee052a3fa4 239
nandgate 0:6dee052a3fa4 240 /**
nandgate 0:6dee052a3fa4 241 * If a request header is not complete we can colect needed header fields.
nandgate 0:6dee052a3fa4 242 * This happens in here.
nandgate 0:6dee052a3fa4 243 */
nandgate 0:6dee052a3fa4 244 void getFields(struct pbuf **q, char **d);
nandgate 0:6dee052a3fa4 245
nandgate 0:6dee052a3fa4 246 char *_request_url;
nandgate 0:6dee052a3fa4 247 char _request_type;
nandgate 0:6dee052a3fa4 248 char *_request_headerfields;
nandgate 0:6dee052a3fa4 249 map<unsigned int, char *> _request_fields;
nandgate 0:6dee052a3fa4 250 int _request_length;
nandgate 0:6dee052a3fa4 251 char *_request_arg_key;
nandgate 0:6dee052a3fa4 252 char *_request_arg_value;
nandgate 0:6dee052a3fa4 253 char _request_arg_state;
nandgate 0:6dee052a3fa4 254
nandgate 0:6dee052a3fa4 255 unsigned int emptypolls; // Last time for timeout
nandgate 0:6dee052a3fa4 256 unsigned int _timeout_max;
nandgate 0:6dee052a3fa4 257
nandgate 0:6dee052a3fa4 258 bool webSocket; // JDL
nandgate 0:6dee052a3fa4 259
nandgate 0:6dee052a3fa4 260 };
nandgate 0:6dee052a3fa4 261
nandgate 0:6dee052a3fa4 262 /* Class HTTPServer
nandgate 0:6dee052a3fa4 263 * An object of this class is an HTTPServer instance and will anwere requests on a given port.
nandgate 0:6dee052a3fa4 264 * It will deliver HTTP pages
nandgate 0:6dee052a3fa4 265 */
nandgate 0:6dee052a3fa4 266 class HTTPServer : public TCPListener {
nandgate 0:6dee052a3fa4 267 public:
nandgate 0:6dee052a3fa4 268
nandgate 0:6dee052a3fa4 269 /* Constructor: HTTPServer
nandgate 0:6dee052a3fa4 270 * Creates an HTTPServer object. You might want to initialise the network server befor.
nandgate 0:6dee052a3fa4 271 * If you dont do it it will be happen by the first post or get request you make.
nandgate 0:6dee052a3fa4 272 *
nandgate 0:6dee052a3fa4 273 * To initialize the network server on creation of the HTTPServer object it's possible to parse some arguments:
nandgate 0:6dee052a3fa4 274 * Variables:
nandgate 0:6dee052a3fa4 275 * hostname - A host name for the device. Might take a while to appear in the network,
nandgate 0:6dee052a3fa4 276 * depends on the network infrastructure. Furthermore in most cases you have
nandgate 0:6dee052a3fa4 277 * to add your domainname after the host name to address the device.
nandgate 0:6dee052a3fa4 278 * Default is NULL.
nandgate 0:6dee052a3fa4 279 * ip - The device ipaddress or ip_addr_any for dhcp. Default is ip_addr_any
nandgate 0:6dee052a3fa4 280 * nm - The device netmask or ip_addr_any for dhcp. Default is ip_addr_any.
nandgate 0:6dee052a3fa4 281 * gw - The device gateway or ip_addr_any for dhcp. Default is ip_addr_any.
nandgate 0:6dee052a3fa4 282 * dns - The device first dns server ip or ip_addr_any for dhcp. Default is ip_addr_any.
nandgate 0:6dee052a3fa4 283 *
nandgate 0:6dee052a3fa4 284 * Example:
nandgate 0:6dee052a3fa4 285 * > HTTPServer http; // Simple DHCP, brings up the TCP/IP stack on bind(). Default prot is port 80.
nandgate 0:6dee052a3fa4 286 * > HTTPServer http(8080); // Port is here 8080.
nandgate 0:6dee052a3fa4 287 *
nandgate 0:6dee052a3fa4 288 * > HTTPServer http("worf"); // Brings up the device with DHCP and sets the host name "worf"
nandgate 0:6dee052a3fa4 289 * > // The device will be available under worf.<your local domain>
nandgate 0:6dee052a3fa4 290 * > // for example worf.1-2-3-4.dynamic.sky.com
nandgate 0:6dee052a3fa4 291 *
nandgate 0:6dee052a3fa4 292 * > HTTPServer http("wolf", // Brings up the device with static IP address and domain name.
nandgate 0:6dee052a3fa4 293 * > IPv4(192,168,0,44), // IPv4 is a helper function which allows to rtype ipaddresses direct
nandgate 0:6dee052a3fa4 294 * > IPv4(255,255,255,0), // as numbers in C++.
nandgate 0:6dee052a3fa4 295 * > IPv4(192,168,0,1), // the device address is set to 192.168.0.44, netmask 255.255.255.0
nandgate 0:6dee052a3fa4 296 * > IPv4(192,168,0,1) // default gateway is 192.168.0.1 and dns to 192.168.0.1 as well.
nandgate 0:6dee052a3fa4 297 * > 8080); // And port is on 8080. Default port is 80.
nandgate 0:6dee052a3fa4 298 */
nandgate 0:6dee052a3fa4 299
nandgate 0:6dee052a3fa4 300 HTTPServer(const char *hostname, struct ip_addr ip = ip_addr_any, struct ip_addr nm = ip_addr_any, struct ip_addr gw = ip_addr_any, struct ip_addr dns = ip_addr_any, unsigned short port = 80);
nandgate 0:6dee052a3fa4 301 HTTPServer(unsigned short port = 80);
nandgate 0:6dee052a3fa4 302
nandgate 0:6dee052a3fa4 303 /* Destructor: ~HTTPServer
nandgate 0:6dee052a3fa4 304 * Destroys the HTTPServer and all open connections.
nandgate 0:6dee052a3fa4 305 */
nandgate 0:6dee052a3fa4 306 virtual ~HTTPServer() {
nandgate 0:6dee052a3fa4 307 fields.clear();
nandgate 0:6dee052a3fa4 308 _handler.clear();
nandgate 0:6dee052a3fa4 309 }
nandgate 0:6dee052a3fa4 310
nandgate 0:6dee052a3fa4 311 /* Function: addHandler
nandgate 0:6dee052a3fa4 312 * Add a new content handler to handle requests.
nandgate 0:6dee052a3fa4 313 * Content handler are URL prefix specific.
nandgate 0:6dee052a3fa4 314 * Have a look at HTTPRPC and HTTPFileSystemHandler for examples.
nandgate 0:6dee052a3fa4 315 */
nandgate 0:6dee052a3fa4 316 virtual void addHandler(HTTPHandler *handler) {
nandgate 0:6dee052a3fa4 317 _handler.push_back(handler);
nandgate 0:6dee052a3fa4 318 handler->reg(this);
nandgate 0:6dee052a3fa4 319 }
nandgate 0:6dee052a3fa4 320
nandgate 0:6dee052a3fa4 321 /* Function registerField
nandgate 0:6dee052a3fa4 322 * Register needed header fields to filter from a request header.
nandgate 0:6dee052a3fa4 323 * Should be called from HTTPHandler::reg()
nandgate 0:6dee052a3fa4 324 */
nandgate 0:6dee052a3fa4 325 virtual void registerField(char *name) {
nandgate 0:6dee052a3fa4 326 fields.insert(hash((unsigned char *)name));
nandgate 0:6dee052a3fa4 327 }
nandgate 0:6dee052a3fa4 328
nandgate 0:6dee052a3fa4 329 /* Function isField
nandgate 0:6dee052a3fa4 330 * A short lookup if the headerfield is registerd.
nandgate 0:6dee052a3fa4 331 */
nandgate 0:6dee052a3fa4 332 virtual bool isField(unsigned long h) const {
nandgate 0:6dee052a3fa4 333 return fields.find(h) != fields.end();
nandgate 0:6dee052a3fa4 334 }
nandgate 0:6dee052a3fa4 335
nandgate 0:6dee052a3fa4 336 /* Function: poll
nandgate 0:6dee052a3fa4 337 * You have to call this method at least every 250ms to let the http server run.
nandgate 0:6dee052a3fa4 338 * But I would recomend to call this function as fast as possible.
nandgate 0:6dee052a3fa4 339 * This function is directly coupled to the answere time of your HTTPServer instance.
nandgate 0:6dee052a3fa4 340 */
nandgate 0:6dee052a3fa4 341 inline static void poll() {
nandgate 0:6dee052a3fa4 342 NetServer::poll();
nandgate 0:6dee052a3fa4 343 }
nandgate 0:6dee052a3fa4 344
nandgate 0:6dee052a3fa4 345 /* Function: timeout
nandgate 0:6dee052a3fa4 346 * Sets the timout for a HTTP request.
nandgate 0:6dee052a3fa4 347 * The timout is the time wich is allowed to spent between two incomming TCP packets.
nandgate 0:6dee052a3fa4 348 * If the time is passed the connection will be closed.
nandgate 0:6dee052a3fa4 349 */
nandgate 0:6dee052a3fa4 350 void timeout(int value) {
nandgate 0:6dee052a3fa4 351 _timeout_max = value;
nandgate 0:6dee052a3fa4 352 }
nandgate 0:6dee052a3fa4 353
nandgate 0:6dee052a3fa4 354 /* Function timeout
nandgate 0:6dee052a3fa4 355 * Returns the timout to use it in HTTPHandlers and HTTPConnections
nandgate 0:6dee052a3fa4 356 */
nandgate 0:6dee052a3fa4 357 int timeout() {
nandgate 0:6dee052a3fa4 358 return _timeout_max;
nandgate 0:6dee052a3fa4 359 }
nandgate 0:6dee052a3fa4 360 private:
nandgate 0:6dee052a3fa4 361 /**
nandgate 0:6dee052a3fa4 362 * Pick up the right handler to deliver the response.
nandgate 0:6dee052a3fa4 363 */
nandgate 0:6dee052a3fa4 364 virtual HTTPHandler *handle(HTTPConnection *con) const {
nandgate 0:6dee052a3fa4 365 for(list<HTTPHandler *>::const_iterator iter = _handler.begin(); iter != _handler.end(); iter++) {
nandgate 0:6dee052a3fa4 366 if(strncmp((*iter)->getPrefix(), con->getURL(), strlen((*iter)->getPrefix()))==0) {
nandgate 0:6dee052a3fa4 367 HTTPHandler *handler = *iter;
nandgate 0:6dee052a3fa4 368 if(handler->action(con)==HTTP_Deliver) {
nandgate 0:6dee052a3fa4 369 return *iter;
nandgate 0:6dee052a3fa4 370 }
nandgate 0:6dee052a3fa4 371 }
nandgate 0:6dee052a3fa4 372 }
nandgate 0:6dee052a3fa4 373 return NULL;
nandgate 0:6dee052a3fa4 374 }
nandgate 0:6dee052a3fa4 375
nandgate 0:6dee052a3fa4 376 /**
nandgate 0:6dee052a3fa4 377 * Accept an incomming connection and fork a HTTPConnection if we have enought memory.
nandgate 0:6dee052a3fa4 378 */
nandgate 0:6dee052a3fa4 379 virtual err_t accept(struct tcp_pcb *pcb, err_t err) {
nandgate 0:6dee052a3fa4 380 LWIP_UNUSED_ARG(err);
nandgate 0:6dee052a3fa4 381 HTTPConnection *con = new HTTPConnection(this, pcb);
nandgate 0:6dee052a3fa4 382 // printf("New Connection opend. Now are %u connections open\n", ++gconnections);
nandgate 0:6dee052a3fa4 383 if(con == NULL) {
nandgate 0:6dee052a3fa4 384 printf("http_accept: Out of memory\n");
nandgate 0:6dee052a3fa4 385 return ERR_MEM;
nandgate 0:6dee052a3fa4 386 }
nandgate 0:6dee052a3fa4 387 con->set_poll_interval(1);
nandgate 0:6dee052a3fa4 388 tcp_setprio(pcb, TCP_PRIO_MIN);
nandgate 0:6dee052a3fa4 389 return ERR_OK;
nandgate 0:6dee052a3fa4 390 }
nandgate 0:6dee052a3fa4 391
nandgate 0:6dee052a3fa4 392 /** The registerd request header fields */
nandgate 0:6dee052a3fa4 393 set<unsigned int> fields;
nandgate 0:6dee052a3fa4 394
nandgate 0:6dee052a3fa4 395 /** A List of all registered handler. */
nandgate 0:6dee052a3fa4 396 list<HTTPHandler *> _handler;
nandgate 0:6dee052a3fa4 397
nandgate 0:6dee052a3fa4 398 int _timeout_max;
nandgate 0:6dee052a3fa4 399
nandgate 0:6dee052a3fa4 400 friend HTTPConnection;
nandgate 0:6dee052a3fa4 401 };
nandgate 0:6dee052a3fa4 402
nandgate 0:6dee052a3fa4 403 };
nandgate 0:6dee052a3fa4 404
nandgate 0:6dee052a3fa4 405 #include "HTTPRPC.h"
nandgate 0:6dee052a3fa4 406 #include "HTTPFS.h"
nandgate 0:6dee052a3fa4 407 #include "HTTPFields.h"
nandgate 0:6dee052a3fa4 408
nandgate 0:6dee052a3fa4 409 #endif /* HTTP_H */