A simple web server that can be bound to either the EthernetInterface or the WiflyInterface.
Dependents: Smart-WiFly-WebServer WattEye X10Svr SSDP_Server
Diff: SW_HTTPServer.cpp
- Revision:
- 37:0cb2774e2410
- Parent:
- 36:1bb5fa6b109c
- Child:
- 38:c8fa31e6fe02
diff -r 1bb5fa6b109c -r 0cb2774e2410 SW_HTTPServer.cpp --- a/SW_HTTPServer.cpp Fri May 02 00:26:06 2014 +0000 +++ b/SW_HTTPServer.cpp Sun May 11 21:16:42 2014 +0000 @@ -17,20 +17,6 @@ #include "SW_HTTPServer.h" // define DEBUG before this -#if 0 -#if (defined(DEBUG) && !defined(TARGET_LPC11U24)) -#define DBG(x, ...) pc->printf("[DBG %s%4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); -#define WARN(x, ...) pc->printf("[WRN %s%4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); -#define ERR(x, ...) pc->printf("[ERR %s%4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); -#define INFO(x, ...) pc->printf("[INF %s%4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); -#else -#define DBG(x, ...) -#define WARN(x, ...) -#define ERR(x, ...) -#define INFO(x, ...) -#endif -#endif - #define CHUNK_SIZE 1500 // max size of a single chunk (probably limited by Ethernet to 1500) #define HANG_TIMEOUT_MS 250 // If we're waiting on the host, which may never respond, this is the timeout @@ -368,17 +354,21 @@ const char * HTTPServer::GetParameter(const char * name) { + INFO("GetParameter(%s)", name); for (int i=0; i<queryParamCount; i++) { + INFO(" %d: %s = %s", i, queryParams[i].name, queryParams[i].value); if (strcmp(queryParams[i].name, name) == 0) { + INFO(" value {%s}", queryParams[i].value); return queryParams[i].value; } } return NULL; } + // this=that&who=what&more=stuff... // ^ ^ ^ -void HTTPServer::ParseParameters(char * pName) +int HTTPServer::ParseParameters(char * pName) { char * pVal; char * pNextName; @@ -388,6 +378,7 @@ if (pVal) *pVal = '\0'; do { + INFO("ParseParameters(%s)", pName); queryParams[queryParamCount].name = pName; pVal = strchr(pName, '='); pNextName = strchr(pName,'&'); @@ -398,14 +389,17 @@ pName = pVal; } } - queryParamCount++; if (pNextName) { pName = pNextName; *pName++ = '\0'; } else { pName = NULL; } + INFO(" param{%s}={%s}", queryParams[queryParamCount].name, queryParams[queryParamCount].value); + queryParamCount++; } while (pName && queryParamCount < maxqueryParams); + INFO(" count %d", queryParamCount); + return queryParamCount; } @@ -580,6 +574,7 @@ // GET /QueryString?this=that&sky=blue HTTP/1.1\r\n // GET /QueryString HTTP/1.1\r\nHost: 192.168.1.140\r\nCache-Con // GET /QueryString HTTP/1.1\r\nHost: 192.168.1.140\r\nCache-Control: max-age=0\r\n\r\n + // POST /dyn2 HTTP/1.2\r\nAccept: text/html, application/xhtml+xml, */*\r\n\r\nle dblCR = strstr(buffer,"\r\n\r\n"); if (dblCR) { // Have to scan from the beginning in case split on \r INFO("\r\n==\r\n%s==", buffer); @@ -596,14 +591,15 @@ *(eoRec-1) = '\0'; // Inspect the supported query types (GET, POST) and ignore (HEAD, PUT, OPTION, DELETE, TRACE, CONNECT] // This is very clumsy - if (strstr(soRec, "GET ") == soRec) { + INFO("method: %s", soRec); + if (strstr(soRec, "GET ") == soRec) { Extract(soRec, "GET", &queryString); if (queryString) { queryType = (char *)mymalloc(strlen("GET")+1); strcpy(queryType, "GET"); } } else if (strstr(soRec, "POST ") == soRec) { - Extract(soRec, "POST", &queryString); + Extract(soRec, "POST", &queryString); if (queryString) { queryType = (char *)mymalloc(strlen("POST")+1); strcpy(queryType, "POST"); @@ -621,8 +617,8 @@ *delim++ = '\0'; headerParams[headerParamCount].name = soRec; headerParams[headerParamCount].value = delim; - //INFO("%d: headerParams[%s] = {%s}", headerParamCount, - // headerParams[headerParamCount].name, headerParams[headerParamCount].value); + INFO("%d: headerParams[%s] = {%s}", headerParamCount, + headerParams[headerParamCount].name, headerParams[headerParamCount].value); headerParamCount++; } soRec = eoRec + 1; @@ -631,7 +627,7 @@ if (queryString) { // We have enough to try to reply - INFO("create reply queryType{%s}, queryString{%s}", "GET", queryString); + INFO("create reply queryType{%s}, queryString{%s}", queryType, queryString); // parse queryParams - if any // /file.htm?name1=value1&name2=value2... // /file.htm?name1&name2=value2... @@ -640,7 +636,7 @@ if (paramDelim) { *paramDelim++ = '\0'; UnescapeString(paramDelim); // everything after the '?' - ParseParameters(paramDelim); // pointing at the NULL, but there are queryParams beyond + ParseParameters(paramDelim); // pointing past the NULL, and there are queryParams here } } else { ERR("queryString not found in (%s) [this should never happen]", soRec); @@ -656,19 +652,21 @@ int postBytes = atoi(GetHeaderValue("Content-Length")); CallBackResults acceptIt = ACCEPT_ERROR; if (strcmp(queryType, "POST") == 0 && postBytes > 0 ) { + INFO("parse POST data %d bytes", postBytes); if (postBytes) { int ndxHandler = 0; bool regHandled = false; // Registered Dynamic Handler // Callback and ask if they want to accept this data for (ndxHandler=0; ndxHandler<handlercount; ndxHandler++) { + INFO("is '%s' a handler for '%s' ?", handlers[ndxHandler].path, queryString); if (strcmp(handlers[ndxHandler].path, queryString) == 0) { acceptIt = (*handlers[ndxHandler].callback)(this, CONTENT_LENGTH_REQUEST, queryString, queryParams, queryParamCount); regHandled = true; break; // only one callback per path allowed } } - + INFO("reghandled: %d, acceptIt: %d", regHandled, acceptIt); if (regHandled && acceptIt != ACCEPT_ERROR) { // @todo need to refactor - if the thing is bigger than the buffer, // then we can receive it a chunk at a time, and hand off @@ -679,22 +677,28 @@ // // If so, we'll make space for it postQueryString = (char *)mymalloc(CHUNK_SIZE); - INFO("Free space %d", Free()); + //INFO("Free space %d", Free()); + INFO("postQueryString %p", postQueryString); if (postQueryString) { - int len; - int ttlCount = 4; // includes the doubleCR in the total count from Content-Length + int len = 0; + int ttlCount; Timer escapePlan; bool escape = false; + INFO("Processing tail..."); escapePlan.start(); - //INFO("Processing"); - while (ttlCount < postBytes && !escape) { - len = client.receive_all(postQueryString, CHUNK_SIZE); + dblCR += 4; // There may be some after the double CR that we need + ttlCount = strlen(dblCR); + strcpy(postQueryString, dblCR); + INFO(" {%s}", postQueryString); + while (ttlCount <= postBytes && !escape) { + INFO("ttlCount: %d < postBytes: %d, of chunk %d", ttlCount, postBytes, CHUNK_SIZE); + len = client.receive_all(postQueryString + ttlCount, CHUNK_SIZE - ttlCount); if (len > 0) { + INFO(" len: %d, ttlCount: %d < postBytes %d, {%s}", len, ttlCount, postBytes, postQueryString); ttlCount += len; postQueryString[len] = '\0'; // Whether binary or ASCII, this is ok as it's after the data - //INFO("%d bytes is %d of %d: [%s]", len, ttlCount, postBytes, postQueryString); - acceptIt = (*handlers[ndxHandler].callback)(this, DATA_TRANSFER, postQueryString, NULL, len); + INFO(" postBytes %d: [%s], [%d]", postBytes, postQueryString, ndxHandler); escapePlan.reset(); } else if (len < 0) { INFO("*** connection closed ***"); @@ -707,7 +711,8 @@ WARN("Escape plan activated."); } } - //INFO("..processing exit"); + acceptIt = (*handlers[ndxHandler].callback)(this, DATA_TRANSFER, postQueryString, NULL, 0); + INFO("..processing exit"); acceptIt = (*handlers[ndxHandler].callback)(this, DATA_TRANSFER_END, NULL, NULL, 0); myfree(postQueryString); } else { @@ -715,6 +720,7 @@ } } else { // Simply copy it to the bitbucket + WARN("to the bit bucket..."); int bytesToDump = postBytes; char * bitbucket = (char *)mymalloc(201);