A simple web server that can be bound to either the EthernetInterface or the WiflyInterface.
Dependents: Smart-WiFly-WebServer WattEye X10Svr SSDP_Server
SW_HTTPServer.h@49:cd391662f254, 2017-04-09 (annotated)
- Committer:
- WiredHome
- Date:
- Sun Apr 09 18:39:37 2017 +0000
- Revision:
- 49:cd391662f254
- Parent:
- 48:078adbe279ac
- Child:
- 52:611a3b360f8c
- Child:
- 53:e5d96abe5e9b
Integrate the blocking time parameter into the code.; Correct/improve the documentation for sending custom headers.
Who changed what in which revision?
User | Revision | Line number | New 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 "TCPSocketServer.h" |
WiredHome | 1:54353af0d20a | 6 | #include "TCPSocketConnection.h" |
WiredHome | 1:54353af0d20a | 7 | |
WiredHome | 1:54353af0d20a | 8 | #ifdef MODSERIAL_H |
WiredHome | 1:54353af0d20a | 9 | #define PC MODSERIAL |
WiredHome | 1:54353af0d20a | 10 | #else |
WiredHome | 36:1bb5fa6b109c | 11 | #define PC RawSerial |
WiredHome | 1:54353af0d20a | 12 | #endif |
WiredHome | 1:54353af0d20a | 13 | |
WiredHome | 9:2ea342765c9d | 14 | /// This is the default buffer size used to send files. You might size |
WiredHome | 9:2ea342765c9d | 15 | /// this to be equal or less than the payload size of 1460 bytes. |
WiredHome | 44:71f09e4255f4 | 16 | /// For WiFly: see User Manual 3.6.1. |
WiredHome | 44:71f09e4255f4 | 17 | #define FILESEND_BUF_SIZE 500 |
WiredHome | 3:17928786bdb5 | 18 | |
WiredHome | 3:17928786bdb5 | 19 | |
WiredHome | 12:109bf1558300 | 20 | /// MAX_HEADER_SIZE is the default size to contain the largest header. |
WiredHome | 9:2ea342765c9d | 21 | /// This is the size of the URL and query string, and also all the |
WiredHome | 3:17928786bdb5 | 22 | /// other header information about the client. This can be |
WiredHome | 12:109bf1558300 | 23 | /// a couple of K, larger if you have big forms as it includes the |
WiredHome | 3:17928786bdb5 | 24 | /// form data that is submitted. |
WiredHome | 3:17928786bdb5 | 25 | #define MAX_HEADER_SIZE 1000 |
WiredHome | 3:17928786bdb5 | 26 | |
WiredHome | 9:2ea342765c9d | 27 | |
WiredHome | 39:0427544a5c08 | 28 | /// HTTPServer is a simple web server leveraging a network interface. |
WiredHome | 12:109bf1558300 | 29 | /// |
WiredHome | 3:17928786bdb5 | 30 | /// While simple, it is a capable, web server. The basic mode |
WiredHome | 3:17928786bdb5 | 31 | /// of operation is for it to serve static web pages from an available |
WiredHome | 3:17928786bdb5 | 32 | /// file system. |
WiredHome | 12:109bf1558300 | 33 | /// |
WiredHome | 3:17928786bdb5 | 34 | /// The default page is index.htm (compile time defined) |
WiredHome | 3:17928786bdb5 | 35 | /// standard support to serve a number of standard file types; |
WiredHome | 3:17928786bdb5 | 36 | /// gif, jpg, jpeg, ico, png, zip, gz, tar, txt, pdf, htm, html |
WiredHome | 3:17928786bdb5 | 37 | /// (this list is also compile time defined) |
WiredHome | 3:17928786bdb5 | 38 | /// |
WiredHome | 3:17928786bdb5 | 39 | /// It can also serve dynamically generated pages, and therefore |
WiredHome | 3:17928786bdb5 | 40 | /// respond to form submission. Through the dynamic interface it is |
WiredHome | 3:17928786bdb5 | 41 | /// then quite easy to interact with the hardware, reading the inputs |
WiredHome | 3:17928786bdb5 | 42 | /// or signaling outputs. |
WiredHome | 3:17928786bdb5 | 43 | /// |
WiredHome | 3:17928786bdb5 | 44 | /// @code |
WiredHome | 39:0427544a5c08 | 45 | /// HTTPServer svr(HTTP_SERVER_PORT, "/local", 15, 30, 10, &pc); |
WiredHome | 3:17928786bdb5 | 46 | /// svr.RegisterHandler("/dyn1", SimpleDynamicPage); |
WiredHome | 44:71f09e4255f4 | 47 | /// while (true) { |
WiredHome | 44:71f09e4255f4 | 48 | /// svr.Poll(); // this is non blocking process, with variable execution |
WiredHome | 44:71f09e4255f4 | 49 | /// } |
WiredHome | 3:17928786bdb5 | 50 | /// @endcode |
WiredHome | 3:17928786bdb5 | 51 | /// |
WiredHome | 44:71f09e4255f4 | 52 | /// This web server used nweb as a starting point, but expanded well beyond that. |
WiredHome | 46:eaa86d48be6f | 53 | /// http://nmon.sourceforge.net/pmwiki.php?n=Site.Nweb&cm_mc_uid=21286415979014862330090&cm_mc_sid_50200000=1486233009 |
WiredHome | 0:729320f63c5c | 54 | /// |
WiredHome | 3:17928786bdb5 | 55 | /// Given: scheme://server:port/path?query_string#fragment_id |
WiredHome | 0:729320f63c5c | 56 | /// @li scheme is "http" |
WiredHome | 3:17928786bdb5 | 57 | /// @li server is whatever IP the server has |
WiredHome | 0:729320f63c5c | 58 | /// @li port is the registered port |
WiredHome | 0:729320f63c5c | 59 | /// @li /path is the reference to the file (actual or logical) on the server |
WiredHome | 0:729320f63c5c | 60 | /// @li query_string is any combination of name=value pairs |
WiredHome | 0:729320f63c5c | 61 | /// @li fragment_id is a reference to an anchor on the page |
WiredHome | 0:729320f63c5c | 62 | /// |
WiredHome | 3:17928786bdb5 | 63 | /// Features: |
WiredHome | 3:17928786bdb5 | 64 | /// @li Serves static pages from a file system. Many normal filetypes are |
WiredHome | 3:17928786bdb5 | 65 | /// supported. |
WiredHome | 3:17928786bdb5 | 66 | /// @li Compile time configurable for the "default" file, typically index.htm. |
WiredHome | 3:17928786bdb5 | 67 | /// @li Provides a registration interface for dynamically generated pages that |
WiredHome | 3:17928786bdb5 | 68 | /// can then interact with other hardware. |
WiredHome | 3:17928786bdb5 | 69 | /// @li Revised to be Non-blocking, however the execution time is variable |
WiredHome | 44:71f09e4255f4 | 70 | /// depending on the actions being performed and can span hundreds of msec |
WiredHome | 44:71f09e4255f4 | 71 | /// when using a WiFly module as the network interface. |
WiredHome | 44:71f09e4255f4 | 72 | /// @li Support for filenames aliases, which permit using long filenames with |
WiredHome | 44:71f09e4255f4 | 73 | /// the LocalFileSystem (which has an 8.3 constraint). |
WiredHome | 3:17928786bdb5 | 74 | /// |
WiredHome | 3:17928786bdb5 | 75 | /// Limitations: |
WiredHome | 39:0427544a5c08 | 76 | /// @li When used with Wifly network interface it supports only a single |
WiredHome | 39:0427544a5c08 | 77 | /// connection at a time. A web page with served objects (img src=...) |
WiredHome | 39:0427544a5c08 | 78 | /// is rarely served properly. It might trace to forcing the connection to |
WiredHome | 39:0427544a5c08 | 79 | /// close, but not yet sure. Explore "Set Uart Rx Data Buffer" in |
WiredHome | 39:0427544a5c08 | 80 | /// WiFly manual 2.3.65. This is a limitation of the Wifly module. |
WiredHome | 39:0427544a5c08 | 81 | /// No solution is forthcoming, so a crude workaround is to use javascript |
WiredHome | 39:0427544a5c08 | 82 | /// to load the images after the page loads. |
WiredHome | 3:17928786bdb5 | 83 | /// @li Rapid requests for page objects (e.g. embedded images) are lost. Still |
WiredHome | 3:17928786bdb5 | 84 | /// working to understand this issue. |
WiredHome | 3:17928786bdb5 | 85 | /// |
WiredHome | 43:3fc773c2986e | 86 | /// Improvements (TODO): |
WiredHome | 43:3fc773c2986e | 87 | /// @li Add hook for a custom 404 page, which might show a page, or might redirect. |
WiredHome | 43:3fc773c2986e | 88 | /// @li Combine the API for accessing parameters for the GET and POST, as they |
WiredHome | 43:3fc773c2986e | 89 | /// are normally [always?] mutually exclusive. |
WiredHome | 43:3fc773c2986e | 90 | /// @li Keep only the public functions public, make the rest private/protected. |
WiredHome | 43:3fc773c2986e | 91 | /// Add another interface for dynamic pages to give them access to private/protected |
WiredHome | 43:3fc773c2986e | 92 | /// functions. |
WiredHome | 43:3fc773c2986e | 93 | /// @li Try to reduce the size of the header buffer, since that is quite large. |
WiredHome | 43:3fc773c2986e | 94 | /// @li General clean-up, refactoring, de-duplication. |
WiredHome | 43:3fc773c2986e | 95 | /// @li Leverage mbed os, so one receive handler can spawn up to N response handlers. |
WiredHome | 43:3fc773c2986e | 96 | /// This may improve overall performance. |
WiredHome | 43:3fc773c2986e | 97 | /// @li Since some transactions can't be easily buffered (the stream may be too |
WiredHome | 43:3fc773c2986e | 98 | /// large, consider how to shuttle parts of the transaction back and forth |
WiredHome | 43:3fc773c2986e | 99 | /// between the user-code and the server. |
WiredHome | 18:6199558632c0 | 100 | /// |
WiredHome | 43:3fc773c2986e | 101 | /// History (TO-Done): |
WiredHome | 48:078adbe279ac | 102 | /// @li 20170408 Added another optional parameter to the constructor to control the |
WiredHome | 48:078adbe279ac | 103 | /// blocking time when Poll() is called. |
WiredHome | 43:3fc773c2986e | 104 | /// @li 20140913 Removed the relationship to the Wifly module, which caused an API change |
WiredHome | 43:3fc773c2986e | 105 | /// in the constructor by elimination of the first parameter. |
WiredHome | 43:3fc773c2986e | 106 | /// @li 20140913 parses the header similar to the query string, and then makes |
WiredHome | 43:3fc773c2986e | 107 | /// those parameters accessible. |
WiredHome | 43:3fc773c2986e | 108 | /// @li 20140913 Added basic password capability to dynamic web pages. |
WiredHome | 43:3fc773c2986e | 109 | /// @li 20140913 move part of the POST method handler to the registered handler, so |
WiredHome | 0:729320f63c5c | 110 | /// it can decide if it should allocate the needed memory. |
WiredHome | 43:3fc773c2986e | 111 | /// @li 20140201 hunted down several lengthy operations - the speed of the file system |
WiredHome | 43:3fc773c2986e | 112 | /// and the "close" operation which requires <delay 0.25s>$$$<delay>close\r. |
WiredHome | 2:a29c32190037 | 113 | /// @li 20130530 Initial version |
WiredHome | 2:a29c32190037 | 114 | /// @li 20130601 Renamed ip_process to Poll |
WiredHome | 3:17928786bdb5 | 115 | /// @li 20130617 Cleaned up some of the documentation changes |
WiredHome | 3:17928786bdb5 | 116 | /// @li 20130623 Make it non-blocking. "Poll" takes a variable amount |
WiredHome | 3:17928786bdb5 | 117 | /// of time, based on whether it is idle, or how much it |
WiredHome | 3:17928786bdb5 | 118 | /// has to do. |
WiredHome | 18:6199558632c0 | 119 | /// @li 20130911 Lots of incremental changes along this way, this update |
WiredHome | 18:6199558632c0 | 120 | /// refreshes the documentation. |
WiredHome | 0:729320f63c5c | 121 | /// |
WiredHome | 46:eaa86d48be6f | 122 | /// @note Copyright © 2014-2017 by Smartware Computing, all rights reserved. |
WiredHome | 0:729320f63c5c | 123 | /// Individuals may use this application for evaluation or non-commercial |
WiredHome | 0:729320f63c5c | 124 | /// purposes. Within this restriction, changes may be made to this application |
WiredHome | 0:729320f63c5c | 125 | /// as long as this copyright notice is retained. The user shall make |
WiredHome | 0:729320f63c5c | 126 | /// clear that their work is a derived work, and not the original. |
WiredHome | 0:729320f63c5c | 127 | /// Users of this application and sources accept this application "as is" and |
WiredHome | 0:729320f63c5c | 128 | /// shall hold harmless Smartware Computing, for any undesired results while |
WiredHome | 0:729320f63c5c | 129 | /// using this application - whether real or imagined. |
WiredHome | 0:729320f63c5c | 130 | /// |
WiredHome | 0:729320f63c5c | 131 | /// @author David Smart, Smartware Computing |
WiredHome | 0:729320f63c5c | 132 | /// |
WiredHome | 0:729320f63c5c | 133 | class HTTPServer |
WiredHome | 0:729320f63c5c | 134 | { |
WiredHome | 0:729320f63c5c | 135 | public: |
WiredHome | 0:729320f63c5c | 136 | /** |
WiredHome | 3:17928786bdb5 | 137 | * name-value pairs for parameters |
WiredHome | 0:729320f63c5c | 138 | */ |
WiredHome | 3:17928786bdb5 | 139 | typedef struct NAMEVALUE { |
WiredHome | 0:729320f63c5c | 140 | char * name; |
WiredHome | 0:729320f63c5c | 141 | char * value; |
WiredHome | 0:729320f63c5c | 142 | } namevalue; |
WiredHome | 12:109bf1558300 | 143 | |
WiredHome | 2:a29c32190037 | 144 | /** |
WiredHome | 3:17928786bdb5 | 145 | * Indicates the purpose of the Handler callback |
WiredHome | 3:17928786bdb5 | 146 | * |
WiredHome | 12:109bf1558300 | 147 | * Application code in a dynamic page uses this to determine the state |
WiredHome | 3:17928786bdb5 | 148 | * and therefore the needed operation to be performed. |
WiredHome | 3:17928786bdb5 | 149 | * |
WiredHome | 3:17928786bdb5 | 150 | * @code |
WiredHome | 13:8975d7928678 | 151 | * bool SimpleDynamicPage(HTTPServer *svr, HTTPServer::CallBackType type, |
WiredHome | 13:8975d7928678 | 152 | * const char * path, const HTTPServer::namevalue *queryParams, |
WiredHome | 13:8975d7928678 | 153 | * int queryParamCount) { |
WiredHome | 3:17928786bdb5 | 154 | * char buf[100]; |
WiredHome | 3:17928786bdb5 | 155 | * bool ret = false; |
WiredHome | 12:109bf1558300 | 156 | * |
WiredHome | 3:17928786bdb5 | 157 | * switch (type) { |
WiredHome | 3:17928786bdb5 | 158 | * case HTTPServer::SEND_PAGE: |
WiredHome | 3:17928786bdb5 | 159 | * svr->header(200, "OK", "Content-Type: text/html\r\n"); |
WiredHome | 3:17928786bdb5 | 160 | * svr->send("<html><head><title>Dynamic Page</title></head>\r\n"); |
WiredHome | 3:17928786bdb5 | 161 | * svr->send("<body>\r\n"); |
WiredHome | 3:17928786bdb5 | 162 | * svr->send("This page was generated dynamically. Create your own name=value pairs on the URL " |
WiredHome | 3:17928786bdb5 | 163 | * "which uses the GET method.<br/>\r\n"); |
WiredHome | 13:8975d7928678 | 164 | * sprintf(buf, "%d parameters passed to {%s}:<br/>\r\n", queryParamCount, path); |
WiredHome | 3:17928786bdb5 | 165 | * svr->send(buf); |
WiredHome | 13:8975d7928678 | 166 | * for (int i=0; i<queryParamCount; i++) { |
WiredHome | 13:8975d7928678 | 167 | * sprintf(buf, "%d: %s = %s<br/>\r\n", i, queryParams[i].name, queryParams[i].value); |
WiredHome | 3:17928786bdb5 | 168 | * svr->send(buf); |
WiredHome | 3:17928786bdb5 | 169 | * } |
WiredHome | 3:17928786bdb5 | 170 | * svr->send("<br/><a href='/'>back to main</a></body></html>\r\n"); |
WiredHome | 3:17928786bdb5 | 171 | * ret = true; |
WiredHome | 3:17928786bdb5 | 172 | * break; |
WiredHome | 3:17928786bdb5 | 173 | * case HTTPServer::CONTENT_LENGTH_REQUEST: |
WiredHome | 3:17928786bdb5 | 174 | * ret = true; |
WiredHome | 3:17928786bdb5 | 175 | * break; |
WiredHome | 3:17928786bdb5 | 176 | * case HTTPServer::DATA_TRANSFER: |
WiredHome | 3:17928786bdb5 | 177 | * ret = true; |
WiredHome | 3:17928786bdb5 | 178 | * break; |
WiredHome | 3:17928786bdb5 | 179 | * default: |
WiredHome | 3:17928786bdb5 | 180 | * ret = false; |
WiredHome | 3:17928786bdb5 | 181 | * break; |
WiredHome | 3:17928786bdb5 | 182 | * } |
WiredHome | 3:17928786bdb5 | 183 | * return ret; |
WiredHome | 3:17928786bdb5 | 184 | * } |
WiredHome | 3:17928786bdb5 | 185 | * @endcode |
WiredHome | 2:a29c32190037 | 186 | */ |
WiredHome | 3:17928786bdb5 | 187 | typedef enum CALLBACKTYPE { |
WiredHome | 14:19c5f6151319 | 188 | CONTENT_LENGTH_REQUEST, ///< ask the client if they wish to accept the data, typically from a POST event |
WiredHome | 27:90a1f5a5392f | 189 | DATA_TRANSFER, ///< used when submitting a file via a form |
WiredHome | 33:ef165a67ab22 | 190 | DATA_TRANSFER_END, ///< used when all data has been given to the client (may be used to close the file) |
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 | 44:71f09e4255f4 | 200 | /// This is the set of header codes that are generally recognized. Note that many are |
WiredHome | 44:71f09e4255f4 | 201 | /// not supported, so may not be listed here. |
WiredHome | 44:71f09e4255f4 | 202 | typedef enum HEADERCODES { |
WiredHome | 44:71f09e4255f4 | 203 | // 1xx: Information |
WiredHome | 44:71f09e4255f4 | 204 | //Continue = 100, ///< Server has received the headers, client should send the body. |
WiredHome | 44:71f09e4255f4 | 205 | //Switching = 101, ///< Request to switch protocols - not supported. |
WiredHome | 44:71f09e4255f4 | 206 | //Checkpoint = 102, ///< resume aborted PUT/POST - not supported. |
WiredHome | 44:71f09e4255f4 | 207 | |
WiredHome | 44:71f09e4255f4 | 208 | // 2xx: Successful |
WiredHome | 44:71f09e4255f4 | 209 | OK = 200, ///< request is OK. |
WiredHome | 44:71f09e4255f4 | 210 | //Created = 201, ///< The request has been fulfilled - not supported. |
WiredHome | 44:71f09e4255f4 | 211 | //Accepted = 202, ///< The request has been accepted for processing - not supported. |
WiredHome | 44:71f09e4255f4 | 212 | //Non_Auth = 203, ///< The request has been successfully processed - not supported. |
WiredHome | 44:71f09e4255f4 | 213 | //No_Content = 204, ///< The request has been successfully processed, but is not returning any content |
WiredHome | 44:71f09e4255f4 | 214 | //Reset_Content = 205, ///< The request has been successfully processed, but is not returning any content, |
WiredHome | 44:71f09e4255f4 | 215 | // /// and requires that the requester reset the document view |
WiredHome | 44:71f09e4255f4 | 216 | //Partial_Content = 206, /// The server is delivering only part of the resource due to a range header sent by the client |
WiredHome | 44:71f09e4255f4 | 217 | |
WiredHome | 44:71f09e4255f4 | 218 | // 3xx: Redirection |
WiredHome | 44:71f09e4255f4 | 219 | //Multiple_Choices = 300, /// A link list. The user can select a link and go to that location. Maximum five addresses. |
WiredHome | 44:71f09e4255f4 | 220 | Moved_Permanently = 301, ///< The requested page has moved to a new URL. |
WiredHome | 44:71f09e4255f4 | 221 | //Found = 302, /// The requested page has moved temporarily to a new URL |
WiredHome | 44:71f09e4255f4 | 222 | //See_Other = 303, /// The requested page can be found under a different URL |
WiredHome | 44:71f09e4255f4 | 223 | //Not_Modified = 304, /// Indicates the requested page has not been modified since last requested |
WiredHome | 44:71f09e4255f4 | 224 | // 306 Switch Proxy No longer used |
WiredHome | 44:71f09e4255f4 | 225 | // 307 Temporary Redirect The requested page has moved temporarily to a new URL |
WiredHome | 44:71f09e4255f4 | 226 | // 308 Resume Incomplete Used in the resumable requests proposal to resume aborted PUT or POST requests |
WiredHome | 44:71f09e4255f4 | 227 | |
WiredHome | 44:71f09e4255f4 | 228 | // 4xx: Client Error |
WiredHome | 44:71f09e4255f4 | 229 | Bad_Request = 400, ///< The request cannot be fulfilled due to bad syntax |
WiredHome | 44:71f09e4255f4 | 230 | Unauthorized = 401, ///< The request was a legal request, but the server is refusing to respond to it. For use when authentication is possible but has failed or not yet been provided |
WiredHome | 44:71f09e4255f4 | 231 | // 402 Payment Required Reserved for future use |
WiredHome | 44:71f09e4255f4 | 232 | // 403 Forbidden The request was a legal request, but the server is refusing to respond to it |
WiredHome | 44:71f09e4255f4 | 233 | Not_Found = 404, ///< The requested page could not be found but may be available again in the future |
WiredHome | 44:71f09e4255f4 | 234 | // Method Not Allowed 405 A request was made of a page using a request method not supported by that page |
WiredHome | 44:71f09e4255f4 | 235 | // Not Acceptable 406 The server can only generate a response that is not accepted by the client |
WiredHome | 44:71f09e4255f4 | 236 | // Proxy Auth Reqd 407 The client must first authenticate itself with the proxy |
WiredHome | 44:71f09e4255f4 | 237 | Request_Timeout = 408, ///< The server timed out waiting for the request |
WiredHome | 44:71f09e4255f4 | 238 | // 409 Conflict The request could not be completed because of a conflict in the request |
WiredHome | 44:71f09e4255f4 | 239 | // 410 Gone The requested page is no longer available |
WiredHome | 44:71f09e4255f4 | 240 | // 411 Length Required The "Content-Length" is not defined. The server will not accept the request without it |
WiredHome | 44:71f09e4255f4 | 241 | // 412 Precondition Failed The precondition given in the request evaluated to false by the server |
WiredHome | 44:71f09e4255f4 | 242 | // 413 Request Entity Too Large The server will not accept the request, because the request entity is too large |
WiredHome | 44:71f09e4255f4 | 243 | // 414 Request-URI Too Long The server will not accept the request, because the URL is too long. Occurs when you convert a POST request to a GET request with a long query information |
WiredHome | 44:71f09e4255f4 | 244 | Unsupported_Media_Type = 415, ///< The server will not accept the request, because the media type is not supported |
WiredHome | 44:71f09e4255f4 | 245 | // 416 Requested Range Not Satisfiable The client has asked for a portion of the file, but the server cannot supply that portion |
WiredHome | 44:71f09e4255f4 | 246 | // 417 Expectation Failed The server cannot meet the requirements of the Expect request-header field |
WiredHome | 44:71f09e4255f4 | 247 | |
WiredHome | 44:71f09e4255f4 | 248 | // 5xx: Server Error |
WiredHome | 44:71f09e4255f4 | 249 | // Message: Description: |
WiredHome | 44:71f09e4255f4 | 250 | Server_Error = 500, ///< A generic error message, given when no more specific message is suitable |
WiredHome | 44:71f09e4255f4 | 251 | // 501 Not Implemented The server either does not recognize the request method, or it lacks the ability to fulfill the request |
WiredHome | 44:71f09e4255f4 | 252 | // 502 Bad Gateway The server was acting as a gateway or proxy and received an invalid response from the upstream server |
WiredHome | 44:71f09e4255f4 | 253 | // 503 Service Unavailable The server is currently unavailable (overloaded or down) |
WiredHome | 44:71f09e4255f4 | 254 | // 504 Gateway Timeout The server was acting as a gateway or proxy and did not receive a timely response from the upstream server |
WiredHome | 44:71f09e4255f4 | 255 | // 505 HTTP Version Not Supported The server does not support the HTTP protocol version used in the request |
WiredHome | 44:71f09e4255f4 | 256 | // 511 Network Authentication Required The client needs to authenticate to gain network access |
WiredHome | 44:71f09e4255f4 | 257 | } HeaderCodes; |
WiredHome | 44:71f09e4255f4 | 258 | |
WiredHome | 12:109bf1558300 | 259 | /** |
WiredHome | 3:17928786bdb5 | 260 | * This is the prototype for custom handlers that are activated via a callback |
WiredHome | 0:729320f63c5c | 261 | * |
WiredHome | 37:0cb2774e2410 | 262 | * This callback gets overloaded for a few purposes, which can be identified by the |
WiredHome | 37:0cb2774e2410 | 263 | * \see CallBackType parameter. |
WiredHome | 37:0cb2774e2410 | 264 | * |
WiredHome | 27:90a1f5a5392f | 265 | * @li CONTENT_LENGTH_REQUEST - the server is asking the callback if it wants to receive the message, |
WiredHome | 27:90a1f5a5392f | 266 | * which may require significant memory. If the request is accepted, true should be returned. |
WiredHome | 27:90a1f5a5392f | 267 | * If the request is denied, false should be returned. |
WiredHome | 27:90a1f5a5392f | 268 | * @li DATA_TRANSFER - the server is handing off a large body of data, which was accepted based |
WiredHome | 27:90a1f5a5392f | 269 | * on the CONTENT_LENGTH_REQUEST callback. The data is now available for processing. |
WiredHome | 27:90a1f5a5392f | 270 | * The callback should return true to continue the processing. |
WiredHome | 12:109bf1558300 | 271 | * @li SEND_PAGE - the callback should now send the html page, using as many svr->send() as needed. |
WiredHome | 29:00116fc9da74 | 272 | * When the callback returns, it should always indicate true that it has sent the page. |
WiredHome | 27:90a1f5a5392f | 273 | * |
WiredHome | 27:90a1f5a5392f | 274 | * @note The queryParams pointer purpose depends on the callback type. |
WiredHome | 33:ef165a67ab22 | 275 | * For CONTENT_LENGTH_REQUEST, the pointer points to the name=value pairs from the |
WiredHome | 27:90a1f5a5392f | 276 | * header. |
WiredHome | 33:ef165a67ab22 | 277 | * For DATA_TRANSFER, the pointer points to the start of the actual data. |
WiredHome | 29:00116fc9da74 | 278 | * For SEND_PAGE, ... <to be determined> |
WiredHome | 12:109bf1558300 | 279 | * |
WiredHome | 48:078adbe279ac | 280 | * @param[in] svr is a handle to this class, so the callback has access to member functions |
WiredHome | 48:078adbe279ac | 281 | * @param[in] type is the callback type @see CallBackType |
WiredHome | 48:078adbe279ac | 282 | * @param[in] path is the pointer to a large block of information being transferred. This pointer |
WiredHome | 37:0cb2774e2410 | 283 | * references a dynamically managed resource, so any information of value must be |
WiredHome | 37:0cb2774e2410 | 284 | * extracted from here, and not referenced into this memory space. |
WiredHome | 48:078adbe279ac | 285 | * @param[in] queryParams is a pointer based on the callback type. |
WiredHome | 48:078adbe279ac | 286 | * @param[in] count is the number of items - for type = CONTENT_LENGTH_REQUEST this is the number of |
WiredHome | 33:ef165a67ab22 | 287 | * name=value pars in the queryParams parameter, and for the DATA_TRANSFER this is the |
WiredHome | 33:ef165a67ab22 | 288 | * number of bytes being passed in the path parameters. |
WiredHome | 33:ef165a67ab22 | 289 | * @return one of the @see CallBackResults signals indicating error or successes |
WiredHome | 0:729320f63c5c | 290 | */ |
WiredHome | 37:0cb2774e2410 | 291 | typedef CallBackResults (* Handler)(HTTPServer * svr, CallBackType type, const char *path, |
WiredHome | 37:0cb2774e2410 | 292 | const namevalue *queryParams, int queryParamCount); |
WiredHome | 12:109bf1558300 | 293 | |
WiredHome | 0:729320f63c5c | 294 | /** |
WiredHome | 0:729320f63c5c | 295 | * Create the HTTPServer object. |
WiredHome | 12:109bf1558300 | 296 | * |
WiredHome | 48:078adbe279ac | 297 | * @param[in] port is the optional parameter for the port number to use, default is 80. |
WiredHome | 48:078adbe279ac | 298 | * @param[in] webroot is a file system path to the root folder for the web space. If any trailing '/' |
WiredHome | 27:90a1f5a5392f | 299 | * is included (e.g. "/web/path/") it will be removed (to "/web/path"). |
WiredHome | 48:078adbe279ac | 300 | * @param[in] maxheaderParams defines the maximum number of parameters to extract from a header |
WiredHome | 37:0cb2774e2410 | 301 | * (Host: 192..\r\nConnection: keep-alive\r\n...) |
WiredHome | 48:078adbe279ac | 302 | * @param[in] maxqueryParams defines the maximum number of query parameters to a dynamic function |
WiredHome | 37:0cb2774e2410 | 303 | * (and the memory to support them). |
WiredHome | 48:078adbe279ac | 304 | * @param[in] maxdynamicpages defines the maximum number of dynamic pages that can be registered. |
WiredHome | 49:cd391662f254 | 305 | * @param[in] blockingtime is the time that the Poll process will pause, waiting for input. |
WiredHome | 48:078adbe279ac | 306 | * @param[in] pc is the serial port for debug information (I should transform this to a log interface) |
WiredHome | 48:078adbe279ac | 307 | * @param[in] allocforheader is the memory allocation to support the largest expected header from a client |
WiredHome | 48:078adbe279ac | 308 | * @param[in] allocforfile is the memory allocation to support sending a file to the client. This is |
WiredHome | 37:0cb2774e2410 | 309 | * typically sized to fit an ethernet frame. |
WiredHome | 0:729320f63c5c | 310 | */ |
WiredHome | 39:0427544a5c08 | 311 | HTTPServer(int port = 80, const char * webroot = "/", int maxheaderParams = 15, |
WiredHome | 37:0cb2774e2410 | 312 | int maxqueryParams = 30, int maxdynamicpages = 10, |
WiredHome | 49:cd391662f254 | 313 | int blockingtime = 10, |
WiredHome | 49:cd391662f254 | 314 | PC * pc = NULL, int _allocforheader = MAX_HEADER_SIZE, int _allocforfile = FILESEND_BUF_SIZE |
WiredHome | 49:cd391662f254 | 315 | ); |
WiredHome | 12:109bf1558300 | 316 | |
WiredHome | 0:729320f63c5c | 317 | /** |
WiredHome | 3:17928786bdb5 | 318 | * Destructor, which can clean up memory. |
WiredHome | 0:729320f63c5c | 319 | */ |
WiredHome | 0:729320f63c5c | 320 | ~HTTPServer(); |
WiredHome | 12:109bf1558300 | 321 | |
WiredHome | 0:729320f63c5c | 322 | /** |
WiredHome | 27:90a1f5a5392f | 323 | * Get the path to the webroot, for applications that need to |
WiredHome | 27:90a1f5a5392f | 324 | * reference the file system relative to that point. |
WiredHome | 24:062431453abb | 325 | * |
WiredHome | 27:90a1f5a5392f | 326 | * @note The returned value may not be exactly as set at instantiation |
WiredHome | 27:90a1f5a5392f | 327 | * as trailing '/' were removed (unless the web root == "/"). |
WiredHome | 27:90a1f5a5392f | 328 | * e.g. "/msc/web/" becomes "/msc/web" |
WiredHome | 27:90a1f5a5392f | 329 | * |
WiredHome | 27:90a1f5a5392f | 330 | * @returns pointer to the webroot string. |
WiredHome | 24:062431453abb | 331 | */ |
WiredHome | 24:062431453abb | 332 | const char * GetWebRoot() { |
WiredHome | 27:90a1f5a5392f | 333 | return (const char *)webroot; |
WiredHome | 27:90a1f5a5392f | 334 | }; |
WiredHome | 24:062431453abb | 335 | |
WiredHome | 44:71f09e4255f4 | 336 | |
WiredHome | 44:71f09e4255f4 | 337 | /** |
WiredHome | 44:71f09e4255f4 | 338 | * Search a haystack of name:value pairs for the needle. |
WiredHome | 44:71f09e4255f4 | 339 | * |
WiredHome | 44:71f09e4255f4 | 340 | * This is a case-sensitive search. If it cannot find an alias, |
WiredHome | 44:71f09e4255f4 | 341 | * it returns the needle. |
WiredHome | 44:71f09e4255f4 | 342 | * |
WiredHome | 44:71f09e4255f4 | 343 | * This is used in the web server for conveniently mapping long filenames |
WiredHome | 44:71f09e4255f4 | 344 | * to short filenames if you are using the LocalFileSystem which only |
WiredHome | 44:71f09e4255f4 | 345 | * supports short filenames. |
WiredHome | 44:71f09e4255f4 | 346 | * |
WiredHome | 44:71f09e4255f4 | 347 | * @code |
WiredHome | 44:71f09e4255f4 | 348 | * char * ptr; |
WiredHome | 44:71f09e4255f4 | 349 | * namevalue list[] = { |
WiredHome | 44:71f09e4255f4 | 350 | * {"/local/longfilename.ext", "/local/short.ext"}, |
WiredHome | 44:71f09e4255f4 | 351 | * {"/local/verylongname2.ext", "/local/verylo~1.ext"}, |
WiredHome | 44:71f09e4255f4 | 352 | * {NULL, NULL} |
WiredHome | 44:71f09e4255f4 | 353 | * }; |
WiredHome | 44:71f09e4255f4 | 354 | * |
WiredHome | 44:71f09e4255f4 | 355 | * ptr = FindAlias(list, "/local/verylongname2.ext"); |
WiredHome | 44:71f09e4255f4 | 356 | * // ptr now references "/local/verylo~1.ext" |
WiredHome | 44:71f09e4255f4 | 357 | * @endcode |
WiredHome | 44:71f09e4255f4 | 358 | * |
WiredHome | 44:71f09e4255f4 | 359 | * @param[in] haystack is the NULL terminated namevalue pair list. |
WiredHome | 44:71f09e4255f4 | 360 | * @param[in] needle is a pointer to the name to find. |
WiredHome | 44:71f09e4255f4 | 361 | * @returns the alias (value) if the needle is found, otherwise |
WiredHome | 44:71f09e4255f4 | 362 | * returns the needle. |
WiredHome | 44:71f09e4255f4 | 363 | */ |
WiredHome | 44:71f09e4255f4 | 364 | const char * FindAlias(const namevalue * haystack, const char * needle); |
WiredHome | 44:71f09e4255f4 | 365 | |
WiredHome | 44:71f09e4255f4 | 366 | |
WiredHome | 44:71f09e4255f4 | 367 | /** |
WiredHome | 44:71f09e4255f4 | 368 | * Register a list of filename aliases to webroot. |
WiredHome | 44:71f09e4255f4 | 369 | * |
WiredHome | 44:71f09e4255f4 | 370 | * Some uses of this could be on the LocalFileSystem, which only supports |
WiredHome | 44:71f09e4255f4 | 371 | * an 8.3 naming convention. This API lets you register a list of |
WiredHome | 44:71f09e4255f4 | 372 | * name:value pairs, where the name is the long filename and the |
WiredHome | 44:71f09e4255f4 | 373 | * value is the corresponding short filename. |
WiredHome | 44:71f09e4255f4 | 374 | * |
WiredHome | 44:71f09e4255f4 | 375 | * @param[in] namevaluelist is a pointer to a NULL terminated long |
WiredHome | 44:71f09e4255f4 | 376 | * to short filename list. |
WiredHome | 44:71f09e4255f4 | 377 | */ |
WiredHome | 44:71f09e4255f4 | 378 | void RegisterFilenameAliasList(const namevalue * namevaluelist); |
WiredHome | 44:71f09e4255f4 | 379 | |
WiredHome | 24:062431453abb | 380 | /** |
WiredHome | 3:17928786bdb5 | 381 | * The process to call whenever there is free time, as this basically does |
WiredHome | 0:729320f63c5c | 382 | * all the work to monitor for connections and handle replies. |
WiredHome | 2:a29c32190037 | 383 | * |
WiredHome | 44:71f09e4255f4 | 384 | * Activate this API as often as you can, typically from the loop in main. |
WiredHome | 44:71f09e4255f4 | 385 | * |
WiredHome | 48:078adbe279ac | 386 | * @note This API will pause execution for the "blocking time" value configured |
WiredHome | 48:078adbe279ac | 387 | * in the constructor. |
WiredHome | 0:729320f63c5c | 388 | */ |
WiredHome | 2:a29c32190037 | 389 | void Poll(); |
WiredHome | 12:109bf1558300 | 390 | |
WiredHome | 0:729320f63c5c | 391 | /** |
WiredHome | 12:109bf1558300 | 392 | * Send typical header data, and some optional data back to the client. |
WiredHome | 3:17928786bdb5 | 393 | * |
WiredHome | 3:17928786bdb5 | 394 | * This forms and sends the typical header back to the client. It may also send |
WiredHome | 3:17928786bdb5 | 395 | * optional data (which must end with "\r\n"). It then sends the second newline |
WiredHome | 3:17928786bdb5 | 396 | * sequence that signals the end of the header. |
WiredHome | 0:729320f63c5c | 397 | * |
WiredHome | 44:71f09e4255f4 | 398 | * @code |
WiredHome | 44:71f09e4255f4 | 399 | * svr->header(200, "OK", "Content-Type: text/html\r\n"); |
WiredHome | 44:71f09e4255f4 | 400 | * ... |
WiredHome | 44:71f09e4255f4 | 401 | * svr->header(200, "OK", "Content-Type: text/html\r\n", "SpecialParam: 13\r\n"); |
WiredHome | 44:71f09e4255f4 | 402 | * svr->header("NextParam: 14\r\n"); |
WiredHome | 44:71f09e4255f4 | 403 | * svr->header(""); // sends the final \r\n to end the header |
WiredHome | 44:71f09e4255f4 | 404 | * @endcode |
WiredHome | 44:71f09e4255f4 | 405 | * |
WiredHome | 44:71f09e4255f4 | 406 | * @param[in] code is the optional return code; 200 = OK, if not provided then 404 = Not found is returned |
WiredHome | 44:71f09e4255f4 | 407 | * @param[in] code_text is the text to align with the code (e.g. 404, "Not Found") |
WiredHome | 44:71f09e4255f4 | 408 | * @param[in] content_type is a pointer to "Content-Type: text/html\r\n" (for example). The string |
WiredHome | 44:71f09e4255f4 | 409 | * must have a \r\n termination. If this parameter is NULL, no alternate is substituted. |
WiredHome | 44:71f09e4255f4 | 410 | * @param[in] optional_text is a pointer to any other text that is part of the header, which must |
WiredHome | 44:71f09e4255f4 | 411 | * have \r\n termination. It is permissible to string several header items together, |
WiredHome | 44:71f09e4255f4 | 412 | * each with the \r\n termination (which includes \r\n termination at the end). |
WiredHome | 44:71f09e4255f4 | 413 | * If this parameter is NULL, a standard template response will be sent consisting |
WiredHome | 44:71f09e4255f4 | 414 | * of "Max-age: 0\r\nServer: Smart_Server v0.2\r\nConnection: close\r\n\r\n" |
WiredHome | 49:cd391662f254 | 415 | * If this parameter is not NULL, the user must call header(""), or ensure that |
WiredHome | 44:71f09e4255f4 | 416 | * the termination double (\r\n\r\n) ends the optional_text. |
WiredHome | 0:729320f63c5c | 417 | */ |
WiredHome | 44:71f09e4255f4 | 418 | void header(HeaderCodes code = Not_Found, const char * code_text = "Not Found", const char * content_type = NULL, |
WiredHome | 37:0cb2774e2410 | 419 | const char * optional_text = NULL); |
WiredHome | 0:729320f63c5c | 420 | |
WiredHome | 0:729320f63c5c | 421 | /** |
WiredHome | 44:71f09e4255f4 | 422 | * Send a fragment of a header to the client. |
WiredHome | 44:71f09e4255f4 | 423 | * |
WiredHome | 49:cd391662f254 | 424 | * @code |
WiredHome | 49:cd391662f254 | 425 | * ... |
WiredHome | 49:cd391662f254 | 426 | * svr->header("NextParam: 14\r\n"); |
WiredHome | 49:cd391662f254 | 427 | * svr->header(""); // sends the final \r\n to end the header |
WiredHome | 49:cd391662f254 | 428 | * @endcode |
WiredHome | 49:cd391662f254 | 429 | * |
WiredHome | 44:71f09e4255f4 | 430 | * This API lets you send header information a fragment at a time. A fragment can be a single |
WiredHome | 44:71f09e4255f4 | 431 | * line of text, or it can be several strung together with \r\n. |
WiredHome | 44:71f09e4255f4 | 432 | * |
WiredHome | 44:71f09e4255f4 | 433 | * @param[in] partialheader is a pointer to \r\n terminated text. If partial is a pointer to NULL, |
WiredHome | 44:71f09e4255f4 | 434 | * then a terminating \r\n is sent, which ends the header record. |
WiredHome | 44:71f09e4255f4 | 435 | */ |
WiredHome | 44:71f09e4255f4 | 436 | void header(const char * partialheader); |
WiredHome | 44:71f09e4255f4 | 437 | |
WiredHome | 44:71f09e4255f4 | 438 | /** |
WiredHome | 0:729320f63c5c | 439 | * Send text to the client |
WiredHome | 0:729320f63c5c | 440 | * |
WiredHome | 3:17928786bdb5 | 441 | * This sends the specified text to the client. If the number of bytes is not set, |
WiredHome | 3:17928786bdb5 | 442 | * then it calculates the number of bytes as a string. For binary transfers, the |
WiredHome | 3:17928786bdb5 | 443 | * number of bytes to send is required for proper operation. |
WiredHome | 3:17928786bdb5 | 444 | * |
WiredHome | 44:71f09e4255f4 | 445 | * @param[in] msg is the text string to send |
WiredHome | 44:71f09e4255f4 | 446 | * @param[in] bytes is the number of bytes to send. If not set, then strlen is calculated. |
WiredHome | 0:729320f63c5c | 447 | */ |
WiredHome | 0:729320f63c5c | 448 | void send(const char * msg, int bytes = -1); |
WiredHome | 12:109bf1558300 | 449 | |
WiredHome | 0:729320f63c5c | 450 | /** |
WiredHome | 44:71f09e4255f4 | 451 | * Get the size of the file |
WiredHome | 44:71f09e4255f4 | 452 | * |
WiredHome | 44:71f09e4255f4 | 453 | * This returns the size of the file. If the specified file is not found, it returns zero. |
WiredHome | 44:71f09e4255f4 | 454 | * |
WiredHome | 44:71f09e4255f4 | 455 | * @param[in] filename is the file to read. |
WiredHome | 44:71f09e4255f4 | 456 | * @returns the size of the file, or zero if the file was not found/opened. |
WiredHome | 44:71f09e4255f4 | 457 | */ |
WiredHome | 44:71f09e4255f4 | 458 | uint32_t FileSize(const char * filename); |
WiredHome | 44:71f09e4255f4 | 459 | |
WiredHome | 44:71f09e4255f4 | 460 | /** |
WiredHome | 3:17928786bdb5 | 461 | * Send a referenced file to the client, including the header |
WiredHome | 3:17928786bdb5 | 462 | * |
WiredHome | 3:17928786bdb5 | 463 | * This sends a file from the filesystem to the client. It must be of a supported type |
WiredHome | 3:17928786bdb5 | 464 | * in order to properly create the header. |
WiredHome | 0:729320f63c5c | 465 | * |
WiredHome | 44:71f09e4255f4 | 466 | * @param[in] filename is the fully qualified path and filename |
WiredHome | 44:71f09e4255f4 | 467 | * @param[in] filetype is the header information (e.g. "Content-Type: application/pdf") |
WiredHome | 0:729320f63c5c | 468 | * @return true if it thinks it sent ok, false otherwise. |
WiredHome | 0:729320f63c5c | 469 | */ |
WiredHome | 0:729320f63c5c | 470 | bool SendFile(const char * filename, const char * filetype); |
WiredHome | 12:109bf1558300 | 471 | |
WiredHome | 12:109bf1558300 | 472 | /** |
WiredHome | 0:729320f63c5c | 473 | * register a handler for a specific URL. |
WiredHome | 0:729320f63c5c | 474 | * |
WiredHome | 3:17928786bdb5 | 475 | * This api lets you register a dynamic handler in the web server. This is |
WiredHome | 3:17928786bdb5 | 476 | * most useful for interactive web pages, rather than simply serving static |
WiredHome | 3:17928786bdb5 | 477 | * pages. |
WiredHome | 3:17928786bdb5 | 478 | * |
WiredHome | 3:17928786bdb5 | 479 | * @code |
WiredHome | 12:109bf1558300 | 480 | * |
WiredHome | 3:17928786bdb5 | 481 | * ... |
WiredHome | 44:71f09e4255f4 | 482 | * svr.RegisterHandler("/dyn1", SimpleDynamicPage); |
WiredHome | 3:17928786bdb5 | 483 | * ... |
WiredHome | 3:17928786bdb5 | 484 | * |
WiredHome | 46:eaa86d48be6f | 485 | * HTTPServer::CallBackResults SimpleDynamicPage(HTTPServer *svr, HTTPServer::CallBackType type, const char * path, |
WiredHome | 37:0cb2774e2410 | 486 | * const HTTPServer::namevalue *queryParams, int queryParamCount) { |
WiredHome | 3:17928786bdb5 | 487 | * char buf[100]; |
WiredHome | 46:eaa86d48be6f | 488 | * HTTPServer::CallBackResults ret = HTTPServer::ACCEPT_ERROR; |
WiredHome | 12:109bf1558300 | 489 | * |
WiredHome | 3:17928786bdb5 | 490 | * switch (type) { |
WiredHome | 3:17928786bdb5 | 491 | * case HTTPServer::SEND_PAGE: |
WiredHome | 46:eaa86d48be6f | 492 | * svr->header(HTTPServer::OK, "OK", "Content-Type: text/html\r\n"); |
WiredHome | 3:17928786bdb5 | 493 | * svr->send("<html><head><title>Dynamic Page</title></head>\r\n"); |
WiredHome | 3:17928786bdb5 | 494 | * svr->send("<body>\r\n"); |
WiredHome | 3:17928786bdb5 | 495 | * svr->send("This page was generated dynamically. Create your own name=value pairs on the URL " |
WiredHome | 3:17928786bdb5 | 496 | * "which uses the GET method.<br/>\r\n"); |
WiredHome | 13:8975d7928678 | 497 | * sprintf(buf, "%d parameters passed to {%s}:<br/>\r\n", queryParamCount, path); |
WiredHome | 3:17928786bdb5 | 498 | * svr->send(buf); |
WiredHome | 13:8975d7928678 | 499 | * for (int i=0; i<queryParamCount; i++) { |
WiredHome | 13:8975d7928678 | 500 | * sprintf(buf, "%d: %s = %s<br/>\r\n", i, queryParams[i].name, queryParams[i].value); |
WiredHome | 3:17928786bdb5 | 501 | * svr->send(buf); |
WiredHome | 3:17928786bdb5 | 502 | * } |
WiredHome | 3:17928786bdb5 | 503 | * svr->send("Stats:<br/>\r\n"); |
WiredHome | 3:17928786bdb5 | 504 | * sprintf(buf,"Free memory space: %d<br/>\r\n", Free()); |
WiredHome | 3:17928786bdb5 | 505 | * svr->send(buf); |
WiredHome | 3:17928786bdb5 | 506 | * sprintf(buf,"Max Header size: %d<br/>\r\n", svr->GetMaxHeaderSize()); |
WiredHome | 3:17928786bdb5 | 507 | * svr->send(buf); |
WiredHome | 3:17928786bdb5 | 508 | * svr->send("<br/><a href='/'>back to main</a></body></html>\r\n"); |
WiredHome | 46:eaa86d48be6f | 509 | * ret = HTTPServer::ACCEPT_COMPLETE; |
WiredHome | 3:17928786bdb5 | 510 | * break; |
WiredHome | 3:17928786bdb5 | 511 | * case HTTPServer::CONTENT_LENGTH_REQUEST: |
WiredHome | 46:eaa86d48be6f | 512 | * ret = HTTPServer::ACCEPT_COMPLETE; |
WiredHome | 3:17928786bdb5 | 513 | * break; |
WiredHome | 3:17928786bdb5 | 514 | * case HTTPServer::DATA_TRANSFER: |
WiredHome | 46:eaa86d48be6f | 515 | * ret = HTTPServer::ACCEPT_COMPLETE; |
WiredHome | 3:17928786bdb5 | 516 | * break; |
WiredHome | 3:17928786bdb5 | 517 | * default: |
WiredHome | 46:eaa86d48be6f | 518 | * ret = HTTPServer::ACCEPT_ERROR; |
WiredHome | 3:17928786bdb5 | 519 | * break; |
WiredHome | 3:17928786bdb5 | 520 | * } |
WiredHome | 46:eaa86d48be6f | 521 | * return ret; |
WiredHome | 3:17928786bdb5 | 522 | * } |
WiredHome | 3:17928786bdb5 | 523 | * @endcode |
WiredHome | 3:17928786bdb5 | 524 | * |
WiredHome | 44:71f09e4255f4 | 525 | * @param[in] path to register |
WiredHome | 44:71f09e4255f4 | 526 | * @param[in] callback of type Handler |
WiredHome | 0:729320f63c5c | 527 | * @return true if successfully registered |
WiredHome | 0:729320f63c5c | 528 | */ |
WiredHome | 0:729320f63c5c | 529 | bool RegisterHandler(const char * path, Handler callback); |
WiredHome | 12:109bf1558300 | 530 | |
WiredHome | 0:729320f63c5c | 531 | /** |
WiredHome | 16:6ebacf2946d8 | 532 | * determine if the named file is a supported type (htm, html, jpg, etc) |
WiredHome | 0:729320f63c5c | 533 | * |
WiredHome | 3:17928786bdb5 | 534 | * if you pass in a filename, it will attempt to extract the extension |
WiredHome | 3:17928786bdb5 | 535 | * and compare that to the list of supported file types. If it finds a |
WiredHome | 3:17928786bdb5 | 536 | * match, then it will return a pointer to the content-type string. |
WiredHome | 3:17928786bdb5 | 537 | * |
WiredHome | 3:17928786bdb5 | 538 | * @code |
WiredHome | 3:17928786bdb5 | 539 | * fType = GetSupportedType("mypix.jpg"); |
WiredHome | 3:17928786bdb5 | 540 | * if (fType) { |
WiredHome | 3:17928786bdb5 | 541 | * ... |
WiredHome | 3:17928786bdb5 | 542 | * @endcode |
WiredHome | 12:109bf1558300 | 543 | * |
WiredHome | 44:71f09e4255f4 | 544 | * @param[in] filename is the filename to test, based on the extension |
WiredHome | 0:729320f63c5c | 545 | * @return pointer to a Content-Type string if supported, or NULL if not. |
WiredHome | 0:729320f63c5c | 546 | */ |
WiredHome | 0:729320f63c5c | 547 | const char * GetSupportedType(const char * filename); |
WiredHome | 0:729320f63c5c | 548 | |
WiredHome | 0:729320f63c5c | 549 | /** |
WiredHome | 39:0427544a5c08 | 550 | * search the available query parameters for 'name' and if found, return the 'value' |
WiredHome | 0:729320f63c5c | 551 | * |
WiredHome | 12:109bf1558300 | 552 | * After the querystring is parsed, the server maintains an array of |
WiredHome | 3:17928786bdb5 | 553 | * name=value pairs. This Get function will search for the passed in name |
WiredHome | 3:17928786bdb5 | 554 | * and provide access to the value. |
WiredHome | 3:17928786bdb5 | 555 | * |
WiredHome | 3:17928786bdb5 | 556 | * @code |
WiredHome | 3:17928786bdb5 | 557 | * BusOut leds(LED1,LED2,LED3,LED4); |
WiredHome | 3:17928786bdb5 | 558 | * ... |
WiredHome | 3:17928786bdb5 | 559 | * leds = atoi(svr->GetParameter("leds")); |
WiredHome | 3:17928786bdb5 | 560 | * @endcode |
WiredHome | 3:17928786bdb5 | 561 | * |
WiredHome | 44:71f09e4255f4 | 562 | * @param[in] name is the name to search for |
WiredHome | 0:729320f63c5c | 563 | * @return pointer to the value, or NULL |
WiredHome | 0:729320f63c5c | 564 | */ |
WiredHome | 0:729320f63c5c | 565 | const char * GetParameter(const char * name); |
WiredHome | 0:729320f63c5c | 566 | |
WiredHome | 0:729320f63c5c | 567 | /** |
WiredHome | 39:0427544a5c08 | 568 | * get a pointer to a name-value pair based on the index. |
WiredHome | 39:0427544a5c08 | 569 | * |
WiredHome | 44:71f09e4255f4 | 570 | * @param[in] index is the item being referenced |
WiredHome | 39:0427544a5c08 | 571 | * @return pointer to the namevalue, or NULL |
WiredHome | 39:0427544a5c08 | 572 | */ |
WiredHome | 44:71f09e4255f4 | 573 | const namevalue * GetParameter(int index); |
WiredHome | 39:0427544a5c08 | 574 | |
WiredHome | 39:0427544a5c08 | 575 | /** |
WiredHome | 39:0427544a5c08 | 576 | * Get the count of query parameters from the active transaction. |
WiredHome | 39:0427544a5c08 | 577 | * |
WiredHome | 39:0427544a5c08 | 578 | * @returns count of parameters. |
WiredHome | 39:0427544a5c08 | 579 | */ |
WiredHome | 39:0427544a5c08 | 580 | int GetParameterCount(void) |
WiredHome | 39:0427544a5c08 | 581 | { |
WiredHome | 39:0427544a5c08 | 582 | return queryParamCount; |
WiredHome | 39:0427544a5c08 | 583 | }; |
WiredHome | 39:0427544a5c08 | 584 | |
WiredHome | 39:0427544a5c08 | 585 | /** |
WiredHome | 39:0427544a5c08 | 586 | * search the available post parameters for 'name' and if found, return the 'value' |
WiredHome | 39:0427544a5c08 | 587 | * |
WiredHome | 39:0427544a5c08 | 588 | * After the post parameter string is parsed, the server maintains an array of |
WiredHome | 39:0427544a5c08 | 589 | * name=value pairs. This Get function will search for the passed in name |
WiredHome | 39:0427544a5c08 | 590 | * and provide access to the value. |
WiredHome | 39:0427544a5c08 | 591 | * |
WiredHome | 39:0427544a5c08 | 592 | * @code |
WiredHome | 39:0427544a5c08 | 593 | * BusOut leds(LED1,LED2,LED3,LED4); |
WiredHome | 39:0427544a5c08 | 594 | * ... |
WiredHome | 39:0427544a5c08 | 595 | * leds = atoi(svr->GetPostParameter("leds")); |
WiredHome | 39:0427544a5c08 | 596 | * @endcode |
WiredHome | 39:0427544a5c08 | 597 | * |
WiredHome | 44:71f09e4255f4 | 598 | * @param[in] name is the name to search for |
WiredHome | 39:0427544a5c08 | 599 | * @return pointer to the value, or NULL |
WiredHome | 39:0427544a5c08 | 600 | */ |
WiredHome | 39:0427544a5c08 | 601 | const char * GetPostParameter(const char * name); |
WiredHome | 39:0427544a5c08 | 602 | |
WiredHome | 39:0427544a5c08 | 603 | /** |
WiredHome | 39:0427544a5c08 | 604 | * get a pointer to a post parameter name-value pair based on the index. |
WiredHome | 39:0427544a5c08 | 605 | * |
WiredHome | 44:71f09e4255f4 | 606 | * @param[in] index is the item being referenced |
WiredHome | 39:0427544a5c08 | 607 | * @return pointer to the namevalue, or NULL |
WiredHome | 39:0427544a5c08 | 608 | */ |
WiredHome | 39:0427544a5c08 | 609 | namevalue * GetPostParameter(int index); |
WiredHome | 39:0427544a5c08 | 610 | |
WiredHome | 39:0427544a5c08 | 611 | /** |
WiredHome | 39:0427544a5c08 | 612 | * Get the count of post parameters from the active transaction. |
WiredHome | 39:0427544a5c08 | 613 | * |
WiredHome | 39:0427544a5c08 | 614 | * @returns count of parameters. |
WiredHome | 39:0427544a5c08 | 615 | */ |
WiredHome | 39:0427544a5c08 | 616 | int GetPostParameterCount(void) |
WiredHome | 39:0427544a5c08 | 617 | { |
WiredHome | 39:0427544a5c08 | 618 | return postParamCount; |
WiredHome | 39:0427544a5c08 | 619 | }; |
WiredHome | 39:0427544a5c08 | 620 | |
WiredHome | 39:0427544a5c08 | 621 | /** |
WiredHome | 12:109bf1558300 | 622 | * Parse the text string into name=value parameters. |
WiredHome | 3:17928786bdb5 | 623 | * |
WiredHome | 12:109bf1558300 | 624 | * This will directly modify the referenced string. If there is a |
WiredHome | 3:17928786bdb5 | 625 | * #fragment_id on the end of the string, it will be removed. |
WiredHome | 0:729320f63c5c | 626 | * |
WiredHome | 44:71f09e4255f4 | 627 | * @param[in] qP is a pointer to a namevalue set |
WiredHome | 44:71f09e4255f4 | 628 | * @param[in] qpCount is a pointer to a counter of what is in the set |
WiredHome | 44:71f09e4255f4 | 629 | * @param[in] maxP is the maximum number of parameters for which space has been allocated. |
WiredHome | 44:71f09e4255f4 | 630 | * @param[in,out] pName is a pointer to the string. |
WiredHome | 37:0cb2774e2410 | 631 | * @returns The total number of items that have been parsed, |
WiredHome | 37:0cb2774e2410 | 632 | * which can include a count from a url query string. |
WiredHome | 0:729320f63c5c | 633 | */ |
WiredHome | 39:0427544a5c08 | 634 | int ParseParameters(namevalue * qP, int * qpCount, int maxP, char * pName); |
WiredHome | 12:109bf1558300 | 635 | |
WiredHome | 0:729320f63c5c | 636 | /** |
WiredHome | 16:6ebacf2946d8 | 637 | * Unescape string converts a coded string "in place" into a normal string. |
WiredHome | 3:17928786bdb5 | 638 | * |
WiredHome | 3:17928786bdb5 | 639 | * A query string will have a number of characters replaced for communication |
WiredHome | 3:17928786bdb5 | 640 | * which includes spaces, quotes, question marks and more. Most of them |
WiredHome | 12:109bf1558300 | 641 | * will be replaced with a %xx format, where xx is the hex code for the |
WiredHome | 3:17928786bdb5 | 642 | * character. Since the string will only get shorter when this happens |
WiredHome | 3:17928786bdb5 | 643 | * the operation is performed in place. |
WiredHome | 3:17928786bdb5 | 644 | * |
WiredHome | 0:729320f63c5c | 645 | * this "This%20is%20a%20question%3F%20and%20an%20answer." |
WiredHome | 12:109bf1558300 | 646 | * |
WiredHome | 0:729320f63c5c | 647 | * becomes "This is a question? and an answer." |
WiredHome | 3:17928786bdb5 | 648 | * |
WiredHome | 0:729320f63c5c | 649 | * @note '+' is another form of space, so is converted to a space before the %xx |
WiredHome | 0:729320f63c5c | 650 | * |
WiredHome | 44:71f09e4255f4 | 651 | * @param[in,out] encoded string to be converted |
WiredHome | 0:729320f63c5c | 652 | */ |
WiredHome | 0:729320f63c5c | 653 | void UnescapeString(char * encoded); |
WiredHome | 12:109bf1558300 | 654 | |
WiredHome | 12:109bf1558300 | 655 | /** |
WiredHome | 16:6ebacf2946d8 | 656 | * This is used to force a connection to close. |
WiredHome | 3:17928786bdb5 | 657 | * |
WiredHome | 44:71f09e4255f4 | 658 | * @note When WiFly is the interface, this switches the module into |
WiredHome | 44:71f09e4255f4 | 659 | * command mode, performs the close, and then switches it back to data mode. |
WiredHome | 44:71f09e4255f4 | 660 | * So, this is a time-expensive command. |
WiredHome | 7:99ad7a67f05e | 661 | * |
WiredHome | 7:99ad7a67f05e | 662 | * @returns true if successful |
WiredHome | 0:729320f63c5c | 663 | */ |
WiredHome | 7:99ad7a67f05e | 664 | bool close_connection(); |
WiredHome | 12:109bf1558300 | 665 | |
WiredHome | 3:17928786bdb5 | 666 | /** |
WiredHome | 16:6ebacf2946d8 | 667 | * Diagnostic to get the size of the largest header. |
WiredHome | 3:17928786bdb5 | 668 | * |
WiredHome | 12:109bf1558300 | 669 | * This is a diagnostic function, so you can resize the allocated |
WiredHome | 12:109bf1558300 | 670 | * buffer for your application. With proper sizing, more of the |
WiredHome | 3:17928786bdb5 | 671 | * system memory is available for your application. |
WiredHome | 3:17928786bdb5 | 672 | * |
WiredHome | 3:17928786bdb5 | 673 | * @code |
WiredHome | 3:17928786bdb5 | 674 | * sprintf(buf,"Max Header size: %d<br/>\r\n", svr->GetMaxHeaderSize()); |
WiredHome | 3:17928786bdb5 | 675 | * svr->send(buf); |
WiredHome | 3:17928786bdb5 | 676 | * @endcode |
WiredHome | 12:109bf1558300 | 677 | * |
WiredHome | 3:17928786bdb5 | 678 | * @returns size in bytes of the larger header measured. |
WiredHome | 3:17928786bdb5 | 679 | */ |
WiredHome | 3:17928786bdb5 | 680 | int GetMaxHeaderSize(); |
WiredHome | 3:17928786bdb5 | 681 | |
WiredHome | 13:8975d7928678 | 682 | /** |
WiredHome | 16:6ebacf2946d8 | 683 | * Get a value from the http header, if it exists. |
WiredHome | 13:8975d7928678 | 684 | * |
WiredHome | 48:078adbe279ac | 685 | * @param[in] hdr is the string to search for (e.g. "Content-Length") |
WiredHome | 48:078adbe279ac | 686 | * @returns pointer to the value associated with that header. |
WiredHome | 13:8975d7928678 | 687 | * @returns NULL if the header is not found. |
WiredHome | 13:8975d7928678 | 688 | */ |
WiredHome | 13:8975d7928678 | 689 | const char * GetHeaderValue(const char * hdr); |
WiredHome | 3:17928786bdb5 | 690 | |
WiredHome | 3:17928786bdb5 | 691 | /** |
WiredHome | 3:17928786bdb5 | 692 | * Performance parameter |
WiredHome | 3:17928786bdb5 | 693 | */ |
WiredHome | 3:17928786bdb5 | 694 | typedef struct SW_PERFPARAM { |
WiredHome | 3:17928786bdb5 | 695 | unsigned long long TotalTime_us; |
WiredHome | 3:17928786bdb5 | 696 | unsigned long Samples; |
WiredHome | 3:17928786bdb5 | 697 | unsigned long MaxTime_us; |
WiredHome | 3:17928786bdb5 | 698 | } SW_PerformanceParam; |
WiredHome | 12:109bf1558300 | 699 | |
WiredHome | 3:17928786bdb5 | 700 | /** |
WiredHome | 3:17928786bdb5 | 701 | * Performance metrics |
WiredHome | 3:17928786bdb5 | 702 | */ |
WiredHome | 3:17928786bdb5 | 703 | typedef struct SW_PERFDATA { |
WiredHome | 17:69ff00ce39f4 | 704 | SW_PerformanceParam ConnectionAccepted; |
WiredHome | 17:69ff00ce39f4 | 705 | SW_PerformanceParam HeaderParsed; |
WiredHome | 17:69ff00ce39f4 | 706 | SW_PerformanceParam ResponseSent; |
WiredHome | 17:69ff00ce39f4 | 707 | SW_PerformanceParam ConnectionClosed; |
WiredHome | 3:17928786bdb5 | 708 | //SW_PerformanceParam SendFile; |
WiredHome | 3:17928786bdb5 | 709 | } SW_PerformanceData; |
WiredHome | 12:109bf1558300 | 710 | |
WiredHome | 3:17928786bdb5 | 711 | /** |
WiredHome | 3:17928786bdb5 | 712 | * Get performance metrics from the web server. |
WiredHome | 3:17928786bdb5 | 713 | * |
WiredHome | 3:17928786bdb5 | 714 | * This is a diagnostic function, and gathers data on the internal |
WiredHome | 3:17928786bdb5 | 715 | * performance of the server, as it works various actions. |
WiredHome | 3:17928786bdb5 | 716 | * |
WiredHome | 44:71f09e4255f4 | 717 | * @param[in] p is a pointer to a SW_PerformanceData structure to be populated |
WiredHome | 3:17928786bdb5 | 718 | */ |
WiredHome | 3:17928786bdb5 | 719 | void GetPerformanceData(SW_PerformanceData * p); |
WiredHome | 12:109bf1558300 | 720 | |
WiredHome | 3:17928786bdb5 | 721 | /** |
WiredHome | 3:17928786bdb5 | 722 | * Reset performance metrics. |
WiredHome | 3:17928786bdb5 | 723 | */ |
WiredHome | 3:17928786bdb5 | 724 | void ResetPerformanceData(); |
WiredHome | 17:69ff00ce39f4 | 725 | |
WiredHome | 17:69ff00ce39f4 | 726 | /** |
WiredHome | 17:69ff00ce39f4 | 727 | * Get performance clock |
WiredHome | 17:69ff00ce39f4 | 728 | */ |
WiredHome | 17:69ff00ce39f4 | 729 | unsigned int GetPerformanceClock(); |
WiredHome | 12:109bf1558300 | 730 | |
WiredHome | 0:729320f63c5c | 731 | private: |
WiredHome | 0:729320f63c5c | 732 | char * webroot; |
WiredHome | 0:729320f63c5c | 733 | PC * pc; |
WiredHome | 0:729320f63c5c | 734 | TCPSocketServer * server; |
WiredHome | 0:729320f63c5c | 735 | TCPSocketConnection client; |
WiredHome | 0:729320f63c5c | 736 | char * rewriteWithDefaultFile(char * queryString); |
WiredHome | 0:729320f63c5c | 737 | char * rewritePrependWebroot(char * queryString); |
WiredHome | 13:8975d7928678 | 738 | |
WiredHome | 13:8975d7928678 | 739 | namevalue *queryParams; // Query Parameters from the URL this=that&sky=blue&... |
WiredHome | 13:8975d7928678 | 740 | int maxqueryParams; |
WiredHome | 13:8975d7928678 | 741 | int queryParamCount; |
WiredHome | 13:8975d7928678 | 742 | |
WiredHome | 39:0427544a5c08 | 743 | namevalue *postParams; // Same as Query params, but for post method |
WiredHome | 39:0427544a5c08 | 744 | int maxPostParams; |
WiredHome | 39:0427544a5c08 | 745 | int postParamCount; |
WiredHome | 39:0427544a5c08 | 746 | |
WiredHome | 13:8975d7928678 | 747 | namevalue *headerParams; // Header params Host: 192.168...\r\nConnection: keep-alive\r\n... |
WiredHome | 13:8975d7928678 | 748 | int maxheaderParams; |
WiredHome | 13:8975d7928678 | 749 | int headerParamCount; |
WiredHome | 13:8975d7928678 | 750 | |
WiredHome | 3:17928786bdb5 | 751 | int maxheaderbytes; |
WiredHome | 3:17928786bdb5 | 752 | char * headerbuffer; |
WiredHome | 3:17928786bdb5 | 753 | int headerbuffersize; |
WiredHome | 12:109bf1558300 | 754 | |
WiredHome | 10:9c8d2c6a3469 | 755 | Timer PerformanceTimer; |
WiredHome | 3:17928786bdb5 | 756 | /** |
WiredHome | 3:17928786bdb5 | 757 | * Records performance data |
WiredHome | 12:109bf1558300 | 758 | * |
WiredHome | 3:17928786bdb5 | 759 | * This will take a pointer to a SW_PerformanceParam, and it will |
WiredHome | 3:17928786bdb5 | 760 | * take the time when the performance measurement started. It locally |
WiredHome | 3:17928786bdb5 | 761 | * accesses the current time to measure the elapsed. |
WiredHome | 3:17928786bdb5 | 762 | * |
WiredHome | 48:078adbe279ac | 763 | * @param[in] param is the performance parameter to update |
WiredHome | 48:078adbe279ac | 764 | * @param[in] value is the reference time. |
WiredHome | 3:17928786bdb5 | 765 | * @returns the current time which may be used as the reference time |
WiredHome | 3:17928786bdb5 | 766 | * for further measurements. |
WiredHome | 3:17928786bdb5 | 767 | */ |
WiredHome | 16:6ebacf2946d8 | 768 | unsigned int RecordPerformanceData(SW_PerformanceParam * param, unsigned int value); |
WiredHome | 3:17928786bdb5 | 769 | SW_PerformanceData perfData; |
WiredHome | 12:109bf1558300 | 770 | |
WiredHome | 3:17928786bdb5 | 771 | typedef struct HANDLER { |
WiredHome | 0:729320f63c5c | 772 | char * path; |
WiredHome | 0:729320f63c5c | 773 | Handler callback; |
WiredHome | 0:729320f63c5c | 774 | } handler; |
WiredHome | 0:729320f63c5c | 775 | int maxdynamicpages; |
WiredHome | 0:729320f63c5c | 776 | handler *handlers; |
WiredHome | 0:729320f63c5c | 777 | int handlercount; |
WiredHome | 3:17928786bdb5 | 778 | |
WiredHome | 3:17928786bdb5 | 779 | char * queryType; |
WiredHome | 44:71f09e4255f4 | 780 | char * queryString; // the query string [and 'GET' data] passed on the URL (e.g. ?name1=value1&name2=value2...) |
WiredHome | 44:71f09e4255f4 | 781 | char * postQueryString; // the post data |
WiredHome | 44:71f09e4255f4 | 782 | const namevalue * filenameAliasList; // pointer to a filename alias list |
WiredHome | 44:71f09e4255f4 | 783 | |
WiredHome | 0:729320f63c5c | 784 | /** |
WiredHome | 8:262583f054f6 | 785 | * Extract the parameter from the record, by searching for the needle in the haystack. |
WiredHome | 8:262583f054f6 | 786 | * |
WiredHome | 8:262583f054f6 | 787 | * The parameter of interest follows the needle, and may be ' ' delimited |
WiredHome | 0:729320f63c5c | 788 | * Can damage haystack while processing it. |
WiredHome | 0:729320f63c5c | 789 | * |
WiredHome | 48:078adbe279ac | 790 | * @param[in] haystack is the record to search |
WiredHome | 48:078adbe279ac | 791 | * @param[in] needle is the text to search for, which precedes the text to return |
WiredHome | 48:078adbe279ac | 792 | * @param[out] string is the text following the needle |
WiredHome | 0:729320f63c5c | 793 | * @return true if it extracted something successfully |
WiredHome | 0:729320f63c5c | 794 | */ |
WiredHome | 48:078adbe279ac | 795 | bool Extract(char * haystack, char * needle, char ** string); |
WiredHome | 0:729320f63c5c | 796 | |
WiredHome | 3:17928786bdb5 | 797 | void SendResponse(); |
WiredHome | 29:00116fc9da74 | 798 | HTTPServer::CallBackResults ParseHeader(char * bPtr); |
WiredHome | 3:17928786bdb5 | 799 | bool CheckDynamicHandlers(); |
WiredHome | 3:17928786bdb5 | 800 | |
WiredHome | 0:729320f63c5c | 801 | int HexCharToInt(char c); |
WiredHome | 0:729320f63c5c | 802 | char HexPairToChar(char * p); |
WiredHome | 29:00116fc9da74 | 803 | |
WiredHome | 29:00116fc9da74 | 804 | #ifdef DEBUG |
WiredHome | 29:00116fc9da74 | 805 | void * MyMalloc(int x, int y); |
WiredHome | 29:00116fc9da74 | 806 | char toP(void * x); |
WiredHome | 29:00116fc9da74 | 807 | #endif |
WiredHome | 0:729320f63c5c | 808 | }; |
WiredHome | 0:729320f63c5c | 809 | #endif //SW_HTTPSERVER_H |
WiredHome | 4:f34642902056 | 810 | |
WiredHome | 7:99ad7a67f05e | 811 |