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_OK = 200, 00038 HTTP_BadRequest = 400, 00039 HTTP_Unauthorized = 401, 00040 HTTP_Forbidden = 403, 00041 HTTP_NotFound = 404, 00042 HTTP_MethodNotAllowed = 405, 00043 HTTP_InternalServerError = 500, 00044 HTTP_NotImplemented = 501, 00045 }; 00046 00047 /** 00048 * The result of a chunk of data used for the HTTPHandler Methodes data and send 00049 */ 00050 enum HTTPHandle { 00051 /** Execution Succeeded but more data expected. */ 00052 HTTP_Success = 600, 00053 00054 /** Running out of memory waiting for memory */ 00055 HTTP_SenderMemory = 601, 00056 00057 00058 /** Execution Succeeded and no more data expected. */ 00059 HTTP_SuccessEnded = 700, 00060 00061 /** Execution failed. Close conection*/ 00062 HTTP_Failed = 701, 00063 00064 /** This module will deliver the data. */ 00065 HTTP_Deliver = 800, 00066 00067 /** This module has add header fields to the request. */ 00068 HTTP_AddFields = 801, 00069 }; 00070 00071 /** 00072 * A parent object for a data storage container for all HTTPHandler objects. 00073 */ 00074 class HTTPData { 00075 public: 00076 HTTPData() {} 00077 virtual ~HTTPData() {} 00078 }; 00079 00080 /** 00081 * A HTTPHandler will serve the requested data if there is an object of a 00082 * child class from HTTPHandler which is registert to an matching prefix. 00083 * To see how to implement your own HTTPHandler classes have a look at 00084 * HTTPRPC HTTPStaticPage and HTTPFileSystemHandler. 00085 */ 00086 class HTTPHandler { 00087 public: 00088 HTTPHandler(const char *prefix) : _prefix(prefix) {}; 00089 virtual ~HTTPHandler() { 00090 delete _prefix; 00091 }; 00092 00093 protected: 00094 /** 00095 * Register needed header fields by the HTTPServer. 00096 * Because of memory size the server will throw away all request header fields which are not registert. 00097 * Register the fields you need in your implementation of this method. 00098 */ 00099 virtual void reg(HTTPServer *) {}; 00100 00101 /** 00102 * This Method returns if you will deliver the requested page or not. 00103 * It will only executed if the prefix is matched by the URL. 00104 * If you want to add something to the headerfiles use this method and return HTTP_AddFields. See HTTPFields 00105 * This would be the right method to implement an Auth Handler. 00106 */ 00107 virtual HTTPHandle action(HTTPConnection *) const {return HTTP_Deliver;} 00108 00109 /** 00110 * If action returned HTTP_Deliver. 00111 * This function will be executed and it means your handler will be deliver the requested data. 00112 * In this method is the right place to allocate the needed space for your request data and to prepare the sended Header. 00113 */ 00114 virtual HTTPStatus init(HTTPConnection *) const {return HTTP_NotFound;} 00115 00116 /** 00117 * If data from a post request is arrived for an request you accepted this function will be executed with the data. 00118 * @param data A pointer to the received data. 00119 * @param len The length of the received data. 00120 * @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). 00121 */ 00122 virtual HTTPHandle data(HTTPConnection *, void *data, int len) const {return HTTP_SuccessEnded;} 00123 00124 /** 00125 * If tere is new space in the sendbuffer this function is executed. You can send maximal Bytes of data. 00126 * @return Return an HTTPHandle. For example HTTP_SuccessEnded if you send out all your data and you want to close the connection. 00127 */ 00128 virtual HTTPHandle send(HTTPConnection *, int) const {return HTTP_SuccessEnded;} 00129 00130 /** 00131 * returns the Prefix from the HTTPHandler 00132 */ 00133 const char *getPrefix() const {return _prefix;} 00134 00135 const char *_prefix; 00136 00137 friend HTTPServer; 00138 friend HTTPConnection; 00139 }; 00140 00141 /** 00142 * For every incomming connection we have a HTTPConnection object which will handle the requests of this connection. 00143 */ 00144 class HTTPConnection : public TCPConnection { 00145 public: 00146 /** 00147 * Constructs a new connection object from a server. 00148 * It just need the server object to contact the handlers 00149 * and the tcp connection pcb. 00150 * @param parent The server which created the connection. 00151 * @param pcb The pcb object NetServers internal representation of an TCP Connection 00152 */ 00153 HTTPConnection(HTTPServer *parent, struct tcp_pcb *pcb); 00154 /** 00155 * Default destructor. Simple cleanup. 00156 */ 00157 virtual ~HTTPConnection(); 00158 00159 /** 00160 * Get the requested url. 00161 * Only set if a request ist received. 00162 */ 00163 char *getURL() const { return _request_url; } 00164 00165 /** 00166 * Gets a string of set fields to send with the answere header. 00167 */ 00168 const char *getHeaderFields() const { return (_request_headerfields)?_request_headerfields:""; } 00169 00170 /** 00171 * Gets the length of the anwere in bytes. This is requiered for the HTTP Header. 00172 * It should be set over setLength by an HTTPHandler in the init() method. 00173 */ 00174 const int &getLength() const { return _request_length; } 00175 00176 /** 00177 * Gets POST or GET or 0 depends on wether ther is a request and what type is requested. 00178 */ 00179 const char &getType() const { return _request_type; } 00180 00181 /** 00182 * Gets a value from a header field of the request header. 00183 * But you must have registerd this headerfield by the HTTPServer before. 00184 * Use the HTTPHandler::reg() method for the registration of important header fields for your Handler. 00185 */ 00186 const char *getField(char *key) const; 00187 00188 /** 00189 * For internal usage. Adds an header field value to its hash. 00190 * If it was registered You can see the Value with the getField method 00191 */ 00192 void addField(char *key, char *value); 00193 00194 /** 00195 * Sets the result length for an request shoud be set in an HTTPHandler.init() call. 00196 * This Value will be send with the response header before the first chunk of data is send. 00197 */ 00198 void setLength(const int &value) { _request_length = value; } 00199 00200 /** 00201 * Set the response header field to a value. 00202 * Should be used in the HTTPHandler::init() method. 00203 * For example if you want to set caching methods. 00204 */ 00205 void setHeaderFields(char *value) { _request_headerfields = value; } 00206 00207 /** Indicates that if a request is received the header is incomplete until now. */ 00208 bool request_incomplete; 00209 00210 /** If an request is complete HTTPHandler:init will be called and can store here its connection data. */ 00211 HTTPData *data; 00212 00213 /** The handler which handles the current request. Depends on the prefix of the URL. */ 00214 HTTPHandler *request_handler; 00215 00216 /** The status of the request. Will be set as result of HTTPHandler::init. */ 00217 HTTPStatus request_status; 00218 00219 /** The HTTTPServer which created this connection. */ 00220 HTTPServer *parent; 00221 private: 00222 virtual void err(err_t err); 00223 virtual err_t poll(); 00224 virtual err_t sent(u16_t len); 00225 virtual err_t recv(struct pbuf *q, err_t err); 00226 00227 /** We will not make any DNS requests. */ 00228 virtual void dnsreply(const char *, struct ip_addr *) {} 00229 00230 /** If a request is finished it will be deleted with this method. Simple cleanup. */ 00231 void deleteRequest(); 00232 00233 /** Call the handler to send the next chunk of data. */ 00234 void send(); 00235 00236 /** Call the handler if we received new data. */ 00237 void store(void *d, struct pbuf *p); 00238 00239 /** 00240 * If a request header is not complete we can colect needed header fields. 00241 * This happens in here. 00242 */ 00243 void getFields(struct pbuf **q, char **d); 00244 00245 char *_request_url; 00246 char _request_type; 00247 char *_request_headerfields; 00248 map<unsigned int, char *> _request_fields; 00249 int _request_length; 00250 char *_request_arg_key; 00251 char *_request_arg_value; 00252 char _request_arg_state; 00253 00254 u8_t emptypolls; 00255 }; 00256 00257 /** 00258 * The HTTPServer class. 00259 * It representates the top class of an HTTPServer. 00260 */ 00261 class HTTPServer : public TCPListener { 00262 public: 00263 /** 00264 * Create a new server instance by default on port 80. 00265 */ 00266 HTTPServer(u16_t = 80); 00267 virtual ~HTTPServer() { 00268 fields.clear(); 00269 _handler.clear(); 00270 } 00271 00272 /** 00273 * Add a new content handler to handle requests. 00274 * Content handler are URL prefix specific. 00275 * Have a look at HTTPRPC and HTTPFileSystemHandler for examples. 00276 */ 00277 virtual void addHandler(HTTPHandler *handler) { 00278 _handler.push_back(handler); 00279 handler->reg(this); 00280 } 00281 00282 /** 00283 * Register needed header fields to filter from a request header. 00284 * Should be called from HTTPHandler::reg() 00285 */ 00286 virtual void registerField(char *name) { 00287 fields.insert(hash((unsigned char *)name)); 00288 } 00289 00290 /** 00291 * A short lookup if the headerfield is registerd. 00292 */ 00293 virtual bool isField(unsigned long h) const { 00294 return fields.find(h) != fields.end(); 00295 } 00296 00297 /** 00298 * You have to call this method at least every 250ms to let the http server run. 00299 * But I would recomend to call this function as fast as possible. 00300 * This function is directly coupled to the answere time of your HTTPServer instance. 00301 */ 00302 inline static void poll() { 00303 NetServer::poll(); 00304 } 00305 private: 00306 /** 00307 * Pick up the right handler to deliver the response. 00308 */ 00309 virtual HTTPHandler *handle(HTTPConnection *con) const { 00310 for(list<HTTPHandler *>::const_iterator iter = _handler.begin(); 00311 iter != _handler.end(); iter++) { 00312 if(strncmp((*iter)->getPrefix(), con->getURL(), strlen((*iter)->getPrefix()))==0) { 00313 HTTPHandler *handler = *iter; 00314 if(handler->action(con)==HTTP_Deliver) { 00315 return *iter; 00316 } 00317 } 00318 } 00319 return NULL; 00320 } 00321 00322 /** 00323 * Accept an incomming connection and fork a HTTPConnection if we have enought memory. 00324 */ 00325 virtual err_t accept(struct tcp_pcb *pcb, err_t err) { 00326 LWIP_UNUSED_ARG(err); 00327 HTTPConnection *con = new HTTPConnection(this, pcb); 00328 // printf("New Connection opend. Now are %u connections open\n", ++gconnections); 00329 if(con == NULL) { 00330 printf("http_accept: Out of memory\n"); 00331 return ERR_MEM; 00332 } 00333 con->set_poll_interval(1); 00334 tcp_setprio(pcb, TCP_PRIO_MIN); 00335 return ERR_OK; 00336 } 00337 00338 /** The registerd request header fields */ 00339 set<unsigned int> fields; 00340 00341 /** A List of all registered handler. */ 00342 list<HTTPHandler *> _handler; 00343 friend HTTPConnection; 00344 }; 00345 00346 }; 00347 00348 #endif /* HTTP_H */
Generated on Tue Jul 12 2022 19:24:05 by
1.7.2