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:
Sun Jun 02 18:32:05 2013 +0000
Revision:
2:a29c32190037
Parent:
1:54353af0d20a
Child:
3:17928786bdb5
turned off debug

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 1:54353af0d20a 16 /// HTTPServer is a simple web server using the WiFly module.
WiredHome 0:729320f63c5c 17 ///
WiredHome 0:729320f63c5c 18 /// Partially derived from nweb
WiredHome 0:729320f63c5c 19 /// http://www.ibm.com/developerworks/systems/library/es-nweb/sidefile1.html
WiredHome 0:729320f63c5c 20 ///
WiredHome 0:729320f63c5c 21 /// Uses a modified WiflyInterface - a number of performance issues
WiredHome 0:729320f63c5c 22 /// were identified and resolved in the local version.
WiredHome 0:729320f63c5c 23 ///
WiredHome 0:729320f63c5c 24 /// Also, if nothing visits its web page for a long time, it seems
WiredHome 0:729320f63c5c 25 /// to disable. Might be a sleep timer I'm not spotting.
WiredHome 0:729320f63c5c 26 ///
WiredHome 0:729320f63c5c 27 /// Given: scheme://domain:port/path?query_string#fragment_id
WiredHome 0:729320f63c5c 28 /// @li scheme is "http"
WiredHome 0:729320f63c5c 29 /// @li domain is whatever IP the server has
WiredHome 0:729320f63c5c 30 /// @li port is the registered port
WiredHome 0:729320f63c5c 31 /// @li /path is the reference to the file (actual or logical) on the server
WiredHome 0:729320f63c5c 32 /// @li query_string is any combination of name=value pairs
WiredHome 0:729320f63c5c 33 /// @li fragment_id is a reference to an anchor on the page
WiredHome 0:729320f63c5c 34 ///
WiredHome 2:a29c32190037 35 /// Feature request list:
WiredHome 0:729320f63c5c 36 /// @todo make it non-blocking.
WiredHome 0:729320f63c5c 37 /// @todo hunt down lengthy operations - there seems to be a long timeout somewhere.
WiredHome 2:a29c32190037 38 /// @todo parse the header similar to the query string, and then make
WiredHome 2:a29c32190037 39 /// those parameters accessible - perhaps like environment vars.
WiredHome 0:729320f63c5c 40 /// @todo move part of the POST method handler to the registered handler, so
WiredHome 0:729320f63c5c 41 /// it can decide if it should allocate the needed memory.
WiredHome 2:a29c32190037 42 /// @todo Add password capability to some web pages
WiredHome 0:729320f63c5c 43 /// @todo transform the pc serial interface to a log interface, which might
WiredHome 0:729320f63c5c 44 /// be more useful.
WiredHome 2:a29c32190037 45 /// @todo Add ability to put WiFly in AP mode and then configuration pages
WiredHome 2:a29c32190037 46 /// to find and join a network.
WiredHome 2:a29c32190037 47 /// @todo Add ability to change/update SW in the WiFly module
WiredHome 2:a29c32190037 48 /// @todo Add ability to upload a new application to the mbed
WiredHome 2:a29c32190037 49 ///
WiredHome 2:a29c32190037 50 /// History:
WiredHome 2:a29c32190037 51 /// @li 20130530 Initial version
WiredHome 2:a29c32190037 52 /// @li 20130601 Renamed ip_process to Poll
WiredHome 0:729320f63c5c 53 ///
WiredHome 0:729320f63c5c 54 /// @note Copyright © 2013 by Smartware Computing, all rights reserved.
WiredHome 0:729320f63c5c 55 /// Individuals may use this application for evaluation or non-commercial
WiredHome 0:729320f63c5c 56 /// purposes. Within this restriction, changes may be made to this application
WiredHome 0:729320f63c5c 57 /// as long as this copyright notice is retained. The user shall make
WiredHome 0:729320f63c5c 58 /// clear that their work is a derived work, and not the original.
WiredHome 0:729320f63c5c 59 /// Users of this application and sources accept this application "as is" and
WiredHome 0:729320f63c5c 60 /// shall hold harmless Smartware Computing, for any undesired results while
WiredHome 0:729320f63c5c 61 /// using this application - whether real or imagined.
WiredHome 0:729320f63c5c 62 ///
WiredHome 0:729320f63c5c 63 /// @author David Smart, Smartware Computing
WiredHome 0:729320f63c5c 64 ///
WiredHome 0:729320f63c5c 65 class HTTPServer
WiredHome 0:729320f63c5c 66 {
WiredHome 0:729320f63c5c 67 public:
WiredHome 0:729320f63c5c 68 /**
WiredHome 0:729320f63c5c 69 * namevalue pairs for parameters
WiredHome 0:729320f63c5c 70 */
WiredHome 0:729320f63c5c 71 typedef struct {
WiredHome 0:729320f63c5c 72 char * name;
WiredHome 0:729320f63c5c 73 char * value;
WiredHome 0:729320f63c5c 74 } namevalue;
WiredHome 2:a29c32190037 75
WiredHome 2:a29c32190037 76 /**
WiredHome 2:a29c32190037 77 * Indicates the purpose of the callback
WiredHome 2:a29c32190037 78 */
WiredHome 2:a29c32190037 79 typedef enum {
WiredHome 2:a29c32190037 80 CONTENT_LENGTH_REQUEST, ///<!- ask the user if they wish to accept the data
WiredHome 2:a29c32190037 81 DATA_TRANSFER,
WiredHome 2:a29c32190037 82 SEND_PAGE, ///<! the activated method should now send the page
WiredHome 2:a29c32190037 83 } CallBackType;
WiredHome 0:729320f63c5c 84
WiredHome 0:729320f63c5c 85 /**
WiredHome 0:729320f63c5c 86 * callback prototype for custom handler
WiredHome 0:729320f63c5c 87 *
WiredHome 2:a29c32190037 88 * This callback gets overloaded for a few purposes, which can be identified by the CallBackType parameter
WiredHome 2:a29c32190037 89 * @li SEND_PAGE - the callback should now send the html page, using as many svr->send() as needed.
WiredHome 2:a29c32190037 90 * When the callback returns, it should always indicate true.
WiredHome 2:a29c32190037 91 * @li CONTENT_LENGTH_REQUEST - the server is asking the callback if it wants to receive the message,
WiredHome 2:a29c32190037 92 * which may require significant memory. If the request is accepted, true should be returned.
WiredHome 2:a29c32190037 93 * If the request is denied, false should be returned.
WiredHome 2:a29c32190037 94 *
WiredHome 0:729320f63c5c 95 * @param svr is a handle to this class, so the callback has access to member functions
WiredHome 0:729320f63c5c 96 * @param params is a pointer to an array of name value pairs
WiredHome 0:729320f63c5c 97 * @paramcount is the number of parameters.
WiredHome 2:a29c32190037 98 * @return true if command was accepted
WiredHome 0:729320f63c5c 99 */
WiredHome 2:a29c32190037 100 typedef bool (* Handler)(HTTPServer * svr, CallBackType type, const char *path, const namevalue *params, int paramcount);
WiredHome 0:729320f63c5c 101
WiredHome 0:729320f63c5c 102 /**
WiredHome 0:729320f63c5c 103 * Create the HTTPServer object.
WiredHome 0:729320f63c5c 104 *
WiredHome 0:729320f63c5c 105 * @param wifly is the serial port with the wifly interface.
WiredHome 0:729320f63c5c 106 * @param port is the optional parameter for the port number to use, default is 80.
WiredHome 0:729320f63c5c 107 * @param webroot is a file system path to the root folder for the web space.
WiredHome 0:729320f63c5c 108 * @param maxparams defines the maximum number of parameters to a dynamic function (and the memory to support them).
WiredHome 0:729320f63c5c 109 * @param maxdynamicpages defines the maximum number of dynamic pages that can be registered.
WiredHome 0:729320f63c5c 110 * @param pc is the serial port for debug information (I should transform this to a log interface)
WiredHome 0:729320f63c5c 111 */
WiredHome 0:729320f63c5c 112 HTTPServer(Wifly * wifly, int port = 80, const char * webroot = "/", int maxparams = 30, int maxdynamicpages = 10, PC * pc = NULL);
WiredHome 0:729320f63c5c 113
WiredHome 0:729320f63c5c 114 /**
WiredHome 0:729320f63c5c 115 * destructor, which can clean up a few things
WiredHome 0:729320f63c5c 116 */
WiredHome 0:729320f63c5c 117 ~HTTPServer();
WiredHome 0:729320f63c5c 118
WiredHome 0:729320f63c5c 119 /**
WiredHome 0:729320f63c5c 120 * the process to call whenever there is free time, as this basically does
WiredHome 0:729320f63c5c 121 * all the work to monitor for connections and handle replies.
WiredHome 2:a29c32190037 122 *
WiredHome 2:a29c32190037 123 * 20130601 Renamed from ip_process to Poll
WiredHome 0:729320f63c5c 124 */
WiredHome 2:a29c32190037 125 void Poll();
WiredHome 0:729320f63c5c 126
WiredHome 0:729320f63c5c 127 /**
WiredHome 0:729320f63c5c 128 * Send a header back to the client and automatically appends a "\r\n". Each parameter must
WiredHome 0:729320f63c5c 129 * send a "\r\n" as part of that string.
WiredHome 0:729320f63c5c 130 *
WiredHome 0:729320f63c5c 131 * @param code is the optional return code; 200 = OK, if not provided then 404 = Not found is returned
WiredHome 0:729320f63c5c 132 * @param code_text is the text to align with the code (e.g. 404, "Not Found")
WiredHome 0:729320f63c5c 133 * @param content_type is a pointer to "Content-Type: text/html\r\n" (for example)
WiredHome 0:729320f63c5c 134 * @param optional_text is a pointer to any other text that is part of the header
WiredHome 0:729320f63c5c 135 */
WiredHome 0:729320f63c5c 136 void header(int code = 404, const char * code_text = "Not Found", const char * content_type = NULL, const char * optional_text = NULL);
WiredHome 0:729320f63c5c 137
WiredHome 0:729320f63c5c 138 /**
WiredHome 0:729320f63c5c 139 * Send text to the client
WiredHome 0:729320f63c5c 140 *
WiredHome 0:729320f63c5c 141 * @param msg is the text string to send
WiredHome 0:729320f63c5c 142 * @param bytes is the number of bytes to send. If not set, then strlen is calculated.
WiredHome 0:729320f63c5c 143 */
WiredHome 0:729320f63c5c 144 void send(const char * msg, int bytes = -1);
WiredHome 0:729320f63c5c 145
WiredHome 0:729320f63c5c 146 /**
WiredHome 0:729320f63c5c 147 * Send a file to the client, including the header
WiredHome 0:729320f63c5c 148 *
WiredHome 0:729320f63c5c 149 * @param filename is the fully qualified path and filename
WiredHome 0:729320f63c5c 150 * @param filetype is the header information (e.g. "Content-Type: text/html")
WiredHome 0:729320f63c5c 151 * @return true if it thinks it sent ok, false otherwise.
WiredHome 0:729320f63c5c 152 */
WiredHome 0:729320f63c5c 153 bool SendFile(const char * filename, const char * filetype);
WiredHome 0:729320f63c5c 154
WiredHome 0:729320f63c5c 155 /**
WiredHome 0:729320f63c5c 156 * register a handler for a specific URL.
WiredHome 0:729320f63c5c 157 *
WiredHome 0:729320f63c5c 158 * @param path to register
WiredHome 0:729320f63c5c 159 * @param callback of type Handler
WiredHome 0:729320f63c5c 160 * @return true if successfully registered
WiredHome 0:729320f63c5c 161 */
WiredHome 0:729320f63c5c 162 bool RegisterHandler(const char * path, Handler callback);
WiredHome 0:729320f63c5c 163
WiredHome 0:729320f63c5c 164 /**
WiredHome 0:729320f63c5c 165 * determine if the named file is a supported type (e.g. .htm, .jpg, ...)
WiredHome 0:729320f63c5c 166 *
WiredHome 0:729320f63c5c 167 * @param filename is the filename to test, based on the extension
WiredHome 0:729320f63c5c 168 * @return pointer to a Content-Type string if supported, or NULL if not.
WiredHome 0:729320f63c5c 169 */
WiredHome 0:729320f63c5c 170 const char * GetSupportedType(const char * filename);
WiredHome 0:729320f63c5c 171
WiredHome 0:729320f63c5c 172 /**
WiredHome 0:729320f63c5c 173 * search the available parameters for 'name' and if found, return the 'value'
WiredHome 0:729320f63c5c 174 *
WiredHome 0:729320f63c5c 175 * @param name is the name to search for
WiredHome 0:729320f63c5c 176 * @return pointer to the value, or NULL
WiredHome 0:729320f63c5c 177 */
WiredHome 0:729320f63c5c 178 const char * GetParameter(const char * name);
WiredHome 0:729320f63c5c 179
WiredHome 0:729320f63c5c 180 /**
WiredHome 0:729320f63c5c 181 * parse the text string into name=value parameters. This will directly
WiredHome 0:729320f63c5c 182 * modify the referenced string. If there is a #fragment_id on the end
WiredHome 0:729320f63c5c 183 * of the string, that will be removed.
WiredHome 0:729320f63c5c 184 *
WiredHome 0:729320f63c5c 185 * @param pString is a pointer to the string.
WiredHome 0:729320f63c5c 186 */
WiredHome 0:729320f63c5c 187 void ParseParameters(char * pString);
WiredHome 0:729320f63c5c 188
WiredHome 0:729320f63c5c 189 /**
WiredHome 0:729320f63c5c 190 * Unescape string converts a coded string "in place" into a normal string
WiredHome 0:729320f63c5c 191 * this "This%20is%20a%20question%3F%20and%20an%20answer."
WiredHome 0:729320f63c5c 192 * becomes "This is a question? and an answer."
WiredHome 0:729320f63c5c 193 * @note '+' is another form of space, so is converted to a space before the %xx
WiredHome 0:729320f63c5c 194 *
WiredHome 0:729320f63c5c 195 * @param encoded string to be converted
WiredHome 0:729320f63c5c 196 */
WiredHome 0:729320f63c5c 197 void UnescapeString(char * encoded);
WiredHome 0:729320f63c5c 198
WiredHome 0:729320f63c5c 199 /**
WiredHome 0:729320f63c5c 200 * Get the IP address of the remote node to which we are connected.
WiredHome 0:729320f63c5c 201 * @caution this switches the module into, and out of, command mode
WiredHome 0:729320f63c5c 202 * which has quite a time penalty.
WiredHome 0:729320f63c5c 203 */
WiredHome 0:729320f63c5c 204 void GetRemoteAddr(char * str, int size);
WiredHome 0:729320f63c5c 205
WiredHome 0:729320f63c5c 206 /**
WiredHome 0:729320f63c5c 207 * used to force a connection to close
WiredHome 0:729320f63c5c 208 */
WiredHome 0:729320f63c5c 209 void close_connection();
WiredHome 0:729320f63c5c 210
WiredHome 0:729320f63c5c 211 private:
WiredHome 0:729320f63c5c 212 Wifly * wifly;
WiredHome 0:729320f63c5c 213 char * webroot;
WiredHome 0:729320f63c5c 214 PC * pc;
WiredHome 0:729320f63c5c 215 Timer * timer;
WiredHome 0:729320f63c5c 216 TCPSocketServer * server;
WiredHome 0:729320f63c5c 217 TCPSocketConnection client;
WiredHome 0:729320f63c5c 218 char * rewriteWithDefaultFile(char * queryString);
WiredHome 0:729320f63c5c 219 char * rewritePrependWebroot(char * queryString);
WiredHome 0:729320f63c5c 220 int maxparams;
WiredHome 0:729320f63c5c 221 namevalue *params;
WiredHome 0:729320f63c5c 222 int paramcount;
WiredHome 0:729320f63c5c 223
WiredHome 0:729320f63c5c 224 typedef struct {
WiredHome 0:729320f63c5c 225 char * path;
WiredHome 0:729320f63c5c 226 Handler callback;
WiredHome 0:729320f63c5c 227 } handler;
WiredHome 0:729320f63c5c 228 int maxdynamicpages;
WiredHome 0:729320f63c5c 229 handler *handlers;
WiredHome 0:729320f63c5c 230 int handlercount;
WiredHome 0:729320f63c5c 231
WiredHome 0:729320f63c5c 232 /**
WiredHome 0:729320f63c5c 233 * Extract the message from the record, by searching for the needle
WiredHome 0:729320f63c5c 234 * the string of interest follows the needle, and may be ' ' delimited
WiredHome 0:729320f63c5c 235 * Can damage haystack while processing it.
WiredHome 0:729320f63c5c 236 *
WiredHome 0:729320f63c5c 237 * @param haystack is the record to search
WiredHome 0:729320f63c5c 238 * @param needle is the text to search for, which precedes the text to return
WiredHome 0:729320f63c5c 239 * @param string is the text following the needle
WiredHome 0:729320f63c5c 240 * @return true if it extracted something successfully
WiredHome 0:729320f63c5c 241 */
WiredHome 0:729320f63c5c 242 bool Extract(char * rec, char * needle, char ** string);
WiredHome 0:729320f63c5c 243
WiredHome 0:729320f63c5c 244 int HexCharToInt(char c);
WiredHome 0:729320f63c5c 245 char HexPairToChar(char * p);
WiredHome 0:729320f63c5c 246 };
WiredHome 0:729320f63c5c 247 #endif //SW_HTTPSERVER_H