Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
HTTPServer.h
00001 #ifndef HTTPSERVER_H 00002 #define HTTPSERVER_H 00003 00004 #include "TCPConnection.h" 00005 #include "TCPListener.h" 00006 #include "NetServer.h" 00007 00008 #include <map> 00009 #include <set> 00010 #include <list> 00011 00012 #define HTTP_MAX_EMPTYPOLLS 100 00013 #define GET 4 00014 #define POST 5 00015 00016 //extern unsigned int gconnections; 00017 00018 using namespace std; 00019 00020 namespace mbed { 00021 00022 class HTTPServer; 00023 class HTTPHandler; 00024 class HTTPConnection; 00025 00026 /** 00027 * A simple HASH function to reduce the size of stored Header Fields 00028 * TODO: Make the Hash case insensetive. 00029 */ 00030 unsigned int hash(unsigned char *str); 00031 00032 /** 00033 * The Status of an HTTP Request 00034 * Nedded for HTTPHandler subclasses to define there reults in the HTTPHandler:init Method. 00035 */ 00036 enum HTTPStatus { 00037 HTTP_SwitchProtocols = 101, 00038 HTTP_OK = 200, 00039 HTTP_BadRequest = 400, 00040 HTTP_Unauthorized = 401, 00041 HTTP_Forbidden = 403, 00042 HTTP_NotFound = 404, 00043 HTTP_MethodNotAllowed = 405, 00044 HTTP_InternalServerError = 500, 00045 HTTP_NotImplemented = 501, 00046 }; 00047 00048 /** 00049 * The result of a chunk of data used for the HTTPHandler Methodes data and send 00050 */ 00051 enum HTTPHandle { 00052 /** Execution Succeeded but more data expected. */ 00053 HTTP_Success = 600, 00054 00055 /** Running out of memory waiting for memory */ 00056 HTTP_SenderMemory = 601, 00057 00058 00059 /** Execution Succeeded and no more data expected. */ 00060 HTTP_SuccessEnded = 700, 00061 00062 /** Execution failed. Close conection*/ 00063 HTTP_Failed = 701, 00064 00065 /** This module will deliver the data. */ 00066 HTTP_Deliver = 800, 00067 00068 /** This module has add header fields to the request. */ 00069 HTTP_AddFields = 801, 00070 }; 00071 00072 /** 00073 * A parent object for a data storage container for all HTTPHandler objects. 00074 */ 00075 class HTTPData { 00076 public: 00077 HTTPData() {} 00078 virtual ~HTTPData() {} 00079 }; 00080 00081 /** 00082 * A HTTPHandler will serve the requested data if there is an object of a 00083 * child class from HTTPHandler which is registert to an matching prefix. 00084 * To see how to implement your own HTTPHandler classes have a look at 00085 * HTTPRPC HTTPStaticPage and HTTPFileSystemHandler. 00086 */ 00087 class HTTPHandler { 00088 public: 00089 HTTPHandler(const char *prefix) : _prefix(prefix) {}; 00090 virtual ~HTTPHandler() { 00091 delete _prefix; 00092 }; 00093 00094 protected: 00095 /** 00096 * Register needed header fields by the HTTPServer. 00097 * Because of memory size the server will throw away all request header fields which are not registert. 00098 * Register the fields you need in your implementation of this method. 00099 */ 00100 virtual void reg(HTTPServer *) {}; 00101 00102 /** 00103 * This Method returns if you will deliver the requested page or not. 00104 * It will only executed if the prefix is matched by the URL. 00105 * If you want to add something to the headerfiles use this method and return HTTP_AddFields. See HTTPFields 00106 * This would be the right method to implement an Auth Handler. 00107 */ 00108 virtual HTTPHandle action(HTTPConnection *) const {return HTTP_Deliver;} 00109 00110 /** 00111 * If action returned HTTP_Deliver. 00112 * This function will be executed and it means your handler will be deliver the requested data. 00113 * In this method is the right place to allocate the needed space for your request data and to prepare the sended Header. 00114 */ 00115 virtual HTTPStatus init(HTTPConnection *) const {return HTTP_NotFound;} 00116 00117 /** 00118 * If data from a post request is arrived for an request you accepted this function will be executed with the data. 00119 * @param data A pointer to the received data. 00120 * @param len The length of the received data. 00121 * @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). 00122 */ 00123 virtual HTTPHandle data(HTTPConnection *, void *data, int len) const {return HTTP_SuccessEnded;} 00124 00125 /** 00126 * If tere is new space in the sendbuffer this function is executed. You can send maximal Bytes of data. 00127 * @return Return an HTTPHandle. For example HTTP_SuccessEnded if you send out all your data and you want to close the connection. 00128 */ 00129 virtual HTTPHandle send(HTTPConnection *, int) const {return HTTP_SuccessEnded;} 00130 00131 /** 00132 * returns the Prefix from the HTTPHandler 00133 */ 00134 const char *getPrefix() const {return _prefix;} 00135 00136 const char *_prefix; 00137 00138 friend HTTPServer; 00139 friend HTTPConnection; 00140 }; 00141 00142 /** 00143 * For every incomming connection we have a HTTPConnection object which will handle the requests of this connection. 00144 */ 00145 class HTTPConnection : public TCPConnection { 00146 public: 00147 /** 00148 * Constructs a new connection object from a server. 00149 * It just need the server object to contact the handlers 00150 * and the tcp connection pcb. 00151 * @param parent The server which created the connection. 00152 * @param pcb The pcb object NetServers internal representation of an TCP Connection 00153 */ 00154 HTTPConnection(HTTPServer *parent, struct tcp_pcb *pcb); 00155 /** 00156 * Default destructor. Simple cleanup. 00157 */ 00158 virtual ~HTTPConnection(); 00159 00160 /** 00161 * Get the requested url. 00162 * Only set if a request ist received. 00163 */ 00164 char *getURL() const { return _request_url; } 00165 00166 /** 00167 * Gets a string of set fields to send with the answere header. 00168 */ 00169 const char *getHeaderFields() const { return (_request_headerfields)?_request_headerfields:""; } 00170 00171 /** 00172 * Gets the length of the anwere in bytes. This is requiered for the HTTP Header. 00173 * It should be set over setLength by an HTTPHandler in the init() method. 00174 */ 00175 const int &getLength() const { return _request_length; } 00176 00177 /** 00178 * Gets POST or GET or 0 depends on wether ther is a request and what type is requested. 00179 */ 00180 const char &getType() const { return _request_type; } 00181 00182 /** 00183 * Gets a value from a header field of the request header. 00184 * But you must have registerd this headerfield by the HTTPServer before. 00185 * Use the HTTPHandler::reg() method for the registration of important header fields for your Handler. 00186 */ 00187 const char *getField(char *key) const; 00188 00189 /** 00190 * For internal usage. Adds an header field value to its hash. 00191 * If it was registered You can see the Value with the getField method 00192 */ 00193 void addField(char *key, char *value); 00194 00195 /** 00196 * Sets the result length for an request shoud be set in an HTTPHandler.init() call. 00197 * This Value will be send with the response header before the first chunk of data is send. 00198 */ 00199 void setLength(const int &value) { _request_length = value; } 00200 00201 /** 00202 * Set the response header field to a value. 00203 * Should be used in the HTTPHandler::init() method. 00204 * For example if you want to set caching methods. 00205 */ 00206 void setHeaderFields(char *value) { _request_headerfields = value; } 00207 00208 /** Indicates that if a request is received the header is incomplete until now. */ 00209 bool request_incomplete; 00210 00211 /** If an request is complete HTTPHandler:init will be called and can store here its connection data. */ 00212 HTTPData *data; 00213 00214 /** The handler which handles the current request. Depends on the prefix of the URL. */ 00215 HTTPHandler *request_handler; 00216 00217 /** The status of the request. Will be set as result of HTTPHandler::init. */ 00218 HTTPStatus request_status; 00219 00220 /** The HTTTPServer which created this connection. */ 00221 HTTPServer *parent; 00222 private: 00223 virtual void err(err_t err); 00224 virtual err_t poll(); 00225 virtual err_t sent(u16_t len); 00226 virtual err_t recv(struct pbuf *q, err_t err); 00227 00228 /** We will not make any DNS requests. */ 00229 virtual void dnsreply(const char *, struct ip_addr *) {} 00230 00231 /** If a request is finished it will be deleted with this method. Simple cleanup. */ 00232 void deleteRequest(); 00233 00234 /** Call the handler to send the next chunk of data. */ 00235 void send(); 00236 00237 /** Call the handler if we received new data. */ 00238 void store(void *d, struct pbuf *p); 00239 00240 /** 00241 * If a request header is not complete we can colect needed header fields. 00242 * This happens in here. 00243 */ 00244 void getFields(struct pbuf **q, char **d); 00245 00246 char *_request_url; 00247 char _request_type; 00248 char *_request_headerfields; 00249 map<unsigned int, char *> _request_fields; 00250 int _request_length; 00251 char *_request_arg_key; 00252 char *_request_arg_value; 00253 char _request_arg_state; 00254 00255 unsigned int emptypolls; // Last time for timeout 00256 unsigned int _timeout_max; 00257 00258 bool webSocket; // JDL 00259 00260 }; 00261 00262 /* Class HTTPServer 00263 * An object of this class is an HTTPServer instance and will anwere requests on a given port. 00264 * It will deliver HTTP pages 00265 */ 00266 class HTTPServer : public TCPListener { 00267 public: 00268 00269 /* Constructor: HTTPServer 00270 * Creates an HTTPServer object. You might want to initialise the network server befor. 00271 * If you dont do it it will be happen by the first post or get request you make. 00272 * 00273 * To initialize the network server on creation of the HTTPServer object it's possible to parse some arguments: 00274 * Variables: 00275 * hostname - A host name for the device. Might take a while to appear in the network, 00276 * depends on the network infrastructure. Furthermore in most cases you have 00277 * to add your domainname after the host name to address the device. 00278 * Default is NULL. 00279 * ip - The device ipaddress or ip_addr_any for dhcp. Default is ip_addr_any 00280 * nm - The device netmask or ip_addr_any for dhcp. Default is ip_addr_any. 00281 * gw - The device gateway or ip_addr_any for dhcp. Default is ip_addr_any. 00282 * dns - The device first dns server ip or ip_addr_any for dhcp. Default is ip_addr_any. 00283 * 00284 * Example: 00285 * > HTTPServer http; // Simple DHCP, brings up the TCP/IP stack on bind(). Default prot is port 80. 00286 * > HTTPServer http(8080); // Port is here 8080. 00287 * 00288 * > HTTPServer http("worf"); // Brings up the device with DHCP and sets the host name "worf" 00289 * > // The device will be available under worf.<your local domain> 00290 * > // for example worf.1-2-3-4.dynamic.sky.com 00291 * 00292 * > HTTPServer http("wolf", // Brings up the device with static IP address and domain name. 00293 * > IPv4(192,168,0,44), // IPv4 is a helper function which allows to rtype ipaddresses direct 00294 * > IPv4(255,255,255,0), // as numbers in C++. 00295 * > IPv4(192,168,0,1), // the device address is set to 192.168.0.44, netmask 255.255.255.0 00296 * > IPv4(192,168,0,1) // default gateway is 192.168.0.1 and dns to 192.168.0.1 as well. 00297 * > 8080); // And port is on 8080. Default port is 80. 00298 */ 00299 00300 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); 00301 HTTPServer(unsigned short port = 80); 00302 00303 /* Destructor: ~HTTPServer 00304 * Destroys the HTTPServer and all open connections. 00305 */ 00306 virtual ~HTTPServer() { 00307 fields.clear(); 00308 _handler.clear(); 00309 } 00310 00311 /* Function: addHandler 00312 * Add a new content handler to handle requests. 00313 * Content handler are URL prefix specific. 00314 * Have a look at HTTPRPC and HTTPFileSystemHandler for examples. 00315 */ 00316 virtual void addHandler(HTTPHandler *handler) { 00317 _handler.push_back(handler); 00318 handler->reg(this); 00319 } 00320 00321 /* Function registerField 00322 * Register needed header fields to filter from a request header. 00323 * Should be called from HTTPHandler::reg() 00324 */ 00325 virtual void registerField(char *name) { 00326 fields.insert(hash((unsigned char *)name)); 00327 } 00328 00329 /* Function isField 00330 * A short lookup if the headerfield is registerd. 00331 */ 00332 virtual bool isField(unsigned long h) const { 00333 return fields.find(h) != fields.end(); 00334 } 00335 00336 /* Function: poll 00337 * You have to call this method at least every 250ms to let the http server run. 00338 * But I would recomend to call this function as fast as possible. 00339 * This function is directly coupled to the answere time of your HTTPServer instance. 00340 */ 00341 inline static void poll() { 00342 NetServer::poll(); 00343 } 00344 00345 /* Function: timeout 00346 * Sets the timout for a HTTP request. 00347 * The timout is the time wich is allowed to spent between two incomming TCP packets. 00348 * If the time is passed the connection will be closed. 00349 */ 00350 void timeout(int value) { 00351 _timeout_max = value; 00352 } 00353 00354 /* Function timeout 00355 * Returns the timout to use it in HTTPHandlers and HTTPConnections 00356 */ 00357 int timeout() { 00358 return _timeout_max; 00359 } 00360 private: 00361 /** 00362 * Pick up the right handler to deliver the response. 00363 */ 00364 virtual HTTPHandler *handle(HTTPConnection *con) const { 00365 for(list<HTTPHandler *>::const_iterator iter = _handler.begin(); iter != _handler.end(); iter++) { 00366 if(strncmp((*iter)->getPrefix(), con->getURL(), strlen((*iter)->getPrefix()))==0) { 00367 HTTPHandler *handler = *iter; 00368 if(handler->action(con)==HTTP_Deliver) { 00369 return *iter; 00370 } 00371 } 00372 } 00373 return NULL; 00374 } 00375 00376 /** 00377 * Accept an incomming connection and fork a HTTPConnection if we have enought memory. 00378 */ 00379 virtual err_t accept(struct tcp_pcb *pcb, err_t err) { 00380 LWIP_UNUSED_ARG(err); 00381 HTTPConnection *con = new HTTPConnection(this, pcb); 00382 // printf("New Connection opend. Now are %u connections open\n", ++gconnections); 00383 if(con == NULL) { 00384 printf("http_accept: Out of memory\n"); 00385 return ERR_MEM; 00386 } 00387 con->set_poll_interval(1); 00388 tcp_setprio(pcb, TCP_PRIO_MIN); 00389 return ERR_OK; 00390 } 00391 00392 /** The registerd request header fields */ 00393 set<unsigned int> fields; 00394 00395 /** A List of all registered handler. */ 00396 list<HTTPHandler *> _handler; 00397 00398 int _timeout_max; 00399 00400 friend HTTPConnection; 00401 }; 00402 00403 }; 00404 00405 #include "HTTPRPC.h" 00406 #include "HTTPFS.h" 00407 #include "HTTPFields.h" 00408 00409 #endif /* HTTP_H */
Generated on Wed Jul 13 2022 23:42:33 by
1.7.2