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.
Fork of lwip by
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 unsigned int emptypolls; // Last time for timeout 00255 unsigned int _timeout_max; 00256 }; 00257 00258 /* Class HTTPServer 00259 * An object of this class is an HTTPServer instance and will anwere requests on a given port. 00260 * It will deliver HTTP pages 00261 */ 00262 class HTTPServer : public TCPListener { 00263 public: 00264 00265 /* Constructor: HTTPServer 00266 * Creates an HTTPServer object. You might want to initialise the network server befor. 00267 * If you dont do it it will be happen by the first post or get request you make. 00268 * 00269 * To initialize the network server on creation of the HTTPServer object it's possible to parse some arguments: 00270 * Variables: 00271 * hostname - A host name for the device. Might take a while to appear in the network, 00272 * depends on the network infrastructure. Furthermore in most cases you have 00273 * to add your domainname after the host name to address the device. 00274 * Default is NULL. 00275 * ip - The device ipaddress or ip_addr_any for dhcp. Default is ip_addr_any 00276 * nm - The device netmask or ip_addr_any for dhcp. Default is ip_addr_any. 00277 * gw - The device gateway or ip_addr_any for dhcp. Default is ip_addr_any. 00278 * dns - The device first dns server ip or ip_addr_any for dhcp. Default is ip_addr_any. 00279 * 00280 * Example: 00281 * > HTTPServer http; // Simple DHCP, brings up the TCP/IP stack on bind(). Default prot is port 80. 00282 * > HTTPServer http(8080); // Port is here 8080. 00283 * 00284 * > HTTPServer http("worf"); // Brings up the device with DHCP and sets the host name "worf" 00285 * > // The device will be available under worf.<your local domain> 00286 * > // for example worf.1-2-3-4.dynamic.sky.com 00287 * 00288 * > HTTPServer http("wolf", // Brings up the device with static IP address and domain name. 00289 * > IPv4(192,168,0,44), // IPv4 is a helper function which allows to rtype ipaddresses direct 00290 * > IPv4(255,255,255,0), // as numbers in C++. 00291 * > IPv4(192,168,0,1), // the device address is set to 192.168.0.44, netmask 255.255.255.0 00292 * > IPv4(192,168,0,1) // default gateway is 192.168.0.1 and dns to 192.168.0.1 as well. 00293 * > 8080); // And port is on 8080. Default port is 80. 00294 */ 00295 00296 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); 00297 HTTPServer(unsigned short port = 80); 00298 00299 /* Destructor: ~HTTPServer 00300 * Destroys the HTTPServer and all open connections. 00301 */ 00302 virtual ~HTTPServer() { 00303 fields.clear(); 00304 _handler.clear(); 00305 } 00306 00307 /* Function: addHandler 00308 * Add a new content handler to handle requests. 00309 * Content handler are URL prefix specific. 00310 * Have a look at HTTPRPC and HTTPFileSystemHandler for examples. 00311 */ 00312 virtual void addHandler(HTTPHandler *handler) { 00313 _handler.push_back(handler); 00314 handler->reg(this); 00315 } 00316 00317 /* Function registerField 00318 * Register needed header fields to filter from a request header. 00319 * Should be called from HTTPHandler::reg() 00320 */ 00321 virtual void registerField(char *name) { 00322 fields.insert(hash((unsigned char *)name)); 00323 } 00324 00325 /* Function isField 00326 * A short lookup if the headerfield is registerd. 00327 */ 00328 virtual bool isField(unsigned long h) const { 00329 return fields.find(h) != fields.end(); 00330 } 00331 00332 /* Function: poll 00333 * You have to call this method at least every 250ms to let the http server run. 00334 * But I would recomend to call this function as fast as possible. 00335 * This function is directly coupled to the answere time of your HTTPServer instance. 00336 */ 00337 inline static void poll() { 00338 NetServer::poll(); 00339 } 00340 00341 /* Function: timeout 00342 * Sets the timout for a HTTP request. 00343 * The timout is the time wich is allowed to spent between two incomming TCP packets. 00344 * If the time is passed the connection will be closed. 00345 */ 00346 void timeout(int value) { 00347 _timeout_max = value; 00348 } 00349 00350 /* Function timeout 00351 * Returns the timout to use it in HTTPHandlers and HTTPConnections 00352 */ 00353 int timeout() { 00354 return _timeout_max; 00355 } 00356 private: 00357 /** 00358 * Pick up the right handler to deliver the response. 00359 */ 00360 virtual HTTPHandler *handle(HTTPConnection *con) const { 00361 for(list<HTTPHandler *>::const_iterator iter = _handler.begin(); 00362 iter != _handler.end(); iter++) { 00363 if(strncmp((*iter)->getPrefix(), con->getURL(), strlen((*iter)->getPrefix()))==0) { 00364 HTTPHandler *handler = *iter; 00365 if(handler->action(con)==HTTP_Deliver) { 00366 return *iter; 00367 } 00368 } 00369 } 00370 return NULL; 00371 } 00372 00373 /** 00374 * Accept an incomming connection and fork a HTTPConnection if we have enought memory. 00375 */ 00376 virtual err_t accept(struct tcp_pcb *pcb, err_t err) { 00377 LWIP_UNUSED_ARG(err); 00378 HTTPConnection *con = new HTTPConnection(this, pcb); 00379 // printf("New Connection opend. Now are %u connections open\n", ++gconnections); 00380 if(con == NULL) { 00381 printf("http_accept: Out of memory\n"); 00382 return ERR_MEM; 00383 } 00384 con->set_poll_interval(1); 00385 tcp_setprio(pcb, TCP_PRIO_MIN); 00386 return ERR_OK; 00387 } 00388 00389 /** The registerd request header fields */ 00390 set<unsigned int> fields; 00391 00392 /** A List of all registered handler. */ 00393 list<HTTPHandler *> _handler; 00394 00395 int _timeout_max; 00396 00397 friend HTTPConnection; 00398 }; 00399 00400 }; 00401 00402 #include "HTTPRPC.h" 00403 #include "HTTPFS.h" 00404 #include "HTTPFields.h" 00405 00406 #endif /* HTTP_H */
Generated on Tue Jul 12 2022 16:07:04 by
1.7.2
