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:
Sat Sep 14 22:41:20 2013 +0000
Revision:
20:786aa5749007
Parent:
19:7677fce798fa
Child:
21:660143f20b04
Reduce dependency on Wifly toward more standardized socket interface.

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 5:c9b27e718054 376 bool HTTPServer::GetRemoteAddr(char * str, int strSize)
WiredHome 0:729320f63c5c 377 {
WiredHome 0:729320f63c5c 378 bool res = false;
WiredHome 0:729320f63c5c 379 char *p;
WiredHome 0:729320f63c5c 380
WiredHome 4:f34642902056 381 if (strSize < 16) { // Can only guard it here w/o modifying Wifly class
WiredHome 3:17928786bdb5 382 *str = '\0';
WiredHome 5:c9b27e718054 383 return res;
WiredHome 3:17928786bdb5 384 }
WiredHome 5:c9b27e718054 385 res = wifly->sendCommand("show z\r", NULL, str, strSize);
WiredHome 0:729320f63c5c 386 if (res) {
WiredHome 0:729320f63c5c 387 p = strchr(str, '\n'); // truncate after the octets.
WiredHome 0:729320f63c5c 388 if (p) *p = '\0';
WiredHome 0:729320f63c5c 389 p = strchr(str, ' '); // or a space
WiredHome 0:729320f63c5c 390 if (p) *p = '\0';
WiredHome 0:729320f63c5c 391 p = strchr(str, '<'); // or a <
WiredHome 0:729320f63c5c 392 if (p) *p = '\0';
WiredHome 5:c9b27e718054 393 res = true;
WiredHome 0:729320f63c5c 394 }
WiredHome 0:729320f63c5c 395 wifly->exit();
WiredHome 5:c9b27e718054 396 return res;
WiredHome 0:729320f63c5c 397 }
WiredHome 0:729320f63c5c 398
WiredHome 0:729320f63c5c 399
WiredHome 0:729320f63c5c 400 void HTTPServer::header(int code, const char * code_text, const char * content_type, const char * optional_text)
WiredHome 0:729320f63c5c 401 {
WiredHome 0:729320f63c5c 402 char http[100];
WiredHome 0:729320f63c5c 403
WiredHome 0:729320f63c5c 404 sprintf(http, "%s %i %s\r\n", hdr_httpver, code, code_text);
WiredHome 0:729320f63c5c 405 send(http);
WiredHome 0:729320f63c5c 406 send(hdr_age);
WiredHome 0:729320f63c5c 407 send(hdr_server);
WiredHome 0:729320f63c5c 408 if (content_type) {
WiredHome 0:729320f63c5c 409 send(content_type);
WiredHome 0:729320f63c5c 410 }
WiredHome 0:729320f63c5c 411 if (optional_text) {
WiredHome 0:729320f63c5c 412 send(optional_text);
WiredHome 0:729320f63c5c 413 }
WiredHome 0:729320f63c5c 414 send(hdr_close);
WiredHome 0:729320f63c5c 415 send(nl);
WiredHome 0:729320f63c5c 416 }
WiredHome 0:729320f63c5c 417
WiredHome 14:19c5f6151319 418
WiredHome 7:99ad7a67f05e 419 bool HTTPServer::close_connection()
WiredHome 0:729320f63c5c 420 {
WiredHome 7:99ad7a67f05e 421 bool res;
WiredHome 7:99ad7a67f05e 422
WiredHome 14:19c5f6151319 423 res = server->close();
WiredHome 7:99ad7a67f05e 424 #ifdef DEBUG
WiredHome 7:99ad7a67f05e 425 pc->printf("close connection returned %d\r\n", res);
WiredHome 0:729320f63c5c 426 #endif
WiredHome 7:99ad7a67f05e 427 return res;
WiredHome 0:729320f63c5c 428 }
WiredHome 0:729320f63c5c 429
WiredHome 14:19c5f6151319 430
WiredHome 0:729320f63c5c 431 bool HTTPServer::Extract(char * haystack, char * needle, char ** string)
WiredHome 0:729320f63c5c 432 {
WiredHome 0:729320f63c5c 433 bool ret = false; // assume failure until proven otherwise
WiredHome 0:729320f63c5c 434 char * qs = NULL;
WiredHome 0:729320f63c5c 435 char * eqs = NULL;
WiredHome 0:729320f63c5c 436 char * container = NULL;
WiredHome 0:729320f63c5c 437 char * get = strstr(haystack, needle); // what if not at the front?
WiredHome 0:729320f63c5c 438 if (get) {
WiredHome 0:729320f63c5c 439 // Seems to be a valid "...GET /QueryString HTTP/1.1"
WiredHome 8:262583f054f6 440 // or "...<needle>param..."
WiredHome 0:729320f63c5c 441 qs = get + strlen(needle); // in case the needle didn't have space delimiters
WiredHome 0:729320f63c5c 442 while (*qs == ' ')
WiredHome 0:729320f63c5c 443 qs++;
WiredHome 0:729320f63c5c 444 // /QueryString\0HTTP/1.1\0\0
WiredHome 0:729320f63c5c 445 if (*string) // recycle old string when working a new one
WiredHome 8:262583f054f6 446 myfree(*string);
WiredHome 8:262583f054f6 447 container = (char *)mymalloc(strlen(qs));
WiredHome 0:729320f63c5c 448 if (container) {
WiredHome 0:729320f63c5c 449 strcpy(container, qs);
WiredHome 0:729320f63c5c 450 eqs = strchr(container, ' ');
WiredHome 0:729320f63c5c 451 if (eqs)
WiredHome 0:729320f63c5c 452 *eqs = '\0';
WiredHome 0:729320f63c5c 453 *string = container;
WiredHome 8:262583f054f6 454 #ifdef DEBUG
WiredHome 8:262583f054f6 455 pc->printf("Extract(%s) = %s\r\n", needle, container);
WiredHome 8:262583f054f6 456 #endif
WiredHome 0:729320f63c5c 457 ret = true;
WiredHome 0:729320f63c5c 458 } else {
WiredHome 0:729320f63c5c 459 *string = NULL; // something bad happened... no memory
WiredHome 0:729320f63c5c 460 }
WiredHome 0:729320f63c5c 461 }
WiredHome 0:729320f63c5c 462 return ret;
WiredHome 0:729320f63c5c 463 }
WiredHome 0:729320f63c5c 464
WiredHome 14:19c5f6151319 465
WiredHome 0:729320f63c5c 466 char * HTTPServer::rewriteWithDefaultFile(char * queryString)
WiredHome 0:729320f63c5c 467 {
WiredHome 8:262583f054f6 468 char * temp = (char *)mymalloc(strlen(queryString) + strlen(DEFAULT_FILENAME) + 1);
WiredHome 0:729320f63c5c 469
WiredHome 0:729320f63c5c 470 if (temp) {
WiredHome 0:729320f63c5c 471 *temp = '\0';
WiredHome 0:729320f63c5c 472 strcpy(temp, queryString);
WiredHome 0:729320f63c5c 473 strcat(temp, DEFAULT_FILENAME);
WiredHome 8:262583f054f6 474 myfree(queryString);
WiredHome 0:729320f63c5c 475 return temp;
WiredHome 0:729320f63c5c 476 } else {
WiredHome 0:729320f63c5c 477 return queryString;
WiredHome 0:729320f63c5c 478 }
WiredHome 0:729320f63c5c 479 }
WiredHome 0:729320f63c5c 480
WiredHome 14:19c5f6151319 481
WiredHome 0:729320f63c5c 482 char * HTTPServer::rewritePrependWebroot(char * queryString)
WiredHome 0:729320f63c5c 483 {
WiredHome 8:262583f054f6 484 char * temp = (char *)mymalloc(strlen(webroot) + strlen(queryString) + 1);
WiredHome 0:729320f63c5c 485
WiredHome 0:729320f63c5c 486 if (temp) {
WiredHome 0:729320f63c5c 487 *temp = '\0';
WiredHome 0:729320f63c5c 488 strcpy(temp, webroot);
WiredHome 0:729320f63c5c 489 if (temp[strlen(temp)-1] == '/' && *queryString == '/')
WiredHome 0:729320f63c5c 490 temp[strlen(temp)-1] = '\0';
WiredHome 0:729320f63c5c 491 strcat(temp, queryString);
WiredHome 8:262583f054f6 492 myfree(queryString);
WiredHome 0:729320f63c5c 493 return temp;
WiredHome 0:729320f63c5c 494 } else {
WiredHome 0:729320f63c5c 495 return queryString;
WiredHome 0:729320f63c5c 496 }
WiredHome 0:729320f63c5c 497 }
WiredHome 0:729320f63c5c 498
WiredHome 14:19c5f6151319 499
WiredHome 3:17928786bdb5 500 bool HTTPServer::CheckDynamicHandlers()
WiredHome 3:17928786bdb5 501 {
WiredHome 3:17928786bdb5 502 bool regHandled = false;
WiredHome 0:729320f63c5c 503
WiredHome 3:17928786bdb5 504 // If this queryString is in the list of registered handlers, call that
WiredHome 3:17928786bdb5 505 for (int i=0; i<handlercount; i++) {
WiredHome 3:17928786bdb5 506 if (strcmp(handlers[i].path, queryString) == 0) {
WiredHome 13:8975d7928678 507 (*handlers[i].callback)(this, SEND_PAGE, queryString, queryParams, queryParamCount);
WiredHome 3:17928786bdb5 508 regHandled = true;
WiredHome 3:17928786bdb5 509 break; // we only execute the first one
WiredHome 3:17928786bdb5 510 }
WiredHome 3:17928786bdb5 511 }
WiredHome 3:17928786bdb5 512 return regHandled;
WiredHome 3:17928786bdb5 513 }
WiredHome 3:17928786bdb5 514
WiredHome 14:19c5f6151319 515
WiredHome 3:17928786bdb5 516 void HTTPServer::SendResponse()
WiredHome 3:17928786bdb5 517 {
WiredHome 8:262583f054f6 518 #ifdef DEBUG
WiredHome 17:69ff00ce39f4 519 pc->printf("SendResponse(%s) at %u\r\n", queryType, (unsigned int)PerformanceTimer.read_us());
WiredHome 8:262583f054f6 520 #endif
WiredHome 3:17928786bdb5 521 if (strcmp(queryType, "GET") == 0 || strcmp(queryType, "POST") == 0) {
WiredHome 3:17928786bdb5 522 if (!(queryString[0] == '.' && queryString[1] == '.')) {
WiredHome 3:17928786bdb5 523 const char * fType;
WiredHome 3:17928786bdb5 524
WiredHome 3:17928786bdb5 525 if (!CheckDynamicHandlers()) {
WiredHome 3:17928786bdb5 526 // Otherwise, this queryString must be trying to reference a static file
WiredHome 3:17928786bdb5 527 if (queryString[strlen(queryString)-1] == '/') {
WiredHome 3:17928786bdb5 528 queryString = rewriteWithDefaultFile(queryString);
WiredHome 3:17928786bdb5 529 }
WiredHome 3:17928786bdb5 530 // see if we support this file type
WiredHome 3:17928786bdb5 531 fType = GetSupportedType(queryString);
WiredHome 3:17928786bdb5 532 if (fType) {
WiredHome 3:17928786bdb5 533 queryString = rewritePrependWebroot(queryString);
WiredHome 3:17928786bdb5 534 SendFile(queryString, fType);
WiredHome 3:17928786bdb5 535 } else {
WiredHome 3:17928786bdb5 536 //pc->printf("Unsupported file type %s\r\n", queryString);
WiredHome 3:17928786bdb5 537 header(404, "Not Found", "Pragma: err - Unsupported type\r\n");
WiredHome 3:17928786bdb5 538 }
WiredHome 3:17928786bdb5 539 }
WiredHome 3:17928786bdb5 540 } else {
WiredHome 3:17928786bdb5 541 //pc->printf("Unsupported path %s\r\n", queryString);
WiredHome 3:17928786bdb5 542 header(400, "Bad Request", "Pragma: err - Unsupported path\r\n");
WiredHome 3:17928786bdb5 543 }
WiredHome 3:17928786bdb5 544 } else {
WiredHome 3:17928786bdb5 545 //pc->printf("Unsupported query type %s\r\n", queryType);
WiredHome 3:17928786bdb5 546 header(400, "Bad Request", "Pragma: err - Unsupported query type\r\n");
WiredHome 3:17928786bdb5 547 }
WiredHome 17:69ff00ce39f4 548 #ifdef DEBUG
WiredHome 17:69ff00ce39f4 549 pc->printf(" SendResponse complete at %u\r\n", (unsigned int)PerformanceTimer.read_us());
WiredHome 17:69ff00ce39f4 550 #endif
WiredHome 17:69ff00ce39f4 551
WiredHome 3:17928786bdb5 552 if (queryType) {
WiredHome 8:262583f054f6 553 myfree(queryType);
WiredHome 3:17928786bdb5 554 queryType = NULL;
WiredHome 3:17928786bdb5 555 }
WiredHome 3:17928786bdb5 556 if (queryString) {
WiredHome 8:262583f054f6 557 myfree(queryString);
WiredHome 3:17928786bdb5 558 queryString = NULL;
WiredHome 3:17928786bdb5 559 }
WiredHome 3:17928786bdb5 560 if (postQueryString) {
WiredHome 8:262583f054f6 561 myfree(postQueryString);
WiredHome 3:17928786bdb5 562 postQueryString = NULL;
WiredHome 3:17928786bdb5 563 }
WiredHome 17:69ff00ce39f4 564 #ifdef DEBUG
WiredHome 17:69ff00ce39f4 565 pc->printf(" SendResponse free at %u\r\n", (unsigned int)PerformanceTimer.read_us());
WiredHome 17:69ff00ce39f4 566 #endif
WiredHome 3:17928786bdb5 567 }
WiredHome 3:17928786bdb5 568
WiredHome 14:19c5f6151319 569
WiredHome 3:17928786bdb5 570 bool HTTPServer::ParseHeader(char * buffer)
WiredHome 3:17928786bdb5 571 {
WiredHome 3:17928786bdb5 572 char * dblCR;
WiredHome 3:17928786bdb5 573 bool advanceState = false;
WiredHome 3:17928786bdb5 574 int bytecount;
WiredHome 7:99ad7a67f05e 575
WiredHome 3:17928786bdb5 576 // Buffer could have partial, but the double \r\n is the key
WiredHome 13:8975d7928678 577 // GET /QueryString?this=that&sky=blue HTTP/1.1\r\n
WiredHome 8:262583f054f6 578 // GET /QueryString HTTP/1.1\r\nHost: 192.168.1.140\r\nCache-Con
WiredHome 8:262583f054f6 579 // GET /QueryString HTTP/1.1\r\nHost: 192.168.1.140\r\nCache-Control: max-age=0\r\n\r\n
WiredHome 3:17928786bdb5 580 dblCR = strstr(buffer,"\r\n\r\n");
WiredHome 3:17928786bdb5 581 if (dblCR) { // Have to scan from the beginning in case split on \r
WiredHome 8:262583f054f6 582 #ifdef DEBUG
WiredHome 8:262583f054f6 583 pc->printf("==\r\n%s==\r\n", buffer);
WiredHome 3:17928786bdb5 584 #endif
WiredHome 3:17928786bdb5 585 char * soRec = buffer; // start of the next record of text
WiredHome 13:8975d7928678 586 char * eoRec = strchr(soRec, '\n'); // search for end of the current record
WiredHome 7:99ad7a67f05e 587
WiredHome 13:8975d7928678 588 headerParamCount = 0;
WiredHome 3:17928786bdb5 589 bytecount = strlen(buffer);
WiredHome 3:17928786bdb5 590 if (bytecount > maxheaderbytes)
WiredHome 3:17928786bdb5 591 maxheaderbytes = bytecount;
WiredHome 3:17928786bdb5 592 while (eoRec) {
WiredHome 3:17928786bdb5 593 *eoRec = '\0';
WiredHome 3:17928786bdb5 594 if (*(eoRec-1) == '\r')
WiredHome 3:17928786bdb5 595 *(eoRec-1) = '\0';
WiredHome 8:262583f054f6 596 // Inspect the supported query types (GET, POST) and ignore (HEAD, PUT, OPTION, DELETE, TRACE, CONNECT]
WiredHome 8:262583f054f6 597 // This is very clumsy
WiredHome 8:262583f054f6 598 if (strstr(soRec, "GET ") == soRec) {
WiredHome 8:262583f054f6 599 Extract(soRec, "GET", &queryString);
WiredHome 8:262583f054f6 600 if (queryString) {
WiredHome 8:262583f054f6 601 queryType = (char *)mymalloc(strlen("GET")+1);
WiredHome 8:262583f054f6 602 strcpy(queryType, "GET");
WiredHome 8:262583f054f6 603 }
WiredHome 8:262583f054f6 604 } else if (strstr(soRec, "POST ") == soRec) {
WiredHome 8:262583f054f6 605 Extract(soRec, "POST", &queryString);
WiredHome 8:262583f054f6 606 if (queryString) {
WiredHome 8:262583f054f6 607 queryType = (char *)mymalloc(strlen("POST")+1);
WiredHome 8:262583f054f6 608 strcpy(queryType, "POST");
WiredHome 8:262583f054f6 609 }
WiredHome 10:9c8d2c6a3469 610 }
WiredHome 13:8975d7928678 611
WiredHome 13:8975d7928678 612 // if there is a ": " delimiter, we have a header item to parse into name,value pair
WiredHome 13:8975d7928678 613 // "Connection: keep-alive" becomes "Connection" "keep-alive"
WiredHome 13:8975d7928678 614 char *delim = strstr(soRec, ": ");
WiredHome 13:8975d7928678 615 char *chkSpace = strchr(soRec, ' '); // a field-name has no space ahead of the ":"
WiredHome 13:8975d7928678 616 if (delim
WiredHome 13:8975d7928678 617 && (!chkSpace || (chkSpace && delim < chkSpace))
WiredHome 13:8975d7928678 618 && headerParamCount < maxheaderParams) {
WiredHome 14:19c5f6151319 619 *delim++ = '\0'; // replace ": " with null
WiredHome 13:8975d7928678 620 *delim++ = '\0';
WiredHome 13:8975d7928678 621 headerParams[headerParamCount].name = soRec;
WiredHome 13:8975d7928678 622 headerParams[headerParamCount].value = delim;
WiredHome 13:8975d7928678 623 #ifdef DEBUG
WiredHome 13:8975d7928678 624 pc->printf("%d: headerParams[%s] = {%s}\r\n", headerParamCount,
WiredHome 13:8975d7928678 625 headerParams[headerParamCount].name, headerParams[headerParamCount].value);
WiredHome 13:8975d7928678 626 #endif
WiredHome 13:8975d7928678 627 headerParamCount++;
WiredHome 13:8975d7928678 628 }
WiredHome 3:17928786bdb5 629 soRec = eoRec + 1;
WiredHome 3:17928786bdb5 630 eoRec = strchr(soRec, '\n');
WiredHome 3:17928786bdb5 631 }
WiredHome 3:17928786bdb5 632 if (queryString) {
WiredHome 3:17928786bdb5 633 // We have enough to try to reply
WiredHome 12:109bf1558300 634 #ifdef DEBUG
WiredHome 8:262583f054f6 635 pc->printf("create reply queryType{%s}, queryString{%s}\r\n", "GET", queryString);
WiredHome 12:109bf1558300 636 #endif
WiredHome 13:8975d7928678 637 // parse queryParams - if any
WiredHome 3:17928786bdb5 638 // /file.htm?name1=value1&name2=value2...
WiredHome 3:17928786bdb5 639 // /file.htm?name1&name2=value2...
WiredHome 13:8975d7928678 640 queryParamCount = 0;
WiredHome 3:17928786bdb5 641 char * paramDelim = strchr(queryString, '?');
WiredHome 3:17928786bdb5 642 if (paramDelim) {
WiredHome 3:17928786bdb5 643 *paramDelim++ = '\0';
WiredHome 3:17928786bdb5 644 UnescapeString(paramDelim); // everything after the '?'
WiredHome 13:8975d7928678 645 ParseParameters(paramDelim); // pointing at the NULL, but there are queryParams beyond
WiredHome 3:17928786bdb5 646 }
WiredHome 3:17928786bdb5 647 } else {
WiredHome 10:9c8d2c6a3469 648 pc->printf("ERROR: queryString not found in (%s)\r\n", soRec);
WiredHome 3:17928786bdb5 649 }
WiredHome 3:17928786bdb5 650 advanceState = true;
WiredHome 3:17928786bdb5 651 buffer[0] = 0;
WiredHome 3:17928786bdb5 652
WiredHome 3:17928786bdb5 653 // This part parses the extra data on a POST method.
WiredHome 3:17928786bdb5 654 // Since there has to be a dynamic handler registered for this
WiredHome 3:17928786bdb5 655 // it would make sense to move some of this responsibility to
WiredHome 3:17928786bdb5 656 // that handler. It could then choose if it wanted to allocate
WiredHome 3:17928786bdb5 657 // the requested 'Content-Length' amount of memory.
WiredHome 3:17928786bdb5 658 // Should we check the 'Content-Type' to see if it is
WiredHome 3:17928786bdb5 659 // 'application/x-www-form-urlencoded'?
WiredHome 13:8975d7928678 660 int postBytes = atoi(GetHeaderValue("Content-Length"));
WiredHome 3:17928786bdb5 661 bool acceptIt = false;
WiredHome 3:17928786bdb5 662 if (strcmp(queryType, "POST") == 0 && postBytes > 0 ) {
WiredHome 3:17928786bdb5 663 if (postBytes) {
WiredHome 3:17928786bdb5 664 bool regHandled = false;
WiredHome 3:17928786bdb5 665 // Registered Dynamic Handler
WiredHome 3:17928786bdb5 666 // Callback and ask if they want to accept this data
WiredHome 3:17928786bdb5 667 for (int i=0; i<handlercount; i++) {
WiredHome 3:17928786bdb5 668 if (strcmp(handlers[i].path, queryString) == 0) {
WiredHome 13:8975d7928678 669 acceptIt = (*handlers[i].callback)(this, CONTENT_LENGTH_REQUEST, queryString, queryParams, queryParamCount);
WiredHome 3:17928786bdb5 670 regHandled = true;
WiredHome 3:17928786bdb5 671 break; // we only execute the first one
WiredHome 3:17928786bdb5 672 }
WiredHome 3:17928786bdb5 673 }
WiredHome 3:17928786bdb5 674
WiredHome 3:17928786bdb5 675 if (regHandled && acceptIt) {
WiredHome 3:17928786bdb5 676 // If so, we'll make space for it
WiredHome 8:262583f054f6 677 postQueryString = (char *)mymalloc(postBytes + 1);
WiredHome 3:17928786bdb5 678 if (postQueryString) {
WiredHome 3:17928786bdb5 679 char * offset;
WiredHome 3:17928786bdb5 680 int len;
WiredHome 3:17928786bdb5 681
WiredHome 3:17928786bdb5 682 dblCR += 4; // If we slurped up any of the POST,
WiredHome 3:17928786bdb5 683 while (*dblCR && *dblCR <= ' ')
WiredHome 3:17928786bdb5 684 dblCR++;
WiredHome 3:17928786bdb5 685 strcpy(postQueryString, dblCR); // copy that in and then get the rest
WiredHome 3:17928786bdb5 686 while ((len = strlen(postQueryString)) < postBytes) {
WiredHome 3:17928786bdb5 687 int n;
WiredHome 3:17928786bdb5 688 offset = postQueryString + len;
WiredHome 3:17928786bdb5 689 n = client.receive(offset, postBytes - len);
WiredHome 3:17928786bdb5 690 if (n >=0) {
WiredHome 3:17928786bdb5 691 offset[n] = '\0';
WiredHome 3:17928786bdb5 692 }
WiredHome 3:17928786bdb5 693 }
WiredHome 3:17928786bdb5 694 if (len >= 0) {
WiredHome 3:17928786bdb5 695 UnescapeString(postQueryString);
WiredHome 3:17928786bdb5 696 ParseParameters(postQueryString);
WiredHome 3:17928786bdb5 697 }
WiredHome 3:17928786bdb5 698 }
WiredHome 3:17928786bdb5 699 } else {
WiredHome 3:17928786bdb5 700 // Simply copy it to the bitbucket
WiredHome 3:17928786bdb5 701 int bytesToDump = postBytes;
WiredHome 8:262583f054f6 702 char * bitbucket = (char *)mymalloc(201);
WiredHome 3:17928786bdb5 703 dblCR += 4;
WiredHome 3:17928786bdb5 704 while (*dblCR && *dblCR <= ' ')
WiredHome 3:17928786bdb5 705 dblCR++;
WiredHome 3:17928786bdb5 706 bytesToDump -= strlen(dblCR);
WiredHome 3:17928786bdb5 707 while (bytesToDump > 0) {
WiredHome 3:17928786bdb5 708 int n = (bytesToDump > 200) ? 200 : bytesToDump;
WiredHome 3:17928786bdb5 709 n = client.receive(bitbucket, n);
WiredHome 3:17928786bdb5 710 bytesToDump -= n;
WiredHome 3:17928786bdb5 711 }
WiredHome 8:262583f054f6 712 myfree(bitbucket);
WiredHome 3:17928786bdb5 713 }
WiredHome 3:17928786bdb5 714 }
WiredHome 3:17928786bdb5 715 }
WiredHome 3:17928786bdb5 716 }
WiredHome 3:17928786bdb5 717 return advanceState;
WiredHome 3:17928786bdb5 718 }
WiredHome 3:17928786bdb5 719
WiredHome 14:19c5f6151319 720
WiredHome 13:8975d7928678 721 const char * HTTPServer::GetHeaderValue(const char * hdr)
WiredHome 13:8975d7928678 722 {
WiredHome 13:8975d7928678 723 int i;
WiredHome 13:8975d7928678 724
WiredHome 13:8975d7928678 725 for (i=0; i<headerParamCount; i++)
WiredHome 13:8975d7928678 726 {
WiredHome 13:8975d7928678 727 if (strcmp(hdr, headerParams[i].name) == 0)
WiredHome 13:8975d7928678 728 return headerParams[i].value;
WiredHome 13:8975d7928678 729 }
WiredHome 13:8975d7928678 730 return NULL;
WiredHome 13:8975d7928678 731 }
WiredHome 13:8975d7928678 732
WiredHome 12:109bf1558300 733
WiredHome 7:99ad7a67f05e 734 void HTTPServer::GetPerformanceData(SW_PerformanceData * p)
WiredHome 7:99ad7a67f05e 735 {
WiredHome 3:17928786bdb5 736 memcpy(p, &perfData, sizeof(perfData));
WiredHome 3:17928786bdb5 737 }
WiredHome 3:17928786bdb5 738
WiredHome 17:69ff00ce39f4 739 unsigned int HTTPServer::GetPerformanceClock()
WiredHome 17:69ff00ce39f4 740 {
WiredHome 17:69ff00ce39f4 741 return (unsigned int)PerformanceTimer.read_us();
WiredHome 17:69ff00ce39f4 742 }
WiredHome 14:19c5f6151319 743
WiredHome 16:6ebacf2946d8 744 unsigned int HTTPServer::RecordPerformanceData(SW_PerformanceParam * param, unsigned int refTime)
WiredHome 7:99ad7a67f05e 745 {
WiredHome 16:6ebacf2946d8 746 unsigned int t_now = (unsigned int)PerformanceTimer.read_us();
WiredHome 3:17928786bdb5 747 param->TotalTime_us += (t_now - refTime);
WiredHome 3:17928786bdb5 748 param->Samples++;
WiredHome 3:17928786bdb5 749 if ((t_now - refTime) > param->MaxTime_us)
WiredHome 3:17928786bdb5 750 param->MaxTime_us = (t_now - refTime);
WiredHome 3:17928786bdb5 751 return t_now;
WiredHome 3:17928786bdb5 752 }
WiredHome 3:17928786bdb5 753
WiredHome 14:19c5f6151319 754
WiredHome 7:99ad7a67f05e 755 void HTTPServer::ResetPerformanceData()
WiredHome 7:99ad7a67f05e 756 {
WiredHome 3:17928786bdb5 757 memset(&perfData, 0, sizeof(perfData));
WiredHome 3:17928786bdb5 758 }
WiredHome 3:17928786bdb5 759
WiredHome 4:f34642902056 760