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:
Wed Feb 27 18:06:23 2019 +0000
Revision:
60:d49a346c386f
Parent:
59:9a71ac02c782
Enable header code 302

Who changed what in which revision?

UserRevisionLine numberNew contents of line
WiredHome 0:729320f63c5c 1 //
WiredHome 44:71f09e4255f4 2 // @note Copyright © 2014-2016 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 58:5303e962f711 14 #include "SW_String.h" // Secure methods and others that were missing
WiredHome 29:00116fc9da74 15
WiredHome 59:9a71ac02c782 16 //#define DEBUG "HTTP"
WiredHome 38:c8fa31e6fe02 17 #include <cstdio>
WiredHome 38:c8fa31e6fe02 18 #if (defined(DEBUG) && !defined(TARGET_LPC11U24))
WiredHome 58:5303e962f711 19 #define DBG(x, ...) std::printf("[DBG %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 58:5303e962f711 20 #define WARN(x, ...) std::printf("[WRN %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 58:5303e962f711 21 #define ERR(x, ...) std::printf("[ERR %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 58:5303e962f711 22 #define INFO(x, ...) std::printf("[INF %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 38:c8fa31e6fe02 23 #else
WiredHome 38:c8fa31e6fe02 24 #define DBG(x, ...)
WiredHome 38:c8fa31e6fe02 25 #define WARN(x, ...)
WiredHome 38:c8fa31e6fe02 26 #define ERR(x, ...)
WiredHome 38:c8fa31e6fe02 27 #define INFO(x, ...)
WiredHome 38:c8fa31e6fe02 28 #endif
WiredHome 38:c8fa31e6fe02 29
WiredHome 31:8f72be717a3c 30 #include "SW_HTTPServer.h" // define DEBUG before this
WiredHome 27:90a1f5a5392f 31
WiredHome 33:ef165a67ab22 32 #define CHUNK_SIZE 1500 // max size of a single chunk (probably limited by Ethernet to 1500)
WiredHome 33:ef165a67ab22 33 #define HANG_TIMEOUT_MS 250 // If we're waiting on the host, which may never respond, this is the timeout
WiredHome 0:729320f63c5c 34
WiredHome 0:729320f63c5c 35 const char * DEFAULT_FILENAME = "index.htm";
WiredHome 0:729320f63c5c 36
WiredHome 8:262583f054f6 37 // Header information to always send (must be \r\n terminated)
WiredHome 44:71f09e4255f4 38 static const char hdr_httpver[] = "HTTP/1.1"; // supported HTTP/1.1 protocol (sort of)
WiredHome 44:71f09e4255f4 39 static const char nl[] = "\r\n"; // final \r\n for the termination of the header
WiredHome 0:729320f63c5c 40
WiredHome 44:71f09e4255f4 41 // Header items that are sent if the user does not provide their own options.
WiredHome 44:71f09e4255f4 42 static const char hdr_age[] = "Max-age: 0\r\n"; // expires right away
WiredHome 44:71f09e4255f4 43 static const char hdr_server[] = "Server: Smart_Server v0.2\r\n"; // Server
WiredHome 44:71f09e4255f4 44 static const char hdr_close[] = "Connection: close\r\n"; // tell the client the server closes the connection immediately
WiredHome 14:19c5f6151319 45
WiredHome 0:729320f63c5c 46 static const struct {
WiredHome 0:729320f63c5c 47 char *ext;
WiredHome 0:729320f63c5c 48 char *filetype;
WiredHome 0:729320f63c5c 49 } extensions [] = {
WiredHome 3:17928786bdb5 50 {".gif", "Content-Type: image/gif\r\n" },
WiredHome 3:17928786bdb5 51 {".jpg", "Content-Type: image/jpeg\r\n" },
WiredHome 3:17928786bdb5 52 {".jpeg","Content-Type: image/jpeg\r\n" },
WiredHome 3:17928786bdb5 53 {".ico", "Content-Type: image/x-icon\r\n" },
WiredHome 33:ef165a67ab22 54 {".bmp", "Content-Type: image/bmp\r\n" },
WiredHome 3:17928786bdb5 55 {".png", "Content-Type: image/png\r\n" },
WiredHome 3:17928786bdb5 56 {".zip", "Content-Type: image/zip\r\n" },
WiredHome 3:17928786bdb5 57 {".gz", "Content-Type: image/gz\r\n" },
WiredHome 3:17928786bdb5 58 {".tar", "Content-Type: image/tar\r\n" },
WiredHome 3:17928786bdb5 59 {".txt", "Content-Type: plain/text\r\n" },
WiredHome 3:17928786bdb5 60 {".pdf", "Content-Type: application/pdf\r\n" },
WiredHome 3:17928786bdb5 61 {".htm", "Content-Type: text/html\r\n" },
WiredHome 3:17928786bdb5 62 {".html","Content-Type: text/html\r\n" },
WiredHome 44:71f09e4255f4 63 {".xml", "Content-Type: text/xml\r\n" },
WiredHome 47:4c29c8f0cff2 64 {".js", "Content-Type: text/javascript\r\n" },
WiredHome 0:729320f63c5c 65 {0,0}
WiredHome 0:729320f63c5c 66 };
WiredHome 0:729320f63c5c 67
WiredHome 44:71f09e4255f4 68 typedef struct {
WiredHome 44:71f09e4255f4 69 char * queryType;
WiredHome 44:71f09e4255f4 70 int notused;
WiredHome 44:71f09e4255f4 71 } QueryMethod;
WiredHome 44:71f09e4255f4 72
WiredHome 44:71f09e4255f4 73 // Be sure to include a trailing space.
WiredHome 44:71f09e4255f4 74 static const QueryMethod QueryMethodList[] = {
WiredHome 44:71f09e4255f4 75 {"GET ", 0},
WiredHome 44:71f09e4255f4 76 {"POST ", 0},
WiredHome 44:71f09e4255f4 77 {"HEAD ", 0},
WiredHome 44:71f09e4255f4 78 {"PUT ", 0},
WiredHome 44:71f09e4255f4 79 {"OPTION ", 0},
WiredHome 44:71f09e4255f4 80 {"DELETE ", 0},
WiredHome 44:71f09e4255f4 81 {"TRACE ", 0},
WiredHome 44:71f09e4255f4 82 {"CONNECT ", 0},
WiredHome 44:71f09e4255f4 83 {NULL, 0}
WiredHome 44:71f09e4255f4 84 };
WiredHome 44:71f09e4255f4 85
WiredHome 59:9a71ac02c782 86 #if 1 && defined(DEBUG)
WiredHome 30:864843965b40 87 // Haven't learned anything from this in a long time, so disabled.
WiredHome 12:109bf1558300 88 // This uses standard library dynamic memory management, but for an
WiredHome 9:2ea342765c9d 89 // embedded system there are alternates that may make better sense -
WiredHome 9:2ea342765c9d 90 // search the web for embedded system malloc alternates.
WiredHome 59:9a71ac02c782 91 void * HTTPServer::MyMalloc(int Bytes, int LINE)
WiredHome 8:262583f054f6 92 {
WiredHome 59:9a71ac02c782 93 void * pMem = malloc(Bytes);
WiredHome 59:9a71ac02c782 94 pc->printf("[INF %s %4d] MyMalloc %p = malloc(%d)\r\n", DEBUG, LINE, pMem, Bytes);
WiredHome 59:9a71ac02c782 95 return pMem;
WiredHome 8:262583f054f6 96 }
WiredHome 29:00116fc9da74 97 char HTTPServer::toP(void * x)
WiredHome 11:17d84c41a7b3 98 {
WiredHome 11:17d84c41a7b3 99 char * c = (char *) x;
WiredHome 30:864843965b40 100 if (*c >= ' ' && *c < 0x7F) // isprint()
WiredHome 11:17d84c41a7b3 101 return *c;
WiredHome 11:17d84c41a7b3 102 else
WiredHome 11:17d84c41a7b3 103 return '.';
WiredHome 11:17d84c41a7b3 104 }
WiredHome 59:9a71ac02c782 105 #define mymalloc(Bytes) MyMalloc(Bytes, __LINE__)
WiredHome 8:262583f054f6 106 #define myfree(x) \
WiredHome 59:9a71ac02c782 107 pc->printf("[INF %s %4d] MyMalloc %p = free(%02x %02x %02x %02x %02x ... %c%c%c%c%c)\r\n", \
WiredHome 59:9a71ac02c782 108 DEBUG, __LINE__, \
WiredHome 59:9a71ac02c782 109 x, \
WiredHome 11:17d84c41a7b3 110 *x, *(x+1), *(x+2), *(x+3), *(x+4), \
WiredHome 11:17d84c41a7b3 111 toP(x), toP(x+1), toP(x+2), toP(x+3), toP(x+4) ); \
WiredHome 8:262583f054f6 112 free(x);
WiredHome 8:262583f054f6 113 #else
WiredHome 8:262583f054f6 114 #define mymalloc(x) malloc(x)
WiredHome 8:262583f054f6 115 #define myfree(x) free(x)
WiredHome 8:262583f054f6 116 #endif
WiredHome 8:262583f054f6 117
WiredHome 58:5303e962f711 118
WiredHome 58:5303e962f711 119
WiredHome 3:17928786bdb5 120 HTTPServer::HTTPServer(
WiredHome 7:99ad7a67f05e 121 int port,
WiredHome 7:99ad7a67f05e 122 const char * _webroot,
WiredHome 43:3fc773c2986e 123 int _maxheaderParams,
WiredHome 13:8975d7928678 124 int _maxqueryParams,
WiredHome 7:99ad7a67f05e 125 int _maxdynamicpages,
WiredHome 49:cd391662f254 126 int blockingtime,
WiredHome 7:99ad7a67f05e 127 PC * _pc,
WiredHome 7:99ad7a67f05e 128 int _allocforheader,
WiredHome 49:cd391662f254 129 int _allocforfile
WiredHome 49:cd391662f254 130 )
WiredHome 0:729320f63c5c 131 {
WiredHome 58:5303e962f711 132 int wrSize = strlen(_webroot)+1;
WiredHome 58:5303e962f711 133
WiredHome 58:5303e962f711 134 webroot = (char *)malloc(wrSize);
WiredHome 58:5303e962f711 135 strcpy_s(webroot, wrSize, _webroot);
WiredHome 27:90a1f5a5392f 136 if (strlen(webroot)>1 && webroot[strlen(webroot)-1] == '/') // remove trailing '/'
WiredHome 27:90a1f5a5392f 137 webroot[strlen(webroot)-1] = '\0';
WiredHome 44:71f09e4255f4 138 filenameAliasList = NULL;
WiredHome 43:3fc773c2986e 139 maxheaderParams = _maxheaderParams;
WiredHome 13:8975d7928678 140 headerParams = (namevalue *)malloc(maxheaderParams * sizeof(namevalue));
WiredHome 39:0427544a5c08 141
WiredHome 39:0427544a5c08 142 maxqueryParams = _maxqueryParams;
WiredHome 13:8975d7928678 143 queryParams = (namevalue *)malloc(maxqueryParams * sizeof(namevalue));
WiredHome 39:0427544a5c08 144 queryParamCount = 0;
WiredHome 39:0427544a5c08 145
WiredHome 39:0427544a5c08 146 maxPostParams = _maxqueryParams; // Same as Query params, but for post method
WiredHome 39:0427544a5c08 147 postParams = (namevalue *)malloc(maxPostParams * sizeof(namevalue));
WiredHome 39:0427544a5c08 148 postParamCount = 0;
WiredHome 43:3fc773c2986e 149 maxdynamicpages = _maxdynamicpages;
WiredHome 0:729320f63c5c 150 handlers = (handler *)malloc(maxdynamicpages * sizeof(handler));
WiredHome 59:9a71ac02c782 151 handlercount = 0;
WiredHome 59:9a71ac02c782 152 ndxActiveHandler = -1;
WiredHome 3:17928786bdb5 153 headerbuffersize = _allocforheader;
WiredHome 3:17928786bdb5 154 headerbuffer = (char *)malloc(headerbuffersize);
WiredHome 0:729320f63c5c 155 pc = _pc;
WiredHome 3:17928786bdb5 156 queryType = NULL;
WiredHome 3:17928786bdb5 157 queryString = NULL;
WiredHome 3:17928786bdb5 158 postQueryString = NULL;
WiredHome 3:17928786bdb5 159 maxheaderbytes = 0;
WiredHome 0:729320f63c5c 160 server = new TCPSocketServer();
WiredHome 0:729320f63c5c 161 server->bind(port);
WiredHome 51:758601b9bacd 162 server->listen(5);
WiredHome 57:fb81057b4d77 163 server->set_blocking(false, blockingtime);
WiredHome 56:df915cb8ba9a 164 client.set_blocking(true, blockingtime); //@TODO client is separate from server. any way to combine?
WiredHome 3:17928786bdb5 165 ResetPerformanceData();
WiredHome 10:9c8d2c6a3469 166 PerformanceTimer.start();
WiredHome 0:729320f63c5c 167 }
WiredHome 0:729320f63c5c 168
WiredHome 0:729320f63c5c 169 HTTPServer::~HTTPServer()
WiredHome 0:729320f63c5c 170 {
WiredHome 8:262583f054f6 171 int i;
WiredHome 8:262583f054f6 172
WiredHome 8:262583f054f6 173 for (i=0; i<handlercount; i++)
WiredHome 8:262583f054f6 174 myfree(handlers[i].path);
WiredHome 8:262583f054f6 175 myfree(headerbuffer);
WiredHome 8:262583f054f6 176 myfree(handlers);
WiredHome 13:8975d7928678 177 myfree(queryParams);
WiredHome 8:262583f054f6 178 myfree(webroot);
WiredHome 0:729320f63c5c 179 webroot = NULL;
WiredHome 0:729320f63c5c 180 }
WiredHome 0:729320f63c5c 181
WiredHome 44:71f09e4255f4 182 void HTTPServer::RegisterFilenameAliasList(const namevalue * namevaluelist)
WiredHome 44:71f09e4255f4 183 {
WiredHome 44:71f09e4255f4 184 filenameAliasList = namevaluelist;
WiredHome 44:71f09e4255f4 185 }
WiredHome 44:71f09e4255f4 186
WiredHome 3:17928786bdb5 187 int HTTPServer::GetMaxHeaderSize()
WiredHome 3:17928786bdb5 188 {
WiredHome 3:17928786bdb5 189 return maxheaderbytes;
WiredHome 3:17928786bdb5 190 }
WiredHome 3:17928786bdb5 191
WiredHome 0:729320f63c5c 192 bool HTTPServer::RegisterHandler(const char * path, Handler callback)
WiredHome 0:729320f63c5c 193 {
WiredHome 0:729320f63c5c 194 if (handlercount < maxdynamicpages && path && callback) {
WiredHome 8:262583f054f6 195 handlers[handlercount].path = (char *)mymalloc(strlen(path)+1);
WiredHome 0:729320f63c5c 196 memcpy(handlers[handlercount].path, path, strlen(path)+1);
WiredHome 0:729320f63c5c 197 handlers[handlercount].callback = callback;
WiredHome 0:729320f63c5c 198 handlercount++;
WiredHome 0:729320f63c5c 199 return true;
WiredHome 0:729320f63c5c 200 } else {
WiredHome 0:729320f63c5c 201 return false;
WiredHome 0:729320f63c5c 202 }
WiredHome 0:729320f63c5c 203 }
WiredHome 0:729320f63c5c 204
WiredHome 59:9a71ac02c782 205 const char * HTTPServer::GetActiveHandlerPath(void)
WiredHome 59:9a71ac02c782 206 {
WiredHome 59:9a71ac02c782 207 if (ndxActiveHandler >= 0)
WiredHome 59:9a71ac02c782 208 return handlers[ndxActiveHandler].path;
WiredHome 59:9a71ac02c782 209 else
WiredHome 59:9a71ac02c782 210 return NULL;
WiredHome 59:9a71ac02c782 211 }
WiredHome 59:9a71ac02c782 212
WiredHome 2:a29c32190037 213 // Poll()
WiredHome 0:729320f63c5c 214 //
WiredHome 0:729320f63c5c 215 // *OPEN*GET /x=1 HTTP/1.1
WiredHome 0:729320f63c5c 216 // Host: 192.168.1.140
WiredHome 0:729320f63c5c 217 // Connection: keep-alive
WiredHome 0:729320f63c5c 218 // Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
WiredHome 0:729320f63c5c 219 // 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 220 // Accept-Encoding: gzip,deflate,sdch
WiredHome 0:729320f63c5c 221 // Accept-Language: en-US,en;q=0.8
WiredHome 0:729320f63c5c 222 //
WiredHome 2:a29c32190037 223 void HTTPServer::Poll()
WiredHome 0:729320f63c5c 224 {
WiredHome 3:17928786bdb5 225 typedef enum {
WiredHome 3:17928786bdb5 226 Idle, // waiting for a connection
WiredHome 29:00116fc9da74 227 ReceivingHeader, // receiving header
WiredHome 29:00116fc9da74 228 ReceivingPayload, // receiving a section after the Header
WiredHome 3:17928786bdb5 229 Sending, // send the response
WiredHome 7:99ad7a67f05e 230 WaitingToClose, // small timeout to close
WiredHome 7:99ad7a67f05e 231 Reset
WiredHome 3:17928786bdb5 232 } state;
WiredHome 0:729320f63c5c 233 static state op = Idle;
WiredHome 3:17928786bdb5 234 static char * bPtr = headerbuffer;
WiredHome 0:729320f63c5c 235 int n;
WiredHome 16:6ebacf2946d8 236 static unsigned int t_ref; // reference point for the PerformanceTimer
WiredHome 0:729320f63c5c 237
WiredHome 20:786aa5749007 238 #if defined(DEBUG)
WiredHome 8:262583f054f6 239 static state lastOp = Reset;
WiredHome 7:99ad7a67f05e 240 if (lastOp != op) {
WiredHome 29:00116fc9da74 241 const char *states[] = {"Idle", "ReceivingHeader", "ReceivingPayload", "Sending", "WaitingToClose", "Reset"};
WiredHome 58:5303e962f711 242 INFO("Poll: %-30s ######## %8u us", states[op], (unsigned int)PerformanceTimer.read_us()-t_ref);
WiredHome 7:99ad7a67f05e 243 lastOp = op;
WiredHome 7:99ad7a67f05e 244 }
WiredHome 8:262583f054f6 245 #endif
WiredHome 0:729320f63c5c 246 switch(op) {
WiredHome 3:17928786bdb5 247 default: // not expected to arrive here
WiredHome 3:17928786bdb5 248 op = Idle;
WiredHome 3:17928786bdb5 249 break;
WiredHome 8:262583f054f6 250
WiredHome 3:17928786bdb5 251 case Idle:
WiredHome 10:9c8d2c6a3469 252 PerformanceTimer.reset();
WiredHome 17:69ff00ce39f4 253 t_ref = (unsigned int)PerformanceTimer.read_us();
WiredHome 3:17928786bdb5 254 bPtr = headerbuffer;
WiredHome 11:17d84c41a7b3 255 if (0 == server->accept(client)) {
WiredHome 29:00116fc9da74 256 op = ReceivingHeader;
WiredHome 17:69ff00ce39f4 257 t_ref = RecordPerformanceData(&perfData.ConnectionAccepted, t_ref);
WiredHome 58:5303e962f711 258 INFO("Accepted at %8u us",
WiredHome 58:5303e962f711 259 (unsigned int)PerformanceTimer.read_us()-t_ref);
WiredHome 48:078adbe279ac 260 } else {
WiredHome 49:cd391662f254 261 //INFO("Timeout waiting for accept()");
WiredHome 3:17928786bdb5 262 }
WiredHome 0:729320f63c5c 263 break;
WiredHome 8:262583f054f6 264
WiredHome 29:00116fc9da74 265 case ReceivingHeader:
WiredHome 3:17928786bdb5 266 n = client.receive(bPtr, headerbuffersize - (bPtr - headerbuffer));
WiredHome 58:5303e962f711 267 INFO("client.receive() returned %d, from %s", n, client.get_address());
WiredHome 59:9a71ac02c782 268 INFO(" ReceivingHeader: %s", bPtr);
WiredHome 55:238dd90b6fb3 269 if (n == -2) {
WiredHome 55:238dd90b6fb3 270 // was hang here waiting ... op = Sending; which causes misses
WiredHome 58:5303e962f711 271 op = WaitingToClose;
WiredHome 55:238dd90b6fb3 272 } else if (n < 0) {
WiredHome 58:5303e962f711 273 op = WaitingToClose; // bail out...
WiredHome 3:17928786bdb5 274 } else if (n) {
WiredHome 3:17928786bdb5 275 bPtr[n] = '\0';
WiredHome 29:00116fc9da74 276 switch (ParseHeader(headerbuffer)) {
WiredHome 29:00116fc9da74 277 case ACCEPT_ERROR:
WiredHome 29:00116fc9da74 278 break;
WiredHome 29:00116fc9da74 279 case ACCEPT_COMPLETE:
WiredHome 29:00116fc9da74 280 op = Sending;
WiredHome 29:00116fc9da74 281 t_ref = RecordPerformanceData(&perfData.HeaderParsed, t_ref);
WiredHome 58:5303e962f711 282 INFO("Header Parsed at %8u us",
WiredHome 58:5303e962f711 283 (unsigned int)PerformanceTimer.read_us()-t_ref);
WiredHome 29:00116fc9da74 284 break;
WiredHome 29:00116fc9da74 285 case ACCEPT_CONTINUE:
WiredHome 29:00116fc9da74 286 op = ReceivingPayload;
WiredHome 29:00116fc9da74 287 break;
WiredHome 3:17928786bdb5 288 }
WiredHome 3:17928786bdb5 289 bPtr += n;
WiredHome 0:729320f63c5c 290 }
WiredHome 0:729320f63c5c 291 break;
WiredHome 8:262583f054f6 292
WiredHome 29:00116fc9da74 293 case ReceivingPayload:
WiredHome 29:00116fc9da74 294 // After the header, there is a payload that will be handled
WiredHome 33:ef165a67ab22 295 #if 1
WiredHome 58:5303e962f711 296 INFO("ReceivingPayload %8u us",
WiredHome 58:5303e962f711 297 (unsigned int)PerformanceTimer.read_us()-t_ref);
WiredHome 33:ef165a67ab22 298 n = client.receive(bPtr, headerbuffersize - (bPtr - headerbuffer));
WiredHome 33:ef165a67ab22 299 if (n < 0) {
WiredHome 33:ef165a67ab22 300 op = Sending;
WiredHome 33:ef165a67ab22 301 INFO("*** client.receive() => %d", n);
WiredHome 33:ef165a67ab22 302 } else if (n) {
WiredHome 33:ef165a67ab22 303 bPtr[n] = '\0';
WiredHome 33:ef165a67ab22 304 INFO("*** payload size %d", n);
WiredHome 33:ef165a67ab22 305 }
WiredHome 33:ef165a67ab22 306 #else
WiredHome 29:00116fc9da74 307 op = Sending;
WiredHome 33:ef165a67ab22 308 #endif
WiredHome 29:00116fc9da74 309 break;
WiredHome 29:00116fc9da74 310
WiredHome 0:729320f63c5c 311 case Sending:
WiredHome 58:5303e962f711 312 INFO("SendResponse at %8u us",
WiredHome 58:5303e962f711 313 (unsigned int)PerformanceTimer.read_us()-t_ref);
WiredHome 3:17928786bdb5 314 SendResponse();
WiredHome 0:729320f63c5c 315 op = WaitingToClose;
WiredHome 17:69ff00ce39f4 316 t_ref = RecordPerformanceData(&perfData.ResponseSent, t_ref);
WiredHome 58:5303e962f711 317 INFO("Response Sent at %8u us",
WiredHome 58:5303e962f711 318 (unsigned int)PerformanceTimer.read_us()-t_ref);
WiredHome 0:729320f63c5c 319 break;
WiredHome 9:2ea342765c9d 320
WiredHome 0:729320f63c5c 321 case WaitingToClose:
WiredHome 58:5303e962f711 322 INFO("close_connection %8u us",
WiredHome 58:5303e962f711 323 (unsigned int)PerformanceTimer.read_us()-t_ref);
WiredHome 3:17928786bdb5 324 close_connection();
WiredHome 0:729320f63c5c 325 op = Idle;
WiredHome 17:69ff00ce39f4 326 RecordPerformanceData(&perfData.ConnectionClosed, t_ref);
WiredHome 58:5303e962f711 327 INFO("Connection closed exit: %8u us\r\n\r\n",
WiredHome 58:5303e962f711 328 (unsigned int)PerformanceTimer.read_us()-t_ref);
WiredHome 0:729320f63c5c 329 break;
WiredHome 0:729320f63c5c 330 }
WiredHome 0:729320f63c5c 331 }
WiredHome 0:729320f63c5c 332
WiredHome 0:729320f63c5c 333
WiredHome 0:729320f63c5c 334 const char * HTTPServer::GetSupportedType(const char * filename)
WiredHome 0:729320f63c5c 335 {
WiredHome 0:729320f63c5c 336 int i;
WiredHome 0:729320f63c5c 337 int buflen = strlen(filename);
WiredHome 0:729320f63c5c 338 int extlen;
WiredHome 0:729320f63c5c 339
WiredHome 0:729320f63c5c 340 for (i=0; extensions[i].ext != 0; i++) {
WiredHome 0:729320f63c5c 341 extlen = strlen(extensions[i].ext);
WiredHome 0:729320f63c5c 342 if ( !strncmp(&filename[buflen-extlen], extensions[i].ext, extlen)) {
WiredHome 0:729320f63c5c 343 return extensions[i].filetype;
WiredHome 0:729320f63c5c 344 }
WiredHome 0:729320f63c5c 345 }
WiredHome 0:729320f63c5c 346 return NULL;
WiredHome 0:729320f63c5c 347 }
WiredHome 0:729320f63c5c 348
WiredHome 3:17928786bdb5 349
WiredHome 53:e5d96abe5e9b 350 int HTTPServer::send(const char * msg, int bytes)
WiredHome 0:729320f63c5c 351 {
WiredHome 0:729320f63c5c 352 if (bytes == -1)
WiredHome 0:729320f63c5c 353 bytes = strlen(msg);
WiredHome 44:71f09e4255f4 354 INFO("Sending %d bytes", bytes);
WiredHome 44:71f09e4255f4 355 //INFO("send:\r\n%s", msg);
WiredHome 58:5303e962f711 356 int r = client.send_all((char *)msg, bytes);
WiredHome 44:71f09e4255f4 357 INFO("client.send returned: %d", r);
WiredHome 53:e5d96abe5e9b 358 return r;
WiredHome 0:729320f63c5c 359 }
WiredHome 0:729320f63c5c 360
WiredHome 44:71f09e4255f4 361 const char * HTTPServer::FindAlias(const HTTPServer::namevalue * haystack, const char * needle)
WiredHome 44:71f09e4255f4 362 {
WiredHome 44:71f09e4255f4 363 while (haystack && haystack->name) {
WiredHome 44:71f09e4255f4 364 if (strcmp(haystack->name,needle) == 0)
WiredHome 44:71f09e4255f4 365 return haystack->value;
WiredHome 44:71f09e4255f4 366 haystack++;
WiredHome 44:71f09e4255f4 367 }
WiredHome 44:71f09e4255f4 368 return needle;
WiredHome 44:71f09e4255f4 369 }
WiredHome 44:71f09e4255f4 370
WiredHome 44:71f09e4255f4 371 uint32_t HTTPServer::FileSize(const char * filename)
WiredHome 44:71f09e4255f4 372 {
WiredHome 44:71f09e4255f4 373 uint32_t size = 0;
WiredHome 44:71f09e4255f4 374 FILE * fh;
WiredHome 44:71f09e4255f4 375
WiredHome 44:71f09e4255f4 376 filename = FindAlias(filenameAliasList, filename);
WiredHome 44:71f09e4255f4 377 fh = fopen(filename, "r");
WiredHome 44:71f09e4255f4 378 if (fh) {
WiredHome 44:71f09e4255f4 379 fseek(fh, 0, SEEK_END); // seek to end of file
WiredHome 44:71f09e4255f4 380 size = ftell(fh); // get current file pointer
WiredHome 44:71f09e4255f4 381 fclose(fh);
WiredHome 44:71f09e4255f4 382 }
WiredHome 44:71f09e4255f4 383 return size;
WiredHome 44:71f09e4255f4 384 }
WiredHome 3:17928786bdb5 385
WiredHome 0:729320f63c5c 386 bool HTTPServer::SendFile(const char * filename, const char * filetype)
WiredHome 0:729320f63c5c 387 {
WiredHome 0:729320f63c5c 388 FILE * fp;
WiredHome 3:17928786bdb5 389
WiredHome 44:71f09e4255f4 390 INFO("SendFile(%s,...)", filename);
WiredHome 44:71f09e4255f4 391 filename = FindAlias(filenameAliasList, filename);
WiredHome 44:71f09e4255f4 392 INFO(" Alias(%s,...)", filename);
WiredHome 0:729320f63c5c 393 fp = fopen(filename,"rb");
WiredHome 0:729320f63c5c 394 if (fp) { // can open it
WiredHome 8:262583f054f6 395 char *fbuffer = (char *)mymalloc(FILESEND_BUF_SIZE);
WiredHome 0:729320f63c5c 396 int bytes;
WiredHome 0:729320f63c5c 397
WiredHome 3:17928786bdb5 398 if (fbuffer) {
WiredHome 44:71f09e4255f4 399 char ContentLen[30];
WiredHome 44:71f09e4255f4 400 snprintf(ContentLen, sizeof(ContentLen), "Content-Length: %u\r\n", FileSize(filename));
WiredHome 44:71f09e4255f4 401 header(OK, "OK", filetype, ContentLen);
WiredHome 44:71f09e4255f4 402 header("");
WiredHome 58:5303e962f711 403 bytes = fread(fbuffer,sizeof(char),FILESEND_BUF_SIZE-1,fp);
WiredHome 53:e5d96abe5e9b 404 INFO("Start with %d bytes", bytes);
WiredHome 58:5303e962f711 405 int retryCount = 2;
WiredHome 3:17928786bdb5 406 while (bytes > 0) {
WiredHome 53:e5d96abe5e9b 407 int r = send(fbuffer, bytes);
WiredHome 53:e5d96abe5e9b 408 if (r >= 0) {
WiredHome 58:5303e962f711 409 bytes = fread(fbuffer,sizeof(char),FILESEND_BUF_SIZE-1,fp);
WiredHome 53:e5d96abe5e9b 410 INFO(" Next %d bytes", bytes);
WiredHome 53:e5d96abe5e9b 411 //INFO("::%s", fbuffer);
WiredHome 58:5303e962f711 412 } else if (r == -2) {
WiredHome 58:5303e962f711 413 if (retryCount-- == 0) {
WiredHome 58:5303e962f711 414 ERR("send failed with %d [retries] - terminating SendFile().", r);
WiredHome 58:5303e962f711 415 break;
WiredHome 58:5303e962f711 416 }
WiredHome 58:5303e962f711 417 INFO("send failed with %d (timeout), hopefully it will recover.", r);
WiredHome 58:5303e962f711 418 } else {
WiredHome 58:5303e962f711 419 ERR("send failed with %d, but why? - terminating SendFile().", r);
WiredHome 58:5303e962f711 420 break;
WiredHome 53:e5d96abe5e9b 421 }
WiredHome 3:17928786bdb5 422 }
WiredHome 8:262583f054f6 423 myfree(fbuffer);
WiredHome 3:17928786bdb5 424 } else {
WiredHome 44:71f09e4255f4 425 header(Server_Error, "Server Error", NULL, "Pragma: err - insufficient memory\r\n");
WiredHome 44:71f09e4255f4 426 header("");
WiredHome 0:729320f63c5c 427 }
WiredHome 0:729320f63c5c 428 fclose(fp);
WiredHome 0:729320f63c5c 429 return true;
WiredHome 0:729320f63c5c 430 } else {
WiredHome 44:71f09e4255f4 431 header(Not_Found, "Not Found", NULL, "Pragma: err - Can't open file\r\n");
WiredHome 44:71f09e4255f4 432 header("");
WiredHome 0:729320f63c5c 433 return false;
WiredHome 0:729320f63c5c 434 }
WiredHome 0:729320f63c5c 435 }
WiredHome 0:729320f63c5c 436
WiredHome 0:729320f63c5c 437 int HTTPServer::HexCharToInt(char c)
WiredHome 0:729320f63c5c 438 {
WiredHome 0:729320f63c5c 439 if (c >= 'a' && c <= 'f')
WiredHome 0:729320f63c5c 440 return (c - 'a' + 10);
WiredHome 0:729320f63c5c 441 else if (c >= 'A' && c <= 'F')
WiredHome 0:729320f63c5c 442 return (c - 'A' + 10);
WiredHome 0:729320f63c5c 443 else if (c >= '0' && c <= '9')
WiredHome 0:729320f63c5c 444 return c - '0';
WiredHome 0:729320f63c5c 445 else
WiredHome 0:729320f63c5c 446 return 0;
WiredHome 0:729320f63c5c 447 }
WiredHome 0:729320f63c5c 448
WiredHome 0:729320f63c5c 449 char HTTPServer::HexPairToChar(char * p)
WiredHome 0:729320f63c5c 450 {
WiredHome 0:729320f63c5c 451 return 16 * HexCharToInt(*p) + HexCharToInt(*(p+1));
WiredHome 0:729320f63c5c 452 }
WiredHome 0:729320f63c5c 453
WiredHome 39:0427544a5c08 454 // modifies in-place
WiredHome 0:729320f63c5c 455 void HTTPServer::UnescapeString(char * encoded)
WiredHome 0:729320f63c5c 456 {
WiredHome 0:729320f63c5c 457 char *p;
WiredHome 0:729320f63c5c 458
WiredHome 0:729320f63c5c 459 // first convert '+' to ' '
WiredHome 0:729320f63c5c 460 p = strchr(encoded, '+');
WiredHome 0:729320f63c5c 461 while (p) {
WiredHome 0:729320f63c5c 462 *p = ' ';
WiredHome 0:729320f63c5c 463 p = strchr(encoded, '+');
WiredHome 0:729320f63c5c 464 }
WiredHome 0:729320f63c5c 465 // then convert hex '%xx' to char 'x'
WiredHome 0:729320f63c5c 466 p = strchr(encoded, '%');
WiredHome 0:729320f63c5c 467 while (p) {
WiredHome 0:729320f63c5c 468 if (strchr("0123456789ABCDEFabcdef", *(p+1))
WiredHome 0:729320f63c5c 469 && strchr("0123456789ABCDEFabcdef", *(p+2)) ) {
WiredHome 0:729320f63c5c 470 *p = HexPairToChar(p+1);
WiredHome 0:729320f63c5c 471 p++; // advance past the %
WiredHome 0:729320f63c5c 472 char * a = p;
WiredHome 0:729320f63c5c 473 char * b = p + 2;
WiredHome 0:729320f63c5c 474 do {
WiredHome 0:729320f63c5c 475 *a++ = *b++;
WiredHome 0:729320f63c5c 476 } while (*b);
WiredHome 0:729320f63c5c 477 *a = '\0';
WiredHome 0:729320f63c5c 478 }
WiredHome 0:729320f63c5c 479 p = strchr(p, '%');
WiredHome 0:729320f63c5c 480 }
WiredHome 0:729320f63c5c 481 }
WiredHome 0:729320f63c5c 482
WiredHome 0:729320f63c5c 483 const char * HTTPServer::GetParameter(const char * name)
WiredHome 0:729320f63c5c 484 {
WiredHome 37:0cb2774e2410 485 INFO("GetParameter(%s)", name);
WiredHome 13:8975d7928678 486 for (int i=0; i<queryParamCount; i++) {
WiredHome 37:0cb2774e2410 487 INFO(" %d: %s = %s", i, queryParams[i].name, queryParams[i].value);
WiredHome 13:8975d7928678 488 if (strcmp(queryParams[i].name, name) == 0) {
WiredHome 37:0cb2774e2410 489 INFO(" value {%s}", queryParams[i].value);
WiredHome 13:8975d7928678 490 return queryParams[i].value;
WiredHome 0:729320f63c5c 491 }
WiredHome 0:729320f63c5c 492 }
WiredHome 0:729320f63c5c 493 return NULL;
WiredHome 0:729320f63c5c 494 }
WiredHome 0:729320f63c5c 495
WiredHome 44:71f09e4255f4 496 const HTTPServer::namevalue * HTTPServer::GetParameter(int index)
WiredHome 39:0427544a5c08 497 {
WiredHome 39:0427544a5c08 498 if (index < queryParamCount)
WiredHome 39:0427544a5c08 499 return &queryParams[index];
WiredHome 39:0427544a5c08 500 else
WiredHome 39:0427544a5c08 501 return NULL;
WiredHome 39:0427544a5c08 502 }
WiredHome 39:0427544a5c08 503
WiredHome 39:0427544a5c08 504 const char * HTTPServer::GetPostParameter(const char * name)
WiredHome 39:0427544a5c08 505 {
WiredHome 39:0427544a5c08 506 INFO("GetPostParameter(%s)", name);
WiredHome 39:0427544a5c08 507 for (int i=0; i<postParamCount; i++) {
WiredHome 39:0427544a5c08 508 INFO(" %d: %s = %s", i, postParams[i].name, postParams[i].value);
WiredHome 39:0427544a5c08 509 if (strcmp(postParams[i].name, name) == 0) {
WiredHome 39:0427544a5c08 510 INFO(" value {%s}", postParams[i].value);
WiredHome 39:0427544a5c08 511 return postParams[i].value;
WiredHome 39:0427544a5c08 512 }
WiredHome 39:0427544a5c08 513 }
WiredHome 39:0427544a5c08 514 return NULL;
WiredHome 39:0427544a5c08 515 }
WiredHome 39:0427544a5c08 516
WiredHome 39:0427544a5c08 517 HTTPServer::namevalue * HTTPServer::GetPostParameter(int index)
WiredHome 39:0427544a5c08 518 {
WiredHome 39:0427544a5c08 519 if (index < postParamCount)
WiredHome 39:0427544a5c08 520 return &postParams[index];
WiredHome 39:0427544a5c08 521 else
WiredHome 39:0427544a5c08 522 return NULL;
WiredHome 39:0427544a5c08 523 }
WiredHome 37:0cb2774e2410 524
WiredHome 59:9a71ac02c782 525 int HTTPServer::ParsePostParameters(char * pPostString)
WiredHome 59:9a71ac02c782 526 {
WiredHome 59:9a71ac02c782 527 return ParseParameters(postParams, &postParamCount, maxPostParams, pPostString);
WiredHome 59:9a71ac02c782 528 }
WiredHome 59:9a71ac02c782 529
WiredHome 59:9a71ac02c782 530
WiredHome 0:729320f63c5c 531 // this=that&who=what&more=stuff...
WiredHome 0:729320f63c5c 532 // ^ ^ ^
WiredHome 39:0427544a5c08 533 int HTTPServer::ParseParameters(namevalue * qP, int * qpCount, int maxP, char * pName)
WiredHome 0:729320f63c5c 534 {
WiredHome 0:729320f63c5c 535 char * pVal;
WiredHome 0:729320f63c5c 536 char * pNextName;
WiredHome 0:729320f63c5c 537
WiredHome 13:8975d7928678 538 // Parse queryParams
WiredHome 0:729320f63c5c 539 pVal = strchr(pName, '#'); // If there is a '#fragment_id', we can ignore it
WiredHome 0:729320f63c5c 540 if (pVal)
WiredHome 3:17928786bdb5 541 *pVal = '\0';
WiredHome 0:729320f63c5c 542 do {
Sissors 42:0d5b682bb17a 543 INFO("ParseParameters(%s), qpCount: %d", pName, *qpCount);
WiredHome 39:0427544a5c08 544 qP->name = pName;
WiredHome 0:729320f63c5c 545 pVal = strchr(pName, '=');
WiredHome 0:729320f63c5c 546 pNextName = strchr(pName,'&');
WiredHome 0:729320f63c5c 547 if (pVal) {
WiredHome 0:729320f63c5c 548 if (pNextName == NULL || (pNextName && pNextName > pVal)) {
WiredHome 0:729320f63c5c 549 *pVal++ = '\0';
WiredHome 39:0427544a5c08 550 qP->value = pVal;
WiredHome 0:729320f63c5c 551 pName = pVal;
WiredHome 0:729320f63c5c 552 }
WiredHome 0:729320f63c5c 553 }
WiredHome 0:729320f63c5c 554 if (pNextName) {
WiredHome 0:729320f63c5c 555 pName = pNextName;
WiredHome 0:729320f63c5c 556 *pName++ = '\0';
WiredHome 0:729320f63c5c 557 } else {
WiredHome 0:729320f63c5c 558 pName = NULL;
WiredHome 0:729320f63c5c 559 }
WiredHome 39:0427544a5c08 560 INFO(" param{%s}={%s}", qP->name, qP->value);
WiredHome 39:0427544a5c08 561 *qpCount += 1;
WiredHome 39:0427544a5c08 562 qP++;
WiredHome 39:0427544a5c08 563 } while (pName && *qpCount < maxP);
WiredHome 39:0427544a5c08 564 INFO(" count %d", *qpCount);
WiredHome 39:0427544a5c08 565 return *qpCount;
WiredHome 0:729320f63c5c 566 }
WiredHome 0:729320f63c5c 567
WiredHome 0:729320f63c5c 568
WiredHome 44:71f09e4255f4 569 void HTTPServer::header(HTTPServer::HeaderCodes code, const char * code_text, const char * content_type, const char * optional_text)
WiredHome 0:729320f63c5c 570 {
WiredHome 0:729320f63c5c 571 char http[100];
WiredHome 0:729320f63c5c 572
WiredHome 50:10db483f5154 573 if (optional_text == NULL)
WiredHome 50:10db483f5154 574 optional_text = "";
WiredHome 53:e5d96abe5e9b 575 INFO("header(%d, %s, %s, %s)", code, code_text, content_type, optional_text);
WiredHome 44:71f09e4255f4 576 snprintf(http, sizeof(http), "%s %i %s\r\n", hdr_httpver, code, code_text);
WiredHome 0:729320f63c5c 577 send(http);
WiredHome 0:729320f63c5c 578 if (content_type) {
WiredHome 0:729320f63c5c 579 send(content_type);
WiredHome 0:729320f63c5c 580 }
WiredHome 50:10db483f5154 581 if (*optional_text != '\0') {
WiredHome 50:10db483f5154 582 send(optional_text);
WiredHome 44:71f09e4255f4 583 } else {
WiredHome 50:10db483f5154 584 if (strlen(hdr_age) + strlen(hdr_server) + strlen(hdr_close) + strlen(nl) < sizeof(http)) {
WiredHome 58:5303e962f711 585 strcpy_s(http, 100, hdr_age);
WiredHome 58:5303e962f711 586 strcat_s(http, 100, hdr_server);
WiredHome 58:5303e962f711 587 strcat_s(http, 100, hdr_close);
WiredHome 58:5303e962f711 588 strcat_s(http, 100, nl);
WiredHome 50:10db483f5154 589 send(http);
WiredHome 50:10db483f5154 590 } else {
WiredHome 50:10db483f5154 591 send(hdr_age);
WiredHome 50:10db483f5154 592 send(hdr_server);
WiredHome 50:10db483f5154 593 send(hdr_close);
WiredHome 50:10db483f5154 594 send(nl);
WiredHome 50:10db483f5154 595 }
WiredHome 0:729320f63c5c 596 }
WiredHome 0:729320f63c5c 597 }
WiredHome 0:729320f63c5c 598
WiredHome 44:71f09e4255f4 599 void HTTPServer::header(const char * partialheader)
WiredHome 44:71f09e4255f4 600 {
WiredHome 44:71f09e4255f4 601 if (!partialheader || *partialheader == '\0')
WiredHome 44:71f09e4255f4 602 send(nl);
WiredHome 44:71f09e4255f4 603 else
WiredHome 44:71f09e4255f4 604 send(partialheader);
WiredHome 44:71f09e4255f4 605 }
WiredHome 14:19c5f6151319 606
WiredHome 7:99ad7a67f05e 607 bool HTTPServer::close_connection()
WiredHome 0:729320f63c5c 608 {
WiredHome 7:99ad7a67f05e 609 bool res;
WiredHome 7:99ad7a67f05e 610
Sissors 41:6f2f1fb96742 611 res = client.close();
WiredHome 27:90a1f5a5392f 612 INFO("close connection returned %d", res);
WiredHome 7:99ad7a67f05e 613 return res;
WiredHome 0:729320f63c5c 614 }
WiredHome 0:729320f63c5c 615
WiredHome 14:19c5f6151319 616
WiredHome 0:729320f63c5c 617 bool HTTPServer::Extract(char * haystack, char * needle, char ** string)
WiredHome 0:729320f63c5c 618 {
WiredHome 0:729320f63c5c 619 bool ret = false; // assume failure until proven otherwise
WiredHome 0:729320f63c5c 620 char * qs = NULL;
WiredHome 0:729320f63c5c 621 char * eqs = NULL;
WiredHome 0:729320f63c5c 622 char * container = NULL;
WiredHome 0:729320f63c5c 623 char * get = strstr(haystack, needle); // what if not at the front?
WiredHome 44:71f09e4255f4 624
WiredHome 0:729320f63c5c 625 if (get) {
WiredHome 44:71f09e4255f4 626 // Seems to be a valid "GET /QueryString HTTP/1.1"
WiredHome 44:71f09e4255f4 627 // or "POST /upnp/control/metainfo1 HTTP/1.0"
WiredHome 8:262583f054f6 628 // or "...<needle>param..."
WiredHome 0:729320f63c5c 629 qs = get + strlen(needle); // in case the needle didn't have space delimiters
WiredHome 0:729320f63c5c 630 while (*qs == ' ')
WiredHome 0:729320f63c5c 631 qs++;
WiredHome 0:729320f63c5c 632 // /QueryString\0HTTP/1.1\0\0
WiredHome 0:729320f63c5c 633 if (*string) // recycle old string when working a new one
WiredHome 8:262583f054f6 634 myfree(*string);
WiredHome 58:5303e962f711 635 int ctSize = strlen(qs);
WiredHome 58:5303e962f711 636 container = (char *)mymalloc(ctSize);
WiredHome 0:729320f63c5c 637 if (container) {
WiredHome 58:5303e962f711 638 strcpy_s(container, ctSize, qs);
WiredHome 0:729320f63c5c 639 eqs = strchr(container, ' ');
WiredHome 0:729320f63c5c 640 if (eqs)
WiredHome 0:729320f63c5c 641 *eqs = '\0';
WiredHome 0:729320f63c5c 642 *string = container;
WiredHome 27:90a1f5a5392f 643 INFO("Extract(%s) = %s", needle, container);
WiredHome 0:729320f63c5c 644 ret = true;
WiredHome 0:729320f63c5c 645 } else {
WiredHome 0:729320f63c5c 646 *string = NULL; // something bad happened... no memory
WiredHome 0:729320f63c5c 647 }
WiredHome 0:729320f63c5c 648 }
WiredHome 0:729320f63c5c 649 return ret;
WiredHome 0:729320f63c5c 650 }
WiredHome 0:729320f63c5c 651
WiredHome 14:19c5f6151319 652
WiredHome 0:729320f63c5c 653 char * HTTPServer::rewriteWithDefaultFile(char * queryString)
WiredHome 0:729320f63c5c 654 {
WiredHome 58:5303e962f711 655 int tSize = strlen(queryString) + strlen(DEFAULT_FILENAME) + 1;
WiredHome 58:5303e962f711 656 char * temp = (char *)mymalloc(tSize);
WiredHome 0:729320f63c5c 657
WiredHome 0:729320f63c5c 658 if (temp) {
WiredHome 0:729320f63c5c 659 *temp = '\0';
WiredHome 58:5303e962f711 660 strcpy_s(temp, tSize, queryString);
WiredHome 58:5303e962f711 661 strcat_s(temp, tSize, DEFAULT_FILENAME);
WiredHome 8:262583f054f6 662 myfree(queryString);
WiredHome 0:729320f63c5c 663 return temp;
WiredHome 0:729320f63c5c 664 } else {
WiredHome 0:729320f63c5c 665 return queryString;
WiredHome 0:729320f63c5c 666 }
WiredHome 0:729320f63c5c 667 }
WiredHome 0:729320f63c5c 668
WiredHome 14:19c5f6151319 669
WiredHome 0:729320f63c5c 670 char * HTTPServer::rewritePrependWebroot(char * queryString)
WiredHome 0:729320f63c5c 671 {
WiredHome 58:5303e962f711 672 int tSize = strlen(webroot) + strlen(queryString) + 2;
WiredHome 58:5303e962f711 673 char * temp = (char *)mymalloc(tSize); // save room for '/'
WiredHome 0:729320f63c5c 674
WiredHome 0:729320f63c5c 675 if (temp) {
WiredHome 24:062431453abb 676 char *lastC;
WiredHome 0:729320f63c5c 677 *temp = '\0';
WiredHome 58:5303e962f711 678 strcpy_s(temp, tSize, webroot);
WiredHome 24:062431453abb 679 lastC = &temp[strlen(temp)-1];
WiredHome 24:062431453abb 680 if (*lastC == '/' && *queryString == '/')
WiredHome 24:062431453abb 681 queryString++; // don't create two '/'
WiredHome 24:062431453abb 682 else if (*lastC != '/' && *queryString != '/')
WiredHome 58:5303e962f711 683 strcat_s(temp, tSize, "/");
WiredHome 58:5303e962f711 684 strcat_s(temp, tSize, queryString);
WiredHome 8:262583f054f6 685 myfree(queryString);
WiredHome 0:729320f63c5c 686 return temp;
WiredHome 0:729320f63c5c 687 } else {
WiredHome 0:729320f63c5c 688 return queryString;
WiredHome 0:729320f63c5c 689 }
WiredHome 0:729320f63c5c 690 }
WiredHome 0:729320f63c5c 691
WiredHome 14:19c5f6151319 692
WiredHome 3:17928786bdb5 693 bool HTTPServer::CheckDynamicHandlers()
WiredHome 3:17928786bdb5 694 {
WiredHome 3:17928786bdb5 695 bool regHandled = false;
WiredHome 0:729320f63c5c 696
WiredHome 3:17928786bdb5 697 // If this queryString is in the list of registered handlers, call that
WiredHome 59:9a71ac02c782 698 for (ndxActiveHandler=0; ndxActiveHandler<handlercount; ndxActiveHandler++) {
WiredHome 59:9a71ac02c782 699 if (strcmp(handlers[ndxActiveHandler].path, queryString) == 0) {
WiredHome 59:9a71ac02c782 700 INFO("CheckDynamicHandlers - SEND_PAGE %s", handlers[ndxActiveHandler].path);
WiredHome 59:9a71ac02c782 701 (*handlers[ndxActiveHandler].callback)(this, SEND_PAGE, queryString, queryParams, queryParamCount);
WiredHome 3:17928786bdb5 702 regHandled = true;
WiredHome 59:9a71ac02c782 703 ndxActiveHandler = -1;
WiredHome 3:17928786bdb5 704 break; // we only execute the first one
WiredHome 3:17928786bdb5 705 }
WiredHome 3:17928786bdb5 706 }
WiredHome 3:17928786bdb5 707 return regHandled;
WiredHome 3:17928786bdb5 708 }
WiredHome 3:17928786bdb5 709
WiredHome 14:19c5f6151319 710
WiredHome 3:17928786bdb5 711 void HTTPServer::SendResponse()
WiredHome 3:17928786bdb5 712 {
WiredHome 58:5303e962f711 713 INFO("SendResponse(%5s) at %8u us",
WiredHome 58:5303e962f711 714 queryType, (unsigned int)PerformanceTimer.read_us());
WiredHome 44:71f09e4255f4 715 if (strcmp(queryType, "GET ") == 0 || strcmp(queryType, "POST ") == 0) {
WiredHome 3:17928786bdb5 716 if (!(queryString[0] == '.' && queryString[1] == '.')) {
WiredHome 3:17928786bdb5 717 const char * fType;
WiredHome 3:17928786bdb5 718
WiredHome 3:17928786bdb5 719 if (!CheckDynamicHandlers()) {
WiredHome 3:17928786bdb5 720 // Otherwise, this queryString must be trying to reference a static file
WiredHome 3:17928786bdb5 721 if (queryString[strlen(queryString)-1] == '/') {
WiredHome 3:17928786bdb5 722 queryString = rewriteWithDefaultFile(queryString);
WiredHome 3:17928786bdb5 723 }
WiredHome 44:71f09e4255f4 724 INFO(" queryString: %s", queryString);
WiredHome 3:17928786bdb5 725 // see if we support this file type
WiredHome 3:17928786bdb5 726 fType = GetSupportedType(queryString);
WiredHome 3:17928786bdb5 727 if (fType) {
WiredHome 3:17928786bdb5 728 queryString = rewritePrependWebroot(queryString);
WiredHome 44:71f09e4255f4 729 INFO(" SendFile(%s,%s)", queryString, fType);
WiredHome 3:17928786bdb5 730 SendFile(queryString, fType);
WiredHome 3:17928786bdb5 731 } else {
WiredHome 44:71f09e4255f4 732 header(Not_Found, "Not Found", NULL, "Pragma: err - Unsupported type\r\n");
WiredHome 44:71f09e4255f4 733 header("");
WiredHome 3:17928786bdb5 734 }
WiredHome 3:17928786bdb5 735 }
WiredHome 3:17928786bdb5 736 } else {
WiredHome 44:71f09e4255f4 737 header(Bad_Request, "Bad Request", NULL, "Pragma: err - Unsupported path\r\n");
WiredHome 44:71f09e4255f4 738 header("");
WiredHome 3:17928786bdb5 739 }
WiredHome 3:17928786bdb5 740 } else {
WiredHome 44:71f09e4255f4 741 header(Bad_Request, "Bad Request", NULL, "Pragma: err - Unsupported query type\r\n");
WiredHome 44:71f09e4255f4 742 header("");
WiredHome 3:17928786bdb5 743 }
WiredHome 58:5303e962f711 744 INFO(" SendResponse complete at %8u us",
WiredHome 58:5303e962f711 745 (unsigned int)PerformanceTimer.read_us());
WiredHome 17:69ff00ce39f4 746
WiredHome 59:9a71ac02c782 747 if (postQueryString) {
WiredHome 59:9a71ac02c782 748 myfree(postQueryString);
WiredHome 59:9a71ac02c782 749 postQueryString = NULL;
WiredHome 59:9a71ac02c782 750 }
WiredHome 3:17928786bdb5 751 if (queryType) {
WiredHome 8:262583f054f6 752 myfree(queryType);
WiredHome 3:17928786bdb5 753 queryType = NULL;
WiredHome 3:17928786bdb5 754 }
WiredHome 3:17928786bdb5 755 if (queryString) {
WiredHome 8:262583f054f6 756 myfree(queryString);
WiredHome 3:17928786bdb5 757 queryString = NULL;
WiredHome 3:17928786bdb5 758 }
WiredHome 58:5303e962f711 759 INFO(" SendResponse free at %8u us",
WiredHome 58:5303e962f711 760 (unsigned int)PerformanceTimer.read_us());
WiredHome 3:17928786bdb5 761 }
WiredHome 3:17928786bdb5 762
WiredHome 14:19c5f6151319 763
WiredHome 29:00116fc9da74 764 HTTPServer::CallBackResults HTTPServer::ParseHeader(char * buffer)
WiredHome 3:17928786bdb5 765 {
WiredHome 3:17928786bdb5 766 char * dblCR;
WiredHome 29:00116fc9da74 767 CallBackResults advanceState = ACCEPT_ERROR;
WiredHome 3:17928786bdb5 768 int bytecount;
WiredHome 7:99ad7a67f05e 769
WiredHome 3:17928786bdb5 770 // Buffer could have partial, but the double \r\n is the key
WiredHome 13:8975d7928678 771 // GET /QueryString?this=that&sky=blue HTTP/1.1\r\n
WiredHome 8:262583f054f6 772 // GET /QueryString HTTP/1.1\r\nHost: 192.168.1.140\r\nCache-Con
WiredHome 8:262583f054f6 773 // GET /QueryString HTTP/1.1\r\nHost: 192.168.1.140\r\nCache-Control: max-age=0\r\n\r\n
WiredHome 39:0427544a5c08 774 // POST /dyn2 HTTP/1.2\r\nAccept: text/html, application/xhtml+xml, */*\r\n\r\n
WiredHome 3:17928786bdb5 775 dblCR = strstr(buffer,"\r\n\r\n");
WiredHome 3:17928786bdb5 776 if (dblCR) { // Have to scan from the beginning in case split on \r
WiredHome 44:71f09e4255f4 777 INFO("\r\n==\r\n%s\r\n==", buffer);
WiredHome 3:17928786bdb5 778 char * soRec = buffer; // start of the next record of text
WiredHome 13:8975d7928678 779 char * eoRec = strchr(soRec, '\n'); // search for end of the current record
WiredHome 7:99ad7a67f05e 780
WiredHome 13:8975d7928678 781 headerParamCount = 0;
WiredHome 3:17928786bdb5 782 bytecount = strlen(buffer);
WiredHome 3:17928786bdb5 783 if (bytecount > maxheaderbytes)
WiredHome 3:17928786bdb5 784 maxheaderbytes = bytecount;
WiredHome 3:17928786bdb5 785 while (eoRec) {
WiredHome 3:17928786bdb5 786 *eoRec = '\0';
WiredHome 3:17928786bdb5 787 if (*(eoRec-1) == '\r')
WiredHome 3:17928786bdb5 788 *(eoRec-1) = '\0';
WiredHome 44:71f09e4255f4 789 INFO("method: %s", soRec);
WiredHome 44:71f09e4255f4 790 #if 1
WiredHome 44:71f09e4255f4 791 const QueryMethod * qm = QueryMethodList;
WiredHome 44:71f09e4255f4 792 while (*qm->queryType) {
WiredHome 44:71f09e4255f4 793 if (strstr(soRec, qm->queryType) == soRec) {
WiredHome 44:71f09e4255f4 794 Extract(soRec, qm->queryType, &queryString);
WiredHome 44:71f09e4255f4 795 if (queryString) {
WiredHome 58:5303e962f711 796 int qSize = strlen(qm->queryType)+1;
WiredHome 58:5303e962f711 797 queryType = (char *)mymalloc(qSize);
WiredHome 58:5303e962f711 798 strcpy_s(queryType, qSize, qm->queryType);
WiredHome 44:71f09e4255f4 799 }
WiredHome 44:71f09e4255f4 800 }
WiredHome 44:71f09e4255f4 801 qm++;
WiredHome 44:71f09e4255f4 802 }
WiredHome 44:71f09e4255f4 803 #else
WiredHome 8:262583f054f6 804 // Inspect the supported query types (GET, POST) and ignore (HEAD, PUT, OPTION, DELETE, TRACE, CONNECT]
WiredHome 44:71f09e4255f4 805 // This is presently very clumsy
WiredHome 44:71f09e4255f4 806 if (strstr(soRec, "GET ") == soRec) {
WiredHome 8:262583f054f6 807 Extract(soRec, "GET", &queryString);
WiredHome 8:262583f054f6 808 if (queryString) {
WiredHome 58:5303e962f711 809 int qSize = strlen("GET")+1;
WiredHome 58:5303e962f711 810 queryType = (char *)mymalloc(qSize);
WiredHome 58:5303e962f711 811 strcpy_s(queryType, qSize, "GET");
WiredHome 8:262583f054f6 812 }
WiredHome 8:262583f054f6 813 } else if (strstr(soRec, "POST ") == soRec) {
WiredHome 39:0427544a5c08 814 Extract(soRec, "POST", &queryString);
WiredHome 8:262583f054f6 815 if (queryString) {
WiredHome 58:5303e962f711 816 int qSize = strlen("POST")+1;
WiredHome 58:5303e962f711 817 queryType = (char *)mymalloc(qSize);
WiredHome 58:5303e962f711 818 strcpy_s(queryType, qSize, "POST");
WiredHome 8:262583f054f6 819 }
WiredHome 10:9c8d2c6a3469 820 }
WiredHome 44:71f09e4255f4 821 #endif
WiredHome 44:71f09e4255f4 822
WiredHome 13:8975d7928678 823 // if there is a ": " delimiter, we have a header item to parse into name,value pair
WiredHome 13:8975d7928678 824 // "Connection: keep-alive" becomes "Connection" "keep-alive"
WiredHome 13:8975d7928678 825 char *delim = strstr(soRec, ": ");
WiredHome 13:8975d7928678 826 char *chkSpace = strchr(soRec, ' '); // a field-name has no space ahead of the ":"
WiredHome 44:71f09e4255f4 827 //INFO("hpc:%d,mhp:%d, {%s}", headerParamCount, maxheaderParams, soRec);
WiredHome 29:00116fc9da74 828 if (delim
WiredHome 29:00116fc9da74 829 && (!chkSpace || (chkSpace && delim < chkSpace))
WiredHome 29:00116fc9da74 830 && headerParamCount < maxheaderParams) {
WiredHome 14:19c5f6151319 831 *delim++ = '\0'; // replace ": " with null
WiredHome 13:8975d7928678 832 *delim++ = '\0';
WiredHome 13:8975d7928678 833 headerParams[headerParamCount].name = soRec;
WiredHome 13:8975d7928678 834 headerParams[headerParamCount].value = delim;
WiredHome 37:0cb2774e2410 835 INFO("%d: headerParams[%s] = {%s}", headerParamCount,
WiredHome 37:0cb2774e2410 836 headerParams[headerParamCount].name, headerParams[headerParamCount].value);
WiredHome 13:8975d7928678 837 headerParamCount++;
WiredHome 13:8975d7928678 838 }
WiredHome 3:17928786bdb5 839 soRec = eoRec + 1;
WiredHome 3:17928786bdb5 840 eoRec = strchr(soRec, '\n');
WiredHome 44:71f09e4255f4 841 if (soRec > dblCR) // Just walked past the end of the header
WiredHome 44:71f09e4255f4 842 break;
WiredHome 3:17928786bdb5 843 }
WiredHome 29:00116fc9da74 844
WiredHome 3:17928786bdb5 845 if (queryString) {
WiredHome 3:17928786bdb5 846 // We have enough to try to reply
WiredHome 37:0cb2774e2410 847 INFO("create reply queryType{%s}, queryString{%s}", queryType, queryString);
WiredHome 13:8975d7928678 848 // parse queryParams - if any
WiredHome 3:17928786bdb5 849 // /file.htm?name1=value1&name2=value2...
WiredHome 3:17928786bdb5 850 // /file.htm?name1&name2=value2...
WiredHome 13:8975d7928678 851 queryParamCount = 0;
WiredHome 3:17928786bdb5 852 char * paramDelim = strchr(queryString, '?');
WiredHome 3:17928786bdb5 853 if (paramDelim) {
WiredHome 3:17928786bdb5 854 *paramDelim++ = '\0';
WiredHome 3:17928786bdb5 855 UnescapeString(paramDelim); // everything after the '?'
WiredHome 39:0427544a5c08 856 ParseParameters(queryParams, &queryParamCount, maxqueryParams, paramDelim); // pointing past the NULL, and there are queryParams here
WiredHome 3:17928786bdb5 857 }
WiredHome 3:17928786bdb5 858 } else {
WiredHome 29:00116fc9da74 859 ERR("queryString not found in (%s) [this should never happen]", soRec);
WiredHome 3:17928786bdb5 860 }
WiredHome 44:71f09e4255f4 861 advanceState = ACCEPT_COMPLETE; // Should be ACCEPT_CONTINUE and the stuff below moves out of here
WiredHome 3:17928786bdb5 862 buffer[0] = 0;
WiredHome 3:17928786bdb5 863
WiredHome 3:17928786bdb5 864 // This part parses the extra data on a POST method.
WiredHome 3:17928786bdb5 865 // Since there has to be a dynamic handler registered for this
WiredHome 3:17928786bdb5 866 // it would make sense to move some of this responsibility to
WiredHome 3:17928786bdb5 867 // that handler. It could then choose if it wanted to allocate
WiredHome 3:17928786bdb5 868 // the requested 'Content-Length' amount of memory.
WiredHome 13:8975d7928678 869 int postBytes = atoi(GetHeaderValue("Content-Length"));
WiredHome 28:f93ef41b78e1 870 CallBackResults acceptIt = ACCEPT_ERROR;
WiredHome 44:71f09e4255f4 871 INFO("Content-Length: %d", postBytes);
WiredHome 44:71f09e4255f4 872 if (strcmp(queryType, "POST ") == 0 ) {
WiredHome 44:71f09e4255f4 873 INFO("parse POST data %d bytes", postBytes); // We might have no idea how much data is coming...
WiredHome 44:71f09e4255f4 874 int ndxHandler = 0;
WiredHome 44:71f09e4255f4 875 bool regHandled = false;
WiredHome 44:71f09e4255f4 876 // Registered Dynamic Handler
WiredHome 44:71f09e4255f4 877 // Callback and ask if they want to accept this data
WiredHome 44:71f09e4255f4 878 for (ndxHandler=0; ndxHandler<handlercount; ndxHandler++) {
WiredHome 44:71f09e4255f4 879 INFO("is '%s' a handler for '%s' ?", handlers[ndxHandler].path, queryString);
WiredHome 44:71f09e4255f4 880 if (strcmp(handlers[ndxHandler].path, queryString) == 0) {
WiredHome 44:71f09e4255f4 881 acceptIt = (*handlers[ndxHandler].callback)(this, CONTENT_LENGTH_REQUEST, queryString, queryParams, queryParamCount);
WiredHome 44:71f09e4255f4 882 regHandled = true;
WiredHome 44:71f09e4255f4 883 break; // only one callback per path allowed
WiredHome 3:17928786bdb5 884 }
WiredHome 44:71f09e4255f4 885 }
WiredHome 44:71f09e4255f4 886 INFO("reghandled: %d, acceptIt: %d", regHandled, acceptIt);
WiredHome 44:71f09e4255f4 887 if (regHandled && acceptIt != ACCEPT_ERROR) {
WiredHome 44:71f09e4255f4 888 // @todo need to refactor - if the thing is bigger than the buffer,
WiredHome 44:71f09e4255f4 889 // then we can receive it a chunk at a time, and hand off
WiredHome 44:71f09e4255f4 890 // the chunks to the callback. May need callbacks that
WiredHome 44:71f09e4255f4 891 // are: DATA_TRANSFER: self-detect to extract the filename/object name,
WiredHome 44:71f09e4255f4 892 // DATA_TRANSFER: subsequent chunk of data,
WiredHome 44:71f09e4255f4 893 // DATA_TRANSFER_END: signals that last chunk is enclosed.
WiredHome 44:71f09e4255f4 894 //
WiredHome 44:71f09e4255f4 895 // If so, we'll make space for it
WiredHome 44:71f09e4255f4 896 postQueryString = (char *)mymalloc(CHUNK_SIZE);
WiredHome 44:71f09e4255f4 897 //INFO("Free space %d", Free());
WiredHome 44:71f09e4255f4 898 INFO("postQueryString %p", postQueryString);
WiredHome 44:71f09e4255f4 899 if (postQueryString) {
WiredHome 44:71f09e4255f4 900 int len = 0;
WiredHome 44:71f09e4255f4 901 int ttlCount;
WiredHome 44:71f09e4255f4 902 Timer escapePlan;
WiredHome 44:71f09e4255f4 903 bool escape = false;
WiredHome 44:71f09e4255f4 904
WiredHome 44:71f09e4255f4 905 INFO("Processing tail...");
WiredHome 44:71f09e4255f4 906 escapePlan.start();
WiredHome 44:71f09e4255f4 907 dblCR += 4; // There may be some after the double CR that we need
WiredHome 44:71f09e4255f4 908 ttlCount = strlen(dblCR);
WiredHome 58:5303e962f711 909 strcpy_s(postQueryString, CHUNK_SIZE, dblCR);
WiredHome 59:9a71ac02c782 910 INFO(" {%s}", postQueryString);
WiredHome 44:71f09e4255f4 911 while ((!postBytes || ttlCount < postBytes) && !escape) {
WiredHome 44:71f09e4255f4 912 INFO("ttlCount: %d < postBytes: %d, of max chunk alloc %d", ttlCount, postBytes, CHUNK_SIZE);
WiredHome 44:71f09e4255f4 913 len = client.receive(postQueryString + ttlCount, CHUNK_SIZE - ttlCount);
WiredHome 44:71f09e4255f4 914 if (len > 0) {
WiredHome 44:71f09e4255f4 915 ttlCount += len;
WiredHome 44:71f09e4255f4 916 postQueryString[ttlCount] = '\0'; // Whether binary or ASCII, this is ok as it's after the data
WiredHome 44:71f09e4255f4 917 INFO(" postBytes %d: [%s], [%d]", postBytes, postQueryString, ndxHandler);
WiredHome 44:71f09e4255f4 918 escapePlan.reset();
WiredHome 44:71f09e4255f4 919 } else if (len < 0) {
WiredHome 44:71f09e4255f4 920 INFO("*** connection closed ***");
WiredHome 44:71f09e4255f4 921 break; // no more data, before the plan
WiredHome 44:71f09e4255f4 922 } else { // n == 0
WiredHome 44:71f09e4255f4 923 ;
WiredHome 3:17928786bdb5 924 }
WiredHome 44:71f09e4255f4 925 if (escapePlan.read_ms() > HANG_TIMEOUT_MS) { // if no Content-Length, we wait...
WiredHome 44:71f09e4255f4 926 escape = true;
WiredHome 44:71f09e4255f4 927 WARN("Escape plan activated.");
WiredHome 44:71f09e4255f4 928 }
WiredHome 44:71f09e4255f4 929 if (postBytes > 0 && ttlCount >= postBytes)
WiredHome 44:71f09e4255f4 930 break;
WiredHome 3:17928786bdb5 931 }
WiredHome 44:71f09e4255f4 932 //postParamCount = 0;
WiredHome 59:9a71ac02c782 933 INFO("post: %s", postQueryString);
WiredHome 44:71f09e4255f4 934 //We're after the header, so there is "body" stuff which could be anything...
WiredHome 44:71f09e4255f4 935 //but probably html or xml stuff...
WiredHome 44:71f09e4255f4 936 //ParseParameters(postParams, &postParamCount, maxPostParams, postQueryString);
WiredHome 44:71f09e4255f4 937 acceptIt = (*handlers[ndxHandler].callback)(this, DATA_TRANSFER, postQueryString, NULL, ttlCount);
WiredHome 59:9a71ac02c782 938 INFO("..processing exit [%d]", acceptIt);
WiredHome 44:71f09e4255f4 939 acceptIt = (*handlers[ndxHandler].callback)(this, DATA_TRANSFER_END, NULL, NULL, 0);
WiredHome 59:9a71ac02c782 940 INFO("..transfer end[%d]", acceptIt);
WiredHome 3:17928786bdb5 941 } else {
WiredHome 44:71f09e4255f4 942 ERR("attempt to allocate %d failed.", CHUNK_SIZE);
WiredHome 44:71f09e4255f4 943 }
WiredHome 44:71f09e4255f4 944 } else {
WiredHome 44:71f09e4255f4 945 // Simply copy it to the bitbucket
WiredHome 44:71f09e4255f4 946 WARN("No handler, so to the bit bucket it goes ...");
WiredHome 44:71f09e4255f4 947 int bytesToDump = postBytes;
WiredHome 44:71f09e4255f4 948 char * bitbucket = (char *)mymalloc(201);
WiredHome 44:71f09e4255f4 949
WiredHome 44:71f09e4255f4 950 dblCR += 4;
WiredHome 44:71f09e4255f4 951 while (*dblCR && *dblCR <= ' ')
WiredHome 44:71f09e4255f4 952 dblCR++;
WiredHome 44:71f09e4255f4 953 bytesToDump -= strlen(dblCR);
WiredHome 44:71f09e4255f4 954 while (bytesToDump > 0) {
WiredHome 44:71f09e4255f4 955 int n = (bytesToDump > 200) ? 200 : bytesToDump;
WiredHome 44:71f09e4255f4 956 n = client.receive(bitbucket, n);
WiredHome 44:71f09e4255f4 957 if (n < 0) {
WiredHome 44:71f09e4255f4 958 ERR("to the bitbucket.");
WiredHome 44:71f09e4255f4 959 break;
WiredHome 3:17928786bdb5 960 }
WiredHome 44:71f09e4255f4 961 bytesToDump -= n;
WiredHome 3:17928786bdb5 962 }
WiredHome 44:71f09e4255f4 963 myfree(bitbucket);
WiredHome 3:17928786bdb5 964 }
WiredHome 3:17928786bdb5 965 }
WiredHome 3:17928786bdb5 966 }
WiredHome 3:17928786bdb5 967 return advanceState;
WiredHome 3:17928786bdb5 968 }
WiredHome 3:17928786bdb5 969
WiredHome 14:19c5f6151319 970
WiredHome 27:90a1f5a5392f 971
WiredHome 13:8975d7928678 972 const char * HTTPServer::GetHeaderValue(const char * hdr)
WiredHome 13:8975d7928678 973 {
WiredHome 13:8975d7928678 974 int i;
WiredHome 29:00116fc9da74 975
WiredHome 29:00116fc9da74 976 for (i=0; i<headerParamCount; i++) {
WiredHome 13:8975d7928678 977 if (strcmp(hdr, headerParams[i].name) == 0)
WiredHome 13:8975d7928678 978 return headerParams[i].value;
WiredHome 29:00116fc9da74 979 }
WiredHome 13:8975d7928678 980 return NULL;
WiredHome 13:8975d7928678 981 }
WiredHome 13:8975d7928678 982
WiredHome 12:109bf1558300 983
WiredHome 7:99ad7a67f05e 984 void HTTPServer::GetPerformanceData(SW_PerformanceData * p)
WiredHome 7:99ad7a67f05e 985 {
WiredHome 3:17928786bdb5 986 memcpy(p, &perfData, sizeof(perfData));
WiredHome 3:17928786bdb5 987 }
WiredHome 3:17928786bdb5 988
WiredHome 17:69ff00ce39f4 989 unsigned int HTTPServer::GetPerformanceClock()
WiredHome 17:69ff00ce39f4 990 {
WiredHome 17:69ff00ce39f4 991 return (unsigned int)PerformanceTimer.read_us();
WiredHome 17:69ff00ce39f4 992 }
WiredHome 14:19c5f6151319 993
WiredHome 16:6ebacf2946d8 994 unsigned int HTTPServer::RecordPerformanceData(SW_PerformanceParam * param, unsigned int refTime)
WiredHome 7:99ad7a67f05e 995 {
WiredHome 16:6ebacf2946d8 996 unsigned int t_now = (unsigned int)PerformanceTimer.read_us();
WiredHome 3:17928786bdb5 997 param->TotalTime_us += (t_now - refTime);
WiredHome 3:17928786bdb5 998 param->Samples++;
WiredHome 3:17928786bdb5 999 if ((t_now - refTime) > param->MaxTime_us)
WiredHome 3:17928786bdb5 1000 param->MaxTime_us = (t_now - refTime);
WiredHome 3:17928786bdb5 1001 return t_now;
WiredHome 3:17928786bdb5 1002 }
WiredHome 3:17928786bdb5 1003
WiredHome 14:19c5f6151319 1004
WiredHome 7:99ad7a67f05e 1005 void HTTPServer::ResetPerformanceData()
WiredHome 7:99ad7a67f05e 1006 {
WiredHome 3:17928786bdb5 1007 memset(&perfData, 0, sizeof(perfData));
WiredHome 3:17928786bdb5 1008 }
WiredHome 3:17928786bdb5 1009