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:
Thu Sep 26 23:47:50 2013 +0000
Revision:
21:660143f20b04
Parent:
20:786aa5749007
Child:
22:55974de690c1
Child:
24:062431453abb
Making one API deprecated - the one which fetches the IP of the connected client. This is based on the WiflyInterface, and makes that more compatible with EthernetInterface.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
WiredHome 0:729320f63c5c 1 //
WiredHome 2:a29c32190037 2 // @note Copyright © 2013 by Smartware Computing, all rights reserved.
WiredHome 0:729320f63c5c 3 // Individuals may use this application for evaluation or non-commercial
WiredHome 0:729320f63c5c 4 // purposes. Within this restriction, changes may be made to this application
WiredHome 0:729320f63c5c 5 // as long as this copyright notice is retained. The user shall make
WiredHome 0:729320f63c5c 6 // clear that their work is a derived work, and not the original.
WiredHome 0:729320f63c5c 7 // Users of this application and sources accept this application "as is" and
WiredHome 0:729320f63c5c 8 // shall hold harmless Smartware Computing, for any undesired results while
WiredHome 0:729320f63c5c 9 // using this application - whether real or imagined.
WiredHome 0:729320f63c5c 10 //
WiredHome 0:729320f63c5c 11 // author David Smart, Smartware Computing
WiredHome 0:729320f63c5c 12 //
WiredHome 0:729320f63c5c 13 #include "mbed.h"
WiredHome 0:729320f63c5c 14 #include "SW_HTTPServer.h"
WiredHome 0:729320f63c5c 15 #include "Utility.h"
WiredHome 0:729320f63c5c 16
WiredHome 19:7677fce798fa 17 //#define DEBUG
WiredHome 0:729320f63c5c 18
WiredHome 0:729320f63c5c 19 const char * DEFAULT_FILENAME = "index.htm";
WiredHome 0:729320f63c5c 20
WiredHome 8:262583f054f6 21 // Header information to always send (must be \r\n terminated)
WiredHome 17:69ff00ce39f4 22 const char hdr_httpver[] = "HTTP/1.0"; // Wifly may not be able to support HTTP/1.1 protocol
WiredHome 8:262583f054f6 23 const char hdr_age[] = "Max-age: 0\r\n"; // expires right away
WiredHome 8:262583f054f6 24 const char hdr_server[] = "Server: Smart_Server v0.1\r\n"; // Server
WiredHome 17:69ff00ce39f4 25 const char hdr_close[] = "Connection: close\r\n"; // tell the client the server closes the connection immediately
WiredHome 8:262583f054f6 26 const char nl[] = "\r\n"; // final \r\n for the termination of the header
WiredHome 0:729320f63c5c 27
WiredHome 14:19c5f6151319 28
WiredHome 0:729320f63c5c 29 static const struct {
WiredHome 0:729320f63c5c 30 char *ext;
WiredHome 0:729320f63c5c 31 char *filetype;
WiredHome 0:729320f63c5c 32 } extensions [] = {
WiredHome 3:17928786bdb5 33 {".gif", "Content-Type: image/gif\r\n" },
WiredHome 3:17928786bdb5 34 {".jpg", "Content-Type: image/jpeg\r\n" },
WiredHome 3:17928786bdb5 35 {".jpeg","Content-Type: image/jpeg\r\n" },
WiredHome 3:17928786bdb5 36 {".ico", "Content-Type: image/x-icon\r\n" },
WiredHome 3:17928786bdb5 37 {".png", "Content-Type: image/png\r\n" },
WiredHome 3:17928786bdb5 38 {".zip", "Content-Type: image/zip\r\n" },
WiredHome 3:17928786bdb5 39 {".gz", "Content-Type: image/gz\r\n" },
WiredHome 3:17928786bdb5 40 {".tar", "Content-Type: image/tar\r\n" },
WiredHome 3:17928786bdb5 41 {".txt", "Content-Type: plain/text\r\n" },
WiredHome 3:17928786bdb5 42 {".pdf", "Content-Type: application/pdf\r\n" },
WiredHome 3:17928786bdb5 43 {".htm", "Content-Type: text/html\r\n" },
WiredHome 3:17928786bdb5 44 {".html","Content-Type: text/html\r\n" },
WiredHome 0:729320f63c5c 45 {0,0}
WiredHome 0:729320f63c5c 46 };
WiredHome 0:729320f63c5c 47
WiredHome 8:262583f054f6 48 #ifdef DEBUG
WiredHome 12:109bf1558300 49 // This uses standard library dynamic memory management, but for an
WiredHome 9:2ea342765c9d 50 // embedded system there are alternates that may make better sense -
WiredHome 9:2ea342765c9d 51 // search the web for embedded system malloc alternates.
WiredHome 8:262583f054f6 52 static void * MyMalloc(int x, int y)
WiredHome 8:262583f054f6 53 {
WiredHome 8:262583f054f6 54 std::printf("[%04d] malloc(%d)\r\n", y, x);
WiredHome 8:262583f054f6 55 return malloc(x);
WiredHome 8:262583f054f6 56 }
WiredHome 11:17d84c41a7b3 57 static char toP(void * x)
WiredHome 11:17d84c41a7b3 58 {
WiredHome 11:17d84c41a7b3 59 char * c = (char *) x;
WiredHome 11:17d84c41a7b3 60 if (*c >= ' ' && *c < 0x7F)
WiredHome 11:17d84c41a7b3 61 return *c;
WiredHome 11:17d84c41a7b3 62 else
WiredHome 11:17d84c41a7b3 63 return '.';
WiredHome 11:17d84c41a7b3 64 }
WiredHome 8:262583f054f6 65 #define mymalloc(x) MyMalloc(x, __LINE__)
WiredHome 8:262583f054f6 66 #define myfree(x) \
WiredHome 11:17d84c41a7b3 67 pc->printf("[%4d] free(%02x %02x %02x %02x %02x ... %c%c%c%c%c)\r\n", __LINE__, \
WiredHome 11:17d84c41a7b3 68 *x, *(x+1), *(x+2), *(x+3), *(x+4), \
WiredHome 11:17d84c41a7b3 69 toP(x), toP(x+1), toP(x+2), toP(x+3), toP(x+4) ); \
WiredHome 8:262583f054f6 70 free(x);
WiredHome 8:262583f054f6 71 #else
WiredHome 8:262583f054f6 72 #define mymalloc(x) malloc(x)
WiredHome 8:262583f054f6 73 #define myfree(x) free(x)
WiredHome 8:262583f054f6 74 #endif
WiredHome 8:262583f054f6 75
WiredHome 3:17928786bdb5 76 HTTPServer::HTTPServer(
WiredHome 7:99ad7a67f05e 77 Wifly * _wf,
WiredHome 7:99ad7a67f05e 78 int port,
WiredHome 7:99ad7a67f05e 79 const char * _webroot,
WiredHome 13:8975d7928678 80 int maxheaderParams,
WiredHome 13:8975d7928678 81 int _maxqueryParams,
WiredHome 7:99ad7a67f05e 82 int _maxdynamicpages,
WiredHome 7:99ad7a67f05e 83 PC * _pc,
WiredHome 7:99ad7a67f05e 84 int _allocforheader,
WiredHome 3:17928786bdb5 85 int _allocforfile)
WiredHome 0:729320f63c5c 86 {
WiredHome 0:729320f63c5c 87 wifly = _wf;
WiredHome 0:729320f63c5c 88 webroot = (char *)malloc(strlen(_webroot)+1);
WiredHome 0:729320f63c5c 89 strcpy(webroot, _webroot);
WiredHome 13:8975d7928678 90 maxqueryParams = _maxqueryParams;
WiredHome 0:729320f63c5c 91 maxdynamicpages = _maxdynamicpages;
WiredHome 13:8975d7928678 92 headerParams = (namevalue *)malloc(maxheaderParams * sizeof(namevalue));
WiredHome 13:8975d7928678 93 queryParams = (namevalue *)malloc(maxqueryParams * sizeof(namevalue));
WiredHome 0:729320f63c5c 94 handlers = (handler *)malloc(maxdynamicpages * sizeof(handler));
WiredHome 3:17928786bdb5 95 headerbuffersize = _allocforheader;
WiredHome 3:17928786bdb5 96 headerbuffer = (char *)malloc(headerbuffersize);
WiredHome 0:729320f63c5c 97 pc = _pc;
WiredHome 3:17928786bdb5 98 queryType = NULL;
WiredHome 3:17928786bdb5 99 queryString = NULL;
WiredHome 3:17928786bdb5 100 postQueryString = NULL;
WiredHome 13:8975d7928678 101 queryParamCount = 0;
WiredHome 0:729320f63c5c 102 handlercount = 0;
WiredHome 3:17928786bdb5 103 maxheaderbytes = 0;
WiredHome 0:729320f63c5c 104 server = new TCPSocketServer();
WiredHome 0:729320f63c5c 105 server->bind(port);
WiredHome 0:729320f63c5c 106 server->listen();
WiredHome 16:6ebacf2946d8 107 server->set_blocking(false, 10);
WiredHome 3:17928786bdb5 108 ResetPerformanceData();
WiredHome 10:9c8d2c6a3469 109 PerformanceTimer.start();
WiredHome 0:729320f63c5c 110 }
WiredHome 0:729320f63c5c 111
WiredHome 0:729320f63c5c 112 HTTPServer::~HTTPServer()
WiredHome 0:729320f63c5c 113 {
WiredHome 8:262583f054f6 114 int i;
WiredHome 8:262583f054f6 115
WiredHome 8:262583f054f6 116 for (i=0; i<handlercount; i++)
WiredHome 8:262583f054f6 117 myfree(handlers[i].path);
WiredHome 8:262583f054f6 118 myfree(headerbuffer);
WiredHome 8:262583f054f6 119 myfree(handlers);
WiredHome 13:8975d7928678 120 myfree(queryParams);
WiredHome 8:262583f054f6 121 myfree(webroot);
WiredHome 0:729320f63c5c 122 webroot = NULL;
WiredHome 0:729320f63c5c 123 }
WiredHome 0:729320f63c5c 124
WiredHome 3:17928786bdb5 125 int HTTPServer::GetMaxHeaderSize()
WiredHome 3:17928786bdb5 126 {
WiredHome 3:17928786bdb5 127 return maxheaderbytes;
WiredHome 3:17928786bdb5 128 }
WiredHome 3:17928786bdb5 129
WiredHome 0:729320f63c5c 130 bool HTTPServer::RegisterHandler(const char * path, Handler callback)
WiredHome 0:729320f63c5c 131 {
WiredHome 0:729320f63c5c 132 if (handlercount < maxdynamicpages && path && callback) {
WiredHome 8:262583f054f6 133 handlers[handlercount].path = (char *)mymalloc(strlen(path)+1);
WiredHome 0:729320f63c5c 134 memcpy(handlers[handlercount].path, path, strlen(path)+1);
WiredHome 0:729320f63c5c 135 handlers[handlercount].callback = callback;
WiredHome 0:729320f63c5c 136 handlercount++;
WiredHome 0:729320f63c5c 137 return true;
WiredHome 0:729320f63c5c 138 } else {
WiredHome 0:729320f63c5c 139 return false;
WiredHome 0:729320f63c5c 140 }
WiredHome 0:729320f63c5c 141 }
WiredHome 0:729320f63c5c 142
WiredHome 2:a29c32190037 143 // Poll()
WiredHome 0:729320f63c5c 144 //
WiredHome 0:729320f63c5c 145 // *OPEN*GET /x=1 HTTP/1.1
WiredHome 0:729320f63c5c 146 // Host: 192.168.1.140
WiredHome 0:729320f63c5c 147 // Connection: keep-alive
WiredHome 0:729320f63c5c 148 // Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
WiredHome 0:729320f63c5c 149 // User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.94 Safari/537.36
WiredHome 0:729320f63c5c 150 // Accept-Encoding: gzip,deflate,sdch
WiredHome 0:729320f63c5c 151 // Accept-Language: en-US,en;q=0.8
WiredHome 0:729320f63c5c 152 //
WiredHome 2:a29c32190037 153 void HTTPServer::Poll()
WiredHome 0:729320f63c5c 154 {
WiredHome 3:17928786bdb5 155 typedef enum {
WiredHome 3:17928786bdb5 156 Idle, // waiting for a connection
WiredHome 3:17928786bdb5 157 Receiving, // receiving data
WiredHome 3:17928786bdb5 158 Sending, // send the response
WiredHome 7:99ad7a67f05e 159 WaitingToClose, // small timeout to close
WiredHome 7:99ad7a67f05e 160 Reset
WiredHome 3:17928786bdb5 161 } state;
WiredHome 0:729320f63c5c 162 static state op = Idle;
WiredHome 3:17928786bdb5 163 static char * bPtr = headerbuffer;
WiredHome 0:729320f63c5c 164 int n;
WiredHome 16:6ebacf2946d8 165 static unsigned int t_ref; // reference point for the PerformanceTimer
WiredHome 0:729320f63c5c 166
WiredHome 20:786aa5749007 167 #if defined(DEBUG)
WiredHome 8:262583f054f6 168 static state lastOp = Reset;
WiredHome 7:99ad7a67f05e 169 if (lastOp != op) {
WiredHome 9:2ea342765c9d 170 const char *states[] = {"Idle", "Receiving", "Sending", "WaitingToClose", "Reset"};
WiredHome 8:262583f054f6 171 pc->printf("Poll: %s\r\n", states[op]);
WiredHome 7:99ad7a67f05e 172 lastOp = op;
WiredHome 7:99ad7a67f05e 173 }
WiredHome 8:262583f054f6 174 #endif
WiredHome 0:729320f63c5c 175 switch(op) {
WiredHome 3:17928786bdb5 176 default: // not expected to arrive here
WiredHome 3:17928786bdb5 177 op = Idle;
WiredHome 3:17928786bdb5 178 break;
WiredHome 8:262583f054f6 179
WiredHome 3:17928786bdb5 180 case Idle:
WiredHome 10:9c8d2c6a3469 181 PerformanceTimer.reset();
WiredHome 17:69ff00ce39f4 182 t_ref = (unsigned int)PerformanceTimer.read_us();
WiredHome 3:17928786bdb5 183 bPtr = headerbuffer;
WiredHome 11:17d84c41a7b3 184 if (0 == server->accept(client)) {
WiredHome 3:17928786bdb5 185 op = Receiving;
WiredHome 17:69ff00ce39f4 186 t_ref = RecordPerformanceData(&perfData.ConnectionAccepted, t_ref);
WiredHome 8:262583f054f6 187 #ifdef DEBUG
WiredHome 17:69ff00ce39f4 188 pc->printf("Accepted at %u\r\n", (unsigned int)PerformanceTimer.read_us());
WiredHome 8:262583f054f6 189 #endif
WiredHome 3:17928786bdb5 190 }
WiredHome 0:729320f63c5c 191 break;
WiredHome 8:262583f054f6 192
WiredHome 3:17928786bdb5 193 case Receiving:
WiredHome 3:17928786bdb5 194 n = client.receive(bPtr, headerbuffersize - (bPtr - headerbuffer));
WiredHome 3:17928786bdb5 195 if (n < 0) {
WiredHome 9:2ea342765c9d 196 #ifdef DEBUG
WiredHome 8:262583f054f6 197 pc->printf("*** client.receive() => %d\r\n", n);
WiredHome 9:2ea342765c9d 198 #endif
WiredHome 3:17928786bdb5 199 } else if (n) {
WiredHome 3:17928786bdb5 200 bPtr[n] = '\0';
WiredHome 3:17928786bdb5 201 if (ParseHeader(headerbuffer)) {
WiredHome 3:17928786bdb5 202 op = Sending;
WiredHome 17:69ff00ce39f4 203 t_ref = RecordPerformanceData(&perfData.HeaderParsed, t_ref);
WiredHome 17:69ff00ce39f4 204 #ifdef DEBUG
WiredHome 17:69ff00ce39f4 205 pc->printf("Header Parsed at %u\r\n", (unsigned int)PerformanceTimer.read_us());
WiredHome 17:69ff00ce39f4 206 #endif
WiredHome 3:17928786bdb5 207 }
WiredHome 3:17928786bdb5 208 bPtr += n;
WiredHome 0:729320f63c5c 209 }
WiredHome 0:729320f63c5c 210 break;
WiredHome 8:262583f054f6 211
WiredHome 0:729320f63c5c 212 case Sending:
WiredHome 3:17928786bdb5 213 SendResponse();
WiredHome 0:729320f63c5c 214 op = WaitingToClose;
WiredHome 17:69ff00ce39f4 215 t_ref = RecordPerformanceData(&perfData.ResponseSent, t_ref);
WiredHome 17:69ff00ce39f4 216 #ifdef DEBUG
WiredHome 17:69ff00ce39f4 217 pc->printf("Response Sent at %u\r\n", (unsigned int)PerformanceTimer.read_us());
WiredHome 17:69ff00ce39f4 218 #endif
WiredHome 0:729320f63c5c 219 break;
WiredHome 9:2ea342765c9d 220
WiredHome 0:729320f63c5c 221 case WaitingToClose:
WiredHome 17:69ff00ce39f4 222 #ifdef DEBUG
WiredHome 17:69ff00ce39f4 223 pc->printf("Connection closed entry %u\r\n", (unsigned int)PerformanceTimer.read_us());
WiredHome 17:69ff00ce39f4 224 #endif
WiredHome 3:17928786bdb5 225 close_connection();
WiredHome 0:729320f63c5c 226 op = Idle;
WiredHome 17:69ff00ce39f4 227 RecordPerformanceData(&perfData.ConnectionClosed, t_ref);
WiredHome 17:69ff00ce39f4 228 #ifdef DEBUG
WiredHome 17:69ff00ce39f4 229 pc->printf("Connection closed exit %u\r\n", (unsigned int)PerformanceTimer.read_us());
WiredHome 17:69ff00ce39f4 230 #endif
WiredHome 0:729320f63c5c 231 break;
WiredHome 0:729320f63c5c 232 }
WiredHome 0:729320f63c5c 233 }
WiredHome 0:729320f63c5c 234
WiredHome 0:729320f63c5c 235
WiredHome 0:729320f63c5c 236 const char * HTTPServer::GetSupportedType(const char * filename)
WiredHome 0:729320f63c5c 237 {
WiredHome 0:729320f63c5c 238 int i;
WiredHome 0:729320f63c5c 239 int buflen = strlen(filename);
WiredHome 0:729320f63c5c 240 int extlen;
WiredHome 0:729320f63c5c 241
WiredHome 0:729320f63c5c 242 for (i=0; extensions[i].ext != 0; i++) {
WiredHome 0:729320f63c5c 243 extlen = strlen(extensions[i].ext);
WiredHome 0:729320f63c5c 244 if ( !strncmp(&filename[buflen-extlen], extensions[i].ext, extlen)) {
WiredHome 0:729320f63c5c 245 return extensions[i].filetype;
WiredHome 0:729320f63c5c 246 }
WiredHome 0:729320f63c5c 247 }
WiredHome 0:729320f63c5c 248 return NULL;
WiredHome 0:729320f63c5c 249 }
WiredHome 0:729320f63c5c 250
WiredHome 3:17928786bdb5 251
WiredHome 0:729320f63c5c 252 void HTTPServer::send(const char * msg, int bytes)
WiredHome 0:729320f63c5c 253 {
WiredHome 0:729320f63c5c 254 if (bytes == -1)
WiredHome 0:729320f63c5c 255 bytes = strlen(msg);
WiredHome 20:786aa5749007 256 client.send((char *)msg, bytes);
WiredHome 0:729320f63c5c 257 }
WiredHome 0:729320f63c5c 258
WiredHome 3:17928786bdb5 259
WiredHome 0:729320f63c5c 260 bool HTTPServer::SendFile(const char * filename, const char * filetype)
WiredHome 0:729320f63c5c 261 {
WiredHome 0:729320f63c5c 262 FILE * fp;
WiredHome 3:17928786bdb5 263
WiredHome 0:729320f63c5c 264 fp = fopen(filename,"rb");
WiredHome 0:729320f63c5c 265 if (fp) { // can open it
WiredHome 8:262583f054f6 266 char *fbuffer = (char *)mymalloc(FILESEND_BUF_SIZE);
WiredHome 0:729320f63c5c 267 int bytes;
WiredHome 0:729320f63c5c 268
WiredHome 3:17928786bdb5 269 if (fbuffer) {
WiredHome 3:17928786bdb5 270 header(200, "OK", filetype);
WiredHome 0:729320f63c5c 271 bytes = fread(fbuffer,sizeof(char),FILESEND_BUF_SIZE,fp);
WiredHome 3:17928786bdb5 272 while (bytes > 0) {
WiredHome 3:17928786bdb5 273 send(fbuffer, bytes);
WiredHome 3:17928786bdb5 274 bytes = fread(fbuffer,sizeof(char),FILESEND_BUF_SIZE,fp);
WiredHome 3:17928786bdb5 275 }
WiredHome 8:262583f054f6 276 myfree(fbuffer);
WiredHome 3:17928786bdb5 277 } else {
WiredHome 3:17928786bdb5 278 header(500, "Server Error", "Pragma: err - insufficient memory\r\n");
WiredHome 0:729320f63c5c 279 }
WiredHome 0:729320f63c5c 280 fclose(fp);
WiredHome 0:729320f63c5c 281 return true;
WiredHome 0:729320f63c5c 282 } else {
WiredHome 3:17928786bdb5 283 header(404, "Not Found", "Pragma: err - Can't open file\r\n");
WiredHome 0:729320f63c5c 284 return false;
WiredHome 0:729320f63c5c 285 }
WiredHome 0:729320f63c5c 286 }
WiredHome 0:729320f63c5c 287
WiredHome 0:729320f63c5c 288 int HTTPServer::HexCharToInt(char c)
WiredHome 0:729320f63c5c 289 {
WiredHome 0:729320f63c5c 290 if (c >= 'a' && c <= 'f')
WiredHome 0:729320f63c5c 291 return (c - 'a' + 10);
WiredHome 0:729320f63c5c 292 else if (c >= 'A' && c <= 'F')
WiredHome 0:729320f63c5c 293 return (c - 'A' + 10);
WiredHome 0:729320f63c5c 294 else if (c >= '0' && c <= '9')
WiredHome 0:729320f63c5c 295 return c - '0';
WiredHome 0:729320f63c5c 296 else
WiredHome 0:729320f63c5c 297 return 0;
WiredHome 0:729320f63c5c 298 }
WiredHome 0:729320f63c5c 299
WiredHome 0:729320f63c5c 300 char HTTPServer::HexPairToChar(char * p)
WiredHome 0:729320f63c5c 301 {
WiredHome 0:729320f63c5c 302 return 16 * HexCharToInt(*p) + HexCharToInt(*(p+1));
WiredHome 0:729320f63c5c 303 }
WiredHome 0:729320f63c5c 304
WiredHome 0:729320f63c5c 305 void HTTPServer::UnescapeString(char * encoded)
WiredHome 0:729320f63c5c 306 {
WiredHome 0:729320f63c5c 307 char *p;
WiredHome 0:729320f63c5c 308
WiredHome 0:729320f63c5c 309 // first convert '+' to ' '
WiredHome 0:729320f63c5c 310 p = strchr(encoded, '+');
WiredHome 0:729320f63c5c 311 while (p) {
WiredHome 0:729320f63c5c 312 *p = ' ';
WiredHome 0:729320f63c5c 313 p = strchr(encoded, '+');
WiredHome 0:729320f63c5c 314 }
WiredHome 0:729320f63c5c 315 // then convert hex '%xx' to char 'x'
WiredHome 0:729320f63c5c 316 p = strchr(encoded, '%');
WiredHome 0:729320f63c5c 317 while (p) {
WiredHome 0:729320f63c5c 318 if (strchr("0123456789ABCDEFabcdef", *(p+1))
WiredHome 0:729320f63c5c 319 && strchr("0123456789ABCDEFabcdef", *(p+2)) ) {
WiredHome 0:729320f63c5c 320 *p = HexPairToChar(p+1);
WiredHome 0:729320f63c5c 321 p++; // advance past the %
WiredHome 0:729320f63c5c 322 char * a = p;
WiredHome 0:729320f63c5c 323 char * b = p + 2;
WiredHome 0:729320f63c5c 324 do {
WiredHome 0:729320f63c5c 325 *a++ = *b++;
WiredHome 0:729320f63c5c 326 } while (*b);
WiredHome 0:729320f63c5c 327 *a = '\0';
WiredHome 0:729320f63c5c 328 }
WiredHome 0:729320f63c5c 329 p = strchr(p, '%');
WiredHome 0:729320f63c5c 330 }
WiredHome 0:729320f63c5c 331 }
WiredHome 0:729320f63c5c 332
WiredHome 0:729320f63c5c 333 const char * HTTPServer::GetParameter(const char * name)
WiredHome 0:729320f63c5c 334 {
WiredHome 13:8975d7928678 335 for (int i=0; i<queryParamCount; i++) {
WiredHome 13:8975d7928678 336 if (strcmp(queryParams[i].name, name) == 0) {
WiredHome 13:8975d7928678 337 return queryParams[i].value;
WiredHome 0:729320f63c5c 338 }
WiredHome 0:729320f63c5c 339 }
WiredHome 0:729320f63c5c 340 return NULL;
WiredHome 0:729320f63c5c 341 }
WiredHome 0:729320f63c5c 342
WiredHome 0:729320f63c5c 343 // this=that&who=what&more=stuff...
WiredHome 0:729320f63c5c 344 // ^ ^ ^
WiredHome 3:17928786bdb5 345 void HTTPServer::ParseParameters(char * pName)
WiredHome 0:729320f63c5c 346 {
WiredHome 0:729320f63c5c 347 char * pVal;
WiredHome 0:729320f63c5c 348 char * pNextName;
WiredHome 0:729320f63c5c 349
WiredHome 13:8975d7928678 350 // Parse queryParams
WiredHome 0:729320f63c5c 351 pVal = strchr(pName, '#'); // If there is a '#fragment_id', we can ignore it
WiredHome 0:729320f63c5c 352 if (pVal)
WiredHome 3:17928786bdb5 353 *pVal = '\0';
WiredHome 0:729320f63c5c 354 do {
WiredHome 13:8975d7928678 355 queryParams[queryParamCount].name = pName;
WiredHome 0:729320f63c5c 356 pVal = strchr(pName, '=');
WiredHome 0:729320f63c5c 357 pNextName = strchr(pName,'&');
WiredHome 0:729320f63c5c 358 if (pVal) {
WiredHome 0:729320f63c5c 359 if (pNextName == NULL || (pNextName && pNextName > pVal)) {
WiredHome 0:729320f63c5c 360 *pVal++ = '\0';
WiredHome 13:8975d7928678 361 queryParams[queryParamCount].value = pVal;
WiredHome 0:729320f63c5c 362 pName = pVal;
WiredHome 0:729320f63c5c 363 }
WiredHome 0:729320f63c5c 364 }
WiredHome 13:8975d7928678 365 queryParamCount++;
WiredHome 0:729320f63c5c 366 if (pNextName) {
WiredHome 0:729320f63c5c 367 pName = pNextName;
WiredHome 0:729320f63c5c 368 *pName++ = '\0';
WiredHome 0:729320f63c5c 369 } else {
WiredHome 0:729320f63c5c 370 pName = NULL;
WiredHome 0:729320f63c5c 371 }
WiredHome 13:8975d7928678 372 } while (pName && queryParamCount < maxqueryParams);
WiredHome 0:729320f63c5c 373 }
WiredHome 0:729320f63c5c 374
WiredHome 0:729320f63c5c 375
WiredHome 0:729320f63c5c 376 void HTTPServer::header(int code, const char * code_text, const char * content_type, const char * optional_text)
WiredHome 0:729320f63c5c 377 {
WiredHome 0:729320f63c5c 378 char http[100];
WiredHome 0:729320f63c5c 379
WiredHome 0:729320f63c5c 380 sprintf(http, "%s %i %s\r\n", hdr_httpver, code, code_text);
WiredHome 0:729320f63c5c 381 send(http);
WiredHome 0:729320f63c5c 382 send(hdr_age);
WiredHome 0:729320f63c5c 383 send(hdr_server);
WiredHome 0:729320f63c5c 384 if (content_type) {
WiredHome 0:729320f63c5c 385 send(content_type);
WiredHome 0:729320f63c5c 386 }
WiredHome 0:729320f63c5c 387 if (optional_text) {
WiredHome 0:729320f63c5c 388 send(optional_text);
WiredHome 0:729320f63c5c 389 }
WiredHome 0:729320f63c5c 390 send(hdr_close);
WiredHome 0:729320f63c5c 391 send(nl);
WiredHome 0:729320f63c5c 392 }
WiredHome 0:729320f63c5c 393
WiredHome 14:19c5f6151319 394
WiredHome 7:99ad7a67f05e 395 bool HTTPServer::close_connection()
WiredHome 0:729320f63c5c 396 {
WiredHome 7:99ad7a67f05e 397 bool res;
WiredHome 7:99ad7a67f05e 398
WiredHome 14:19c5f6151319 399 res = server->close();
WiredHome 7:99ad7a67f05e 400 #ifdef DEBUG
WiredHome 7:99ad7a67f05e 401 pc->printf("close connection returned %d\r\n", res);
WiredHome 0:729320f63c5c 402 #endif
WiredHome 7:99ad7a67f05e 403 return res;
WiredHome 0:729320f63c5c 404 }
WiredHome 0:729320f63c5c 405
WiredHome 14:19c5f6151319 406
WiredHome 0:729320f63c5c 407 bool HTTPServer::Extract(char * haystack, char * needle, char ** string)
WiredHome 0:729320f63c5c 408 {
WiredHome 0:729320f63c5c 409 bool ret = false; // assume failure until proven otherwise
WiredHome 0:729320f63c5c 410 char * qs = NULL;
WiredHome 0:729320f63c5c 411 char * eqs = NULL;
WiredHome 0:729320f63c5c 412 char * container = NULL;
WiredHome 0:729320f63c5c 413 char * get = strstr(haystack, needle); // what if not at the front?
WiredHome 0:729320f63c5c 414 if (get) {
WiredHome 0:729320f63c5c 415 // Seems to be a valid "...GET /QueryString HTTP/1.1"
WiredHome 8:262583f054f6 416 // or "...<needle>param..."
WiredHome 0:729320f63c5c 417 qs = get + strlen(needle); // in case the needle didn't have space delimiters
WiredHome 0:729320f63c5c 418 while (*qs == ' ')
WiredHome 0:729320f63c5c 419 qs++;
WiredHome 0:729320f63c5c 420 // /QueryString\0HTTP/1.1\0\0
WiredHome 0:729320f63c5c 421 if (*string) // recycle old string when working a new one
WiredHome 8:262583f054f6 422 myfree(*string);
WiredHome 8:262583f054f6 423 container = (char *)mymalloc(strlen(qs));
WiredHome 0:729320f63c5c 424 if (container) {
WiredHome 0:729320f63c5c 425 strcpy(container, qs);
WiredHome 0:729320f63c5c 426 eqs = strchr(container, ' ');
WiredHome 0:729320f63c5c 427 if (eqs)
WiredHome 0:729320f63c5c 428 *eqs = '\0';
WiredHome 0:729320f63c5c 429 *string = container;
WiredHome 8:262583f054f6 430 #ifdef DEBUG
WiredHome 8:262583f054f6 431 pc->printf("Extract(%s) = %s\r\n", needle, container);
WiredHome 8:262583f054f6 432 #endif
WiredHome 0:729320f63c5c 433 ret = true;
WiredHome 0:729320f63c5c 434 } else {
WiredHome 0:729320f63c5c 435 *string = NULL; // something bad happened... no memory
WiredHome 0:729320f63c5c 436 }
WiredHome 0:729320f63c5c 437 }
WiredHome 0:729320f63c5c 438 return ret;
WiredHome 0:729320f63c5c 439 }
WiredHome 0:729320f63c5c 440
WiredHome 14:19c5f6151319 441
WiredHome 0:729320f63c5c 442 char * HTTPServer::rewriteWithDefaultFile(char * queryString)
WiredHome 0:729320f63c5c 443 {
WiredHome 8:262583f054f6 444 char * temp = (char *)mymalloc(strlen(queryString) + strlen(DEFAULT_FILENAME) + 1);
WiredHome 0:729320f63c5c 445
WiredHome 0:729320f63c5c 446 if (temp) {
WiredHome 0:729320f63c5c 447 *temp = '\0';
WiredHome 0:729320f63c5c 448 strcpy(temp, queryString);
WiredHome 0:729320f63c5c 449 strcat(temp, DEFAULT_FILENAME);
WiredHome 8:262583f054f6 450 myfree(queryString);
WiredHome 0:729320f63c5c 451 return temp;
WiredHome 0:729320f63c5c 452 } else {
WiredHome 0:729320f63c5c 453 return queryString;
WiredHome 0:729320f63c5c 454 }
WiredHome 0:729320f63c5c 455 }
WiredHome 0:729320f63c5c 456
WiredHome 14:19c5f6151319 457
WiredHome 0:729320f63c5c 458 char * HTTPServer::rewritePrependWebroot(char * queryString)
WiredHome 0:729320f63c5c 459 {
WiredHome 8:262583f054f6 460 char * temp = (char *)mymalloc(strlen(webroot) + strlen(queryString) + 1);
WiredHome 0:729320f63c5c 461
WiredHome 0:729320f63c5c 462 if (temp) {
WiredHome 0:729320f63c5c 463 *temp = '\0';
WiredHome 0:729320f63c5c 464 strcpy(temp, webroot);
WiredHome 0:729320f63c5c 465 if (temp[strlen(temp)-1] == '/' && *queryString == '/')
WiredHome 0:729320f63c5c 466 temp[strlen(temp)-1] = '\0';
WiredHome 0:729320f63c5c 467 strcat(temp, queryString);
WiredHome 8:262583f054f6 468 myfree(queryString);
WiredHome 0:729320f63c5c 469 return temp;
WiredHome 0:729320f63c5c 470 } else {
WiredHome 0:729320f63c5c 471 return queryString;
WiredHome 0:729320f63c5c 472 }
WiredHome 0:729320f63c5c 473 }
WiredHome 0:729320f63c5c 474
WiredHome 14:19c5f6151319 475
WiredHome 3:17928786bdb5 476 bool HTTPServer::CheckDynamicHandlers()
WiredHome 3:17928786bdb5 477 {
WiredHome 3:17928786bdb5 478 bool regHandled = false;
WiredHome 0:729320f63c5c 479
WiredHome 3:17928786bdb5 480 // If this queryString is in the list of registered handlers, call that
WiredHome 3:17928786bdb5 481 for (int i=0; i<handlercount; i++) {
WiredHome 3:17928786bdb5 482 if (strcmp(handlers[i].path, queryString) == 0) {
WiredHome 13:8975d7928678 483 (*handlers[i].callback)(this, SEND_PAGE, queryString, queryParams, queryParamCount);
WiredHome 3:17928786bdb5 484 regHandled = true;
WiredHome 3:17928786bdb5 485 break; // we only execute the first one
WiredHome 3:17928786bdb5 486 }
WiredHome 3:17928786bdb5 487 }
WiredHome 3:17928786bdb5 488 return regHandled;
WiredHome 3:17928786bdb5 489 }
WiredHome 3:17928786bdb5 490
WiredHome 14:19c5f6151319 491
WiredHome 3:17928786bdb5 492 void HTTPServer::SendResponse()
WiredHome 3:17928786bdb5 493 {
WiredHome 8:262583f054f6 494 #ifdef DEBUG
WiredHome 17:69ff00ce39f4 495 pc->printf("SendResponse(%s) at %u\r\n", queryType, (unsigned int)PerformanceTimer.read_us());
WiredHome 8:262583f054f6 496 #endif
WiredHome 3:17928786bdb5 497 if (strcmp(queryType, "GET") == 0 || strcmp(queryType, "POST") == 0) {
WiredHome 3:17928786bdb5 498 if (!(queryString[0] == '.' && queryString[1] == '.')) {
WiredHome 3:17928786bdb5 499 const char * fType;
WiredHome 3:17928786bdb5 500
WiredHome 3:17928786bdb5 501 if (!CheckDynamicHandlers()) {
WiredHome 3:17928786bdb5 502 // Otherwise, this queryString must be trying to reference a static file
WiredHome 3:17928786bdb5 503 if (queryString[strlen(queryString)-1] == '/') {
WiredHome 3:17928786bdb5 504 queryString = rewriteWithDefaultFile(queryString);
WiredHome 3:17928786bdb5 505 }
WiredHome 3:17928786bdb5 506 // see if we support this file type
WiredHome 3:17928786bdb5 507 fType = GetSupportedType(queryString);
WiredHome 3:17928786bdb5 508 if (fType) {
WiredHome 3:17928786bdb5 509 queryString = rewritePrependWebroot(queryString);
WiredHome 3:17928786bdb5 510 SendFile(queryString, fType);
WiredHome 3:17928786bdb5 511 } else {
WiredHome 3:17928786bdb5 512 //pc->printf("Unsupported file type %s\r\n", queryString);
WiredHome 3:17928786bdb5 513 header(404, "Not Found", "Pragma: err - Unsupported type\r\n");
WiredHome 3:17928786bdb5 514 }
WiredHome 3:17928786bdb5 515 }
WiredHome 3:17928786bdb5 516 } else {
WiredHome 3:17928786bdb5 517 //pc->printf("Unsupported path %s\r\n", queryString);
WiredHome 3:17928786bdb5 518 header(400, "Bad Request", "Pragma: err - Unsupported path\r\n");
WiredHome 3:17928786bdb5 519 }
WiredHome 3:17928786bdb5 520 } else {
WiredHome 3:17928786bdb5 521 //pc->printf("Unsupported query type %s\r\n", queryType);
WiredHome 3:17928786bdb5 522 header(400, "Bad Request", "Pragma: err - Unsupported query type\r\n");
WiredHome 3:17928786bdb5 523 }
WiredHome 17:69ff00ce39f4 524 #ifdef DEBUG
WiredHome 17:69ff00ce39f4 525 pc->printf(" SendResponse complete at %u\r\n", (unsigned int)PerformanceTimer.read_us());
WiredHome 17:69ff00ce39f4 526 #endif
WiredHome 17:69ff00ce39f4 527
WiredHome 3:17928786bdb5 528 if (queryType) {
WiredHome 8:262583f054f6 529 myfree(queryType);
WiredHome 3:17928786bdb5 530 queryType = NULL;
WiredHome 3:17928786bdb5 531 }
WiredHome 3:17928786bdb5 532 if (queryString) {
WiredHome 8:262583f054f6 533 myfree(queryString);
WiredHome 3:17928786bdb5 534 queryString = NULL;
WiredHome 3:17928786bdb5 535 }
WiredHome 3:17928786bdb5 536 if (postQueryString) {
WiredHome 8:262583f054f6 537 myfree(postQueryString);
WiredHome 3:17928786bdb5 538 postQueryString = NULL;
WiredHome 3:17928786bdb5 539 }
WiredHome 17:69ff00ce39f4 540 #ifdef DEBUG
WiredHome 17:69ff00ce39f4 541 pc->printf(" SendResponse free at %u\r\n", (unsigned int)PerformanceTimer.read_us());
WiredHome 17:69ff00ce39f4 542 #endif
WiredHome 3:17928786bdb5 543 }
WiredHome 3:17928786bdb5 544
WiredHome 14:19c5f6151319 545
WiredHome 3:17928786bdb5 546 bool HTTPServer::ParseHeader(char * buffer)
WiredHome 3:17928786bdb5 547 {
WiredHome 3:17928786bdb5 548 char * dblCR;
WiredHome 3:17928786bdb5 549 bool advanceState = false;
WiredHome 3:17928786bdb5 550 int bytecount;
WiredHome 7:99ad7a67f05e 551
WiredHome 3:17928786bdb5 552 // Buffer could have partial, but the double \r\n is the key
WiredHome 13:8975d7928678 553 // GET /QueryString?this=that&sky=blue HTTP/1.1\r\n
WiredHome 8:262583f054f6 554 // GET /QueryString HTTP/1.1\r\nHost: 192.168.1.140\r\nCache-Con
WiredHome 8:262583f054f6 555 // GET /QueryString HTTP/1.1\r\nHost: 192.168.1.140\r\nCache-Control: max-age=0\r\n\r\n
WiredHome 3:17928786bdb5 556 dblCR = strstr(buffer,"\r\n\r\n");
WiredHome 3:17928786bdb5 557 if (dblCR) { // Have to scan from the beginning in case split on \r
WiredHome 8:262583f054f6 558 #ifdef DEBUG
WiredHome 8:262583f054f6 559 pc->printf("==\r\n%s==\r\n", buffer);
WiredHome 3:17928786bdb5 560 #endif
WiredHome 3:17928786bdb5 561 char * soRec = buffer; // start of the next record of text
WiredHome 13:8975d7928678 562 char * eoRec = strchr(soRec, '\n'); // search for end of the current record
WiredHome 7:99ad7a67f05e 563
WiredHome 13:8975d7928678 564 headerParamCount = 0;
WiredHome 3:17928786bdb5 565 bytecount = strlen(buffer);
WiredHome 3:17928786bdb5 566 if (bytecount > maxheaderbytes)
WiredHome 3:17928786bdb5 567 maxheaderbytes = bytecount;
WiredHome 3:17928786bdb5 568 while (eoRec) {
WiredHome 3:17928786bdb5 569 *eoRec = '\0';
WiredHome 3:17928786bdb5 570 if (*(eoRec-1) == '\r')
WiredHome 3:17928786bdb5 571 *(eoRec-1) = '\0';
WiredHome 8:262583f054f6 572 // Inspect the supported query types (GET, POST) and ignore (HEAD, PUT, OPTION, DELETE, TRACE, CONNECT]
WiredHome 8:262583f054f6 573 // This is very clumsy
WiredHome 8:262583f054f6 574 if (strstr(soRec, "GET ") == soRec) {
WiredHome 8:262583f054f6 575 Extract(soRec, "GET", &queryString);
WiredHome 8:262583f054f6 576 if (queryString) {
WiredHome 8:262583f054f6 577 queryType = (char *)mymalloc(strlen("GET")+1);
WiredHome 8:262583f054f6 578 strcpy(queryType, "GET");
WiredHome 8:262583f054f6 579 }
WiredHome 8:262583f054f6 580 } else if (strstr(soRec, "POST ") == soRec) {
WiredHome 8:262583f054f6 581 Extract(soRec, "POST", &queryString);
WiredHome 8:262583f054f6 582 if (queryString) {
WiredHome 8:262583f054f6 583 queryType = (char *)mymalloc(strlen("POST")+1);
WiredHome 8:262583f054f6 584 strcpy(queryType, "POST");
WiredHome 8:262583f054f6 585 }
WiredHome 10:9c8d2c6a3469 586 }
WiredHome 13:8975d7928678 587
WiredHome 13:8975d7928678 588 // if there is a ": " delimiter, we have a header item to parse into name,value pair
WiredHome 13:8975d7928678 589 // "Connection: keep-alive" becomes "Connection" "keep-alive"
WiredHome 13:8975d7928678 590 char *delim = strstr(soRec, ": ");
WiredHome 13:8975d7928678 591 char *chkSpace = strchr(soRec, ' '); // a field-name has no space ahead of the ":"
WiredHome 13:8975d7928678 592 if (delim
WiredHome 13:8975d7928678 593 && (!chkSpace || (chkSpace && delim < chkSpace))
WiredHome 13:8975d7928678 594 && headerParamCount < maxheaderParams) {
WiredHome 14:19c5f6151319 595 *delim++ = '\0'; // replace ": " with null
WiredHome 13:8975d7928678 596 *delim++ = '\0';
WiredHome 13:8975d7928678 597 headerParams[headerParamCount].name = soRec;
WiredHome 13:8975d7928678 598 headerParams[headerParamCount].value = delim;
WiredHome 13:8975d7928678 599 #ifdef DEBUG
WiredHome 13:8975d7928678 600 pc->printf("%d: headerParams[%s] = {%s}\r\n", headerParamCount,
WiredHome 13:8975d7928678 601 headerParams[headerParamCount].name, headerParams[headerParamCount].value);
WiredHome 13:8975d7928678 602 #endif
WiredHome 13:8975d7928678 603 headerParamCount++;
WiredHome 13:8975d7928678 604 }
WiredHome 3:17928786bdb5 605 soRec = eoRec + 1;
WiredHome 3:17928786bdb5 606 eoRec = strchr(soRec, '\n');
WiredHome 3:17928786bdb5 607 }
WiredHome 3:17928786bdb5 608 if (queryString) {
WiredHome 3:17928786bdb5 609 // We have enough to try to reply
WiredHome 12:109bf1558300 610 #ifdef DEBUG
WiredHome 8:262583f054f6 611 pc->printf("create reply queryType{%s}, queryString{%s}\r\n", "GET", queryString);
WiredHome 12:109bf1558300 612 #endif
WiredHome 13:8975d7928678 613 // parse queryParams - if any
WiredHome 3:17928786bdb5 614 // /file.htm?name1=value1&name2=value2...
WiredHome 3:17928786bdb5 615 // /file.htm?name1&name2=value2...
WiredHome 13:8975d7928678 616 queryParamCount = 0;
WiredHome 3:17928786bdb5 617 char * paramDelim = strchr(queryString, '?');
WiredHome 3:17928786bdb5 618 if (paramDelim) {
WiredHome 3:17928786bdb5 619 *paramDelim++ = '\0';
WiredHome 3:17928786bdb5 620 UnescapeString(paramDelim); // everything after the '?'
WiredHome 13:8975d7928678 621 ParseParameters(paramDelim); // pointing at the NULL, but there are queryParams beyond
WiredHome 3:17928786bdb5 622 }
WiredHome 3:17928786bdb5 623 } else {
WiredHome 10:9c8d2c6a3469 624 pc->printf("ERROR: queryString not found in (%s)\r\n", soRec);
WiredHome 3:17928786bdb5 625 }
WiredHome 3:17928786bdb5 626 advanceState = true;
WiredHome 3:17928786bdb5 627 buffer[0] = 0;
WiredHome 3:17928786bdb5 628
WiredHome 3:17928786bdb5 629 // This part parses the extra data on a POST method.
WiredHome 3:17928786bdb5 630 // Since there has to be a dynamic handler registered for this
WiredHome 3:17928786bdb5 631 // it would make sense to move some of this responsibility to
WiredHome 3:17928786bdb5 632 // that handler. It could then choose if it wanted to allocate
WiredHome 3:17928786bdb5 633 // the requested 'Content-Length' amount of memory.
WiredHome 3:17928786bdb5 634 // Should we check the 'Content-Type' to see if it is
WiredHome 3:17928786bdb5 635 // 'application/x-www-form-urlencoded'?
WiredHome 13:8975d7928678 636 int postBytes = atoi(GetHeaderValue("Content-Length"));
WiredHome 3:17928786bdb5 637 bool acceptIt = false;
WiredHome 3:17928786bdb5 638 if (strcmp(queryType, "POST") == 0 && postBytes > 0 ) {
WiredHome 3:17928786bdb5 639 if (postBytes) {
WiredHome 3:17928786bdb5 640 bool regHandled = false;
WiredHome 3:17928786bdb5 641 // Registered Dynamic Handler
WiredHome 3:17928786bdb5 642 // Callback and ask if they want to accept this data
WiredHome 3:17928786bdb5 643 for (int i=0; i<handlercount; i++) {
WiredHome 3:17928786bdb5 644 if (strcmp(handlers[i].path, queryString) == 0) {
WiredHome 13:8975d7928678 645 acceptIt = (*handlers[i].callback)(this, CONTENT_LENGTH_REQUEST, queryString, queryParams, queryParamCount);
WiredHome 3:17928786bdb5 646 regHandled = true;
WiredHome 3:17928786bdb5 647 break; // we only execute the first one
WiredHome 3:17928786bdb5 648 }
WiredHome 3:17928786bdb5 649 }
WiredHome 3:17928786bdb5 650
WiredHome 3:17928786bdb5 651 if (regHandled && acceptIt) {
WiredHome 3:17928786bdb5 652 // If so, we'll make space for it
WiredHome 8:262583f054f6 653 postQueryString = (char *)mymalloc(postBytes + 1);
WiredHome 3:17928786bdb5 654 if (postQueryString) {
WiredHome 3:17928786bdb5 655 char * offset;
WiredHome 3:17928786bdb5 656 int len;
WiredHome 3:17928786bdb5 657
WiredHome 3:17928786bdb5 658 dblCR += 4; // If we slurped up any of the POST,
WiredHome 3:17928786bdb5 659 while (*dblCR && *dblCR <= ' ')
WiredHome 3:17928786bdb5 660 dblCR++;
WiredHome 3:17928786bdb5 661 strcpy(postQueryString, dblCR); // copy that in and then get the rest
WiredHome 3:17928786bdb5 662 while ((len = strlen(postQueryString)) < postBytes) {
WiredHome 3:17928786bdb5 663 int n;
WiredHome 3:17928786bdb5 664 offset = postQueryString + len;
WiredHome 3:17928786bdb5 665 n = client.receive(offset, postBytes - len);
WiredHome 3:17928786bdb5 666 if (n >=0) {
WiredHome 3:17928786bdb5 667 offset[n] = '\0';
WiredHome 3:17928786bdb5 668 }
WiredHome 3:17928786bdb5 669 }
WiredHome 3:17928786bdb5 670 if (len >= 0) {
WiredHome 3:17928786bdb5 671 UnescapeString(postQueryString);
WiredHome 3:17928786bdb5 672 ParseParameters(postQueryString);
WiredHome 3:17928786bdb5 673 }
WiredHome 3:17928786bdb5 674 }
WiredHome 3:17928786bdb5 675 } else {
WiredHome 3:17928786bdb5 676 // Simply copy it to the bitbucket
WiredHome 3:17928786bdb5 677 int bytesToDump = postBytes;
WiredHome 8:262583f054f6 678 char * bitbucket = (char *)mymalloc(201);
WiredHome 3:17928786bdb5 679 dblCR += 4;
WiredHome 3:17928786bdb5 680 while (*dblCR && *dblCR <= ' ')
WiredHome 3:17928786bdb5 681 dblCR++;
WiredHome 3:17928786bdb5 682 bytesToDump -= strlen(dblCR);
WiredHome 3:17928786bdb5 683 while (bytesToDump > 0) {
WiredHome 3:17928786bdb5 684 int n = (bytesToDump > 200) ? 200 : bytesToDump;
WiredHome 3:17928786bdb5 685 n = client.receive(bitbucket, n);
WiredHome 3:17928786bdb5 686 bytesToDump -= n;
WiredHome 3:17928786bdb5 687 }
WiredHome 8:262583f054f6 688 myfree(bitbucket);
WiredHome 3:17928786bdb5 689 }
WiredHome 3:17928786bdb5 690 }
WiredHome 3:17928786bdb5 691 }
WiredHome 3:17928786bdb5 692 }
WiredHome 3:17928786bdb5 693 return advanceState;
WiredHome 3:17928786bdb5 694 }
WiredHome 3:17928786bdb5 695
WiredHome 14:19c5f6151319 696
WiredHome 13:8975d7928678 697 const char * HTTPServer::GetHeaderValue(const char * hdr)
WiredHome 13:8975d7928678 698 {
WiredHome 13:8975d7928678 699 int i;
WiredHome 13:8975d7928678 700
WiredHome 13:8975d7928678 701 for (i=0; i<headerParamCount; i++)
WiredHome 13:8975d7928678 702 {
WiredHome 13:8975d7928678 703 if (strcmp(hdr, headerParams[i].name) == 0)
WiredHome 13:8975d7928678 704 return headerParams[i].value;
WiredHome 13:8975d7928678 705 }
WiredHome 13:8975d7928678 706 return NULL;
WiredHome 13:8975d7928678 707 }
WiredHome 13:8975d7928678 708
WiredHome 12:109bf1558300 709
WiredHome 7:99ad7a67f05e 710 void HTTPServer::GetPerformanceData(SW_PerformanceData * p)
WiredHome 7:99ad7a67f05e 711 {
WiredHome 3:17928786bdb5 712 memcpy(p, &perfData, sizeof(perfData));
WiredHome 3:17928786bdb5 713 }
WiredHome 3:17928786bdb5 714
WiredHome 17:69ff00ce39f4 715 unsigned int HTTPServer::GetPerformanceClock()
WiredHome 17:69ff00ce39f4 716 {
WiredHome 17:69ff00ce39f4 717 return (unsigned int)PerformanceTimer.read_us();
WiredHome 17:69ff00ce39f4 718 }
WiredHome 14:19c5f6151319 719
WiredHome 16:6ebacf2946d8 720 unsigned int HTTPServer::RecordPerformanceData(SW_PerformanceParam * param, unsigned int refTime)
WiredHome 7:99ad7a67f05e 721 {
WiredHome 16:6ebacf2946d8 722 unsigned int t_now = (unsigned int)PerformanceTimer.read_us();
WiredHome 3:17928786bdb5 723 param->TotalTime_us += (t_now - refTime);
WiredHome 3:17928786bdb5 724 param->Samples++;
WiredHome 3:17928786bdb5 725 if ((t_now - refTime) > param->MaxTime_us)
WiredHome 3:17928786bdb5 726 param->MaxTime_us = (t_now - refTime);
WiredHome 3:17928786bdb5 727 return t_now;
WiredHome 3:17928786bdb5 728 }
WiredHome 3:17928786bdb5 729
WiredHome 14:19c5f6151319 730
WiredHome 7:99ad7a67f05e 731 void HTTPServer::ResetPerformanceData()
WiredHome 7:99ad7a67f05e 732 {
WiredHome 3:17928786bdb5 733 memset(&perfData, 0, sizeof(perfData));
WiredHome 3:17928786bdb5 734 }
WiredHome 3:17928786bdb5 735
WiredHome 4:f34642902056 736
WiredHome 21:660143f20b04 737 #ifdef INCLUDE_GETREMOTE
WiredHome 21:660143f20b04 738 bool HTTPServer::GetRemoteAddr(char * str, int strSize)
WiredHome 21:660143f20b04 739 {
WiredHome 21:660143f20b04 740 bool res = false;
WiredHome 21:660143f20b04 741 char *p;
WiredHome 21:660143f20b04 742
WiredHome 21:660143f20b04 743 if (strSize < 16) { // Can only guard it here w/o modifying Wifly class
WiredHome 21:660143f20b04 744 *str = '\0';
WiredHome 21:660143f20b04 745 return res;
WiredHome 21:660143f20b04 746 }
WiredHome 21:660143f20b04 747 res = wifly->sendCommand("show z\r", NULL, str, strSize);
WiredHome 21:660143f20b04 748 if (res) {
WiredHome 21:660143f20b04 749 p = strchr(str, '\n'); // truncate after the octets.
WiredHome 21:660143f20b04 750 if (p) *p = '\0';
WiredHome 21:660143f20b04 751 p = strchr(str, ' '); // or a space
WiredHome 21:660143f20b04 752 if (p) *p = '\0';
WiredHome 21:660143f20b04 753 p = strchr(str, '<'); // or a <
WiredHome 21:660143f20b04 754 if (p) *p = '\0';
WiredHome 21:660143f20b04 755 res = true;
WiredHome 21:660143f20b04 756 }
WiredHome 21:660143f20b04 757 wifly->exit();
WiredHome 21:660143f20b04 758 return res;
WiredHome 21:660143f20b04 759 }
WiredHome 21:660143f20b04 760 #endif