A simple web server that can be bound to either the EthernetInterface or the WiflyInterface.

Dependents:   Smart-WiFly-WebServer WattEye X10Svr SSDP_Server

Committer:
WiredHome
Date:
Fri Oct 11 02:33:46 2013 +0000
Revision:
28:f93ef41b78e1
Parent:
27:90a1f5a5392f
Child:
29:00116fc9da74
Revised the return value from the callback in preparation for more complex transactions.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
WiredHome 1:54353af0d20a 1
WiredHome 1:54353af0d20a 2 #ifndef SW_HTTPSERVER_H
WiredHome 1:54353af0d20a 3 #define SW_HTTPSERVER_H
WiredHome 1:54353af0d20a 4 #include "mbed.h"
WiredHome 1:54353af0d20a 5 //#include "MODSERIAL.h" // would like to hook in mod serial for higher performance, less blocking
WiredHome 1:54353af0d20a 6 #include "Wifly.h"
WiredHome 1:54353af0d20a 7 #include "TCPSocketServer.h"
WiredHome 1:54353af0d20a 8 #include "TCPSocketConnection.h"
WiredHome 1:54353af0d20a 9
WiredHome 1:54353af0d20a 10 #ifdef MODSERIAL_H
WiredHome 1:54353af0d20a 11 #define PC MODSERIAL
WiredHome 1:54353af0d20a 12 #else
WiredHome 1:54353af0d20a 13 #define PC Serial
WiredHome 1:54353af0d20a 14 #endif
WiredHome 1:54353af0d20a 15
WiredHome 9:2ea342765c9d 16 /// This is the default buffer size used to send files. You might size
WiredHome 9:2ea342765c9d 17 /// this to be equal or less than the payload size of 1460 bytes.
WiredHome 9:2ea342765c9d 18 /// See User Manual 3.6.1.
WiredHome 9:2ea342765c9d 19 #define FILESEND_BUF_SIZE 1460
WiredHome 3:17928786bdb5 20
WiredHome 3:17928786bdb5 21
WiredHome 12:109bf1558300 22 /// MAX_HEADER_SIZE is the default size to contain the largest header.
WiredHome 9:2ea342765c9d 23 /// This is the size of the URL and query string, and also all the
WiredHome 3:17928786bdb5 24 /// other header information about the client. This can be
WiredHome 12:109bf1558300 25 /// a couple of K, larger if you have big forms as it includes the
WiredHome 3:17928786bdb5 26 /// form data that is submitted.
WiredHome 3:17928786bdb5 27 #define MAX_HEADER_SIZE 1000
WiredHome 3:17928786bdb5 28
WiredHome 9:2ea342765c9d 29
WiredHome 21:660143f20b04 30 /// INCLUDE_GETREMOTE is used for backward compatibility, however
WiredHome 21:660143f20b04 31 /// this makes the server dependent on the WiFly module. By not
WiredHome 21:660143f20b04 32 /// defining this, the web server can be more readily adapted to
WiredHome 21:660143f20b04 33 /// a wired interface using EthernetInterface.
WiredHome 21:660143f20b04 34 //#define INCLUDE_GETREMOTE
WiredHome 21:660143f20b04 35
WiredHome 21:660143f20b04 36
WiredHome 1:54353af0d20a 37 /// HTTPServer is a simple web server using the WiFly module.
WiredHome 12:109bf1558300 38 ///
WiredHome 3:17928786bdb5 39 /// While simple, it is a capable, web server. The basic mode
WiredHome 3:17928786bdb5 40 /// of operation is for it to serve static web pages from an available
WiredHome 3:17928786bdb5 41 /// file system.
WiredHome 12:109bf1558300 42 ///
WiredHome 3:17928786bdb5 43 /// The default page is index.htm (compile time defined)
WiredHome 3:17928786bdb5 44 /// standard support to serve a number of standard file types;
WiredHome 3:17928786bdb5 45 /// gif, jpg, jpeg, ico, png, zip, gz, tar, txt, pdf, htm, html
WiredHome 3:17928786bdb5 46 /// (this list is also compile time defined)
WiredHome 3:17928786bdb5 47 ///
WiredHome 3:17928786bdb5 48 /// It can also serve dynamically generated pages, and therefore
WiredHome 3:17928786bdb5 49 /// respond to form submission. Through the dynamic interface it is
WiredHome 3:17928786bdb5 50 /// then quite easy to interact with the hardware, reading the inputs
WiredHome 3:17928786bdb5 51 /// or signaling outputs.
WiredHome 3:17928786bdb5 52 ///
WiredHome 3:17928786bdb5 53 /// @code
WiredHome 27:90a1f5a5392f 54 /// HTTPServer svr(&wifly, HTTP_SERVER_PORT, "/local", 15, 30, 10, &pc);
WiredHome 3:17928786bdb5 55 /// svr.RegisterHandler("/dyn1", SimpleDynamicPage);
WiredHome 3:17928786bdb5 56 /// while (true)
WiredHome 3:17928786bdb5 57 /// {
WiredHome 3:17928786bdb5 58 /// svr.Poll(); // this is non blocking process, but variable execution
WiredHome 3:17928786bdb5 59 /// }
WiredHome 3:17928786bdb5 60 /// @endcode
WiredHome 3:17928786bdb5 61 ///
WiredHome 3:17928786bdb5 62 /// This web server used nweb as a starting point, but expanded well beyond there.
WiredHome 0:729320f63c5c 63 /// http://www.ibm.com/developerworks/systems/library/es-nweb/sidefile1.html
WiredHome 0:729320f63c5c 64 ///
WiredHome 3:17928786bdb5 65 /// @note This server uses a modified version of the mbed WiflyInterface - there
WiredHome 3:17928786bdb5 66 /// were a number of performance issues identified and resolved in the local version.
WiredHome 0:729320f63c5c 67 ///
WiredHome 3:17928786bdb5 68 /// Given: scheme://server:port/path?query_string#fragment_id
WiredHome 0:729320f63c5c 69 /// @li scheme is "http"
WiredHome 3:17928786bdb5 70 /// @li server is whatever IP the server has
WiredHome 0:729320f63c5c 71 /// @li port is the registered port
WiredHome 0:729320f63c5c 72 /// @li /path is the reference to the file (actual or logical) on the server
WiredHome 0:729320f63c5c 73 /// @li query_string is any combination of name=value pairs
WiredHome 0:729320f63c5c 74 /// @li fragment_id is a reference to an anchor on the page
WiredHome 0:729320f63c5c 75 ///
WiredHome 3:17928786bdb5 76 /// Features:
WiredHome 3:17928786bdb5 77 /// @li Serves static pages from a file system. Many normal filetypes are
WiredHome 3:17928786bdb5 78 /// supported.
WiredHome 3:17928786bdb5 79 /// @li Compile time configurable for the "default" file, typically index.htm.
WiredHome 3:17928786bdb5 80 /// @li Provides a registration interface for dynamically generated pages that
WiredHome 3:17928786bdb5 81 /// can then interact with other hardware.
WiredHome 3:17928786bdb5 82 /// @li Revised to be Non-blocking, however the execution time is variable
WiredHome 7:99ad7a67f05e 83 /// depending on the actions being performed and can span hundreds of msec.
WiredHome 3:17928786bdb5 84 ///
WiredHome 3:17928786bdb5 85 /// Limitations:
WiredHome 3:17928786bdb5 86 /// @li Supports only a single connection at a time.
WiredHome 18:6199558632c0 87 /// A web page with served objects (img src=...) is rarely served properly. It
WiredHome 18:6199558632c0 88 /// might trace to forcing the connection to close, but not yet sure.
WiredHome 18:6199558632c0 89 /// Explore "Set Uart Rx Data Buffer" in WiFly manual 2.3.65.
WiredHome 18:6199558632c0 90 /// This is a limitation of the Wifly module. No solution is forthcoming,
WiredHome 18:6199558632c0 91 /// so a simple workaround is to use javascript to load the images after
WiredHome 18:6199558632c0 92 /// the page loads.
WiredHome 3:17928786bdb5 93 /// @li Rapid requests for page objects (e.g. embedded images) are lost. Still
WiredHome 3:17928786bdb5 94 /// working to understand this issue.
WiredHome 3:17928786bdb5 95 ///
WiredHome 18:6199558632c0 96 /// Improvements:
WiredHome 18:6199558632c0 97 /// @li hunted down several lengthy operations - the speed of the file system
WiredHome 18:6199558632c0 98 /// and the "close" operation which requires <delay 0.25s>$$$<delay>close\r.
WiredHome 18:6199558632c0 99 /// @li parses the header similar to the query string, and then makes
WiredHome 18:6199558632c0 100 /// those parameters accessible.
WiredHome 18:6199558632c0 101 /// @li Added basic password capability to dynamic web pages.
WiredHome 18:6199558632c0 102 ///
WiredHome 3:17928786bdb5 103 /// ToDo:
WiredHome 3:17928786bdb5 104 /// @li move part of the POST method handler to the registered handler, so
WiredHome 0:729320f63c5c 105 /// it can decide if it should allocate the needed memory.
WiredHome 3:17928786bdb5 106 /// @li transform the pc serial interface to a log interface, which might
WiredHome 0:729320f63c5c 107 /// be more useful.
WiredHome 3:17928786bdb5 108 /// @li Add ability to put WiFly in AP mode and then configuration pages
WiredHome 2:a29c32190037 109 /// to find and join a network.
WiredHome 3:17928786bdb5 110 /// @li Add ability to change/update SW in the WiFly module
WiredHome 3:17928786bdb5 111 /// @li Add ability to upload a new application to the mbed
WiredHome 2:a29c32190037 112 ///
WiredHome 2:a29c32190037 113 /// History:
WiredHome 2:a29c32190037 114 /// @li 20130530 Initial version
WiredHome 2:a29c32190037 115 /// @li 20130601 Renamed ip_process to Poll
WiredHome 3:17928786bdb5 116 /// @li 20130617 Cleaned up some of the documentation changes
WiredHome 3:17928786bdb5 117 /// @li 20130623 Make it non-blocking. "Poll" takes a variable amount
WiredHome 3:17928786bdb5 118 /// of time, based on whether it is idle, or how much it
WiredHome 3:17928786bdb5 119 /// has to do.
WiredHome 18:6199558632c0 120 /// @li 20130911 Lots of incremental changes along this way, this update
WiredHome 18:6199558632c0 121 /// refreshes the documentation.
WiredHome 0:729320f63c5c 122 ///
WiredHome 0:729320f63c5c 123 /// @note Copyright &copy; 2013 by Smartware Computing, all rights reserved.
WiredHome 0:729320f63c5c 124 /// Individuals may use this application for evaluation or non-commercial
WiredHome 0:729320f63c5c 125 /// purposes. Within this restriction, changes may be made to this application
WiredHome 0:729320f63c5c 126 /// as long as this copyright notice is retained. The user shall make
WiredHome 0:729320f63c5c 127 /// clear that their work is a derived work, and not the original.
WiredHome 0:729320f63c5c 128 /// Users of this application and sources accept this application "as is" and
WiredHome 0:729320f63c5c 129 /// shall hold harmless Smartware Computing, for any undesired results while
WiredHome 0:729320f63c5c 130 /// using this application - whether real or imagined.
WiredHome 0:729320f63c5c 131 ///
WiredHome 0:729320f63c5c 132 /// @author David Smart, Smartware Computing
WiredHome 0:729320f63c5c 133 ///
WiredHome 0:729320f63c5c 134 class HTTPServer
WiredHome 0:729320f63c5c 135 {
WiredHome 0:729320f63c5c 136 public:
WiredHome 0:729320f63c5c 137 /**
WiredHome 3:17928786bdb5 138 * name-value pairs for parameters
WiredHome 0:729320f63c5c 139 */
WiredHome 3:17928786bdb5 140 typedef struct NAMEVALUE {
WiredHome 0:729320f63c5c 141 char * name;
WiredHome 0:729320f63c5c 142 char * value;
WiredHome 0:729320f63c5c 143 } namevalue;
WiredHome 12:109bf1558300 144
WiredHome 2:a29c32190037 145 /**
WiredHome 3:17928786bdb5 146 * Indicates the purpose of the Handler callback
WiredHome 3:17928786bdb5 147 *
WiredHome 12:109bf1558300 148 * Application code in a dynamic page uses this to determine the state
WiredHome 3:17928786bdb5 149 * and therefore the needed operation to be performed.
WiredHome 3:17928786bdb5 150 *
WiredHome 3:17928786bdb5 151 * @code
WiredHome 13:8975d7928678 152 * bool SimpleDynamicPage(HTTPServer *svr, HTTPServer::CallBackType type,
WiredHome 13:8975d7928678 153 * const char * path, const HTTPServer::namevalue *queryParams,
WiredHome 13:8975d7928678 154 * int queryParamCount) {
WiredHome 3:17928786bdb5 155 * char buf[100];
WiredHome 3:17928786bdb5 156 * bool ret = false;
WiredHome 12:109bf1558300 157 *
WiredHome 3:17928786bdb5 158 * switch (type) {
WiredHome 3:17928786bdb5 159 * case HTTPServer::SEND_PAGE:
WiredHome 3:17928786bdb5 160 * svr->header(200, "OK", "Content-Type: text/html\r\n");
WiredHome 3:17928786bdb5 161 * svr->send("<html><head><title>Dynamic Page</title></head>\r\n");
WiredHome 3:17928786bdb5 162 * svr->send("<body>\r\n");
WiredHome 3:17928786bdb5 163 * svr->send("This page was generated dynamically. Create your own name=value pairs on the URL "
WiredHome 3:17928786bdb5 164 * "which uses the GET method.<br/>\r\n");
WiredHome 13:8975d7928678 165 * sprintf(buf, "%d parameters passed to {%s}:<br/>\r\n", queryParamCount, path);
WiredHome 3:17928786bdb5 166 * svr->send(buf);
WiredHome 13:8975d7928678 167 * for (int i=0; i<queryParamCount; i++) {
WiredHome 13:8975d7928678 168 * sprintf(buf, "%d: %s = %s<br/>\r\n", i, queryParams[i].name, queryParams[i].value);
WiredHome 3:17928786bdb5 169 * svr->send(buf);
WiredHome 3:17928786bdb5 170 * }
WiredHome 3:17928786bdb5 171 * svr->send("<br/><a href='/'>back to main</a></body></html>\r\n");
WiredHome 3:17928786bdb5 172 * ret = true;
WiredHome 3:17928786bdb5 173 * break;
WiredHome 3:17928786bdb5 174 * case HTTPServer::CONTENT_LENGTH_REQUEST:
WiredHome 3:17928786bdb5 175 * ret = true;
WiredHome 3:17928786bdb5 176 * break;
WiredHome 3:17928786bdb5 177 * case HTTPServer::DATA_TRANSFER:
WiredHome 3:17928786bdb5 178 * ret = true;
WiredHome 3:17928786bdb5 179 * break;
WiredHome 3:17928786bdb5 180 * default:
WiredHome 3:17928786bdb5 181 * ret = false;
WiredHome 3:17928786bdb5 182 * break;
WiredHome 3:17928786bdb5 183 * }
WiredHome 3:17928786bdb5 184 * return ret;
WiredHome 3:17928786bdb5 185 * }
WiredHome 3:17928786bdb5 186 * @endcode
WiredHome 2:a29c32190037 187 */
WiredHome 3:17928786bdb5 188 typedef enum CALLBACKTYPE {
WiredHome 14:19c5f6151319 189 CONTENT_LENGTH_REQUEST, ///< ask the client if they wish to accept the data, typically from a POST event
WiredHome 27:90a1f5a5392f 190 DATA_TRANSFER, ///< used when submitting a file via a form
WiredHome 3:17928786bdb5 191 SEND_PAGE, ///< the activated method should now send the page
WiredHome 2:a29c32190037 192 } CallBackType;
WiredHome 0:729320f63c5c 193
WiredHome 28:f93ef41b78e1 194 typedef enum CALLBACKRESULTS {
WiredHome 28:f93ef41b78e1 195 ACCEPT_ERROR, ///< client not accepting the request.
WiredHome 28:f93ef41b78e1 196 ACCEPT_COMPLETE, ///< client accepted the request, the work is done.
WiredHome 28:f93ef41b78e1 197 ACCEPT_CONTINUE, ///< client accepted the request, additional transactions to complete.
WiredHome 28:f93ef41b78e1 198 } CallBackResults;
WiredHome 28:f93ef41b78e1 199
WiredHome 12:109bf1558300 200 /**
WiredHome 3:17928786bdb5 201 * This is the prototype for custom handlers that are activated via a callback
WiredHome 0:729320f63c5c 202 *
WiredHome 3:17928786bdb5 203 * This callback gets overloaded for a few purposes, which can be identified by the \see CallBackType parameter
WiredHome 27:90a1f5a5392f 204 * @li CONTENT_LENGTH_REQUEST - the server is asking the callback if it wants to receive the message,
WiredHome 27:90a1f5a5392f 205 * which may require significant memory. If the request is accepted, true should be returned.
WiredHome 27:90a1f5a5392f 206 * If the request is denied, false should be returned.
WiredHome 27:90a1f5a5392f 207 * @li DATA_TRANSFER - the server is handing off a large body of data, which was accepted based
WiredHome 27:90a1f5a5392f 208 * on the CONTENT_LENGTH_REQUEST callback. The data is now available for processing.
WiredHome 27:90a1f5a5392f 209 * The callback should return true to continue the processing.
WiredHome 12:109bf1558300 210 * @li SEND_PAGE - the callback should now send the html page, using as many svr->send() as needed.
WiredHome 2:a29c32190037 211 * When the callback returns, it should always indicate true.
WiredHome 27:90a1f5a5392f 212 *
WiredHome 27:90a1f5a5392f 213 * @note The queryParams pointer purpose depends on the callback type.
WiredHome 27:90a1f5a5392f 214 * For CONTENT_LENGTH_REQUEST, the pointer points to the name=value pairs from the
WiredHome 27:90a1f5a5392f 215 * header.
WiredHome 27:90a1f5a5392f 216 * For DATA_TRANSFER, the pointer points to the start of the actual data.
WiredHome 27:90a1f5a5392f 217 * For SEND_PAGE,
WiredHome 12:109bf1558300 218 *
WiredHome 0:729320f63c5c 219 * @param svr is a handle to this class, so the callback has access to member functions
WiredHome 27:90a1f5a5392f 220 * @param queryParams is a pointer based on the callback type.
WiredHome 13:8975d7928678 221 * @queryParamCount is the number of parameters.
WiredHome 2:a29c32190037 222 * @return true if command was accepted
WiredHome 0:729320f63c5c 223 */
WiredHome 28:f93ef41b78e1 224 typedef CallBackResults (* Handler)(HTTPServer * svr, CallBackType type, const char *path, const namevalue *queryParams, int queryParamCount);
WiredHome 12:109bf1558300 225
WiredHome 0:729320f63c5c 226 /**
WiredHome 0:729320f63c5c 227 * Create the HTTPServer object.
WiredHome 12:109bf1558300 228 *
WiredHome 0:729320f63c5c 229 * @param wifly is the serial port with the wifly interface.
WiredHome 0:729320f63c5c 230 * @param port is the optional parameter for the port number to use, default is 80.
WiredHome 27:90a1f5a5392f 231 * @param webroot is a file system path to the root folder for the web space. If any trailing '/'
WiredHome 27:90a1f5a5392f 232 * is included (e.g. "/web/path/") it will be removed (to "/web/path").
WiredHome 13:8975d7928678 233 * @param maxheaderParams defines the maximum number of parameters to extract from a header (Host: 192..\r\nConnection: keep-alive\r\n...)
WiredHome 13:8975d7928678 234 * @param maxqueryParams defines the maximum number of query parameters to a dynamic function (and the memory to support them).
WiredHome 0:729320f63c5c 235 * @param maxdynamicpages defines the maximum number of dynamic pages that can be registered.
WiredHome 0:729320f63c5c 236 * @param pc is the serial port for debug information (I should transform this to a log interface)
WiredHome 3:17928786bdb5 237 * @param allocforheader is the memory allocation to support the largest expected header from a client
WiredHome 12:109bf1558300 238 * @param allocforfile is the memory allocation to support sending a file to the client. This is typically sized to fit
WiredHome 3:17928786bdb5 239 * an ethernet frame.
WiredHome 0:729320f63c5c 240 */
WiredHome 13:8975d7928678 241 HTTPServer(Wifly * wifly, int port = 80, const char * webroot = "/", int maxheaderParams = 15, int maxqueryParams = 30, int maxdynamicpages = 10,
WiredHome 12:109bf1558300 242 PC * pc = NULL, int _allocforheader = MAX_HEADER_SIZE, int _allocforfile = FILESEND_BUF_SIZE);
WiredHome 12:109bf1558300 243
WiredHome 0:729320f63c5c 244 /**
WiredHome 3:17928786bdb5 245 * Destructor, which can clean up memory.
WiredHome 0:729320f63c5c 246 */
WiredHome 0:729320f63c5c 247 ~HTTPServer();
WiredHome 12:109bf1558300 248
WiredHome 0:729320f63c5c 249 /**
WiredHome 27:90a1f5a5392f 250 * Get the path to the webroot, for applications that need to
WiredHome 27:90a1f5a5392f 251 * reference the file system relative to that point.
WiredHome 24:062431453abb 252 *
WiredHome 27:90a1f5a5392f 253 * @note The returned value may not be exactly as set at instantiation
WiredHome 27:90a1f5a5392f 254 * as trailing '/' were removed (unless the web root == "/").
WiredHome 27:90a1f5a5392f 255 * e.g. "/msc/web/" becomes "/msc/web"
WiredHome 27:90a1f5a5392f 256 *
WiredHome 27:90a1f5a5392f 257 * @returns pointer to the webroot string.
WiredHome 24:062431453abb 258 */
WiredHome 24:062431453abb 259 const char * GetWebRoot() {
WiredHome 27:90a1f5a5392f 260 return (const char *)webroot;
WiredHome 27:90a1f5a5392f 261 };
WiredHome 24:062431453abb 262
WiredHome 24:062431453abb 263 /**
WiredHome 3:17928786bdb5 264 * The process to call whenever there is free time, as this basically does
WiredHome 0:729320f63c5c 265 * all the work to monitor for connections and handle replies.
WiredHome 2:a29c32190037 266 *
WiredHome 2:a29c32190037 267 * 20130601 Renamed from ip_process to Poll
WiredHome 0:729320f63c5c 268 */
WiredHome 2:a29c32190037 269 void Poll();
WiredHome 12:109bf1558300 270
WiredHome 0:729320f63c5c 271 /**
WiredHome 12:109bf1558300 272 * Send typical header data, and some optional data back to the client.
WiredHome 3:17928786bdb5 273 *
WiredHome 3:17928786bdb5 274 * This forms and sends the typical header back to the client. It may also send
WiredHome 3:17928786bdb5 275 * optional data (which must end with "\r\n"). It then sends the second newline
WiredHome 3:17928786bdb5 276 * sequence that signals the end of the header.
WiredHome 0:729320f63c5c 277 *
WiredHome 0:729320f63c5c 278 * @param code is the optional return code; 200 = OK, if not provided then 404 = Not found is returned
WiredHome 0:729320f63c5c 279 * @param code_text is the text to align with the code (e.g. 404, "Not Found")
WiredHome 0:729320f63c5c 280 * @param content_type is a pointer to "Content-Type: text/html\r\n" (for example)
WiredHome 3:17928786bdb5 281 * @param optional_text is a pointer to any other text that is part of the header, which must
WiredHome 3:17928786bdb5 282 * have \r\n termination.
WiredHome 0:729320f63c5c 283 */
WiredHome 0:729320f63c5c 284 void header(int code = 404, const char * code_text = "Not Found", const char * content_type = NULL, const char * optional_text = NULL);
WiredHome 0:729320f63c5c 285
WiredHome 0:729320f63c5c 286 /**
WiredHome 0:729320f63c5c 287 * Send text to the client
WiredHome 0:729320f63c5c 288 *
WiredHome 3:17928786bdb5 289 * This sends the specified text to the client. If the number of bytes is not set,
WiredHome 3:17928786bdb5 290 * then it calculates the number of bytes as a string. For binary transfers, the
WiredHome 3:17928786bdb5 291 * number of bytes to send is required for proper operation.
WiredHome 3:17928786bdb5 292 *
WiredHome 0:729320f63c5c 293 * @param msg is the text string to send
WiredHome 0:729320f63c5c 294 * @param bytes is the number of bytes to send. If not set, then strlen is calculated.
WiredHome 0:729320f63c5c 295 */
WiredHome 0:729320f63c5c 296 void send(const char * msg, int bytes = -1);
WiredHome 12:109bf1558300 297
WiredHome 0:729320f63c5c 298 /**
WiredHome 3:17928786bdb5 299 * Send a referenced file to the client, including the header
WiredHome 3:17928786bdb5 300 *
WiredHome 3:17928786bdb5 301 * This sends a file from the filesystem to the client. It must be of a supported type
WiredHome 3:17928786bdb5 302 * in order to properly create the header.
WiredHome 0:729320f63c5c 303 *
WiredHome 0:729320f63c5c 304 * @param filename is the fully qualified path and filename
WiredHome 3:17928786bdb5 305 * @param filetype is the header information (e.g. "Content-Type: application/pdf")
WiredHome 0:729320f63c5c 306 * @return true if it thinks it sent ok, false otherwise.
WiredHome 0:729320f63c5c 307 */
WiredHome 0:729320f63c5c 308 bool SendFile(const char * filename, const char * filetype);
WiredHome 12:109bf1558300 309
WiredHome 12:109bf1558300 310 /**
WiredHome 0:729320f63c5c 311 * register a handler for a specific URL.
WiredHome 0:729320f63c5c 312 *
WiredHome 3:17928786bdb5 313 * This api lets you register a dynamic handler in the web server. This is
WiredHome 3:17928786bdb5 314 * most useful for interactive web pages, rather than simply serving static
WiredHome 3:17928786bdb5 315 * pages.
WiredHome 3:17928786bdb5 316 *
WiredHome 3:17928786bdb5 317 * @code
WiredHome 12:109bf1558300 318 *
WiredHome 3:17928786bdb5 319 * ...
WiredHome 3:17928786bdb5 320 * svr.RegisterHandler("/dyn1", SimpleDynamicPage);svr.RegisterHandler("/dyn1", SimpleDynamicPage);
WiredHome 3:17928786bdb5 321 * ...
WiredHome 3:17928786bdb5 322 *
WiredHome 13:8975d7928678 323 * bool SimpleDynamicPage(HTTPServer *svr, HTTPServer::CallBackType type, const char * path, const HTTPServer::namevalue *queryParams, int queryParamCount) {
WiredHome 3:17928786bdb5 324 * char buf[100];
WiredHome 3:17928786bdb5 325 * bool ret = false;
WiredHome 12:109bf1558300 326 *
WiredHome 3:17928786bdb5 327 * switch (type) {
WiredHome 3:17928786bdb5 328 * case HTTPServer::SEND_PAGE:
WiredHome 3:17928786bdb5 329 * svr->header(200, "OK", "Content-Type: text/html\r\n");
WiredHome 3:17928786bdb5 330 * svr->send("<html><head><title>Dynamic Page</title></head>\r\n");
WiredHome 3:17928786bdb5 331 * svr->send("<body>\r\n");
WiredHome 3:17928786bdb5 332 * svr->send("This page was generated dynamically. Create your own name=value pairs on the URL "
WiredHome 3:17928786bdb5 333 * "which uses the GET method.<br/>\r\n");
WiredHome 13:8975d7928678 334 * sprintf(buf, "%d parameters passed to {%s}:<br/>\r\n", queryParamCount, path);
WiredHome 3:17928786bdb5 335 * svr->send(buf);
WiredHome 13:8975d7928678 336 * for (int i=0; i<queryParamCount; i++) {
WiredHome 13:8975d7928678 337 * sprintf(buf, "%d: %s = %s<br/>\r\n", i, queryParams[i].name, queryParams[i].value);
WiredHome 3:17928786bdb5 338 * svr->send(buf);
WiredHome 3:17928786bdb5 339 * }
WiredHome 3:17928786bdb5 340 * svr->send("Stats:<br/>\r\n");
WiredHome 3:17928786bdb5 341 * sprintf(buf,"Free memory space: %d<br/>\r\n", Free());
WiredHome 3:17928786bdb5 342 * svr->send(buf);
WiredHome 3:17928786bdb5 343 * sprintf(buf,"Max Header size: %d<br/>\r\n", svr->GetMaxHeaderSize());
WiredHome 3:17928786bdb5 344 * svr->send(buf);
WiredHome 3:17928786bdb5 345 * svr->send("<br/><a href='/'>back to main</a></body></html>\r\n");
WiredHome 3:17928786bdb5 346 * ret = true;
WiredHome 3:17928786bdb5 347 * break;
WiredHome 3:17928786bdb5 348 * case HTTPServer::CONTENT_LENGTH_REQUEST:
WiredHome 3:17928786bdb5 349 * ret = true;
WiredHome 3:17928786bdb5 350 * break;
WiredHome 3:17928786bdb5 351 * case HTTPServer::DATA_TRANSFER:
WiredHome 3:17928786bdb5 352 * ret = true;
WiredHome 3:17928786bdb5 353 * break;
WiredHome 3:17928786bdb5 354 * default:
WiredHome 3:17928786bdb5 355 * ret = false;
WiredHome 3:17928786bdb5 356 * break;
WiredHome 3:17928786bdb5 357 * }
WiredHome 3:17928786bdb5 358 * return ret;
WiredHome 3:17928786bdb5 359 * }
WiredHome 3:17928786bdb5 360 * @endcode
WiredHome 3:17928786bdb5 361 *
WiredHome 0:729320f63c5c 362 * @param path to register
WiredHome 0:729320f63c5c 363 * @param callback of type Handler
WiredHome 0:729320f63c5c 364 * @return true if successfully registered
WiredHome 0:729320f63c5c 365 */
WiredHome 0:729320f63c5c 366 bool RegisterHandler(const char * path, Handler callback);
WiredHome 12:109bf1558300 367
WiredHome 0:729320f63c5c 368 /**
WiredHome 16:6ebacf2946d8 369 * determine if the named file is a supported type (htm, html, jpg, etc)
WiredHome 0:729320f63c5c 370 *
WiredHome 3:17928786bdb5 371 * if you pass in a filename, it will attempt to extract the extension
WiredHome 3:17928786bdb5 372 * and compare that to the list of supported file types. If it finds a
WiredHome 3:17928786bdb5 373 * match, then it will return a pointer to the content-type string.
WiredHome 3:17928786bdb5 374 *
WiredHome 3:17928786bdb5 375 * @code
WiredHome 3:17928786bdb5 376 * fType = GetSupportedType("mypix.jpg");
WiredHome 3:17928786bdb5 377 * if (fType) {
WiredHome 3:17928786bdb5 378 * ...
WiredHome 3:17928786bdb5 379 * @endcode
WiredHome 12:109bf1558300 380 *
WiredHome 0:729320f63c5c 381 * @param filename is the filename to test, based on the extension
WiredHome 0:729320f63c5c 382 * @return pointer to a Content-Type string if supported, or NULL if not.
WiredHome 0:729320f63c5c 383 */
WiredHome 0:729320f63c5c 384 const char * GetSupportedType(const char * filename);
WiredHome 0:729320f63c5c 385
WiredHome 0:729320f63c5c 386 /**
WiredHome 0:729320f63c5c 387 * search the available parameters for 'name' and if found, return the 'value'
WiredHome 0:729320f63c5c 388 *
WiredHome 12:109bf1558300 389 * After the querystring is parsed, the server maintains an array of
WiredHome 3:17928786bdb5 390 * name=value pairs. This Get function will search for the passed in name
WiredHome 3:17928786bdb5 391 * and provide access to the value.
WiredHome 3:17928786bdb5 392 *
WiredHome 3:17928786bdb5 393 * @code
WiredHome 3:17928786bdb5 394 * BusOut leds(LED1,LED2,LED3,LED4);
WiredHome 3:17928786bdb5 395 * ...
WiredHome 3:17928786bdb5 396 * leds = atoi(svr->GetParameter("leds"));
WiredHome 3:17928786bdb5 397 * @endcode
WiredHome 3:17928786bdb5 398 *
WiredHome 0:729320f63c5c 399 * @param name is the name to search for
WiredHome 0:729320f63c5c 400 * @return pointer to the value, or NULL
WiredHome 0:729320f63c5c 401 */
WiredHome 0:729320f63c5c 402 const char * GetParameter(const char * name);
WiredHome 0:729320f63c5c 403
WiredHome 0:729320f63c5c 404 /**
WiredHome 12:109bf1558300 405 * Parse the text string into name=value parameters.
WiredHome 3:17928786bdb5 406 *
WiredHome 12:109bf1558300 407 * This will directly modify the referenced string. If there is a
WiredHome 3:17928786bdb5 408 * #fragment_id on the end of the string, it will be removed.
WiredHome 0:729320f63c5c 409 *
WiredHome 0:729320f63c5c 410 * @param pString is a pointer to the string.
WiredHome 0:729320f63c5c 411 */
WiredHome 0:729320f63c5c 412 void ParseParameters(char * pString);
WiredHome 12:109bf1558300 413
WiredHome 0:729320f63c5c 414 /**
WiredHome 16:6ebacf2946d8 415 * Unescape string converts a coded string "in place" into a normal string.
WiredHome 3:17928786bdb5 416 *
WiredHome 3:17928786bdb5 417 * A query string will have a number of characters replaced for communication
WiredHome 3:17928786bdb5 418 * which includes spaces, quotes, question marks and more. Most of them
WiredHome 12:109bf1558300 419 * will be replaced with a %xx format, where xx is the hex code for the
WiredHome 3:17928786bdb5 420 * character. Since the string will only get shorter when this happens
WiredHome 3:17928786bdb5 421 * the operation is performed in place.
WiredHome 3:17928786bdb5 422 *
WiredHome 0:729320f63c5c 423 * this "This%20is%20a%20question%3F%20and%20an%20answer."
WiredHome 12:109bf1558300 424 *
WiredHome 0:729320f63c5c 425 * becomes "This is a question? and an answer."
WiredHome 3:17928786bdb5 426 *
WiredHome 0:729320f63c5c 427 * @note '+' is another form of space, so is converted to a space before the %xx
WiredHome 0:729320f63c5c 428 *
WiredHome 0:729320f63c5c 429 * @param encoded string to be converted
WiredHome 0:729320f63c5c 430 */
WiredHome 0:729320f63c5c 431 void UnescapeString(char * encoded);
WiredHome 12:109bf1558300 432
WiredHome 21:660143f20b04 433
WiredHome 21:660143f20b04 434 #ifdef INCLUDE_GETREMOTE
WiredHome 0:729320f63c5c 435 /**
WiredHome 0:729320f63c5c 436 * Get the IP address of the remote node to which we are connected.
WiredHome 3:17928786bdb5 437 *
WiredHome 3:17928786bdb5 438 * This will get the IP address of the remote node to which we are
WiredHome 12:109bf1558300 439 * currently connected. This is written into the buffer in
WiredHome 3:17928786bdb5 440 * "192.168.100.234" format. If the buffer size is note >= 16 bytes,
WiredHome 3:17928786bdb5 441 * it will set the buffer to null.
WiredHome 12:109bf1558300 442 *
WiredHome 21:660143f20b04 443 * @deprecated This binds the web server to only network interfaces
WiredHome 21:660143f20b04 444 * that support this API (WiFly), so can limit its use.
WiredHome 21:660143f20b04 445 * This API will be removed.
WiredHome 21:660143f20b04 446 *
WiredHome 3:17928786bdb5 447 * @note This switches the module into, and out of, command mode
WiredHome 12:109bf1558300 448 * which has quite a time penalty.
WiredHome 3:17928786bdb5 449 *
WiredHome 3:17928786bdb5 450 * @param str is the string to write the address into, which should be at
WiredHome 3:17928786bdb5 451 * least as large as "192.168.100.203" (16-bytes).
WiredHome 4:f34642902056 452 * @param strSize of the str buffer must be >=16, so it will not buffer overrun.
WiredHome 5:c9b27e718054 453 * @returns true if it succeeded, false otherwise
WiredHome 0:729320f63c5c 454 */
WiredHome 5:c9b27e718054 455 bool GetRemoteAddr(char * str, int strSize);
WiredHome 21:660143f20b04 456 #endif
WiredHome 0:729320f63c5c 457
WiredHome 12:109bf1558300 458 /**
WiredHome 16:6ebacf2946d8 459 * This is used to force a connection to close.
WiredHome 3:17928786bdb5 460 *
WiredHome 3:17928786bdb5 461 * This switches the module into command mode, performs the close,
WiredHome 3:17928786bdb5 462 * then switches it back to data mode. So, this is a time-expensive
WiredHome 3:17928786bdb5 463 * command.
WiredHome 7:99ad7a67f05e 464 *
WiredHome 7:99ad7a67f05e 465 * @returns true if successful
WiredHome 0:729320f63c5c 466 */
WiredHome 7:99ad7a67f05e 467 bool close_connection();
WiredHome 12:109bf1558300 468
WiredHome 3:17928786bdb5 469 /**
WiredHome 16:6ebacf2946d8 470 * Diagnostic to get the size of the largest header.
WiredHome 3:17928786bdb5 471 *
WiredHome 12:109bf1558300 472 * This is a diagnostic function, so you can resize the allocated
WiredHome 12:109bf1558300 473 * buffer for your application. With proper sizing, more of the
WiredHome 3:17928786bdb5 474 * system memory is available for your application.
WiredHome 3:17928786bdb5 475 *
WiredHome 3:17928786bdb5 476 * @code
WiredHome 3:17928786bdb5 477 * sprintf(buf,"Max Header size: %d<br/>\r\n", svr->GetMaxHeaderSize());
WiredHome 3:17928786bdb5 478 * svr->send(buf);
WiredHome 3:17928786bdb5 479 * @endcode
WiredHome 12:109bf1558300 480 *
WiredHome 3:17928786bdb5 481 * @returns size in bytes of the larger header measured.
WiredHome 3:17928786bdb5 482 */
WiredHome 3:17928786bdb5 483 int GetMaxHeaderSize();
WiredHome 3:17928786bdb5 484
WiredHome 13:8975d7928678 485 /**
WiredHome 16:6ebacf2946d8 486 * Get a value from the http header, if it exists.
WiredHome 13:8975d7928678 487 *
WiredHome 13:8975d7928678 488 * @param hdr is the string to search for (e.g. "Content-Length")
WiredHome 13:8975d7928678 489 *
WiredHome 13:8975d7928678 490 * @returns pointer to the value associated with that header.
WiredHome 13:8975d7928678 491 * @returns NULL if the header is not found.
WiredHome 13:8975d7928678 492 */
WiredHome 13:8975d7928678 493 const char * GetHeaderValue(const char * hdr);
WiredHome 3:17928786bdb5 494
WiredHome 3:17928786bdb5 495 /**
WiredHome 3:17928786bdb5 496 * Performance parameter
WiredHome 3:17928786bdb5 497 */
WiredHome 3:17928786bdb5 498 typedef struct SW_PERFPARAM {
WiredHome 3:17928786bdb5 499 unsigned long long TotalTime_us;
WiredHome 3:17928786bdb5 500 unsigned long Samples;
WiredHome 3:17928786bdb5 501 unsigned long MaxTime_us;
WiredHome 3:17928786bdb5 502 } SW_PerformanceParam;
WiredHome 12:109bf1558300 503
WiredHome 3:17928786bdb5 504 /**
WiredHome 3:17928786bdb5 505 * Performance metrics
WiredHome 3:17928786bdb5 506 */
WiredHome 3:17928786bdb5 507 typedef struct SW_PERFDATA {
WiredHome 17:69ff00ce39f4 508 SW_PerformanceParam ConnectionAccepted;
WiredHome 17:69ff00ce39f4 509 SW_PerformanceParam HeaderParsed;
WiredHome 17:69ff00ce39f4 510 SW_PerformanceParam ResponseSent;
WiredHome 17:69ff00ce39f4 511 SW_PerformanceParam ConnectionClosed;
WiredHome 3:17928786bdb5 512 //SW_PerformanceParam SendFile;
WiredHome 3:17928786bdb5 513 } SW_PerformanceData;
WiredHome 12:109bf1558300 514
WiredHome 3:17928786bdb5 515 /**
WiredHome 3:17928786bdb5 516 * Get performance metrics from the web server.
WiredHome 3:17928786bdb5 517 *
WiredHome 3:17928786bdb5 518 * This is a diagnostic function, and gathers data on the internal
WiredHome 3:17928786bdb5 519 * performance of the server, as it works various actions.
WiredHome 3:17928786bdb5 520 *
WiredHome 3:17928786bdb5 521 * @param p is a pointer to a SW_PerformanceData structure to be populated
WiredHome 3:17928786bdb5 522 */
WiredHome 3:17928786bdb5 523 void GetPerformanceData(SW_PerformanceData * p);
WiredHome 12:109bf1558300 524
WiredHome 3:17928786bdb5 525 /**
WiredHome 3:17928786bdb5 526 * Reset performance metrics.
WiredHome 3:17928786bdb5 527 */
WiredHome 3:17928786bdb5 528 void ResetPerformanceData();
WiredHome 17:69ff00ce39f4 529
WiredHome 17:69ff00ce39f4 530 /**
WiredHome 17:69ff00ce39f4 531 * Get performance clock
WiredHome 17:69ff00ce39f4 532 */
WiredHome 17:69ff00ce39f4 533 unsigned int GetPerformanceClock();
WiredHome 12:109bf1558300 534
WiredHome 5:c9b27e718054 535 /**
WiredHome 5:c9b27e718054 536 * Get the underlying wifly object.
WiredHome 6:fdce4464d92b 537 *
WiredHome 6:fdce4464d92b 538 * This lets you get to the underlying wifly object in order to
WiredHome 6:fdce4464d92b 539 * interact with it.
WiredHome 6:fdce4464d92b 540 *
WiredHome 6:fdce4464d92b 541 * @code
WiredHome 13:8975d7928678 542 * HTTPServer svr(&wifly, HTTP_SERVER_PORT, "/local/", 15, 30, 10, &pc);
WiredHome 6:fdce4464d92b 543 * ...
WiredHome 6:fdce4464d92b 544 * svr->GetWifly()->getWiflyVerString()
WiredHome 6:fdce4464d92b 545 * @endcode
WiredHome 6:fdce4464d92b 546 *
WiredHome 6:fdce4464d92b 547 * returns the wifly option.
WiredHome 5:c9b27e718054 548 */
WiredHome 12:109bf1558300 549 Wifly * GetWifly() {
WiredHome 12:109bf1558300 550 return wifly;
WiredHome 12:109bf1558300 551 };
WiredHome 0:729320f63c5c 552
WiredHome 0:729320f63c5c 553 private:
WiredHome 0:729320f63c5c 554 Wifly * wifly;
WiredHome 0:729320f63c5c 555 char * webroot;
WiredHome 0:729320f63c5c 556 PC * pc;
WiredHome 0:729320f63c5c 557 TCPSocketServer * server;
WiredHome 0:729320f63c5c 558 TCPSocketConnection client;
WiredHome 0:729320f63c5c 559 char * rewriteWithDefaultFile(char * queryString);
WiredHome 0:729320f63c5c 560 char * rewritePrependWebroot(char * queryString);
WiredHome 13:8975d7928678 561
WiredHome 13:8975d7928678 562 namevalue *queryParams; // Query Parameters from the URL this=that&sky=blue&...
WiredHome 13:8975d7928678 563 int maxqueryParams;
WiredHome 13:8975d7928678 564 int queryParamCount;
WiredHome 13:8975d7928678 565
WiredHome 13:8975d7928678 566 namevalue *headerParams; // Header params Host: 192.168...\r\nConnection: keep-alive\r\n...
WiredHome 13:8975d7928678 567 int maxheaderParams;
WiredHome 13:8975d7928678 568 int headerParamCount;
WiredHome 13:8975d7928678 569
WiredHome 3:17928786bdb5 570 int maxheaderbytes;
WiredHome 3:17928786bdb5 571 char * headerbuffer;
WiredHome 3:17928786bdb5 572 int headerbuffersize;
WiredHome 12:109bf1558300 573
WiredHome 10:9c8d2c6a3469 574 Timer PerformanceTimer;
WiredHome 3:17928786bdb5 575 /**
WiredHome 3:17928786bdb5 576 * Records performance data
WiredHome 12:109bf1558300 577 *
WiredHome 3:17928786bdb5 578 * This will take a pointer to a SW_PerformanceParam, and it will
WiredHome 3:17928786bdb5 579 * take the time when the performance measurement started. It locally
WiredHome 3:17928786bdb5 580 * accesses the current time to measure the elapsed.
WiredHome 3:17928786bdb5 581 *
WiredHome 3:17928786bdb5 582 * @param param is the performance parameter to update
WiredHome 3:17928786bdb5 583 * @param value is the reference time.
WiredHome 3:17928786bdb5 584 * @returns the current time which may be used as the reference time
WiredHome 3:17928786bdb5 585 * for further measurements.
WiredHome 3:17928786bdb5 586 */
WiredHome 16:6ebacf2946d8 587 unsigned int RecordPerformanceData(SW_PerformanceParam * param, unsigned int value);
WiredHome 3:17928786bdb5 588 SW_PerformanceData perfData;
WiredHome 12:109bf1558300 589
WiredHome 3:17928786bdb5 590 typedef struct HANDLER {
WiredHome 0:729320f63c5c 591 char * path;
WiredHome 0:729320f63c5c 592 Handler callback;
WiredHome 0:729320f63c5c 593 } handler;
WiredHome 0:729320f63c5c 594 int maxdynamicpages;
WiredHome 0:729320f63c5c 595 handler *handlers;
WiredHome 0:729320f63c5c 596 int handlercount;
WiredHome 3:17928786bdb5 597
WiredHome 3:17928786bdb5 598 char * queryType;
WiredHome 3:17928786bdb5 599 char * queryString;
WiredHome 3:17928786bdb5 600 char * postQueryString;
WiredHome 12:109bf1558300 601
WiredHome 0:729320f63c5c 602 /**
WiredHome 8:262583f054f6 603 * Extract the parameter from the record, by searching for the needle in the haystack.
WiredHome 8:262583f054f6 604 *
WiredHome 8:262583f054f6 605 * The parameter of interest follows the needle, and may be ' ' delimited
WiredHome 0:729320f63c5c 606 * Can damage haystack while processing it.
WiredHome 0:729320f63c5c 607 *
WiredHome 0:729320f63c5c 608 * @param haystack is the record to search
WiredHome 0:729320f63c5c 609 * @param needle is the text to search for, which precedes the text to return
WiredHome 0:729320f63c5c 610 * @param string is the text following the needle
WiredHome 0:729320f63c5c 611 * @return true if it extracted something successfully
WiredHome 0:729320f63c5c 612 */
WiredHome 0:729320f63c5c 613 bool Extract(char * rec, char * needle, char ** string);
WiredHome 0:729320f63c5c 614
WiredHome 3:17928786bdb5 615 void SendResponse();
WiredHome 3:17928786bdb5 616 bool ParseHeader(char * bPtr);
WiredHome 3:17928786bdb5 617 bool CheckDynamicHandlers();
WiredHome 3:17928786bdb5 618
WiredHome 0:729320f63c5c 619 int HexCharToInt(char c);
WiredHome 0:729320f63c5c 620 char HexPairToChar(char * p);
WiredHome 0:729320f63c5c 621 };
WiredHome 0:729320f63c5c 622 #endif //SW_HTTPSERVER_H
WiredHome 4:f34642902056 623
WiredHome 7:99ad7a67f05e 624