A version of LWIP, provided for backwards compatibility.
Dependents: AA_DemoBoard DemoBoard HelloServerDemo DemoBoard_RangeIndicator ... more
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 16:06:07 by 1.7.2