Some quick code to use UDP-only (no TCP) with mBed. Echos received packets and sends packets when a button is pressed
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 19:17:23 by 1.7.2