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:
- 27:90a1f5a5392f
- Parent:
- 26:38102ef2b132
- Child:
- 28:f93ef41b78e1
diff -r 38102ef2b132 -r 90a1f5a5392f SW_HTTPServer.cpp --- a/SW_HTTPServer.cpp Thu Oct 10 18:46:55 2013 +0000 +++ b/SW_HTTPServer.cpp Thu Oct 10 20:38:12 2013 +0000 @@ -14,7 +14,20 @@ #include "SW_HTTPServer.h" #include "Utility.h" -#define DEBUG +#define DEBUG "HTTP" + +#if (defined(DEBUG) && !defined(TARGET_LPC11U24)) +#define DBG(x, ...) std::printf("[DBG %s%4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); +#define WARN(x, ...) std::printf("[WRN %s%4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); +#define ERR(x, ...) std::printf("[ERR %s%4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); +#define INFO(x, ...) std::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 + const char * DEFAULT_FILENAME = "index.htm"; @@ -87,6 +100,8 @@ wifly = _wf; webroot = (char *)malloc(strlen(_webroot)+1); strcpy(webroot, _webroot); + if (strlen(webroot)>1 && webroot[strlen(webroot)-1] == '/') // remove trailing '/' + webroot[strlen(webroot)-1] = '\0'; maxqueryParams = _maxqueryParams; maxdynamicpages = _maxdynamicpages; headerParams = (namevalue *)malloc(maxheaderParams * sizeof(namevalue)); @@ -168,7 +183,7 @@ static state lastOp = Reset; if (lastOp != op) { const char *states[] = {"Idle", "Receiving", "Sending", "WaitingToClose", "Reset"}; - pc->printf("Poll: %s\r\n", states[op]); + INFO("Poll: %s", states[op]); lastOp = op; } #endif @@ -184,26 +199,20 @@ if (0 == server->accept(client)) { op = Receiving; t_ref = RecordPerformanceData(&perfData.ConnectionAccepted, t_ref); -#ifdef DEBUG - pc->printf("Accepted at %u\r\n", (unsigned int)PerformanceTimer.read_us()); -#endif + INFO("Accepted at %u", (unsigned int)PerformanceTimer.read_us()); } break; case Receiving: n = client.receive(bPtr, headerbuffersize - (bPtr - headerbuffer)); if (n < 0) { -#ifdef DEBUG - pc->printf("*** client.receive() => %d\r\n", n); -#endif + INFO("*** client.receive() => %d", n); } else if (n) { bPtr[n] = '\0'; if (ParseHeader(headerbuffer)) { op = Sending; t_ref = RecordPerformanceData(&perfData.HeaderParsed, t_ref); -#ifdef DEBUG - pc->printf("Header Parsed at %u\r\n", (unsigned int)PerformanceTimer.read_us()); -#endif + INFO("Header Parsed at %u", (unsigned int)PerformanceTimer.read_us()); } bPtr += n; } @@ -213,21 +222,15 @@ SendResponse(); op = WaitingToClose; t_ref = RecordPerformanceData(&perfData.ResponseSent, t_ref); -#ifdef DEBUG - pc->printf("Response Sent at %u\r\n", (unsigned int)PerformanceTimer.read_us()); -#endif + INFO("Response Sent at %u", (unsigned int)PerformanceTimer.read_us()); break; case WaitingToClose: -#ifdef DEBUG - pc->printf("Connection closed entry %u\r\n", (unsigned int)PerformanceTimer.read_us()); -#endif + INFO("Connection closed entry %u", (unsigned int)PerformanceTimer.read_us()); close_connection(); op = Idle; RecordPerformanceData(&perfData.ConnectionClosed, t_ref); -#ifdef DEBUG - pc->printf("Connection closed exit %u\r\n", (unsigned int)PerformanceTimer.read_us()); -#endif + INFO("Connection closed exit %u", (unsigned int)PerformanceTimer.read_us()); break; } } @@ -397,9 +400,7 @@ bool res; res = server->close(); -#ifdef DEBUG - pc->printf("close connection returned %d\r\n", res); -#endif + INFO("close connection returned %d", res); return res; } @@ -427,9 +428,7 @@ if (eqs) *eqs = '\0'; *string = container; -#ifdef DEBUG - pc->printf("Extract(%s) = %s\r\n", needle, container); -#endif + INFO("Extract(%s) = %s", needle, container); ret = true; } else { *string = NULL; // something bad happened... no memory @@ -495,9 +494,7 @@ void HTTPServer::SendResponse() { -#ifdef DEBUG - pc->printf("SendResponse(%s) at %u\r\n", queryType, (unsigned int)PerformanceTimer.read_us()); -#endif + INFO("SendResponse(%s) at %u", queryType, (unsigned int)PerformanceTimer.read_us()); if (strcmp(queryType, "GET") == 0 || strcmp(queryType, "POST") == 0) { if (!(queryString[0] == '.' && queryString[1] == '.')) { const char * fType; @@ -522,9 +519,7 @@ } else { header(400, "Bad Request", "Pragma: err - Unsupported query type\r\n"); } -#ifdef DEBUG - pc->printf(" SendResponse complete at %u\r\n", (unsigned int)PerformanceTimer.read_us()); -#endif + INFO(" SendResponse complete at %u", (unsigned int)PerformanceTimer.read_us()); if (queryType) { myfree(queryType); @@ -538,9 +533,7 @@ myfree(postQueryString); postQueryString = NULL; } -#ifdef DEBUG - pc->printf(" SendResponse free at %u\r\n", (unsigned int)PerformanceTimer.read_us()); -#endif + INFO(" SendResponse free at %u", (unsigned int)PerformanceTimer.read_us()); } @@ -556,9 +549,7 @@ // GET /QueryString HTTP/1.1\r\nHost: 192.168.1.140\r\nCache-Control: max-age=0\r\n\r\n dblCR = strstr(buffer,"\r\n\r\n"); if (dblCR) { // Have to scan from the beginning in case split on \r -#ifdef DEBUG - pc->printf("==\r\n%s==\r\n", buffer); -#endif + INFO("==\r\n%s==\r\n", buffer); char * soRec = buffer; // start of the next record of text char * eoRec = strchr(soRec, '\n'); // search for end of the current record @@ -597,10 +588,8 @@ *delim++ = '\0'; headerParams[headerParamCount].name = soRec; headerParams[headerParamCount].value = delim; -#ifdef DEBUG - pc->printf("%d: headerParams[%s] = {%s}\r\n", headerParamCount, + INFO("%d: headerParams[%s] = {%s}", headerParamCount, headerParams[headerParamCount].name, headerParams[headerParamCount].value); -#endif headerParamCount++; } soRec = eoRec + 1; @@ -608,9 +597,7 @@ } if (queryString) { // We have enough to try to reply -#ifdef DEBUG - pc->printf("create reply queryType{%s}, queryString{%s}\r\n", "GET", queryString); -#endif + INFO("create reply queryType{%s}, queryString{%s}", "GET", queryString); // parse queryParams - if any // /file.htm?name1=value1&name2=value2... // /file.htm?name1&name2=value2... @@ -622,7 +609,7 @@ ParseParameters(paramDelim); // pointing at the NULL, but there are queryParams beyond } } else { - pc->printf("ERROR: queryString not found in (%s)\r\n", soRec); + ERR("queryString not found in (%s)", soRec); } advanceState = true; buffer[0] = 0; @@ -638,18 +625,26 @@ bool acceptIt = false; if (strcmp(queryType, "POST") == 0 && postBytes > 0 ) { if (postBytes) { + int ndxHandler = 0; bool regHandled = false; // Registered Dynamic Handler // Callback and ask if they want to accept this data - for (int i=0; i<handlercount; i++) { - if (strcmp(handlers[i].path, queryString) == 0) { - acceptIt = (*handlers[i].callback)(this, CONTENT_LENGTH_REQUEST, queryString, queryParams, queryParamCount); + for (ndxHandler=0; ndxHandler<handlercount; ndxHandler++) { + if (strcmp(handlers[ndxHandler].path, queryString) == 0) { + acceptIt = (*handlers[ndxHandler].callback)(this, CONTENT_LENGTH_REQUEST, queryString, queryParams, queryParamCount); regHandled = true; break; // we only execute the first one } } if (regHandled && acceptIt) { + // @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 + // the chunks to the callback. May need callbacks that + // are: START: extract the filename/object name, + // NEXT: a chunk of data, + // END: signals that all chunks were delivered. + // // If so, we'll make space for it postQueryString = (char *)mymalloc(postBytes + 1); if (postQueryString) { @@ -666,12 +661,22 @@ n = client.receive(offset, postBytes - len); if (n >=0) { offset[n] = '\0'; + //printf("HTTPd: %d of %d: [%s]\r\n", len, postBytes, offset); + } else if (n < 0) { + //printf("HTTPd: n=%d\r\n", n); + break; // no more data, before the plan } } if (len >= 0) { - UnescapeString(postQueryString); - ParseParameters(postQueryString); +// UnescapeString(postQueryString); +// ParseParameters(postQueryString); + // use the same handler as for the length check + acceptIt = (*handlers[ndxHandler].callback)(this, DATA_TRANSFER, postQueryString, NULL, 0); + } else { + ERR("HTTPd: len error."); } + } else { + ERR("HTTPd: attempt to allocate %d failed.", postBytes+1); } } else { // Simply copy it to the bitbucket @@ -695,6 +700,7 @@ } + const char * HTTPServer::GetHeaderValue(const char * hdr) { int i;